8 #include <boost/algorithm/string.hpp>
19 std::pair<NumericAddressedRegisterCatalogue, MetadataCatalogue>
MapFileParser::parse(
const std::string& file_name_) {
20 file_name = file_name_;
23 file.open(file_name.c_str());
29 while(std::getline(file, line)) {
33 line.erase(line.begin(), std::find_if(line.begin(), line.end(), [](
int c) { return !isspace(c); }));
36 auto pos = line.find(
'#');
37 if(pos != std::string::npos) {
38 line.erase(pos, std::string::npos);
53 parsedLines.push_back(parseLine(line));
58 for(
const auto& pl : parsedLines) {
59 parsedLinesMap.emplace(pl.pathName, pl);
63 for(
const auto& pl : parsedLines) {
64 if(isScalarOr1D(pl.pathName)) {
66 pl.width, pl.nFractionalBits, pl.signedFlag, pl.registerAccess, pl.type, pl.interruptID);
69 else if(is2D(pl.pathName)) {
72 else if(is2DNewStyle(pl.pathName)) {
77 return {std::move(pmap), std::move(metadataCatalogue)};
82 std::pair<RegisterPath, std::string> MapFileParser::splitStringAtLastDot(
RegisterPath moduleDotName) {
86 return {moduleDotName, regname};
91 std::pair<NumericAddressedRegisterInfo::Type, int> MapFileParser::getTypeAndNFractionalBits(
92 const std::string& bitInterpretation,
unsigned int width) {
99 int nBits = std::stoi(bitInterpretation,
nullptr,
103 catch(std::exception& e) {
105 bitInterpretation +
"', caught exception: " + e.what());
111 std::vector<size_t> MapFileParser::getInterruptId(std::string accessTypeStr) {
112 std::string strToFind(
"INTERRUPT");
113 auto pos = accessTypeStr.find(strToFind);
114 if(pos == std::string::npos)
return {};
115 std::vector<size_t> retVal;
117 accessTypeStr.erase(pos, strToFind.length());
121 delimiterPos = accessTypeStr.find(
':');
122 std::string interruptStr = accessTypeStr.substr(0, delimiterPos);
123 size_t interruptNumber = 0;
125 interruptNumber = std::stoul(interruptStr,
nullptr, 0);
127 catch(std::exception& e) {
129 std::string(
"Map file error in accessString: wrong argument in interrupt controller number. Argument: '") +
130 interruptStr +
"', caught exception: " + e.what());
132 retVal.push_back(interruptNumber);
135 if(delimiterPos != std::string::npos) {
136 accessTypeStr = accessTypeStr.substr(delimiterPos + 1);
138 }
while(delimiterPos != std::string::npos);
147 uint64_t bar, uint32_t width, int32_t nFractionalBits,
bool signedFlag) {
152 throw ChimeraTK::logic_error(std::string(
"Map file error. Register Type is VOID and access mode is READ only. "));
158 if(width || nElements || address || nBytes || bar || nFractionalBits || signedFlag) {
160 std::string(
"Map file error. Register Type is VOID (width field set to 0). All other fields must be '0'."));
167 void MapFileParser::parseMetaData(std::string line) {
168 std::string metadata_name, metadata_value;
171 line.erase(line.begin(), line.begin() + 1);
174 line.erase(line.begin(), std::find_if(line.begin(), line.end(), [](
int c) { return !isspace(c); }));
176 std::istringstream is;
183 line.erase(line.begin(), line.begin() +
static_cast<std::string::difference_type
>(metadata_name.length()));
185 line.erase(std::remove_if(line.begin(), line.end(), [](
unsigned char x) { return std::isspace(x); }),
187 metadata_value = line;
188 metadataCatalogue.
addMetadata(metadata_name, metadata_value);
194 MapFileParser::ParsedLine MapFileParser::parseLine(
const std::string& line) {
197 std::istringstream is;
204 pl.pathName.setAltSeparator(
".");
207 is >> std::setbase(0) >> pl.nElements >> std::setbase(0) >> pl.address >> std::setbase(0) >> pl.nBytes;
215 is >> std::setbase(0) >> pl.bar;
219 is >> std::setbase(0) >> pl.width;
228 std::string bitInterpretation;
229 is >> bitInterpretation;
232 std::tie(pl.type, pl.nFractionalBits) = getTypeAndNFractionalBits(bitInterpretation, pl.width);
233 if(pl.nFractionalBits > 1023 || pl.nFractionalBits < -1024) {
242 is >> std::setbase(0) >> pl.signedFlag;
247 std::string accessString;
251 std::transform(accessString.begin(), accessString.end(), accessString.begin(),
252 [](
unsigned char c) { return std::toupper(c); });
255 auto interruptId = getInterruptId(accessString);
257 if(!interruptId.empty()) {
259 pl.interruptID = interruptId;
261 else if(accessString ==
"RO") {
264 else if(accessString ==
"RW") {
267 else if(accessString ==
"WO") {
277 checkFileConsitencyAndThrowIfError(pl.registerAccess, pl.type, pl.nElements, pl.address, pl.nBytes, pl.bar,
278 pl.width, pl.nFractionalBits, pl.signedFlag);
285 bool MapFileParser::isScalarOr1D(
const RegisterPath& pathName) {
286 auto [module, name] = splitStringAtLastDot(pathName);
294 bool MapFileParser::is2D(
const RegisterPath& pathName) {
295 auto [module, name] = splitStringAtLastDot(pathName);
301 bool MapFileParser::is2DNewStyle(RegisterPath pathName) {
303 pathName.setAltSeparator(
".");
304 auto components = pathName.getComponents();
305 if(components.size() != 2)
return false;
311 RegisterPath MapFileParser::makeSequenceName(
const RegisterPath& pathName,
size_t index) {
312 auto [module, name] = splitStringAtLastDot(pathName);
316 r.setAltSeparator(
".");
322 RegisterPath MapFileParser::make2DName(
const RegisterPath& pathName,
const std::string& prefix) {
323 auto [module, name] = splitStringAtLastDot(pathName);
324 assert(boost::algorithm::starts_with(name, prefix));
325 name = name.substr(prefix.size());
326 auto r = RegisterPath(module) / name;
327 r.setAltSeparator(
".");
333 void MapFileParser::handle2DNewStyle(
const ParsedLine& pl) {
337 std::list<ParsedLine> channelLines;
338 for(
auto& [key, value] : parsedLinesMap) {
339 if(key.startsWith(pl.pathName) and pl.pathName.length() < key.length()) {
341 if(value.address < pl.address) {
343 "Start address of channel smaller than 2D register start address ('" + pl.pathName +
"').");
345 channelLines.push_back(value);
349 channelLines.sort([](
auto& a,
auto& b) {
return a.address < b.address; });
353 void MapFileParser::make2DRegisterInfos(
354 const ParsedLine& pl, std::list<ParsedLine>& channelLines,
const std::string& prefix) {
355 if(channelLines.empty()) {
359 std::vector<NumericAddressedRegisterInfo::ChannelInfo> channels;
360 size_t bytesPerBlock = 0;
362 for(
auto& channel : channelLines) {
363 channels.emplace_back(NumericAddressedRegisterInfo::ChannelInfo{uint32_t(channel.address - pl.address) * 8,
364 channel.type, channel.width, channel.nFractionalBits, channel.signedFlag});
365 bytesPerBlock += channel.nBytes;
366 if(channel.nBytes != 1 && channel.nBytes != 2 && channel.nBytes != 4) {
371 assert(bytesPerBlock > 0);
374 for(
size_t i = 0; i < channels.size() - 1; ++i) {
375 auto actualWidth = channels[i + 1].bitOffset - channels[i].bitOffset;
376 if(channels[i].width > actualWidth) {
377 channels[i].width = actualWidth;
382 auto actualWidth = bytesPerBlock * 8 - channels.back().bitOffset;
383 if(channels.back().width > actualWidth) {
384 channels.back().width = actualWidth;
389 auto nBlocks =
static_cast<uint32_t
>(std::floor(pl.nBytes / bytesPerBlock));
390 auto name2D = make2DName(pl.pathName, prefix);
391 auto registerInfo = NumericAddressedRegisterInfo(
392 name2D, pl.bar, pl.address, nBlocks, bytesPerBlock * 8, channels, pl.registerAccess, pl.interruptID);
396 assert(pl.nBytes % 4 == 0);
397 auto registerInfoMuxedRaw =
398 NumericAddressedRegisterInfo(name2D +
".MULTIPLEXED_RAW", pl.nBytes / 4, pl.address, pl.nBytes, pl.bar, 32, 0,
405 void MapFileParser::handle2D(
const ParsedLine& pl) {
407 std::list<ParsedLine> channelLines;
409 auto it = parsedLinesMap.find(makeSequenceName(pl.pathName, channelLines.size()));
410 if(it == parsedLinesMap.end())
break;
411 if(it->second.address < pl.address) {
413 "Start address of channel smaller than 2D register start address ('" + pl.pathName +
"').");
415 channelLines.push_back(it->second);