-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCacheConfig.cc
77 lines (64 loc) · 2.88 KB
/
CacheConfig.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "CacheConfig.hh"
#include <string>
#include "inipp.h"
CacheConfig::CacheConfig(const CacheType type, const uint64_t size, const int line_size,
const int set_size)
: type(type), size(size), line_size(line_size), set_size(set_size) { }
CacheConfig::CacheConfig(std::istream&& config_file) {
inipp::Ini<char> ini;
ini.parse(config_file);
// Check that at most one level is defined
// Otherwise, a CacheHierarcy, not a single Cache, should be build from this file
if (ini.sections.size() == 1) {
if (!ini.sections.begin()->first.empty())
throw std::invalid_argument("Invalid section in cache config file: " +
ini.sections.begin()->first);
} else if (ini.sections.size() > 2)
throw std::invalid_argument("Too many sections section in cache config file: " +
std::to_string(ini.sections.size()));
else {
// If there are exactly two sections, they must be "hierarchy" and "L1"
for (const auto& section : ini.sections)
if (section.first != "hierarchy" && section.first != "L1")
throw std::invalid_argument("Invalid section in cache config file: " +
section.first);
try {
const int nlevels = std::stoi(ini.sections.at("hierarchy").at("levels"));
if (nlevels != 1)
throw std::invalid_argument("Too many levels for a single cache: " +
std::to_string(nlevels));
} catch (const std::out_of_range& e) {
std::cout << "Malformed config file: " << e.what() << "\n";
}
}
auto config_section =
ini.sections.size() == 1 ? ini.sections.at("") : ini.sections.at("L1");
read_config_map_(config_section);
}
CacheConfig::CacheConfig(const ConfigMap& config_map) { read_config_map_(config_map); }
void CacheConfig::read_config_map_(const ConfigMap& config_map) {
try {
size = std::stoi(config_map.at("cache_size"));
line_size = std::stoi(config_map.at("line_size"));
set_size = config_map.find("set_size") != std::end(config_map)
? std::stoi(config_map.at("set_size"))
: 1;
} catch (const std::out_of_range& e) {
throw std::invalid_argument(std::string("Malformed config file: ") + e.what());
}
auto typestr = config_map.at("type");
typestr.erase(std::remove_if(typestr.begin(), typestr.end(), [](unsigned char c) {
return std::isspace(c) || std::ispunct(c);
}));
std::transform(typestr.begin(), typestr.end(), typestr.begin(),
[](unsigned char c) { return std::tolower(c); });
if (typestr == "infinite")
type = CacheType::Infinite;
else if (typestr == "directmapped")
type = CacheType::DirectMapped;
else if (typestr == "setassociative")
type = CacheType::SetAssociative;
else {
throw std::invalid_argument("Invalid cache type in config file: " + typestr);
}
}