Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-04-01 23:54:04

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 size_t framesPerBX,
0013                                    const size_t tmux,
0014                                    const size_t maxFramesPerFile,
0015                                    const ChannelMap_t& channelSpecs)
0016       : fileFormat_(format),
0017         filePathGen_([=](const size_t i) { return path + "_" + std::to_string(i) + ".txt"; }),
0018         framesPerBX_(framesPerBX),
0019         boardTMUX_(tmux),
0020         maxFramesPerFile_(maxFramesPerFile),
0021         maxEventsPerFile_(maxFramesPerFile_),
0022         eventIndex_(0),
0023         pendingEvents_(0),
0024         channelMap_(channelSpecs) {
0025     if (channelMap_.empty())
0026       throw std::runtime_error("BoardDataWriter channel map cannnot be empty");
0027 
0028     for (const auto& [id, value] : channelMap_) {
0029       const auto& [spec, indices] = value;
0030       for (const auto i : indices)
0031         boardData_.add(i);
0032 
0033       if ((spec.tmux % boardTMUX_) != 0)
0034         throw std::runtime_error("BoardDataWriter, link [" + id.interface + ", " + std::to_string(id.channel) +
0035                                  "]: Specified TMUX period, " + std::to_string(spec.tmux) +
0036                                  ", is not a multiple of the board TMUX, " + std::to_string(boardTMUX_));
0037 
0038       const size_t tmuxRatio(spec.tmux / boardTMUX_);
0039       if (indices.size() != tmuxRatio)
0040         throw std::runtime_error("BoardDataWriter, link [" + id.interface + ", " + std::to_string(id.channel) +
0041                                  "]: Number of channel indices specified, " + std::to_string(indices.size()) +
0042                                  ", does not match link:board TMUX ratio, " + std::to_string(tmuxRatio));
0043 
0044       maxEventsPerFile_ = std::min(maxEventsPerFile_,
0045                                    ((maxFramesPerFile_ - spec.offset) / (framesPerBX_ * boardTMUX_)) - (tmuxRatio - 1));
0046     }
0047 
0048     resetBoardData();
0049   }
0050 
0051   BoardDataWriter::BoardDataWriter(FileFormat format,
0052                                    const std::string& path,
0053                                    const size_t framesPerBX,
0054                                    const size_t tmux,
0055                                    const size_t maxFramesPerFile,
0056                                    const std::map<LinkId, std::vector<size_t>>& channelMap,
0057                                    const std::map<std::string, ChannelSpec>& channelSpecs)
0058       : BoardDataWriter(format, path, framesPerBX, tmux, maxFramesPerFile, mergeMaps(channelMap, channelSpecs)) {}
0059 
0060   void BoardDataWriter::addEvent(const EventData& eventData) {
0061     // Check that data is supplied for each channel
0062     for (const auto& [id, info] : channelMap_) {
0063       if (not eventData.has(id))
0064         throw std::runtime_error("Event data for link " + id.interface + ", " + std::to_string(id.channel) +
0065                                  "] is missing.");
0066     }
0067 
0068     for (const auto& [id, channelData] : eventData) {
0069       // Check that each channel was declared to constructor
0070       if (channelMap_.count(id) == 0)
0071         throw std::runtime_error("Event data for link [" + id.interface + ", " + std::to_string(id.channel) +
0072                                  "] was given to BoardDataWriter, but its structure was not defined");
0073 
0074       const auto& [spec, indices] = channelMap_.at(id);
0075       const size_t chanIndex(indices.at(pendingEvents_ % (spec.tmux / boardTMUX_)));
0076 
0077       // Check that that expected amount of data has been provided
0078       if (channelData.size() > (spec.tmux * framesPerBX_ - spec.interpacketGap))
0079         throw std::runtime_error("Event data for link [" + id.interface + ", " + std::to_string(id.channel) +
0080                                  "] (TMUX " + std::to_string(spec.tmux) + ", " + std::to_string(spec.interpacketGap) +
0081                                  " cycles between packets) is too long (" + std::to_string(channelData.size()) +
0082                                  " 64-bit words)");
0083 
0084       if (channelData.empty())
0085         throw std::runtime_error("Event data for link [" + id.interface + ", " + std::to_string(id.channel) +
0086                                  "] is empty");
0087 
0088       // Copy event data for this channel to board data object
0089       boardData_.at(chanIndex).insert(boardData_.at(chanIndex).end(), channelData.begin(), channelData.end());
0090 
0091       // Override flags for start & end of event
0092       BoardData::Channel::iterator it(boardData_.at(chanIndex).end() - 1);
0093       it->end = true;
0094       it -= (channelData.size() - 1);
0095       it->start = true;
0096 
0097       // Pad link with non-valid frames
0098       boardData_.at(chanIndex).insert(
0099           boardData_.at(chanIndex).end(), spec.tmux * framesPerBX_ - channelData.size(), Frame());
0100     }
0101 
0102     eventIndex_++;
0103     pendingEvents_++;
0104 
0105     if (pendingEvents_ == maxEventsPerFile_)
0106       flush();
0107   }
0108 
0109   void BoardDataWriter::flush() {
0110     if (pendingEvents_ == 0)
0111       return;
0112 
0113     // Pad any channels that aren't full with invalid frames
0114     for (auto& x : boardData_)
0115       x.second.resize(maxFramesPerFile_);
0116 
0117     // Write board data object to file
0118     const std::string filePath = filePathGen_(fileNames_.size());
0119     write(boardData_, filePath, fileFormat_);
0120     fileNames_.push_back(filePath);
0121 
0122     // Clear board data to be ready for next event
0123     resetBoardData();
0124   }
0125 
0126   BoardDataWriter::ChannelMap_t BoardDataWriter::mergeMaps(const std::map<LinkId, std::vector<size_t>>& indexMap,
0127                                                            const std::map<std::string, ChannelSpec>& specMap) {
0128     ChannelMap_t channelMap;
0129     for (const auto& x : indexMap)
0130       channelMap[x.first] = {specMap.at(x.first.interface), x.second};
0131     return channelMap;
0132   }
0133 
0134   void BoardDataWriter::resetBoardData() {
0135     for (auto& x : boardData_)
0136       x.second.clear();
0137 
0138     for (const auto& [id, value] : channelMap_) {
0139       const auto& [spec, indices] = value;
0140       for (size_t tmuxIndex = 0; tmuxIndex < indices.size(); tmuxIndex++)
0141         boardData_.at(indices.at(tmuxIndex)).resize(tmuxIndex * boardTMUX_ * framesPerBX_ + spec.offset);
0142     }
0143 
0144     pendingEvents_ = 0;
0145   }
0146 
0147 }  // namespace l1t::demo