File indexing completed on 2024-04-06 12:19:39
0001 #include "L1Trigger/DemonstratorTools/interface/BoardDataWriter.h"
0002
0003 #include <fstream>
0004
0005 #include "L1Trigger/DemonstratorTools/interface/Frame.h"
0006 #include "L1Trigger/DemonstratorTools/interface/utilities.h"
0007
0008 namespace l1t::demo {
0009
0010 BoardDataWriter::BoardDataWriter(FileFormat format,
0011 const std::string& path,
0012 const std::string& fileExt,
0013 const size_t framesPerBX,
0014 const size_t tmux,
0015 const size_t maxFramesPerFile,
0016 const ChannelMap_t& channelSpecs)
0017 : fileFormat_(format),
0018 boardDataFileID_("CMSSW"),
0019 filePathGen_([=](const size_t i) { return path + "_" + std::to_string(i) + "." + fileExt; }),
0020 framesPerBX_(framesPerBX),
0021 boardTMUX_(tmux),
0022 maxFramesPerFile_(maxFramesPerFile),
0023 maxEventsPerFile_(maxFramesPerFile_),
0024 eventIndex_(0),
0025 pendingEvents_(0),
0026 channelMap_(channelSpecs) {
0027 if (channelMap_.empty())
0028 throw std::runtime_error("BoardDataWriter channel map cannnot be empty");
0029 if (fileExt != "txt" && fileExt != "txt.gz" && fileExt != "txt.xz")
0030 throw std::runtime_error("BoardDataWriter fileExt must be one of txt, txt.gz, txt.xz");
0031
0032 for (const auto& [id, value] : channelMap_) {
0033 const auto& [spec, indices] = value;
0034 for (const auto i : indices)
0035 boardData_.add(i);
0036
0037 if ((spec.tmux % boardTMUX_) != 0)
0038 throw std::runtime_error("BoardDataWriter, link [" + id.interface + ", " + std::to_string(id.channel) +
0039 "]: Specified TMUX period, " + std::to_string(spec.tmux) +
0040 ", is not a multiple of the board TMUX, " + std::to_string(boardTMUX_));
0041
0042 const size_t tmuxRatio(spec.tmux / boardTMUX_);
0043 if (indices.size() != tmuxRatio)
0044 throw std::runtime_error("BoardDataWriter, link [" + id.interface + ", " + std::to_string(id.channel) +
0045 "]: Number of channel indices specified, " + std::to_string(indices.size()) +
0046 ", does not match link:board TMUX ratio, " + std::to_string(tmuxRatio));
0047
0048 maxEventsPerFile_ = std::min(maxEventsPerFile_,
0049 ((maxFramesPerFile_ - spec.offset) / (framesPerBX_ * boardTMUX_)) - (tmuxRatio - 1));
0050 }
0051
0052 resetBoardData();
0053 }
0054
0055 BoardDataWriter::BoardDataWriter(FileFormat format,
0056 const std::string& path,
0057 const std::string& fileExt,
0058 const size_t framesPerBX,
0059 const size_t tmux,
0060 const size_t maxFramesPerFile,
0061 const std::map<LinkId, std::vector<size_t>>& channelMap,
0062 const std::map<std::string, ChannelSpec>& channelSpecs)
0063 : BoardDataWriter(
0064 format, path, fileExt, framesPerBX, tmux, maxFramesPerFile, mergeMaps(channelMap, channelSpecs)) {}
0065
0066 void BoardDataWriter::setBoardDataFileID(const std::string& aId) { boardDataFileID_ = aId; }
0067
0068 void BoardDataWriter::addEvent(const EventData& eventData) {
0069
0070 for (const auto& [id, info] : channelMap_) {
0071 if (not eventData.has(id))
0072 throw std::runtime_error("Event data for link [" + id.interface + ", " + std::to_string(id.channel) +
0073 "] is missing.");
0074 }
0075
0076 for (const auto& [id, channelData] : eventData) {
0077
0078 if (channelMap_.count(id) == 0)
0079 throw std::runtime_error("Event data for link [" + id.interface + ", " + std::to_string(id.channel) +
0080 "] was given to BoardDataWriter, but its structure was not defined");
0081
0082 const auto& [spec, indices] = channelMap_.at(id);
0083 const size_t chanIndex(indices.at(pendingEvents_ % (spec.tmux / boardTMUX_)));
0084
0085
0086 if (channelData.size() > (spec.tmux * framesPerBX_ - spec.interpacketGap))
0087 throw std::runtime_error("Event data for link [" + id.interface + ", " + std::to_string(id.channel) +
0088 "] (TMUX " + std::to_string(spec.tmux) + ", " + std::to_string(spec.interpacketGap) +
0089 " cycles between packets) is too long (" + std::to_string(channelData.size()) +
0090 " 64-bit words)");
0091
0092 if (channelData.empty())
0093 throw std::runtime_error("Event data for link [" + id.interface + ", " + std::to_string(id.channel) +
0094 "] is empty");
0095
0096
0097 boardData_.at(chanIndex).insert(boardData_.at(chanIndex).end(), channelData.begin(), channelData.end());
0098
0099
0100 BoardData::Channel::iterator it(boardData_.at(chanIndex).end() - 1);
0101 it->endOfPacket = true;
0102 it -= (channelData.size() - 1);
0103 it->startOfPacket = true;
0104
0105
0106 boardData_.at(chanIndex).insert(
0107 boardData_.at(chanIndex).end(), spec.tmux * framesPerBX_ - channelData.size(), Frame());
0108 }
0109
0110 eventIndex_++;
0111 pendingEvents_++;
0112
0113 if (pendingEvents_ == maxEventsPerFile_)
0114 flush();
0115 }
0116
0117 void BoardDataWriter::flush() {
0118 if (pendingEvents_ == 0)
0119 return;
0120
0121
0122 for (auto& x : boardData_)
0123 x.second.resize(maxFramesPerFile_);
0124
0125
0126 for (auto& x : boardData_) {
0127 for (auto& frame : x.second) {
0128 if (frame.startOfPacket) {
0129 frame.startOfOrbit = true;
0130 break;
0131 }
0132 }
0133 }
0134
0135
0136 boardData_.name(boardDataFileID_);
0137
0138
0139 const std::string filePath = filePathGen_(fileNames_.size());
0140 write(boardData_, filePath, fileFormat_);
0141 fileNames_.push_back(filePath);
0142
0143
0144 resetBoardData();
0145 }
0146
0147 BoardDataWriter::ChannelMap_t BoardDataWriter::mergeMaps(const std::map<LinkId, std::vector<size_t>>& indexMap,
0148 const std::map<std::string, ChannelSpec>& specMap) {
0149 ChannelMap_t channelMap;
0150 for (const auto& x : indexMap)
0151 channelMap[x.first] = {specMap.at(x.first.interface), x.second};
0152 return channelMap;
0153 }
0154
0155 void BoardDataWriter::resetBoardData() {
0156 for (auto& x : boardData_)
0157 x.second.clear();
0158
0159 for (const auto& [id, value] : channelMap_) {
0160 const auto& [spec, indices] = value;
0161 for (size_t tmuxIndex = 0; tmuxIndex < indices.size(); tmuxIndex++)
0162 boardData_.at(indices.at(tmuxIndex)).resize(tmuxIndex * boardTMUX_ * framesPerBX_ + spec.offset);
0163 }
0164
0165 pendingEvents_ = 0;
0166 }
0167
0168 }