Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:19:39

0001 #include "L1Trigger/DemonstratorTools/interface/BoardDataReader.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   BoardDataReader::BoardDataReader(FileFormat format,
0011                                    const std::vector<std::string>& fileNames,
0012                                    const size_t framesPerBX,
0013                                    const size_t tmux,
0014                                    const size_t emptyFramesAtStart,
0015                                    const ChannelMap_t& channelMap)
0016       : fileFormat_(format),
0017         fileNames_(fileNames),
0018         framesPerBX_(framesPerBX),
0019         boardTMUX_(tmux),
0020         emptyFramesAtStart_(emptyFramesAtStart),
0021         channelMap_(channelMap),
0022         events_() {
0023     // TODO (long term): Move much of this to separate function, and only read files on demand
0024 
0025     // Verify that channel map/spec is self-consistent
0026     for (const auto& [id, value] : channelMap_) {
0027       const auto& [spec, indices] = value;
0028       if ((spec.tmux % boardTMUX_) != 0)
0029         throw std::runtime_error("Link [" + id.interface + ", " + std::to_string(id.channel) +
0030                                  "]: Specified TMUX period, " + std::to_string(spec.tmux) +
0031                                  ", is not a multiple of the board TMUX, " + std::to_string(boardTMUX_));
0032 
0033       const size_t tmuxRatio(spec.tmux / boardTMUX_);
0034       if (indices.size() != tmuxRatio)
0035         throw std::runtime_error("Link [" + id.interface + ", " + std::to_string(id.channel) +
0036                                  "]: Number of channel indices specified, " + std::to_string(indices.size()) +
0037                                  ", does not match link:board TMUX ratio");
0038     }
0039 
0040     // Loop over input files
0041     for (const auto& path : fileNames_) {
0042       BoardData boardData(read(path, fileFormat_));
0043 
0044       // 1) Verify that all expected channels are present
0045       for (const auto& [id, value] : channelMap_) {
0046         const auto& [spec, indices] = value;
0047         for (const auto i : indices) {
0048           if (not boardData.has(i))
0049             throw std::runtime_error("Channel " + std::to_string(i) + " was declared but is missing from file '" +
0050                                      path + "'");
0051         }
0052       }
0053 
0054       // 2) Verify that packet structure is as expected
0055       for (const auto& [id, value] : channelMap) {
0056         const auto& [spec, indices] = value;
0057         for (size_t tmuxIndex = 0; tmuxIndex < indices.size(); tmuxIndex++) {
0058           const auto& chanData = boardData.at(indices.at(tmuxIndex));
0059 
0060           const size_t framesBeforeFirstPacket(emptyFramesAtStart_ + tmuxIndex * boardTMUX_ * framesPerBX_ +
0061                                                spec.offset);
0062           const size_t eventLength(spec.tmux * framesPerBX_);
0063           const size_t packetLength(eventLength - spec.interpacketGap);
0064 
0065           for (size_t j = 0; j < framesBeforeFirstPacket; j++) {
0066             if (chanData.at(j).valid)
0067               throw std::runtime_error("Frame " + std::to_string(j) + " on channel " +
0068                                        std::to_string(indices.at(tmuxIndex)) + " is valid, but first " +
0069                                        std::to_string(framesBeforeFirstPacket) + "frames should be invalid");
0070           }
0071 
0072           for (size_t j = framesBeforeFirstPacket; j < chanData.size(); j++) {
0073             if ((j + (framesPerBX_ * spec.tmux)) >= chanData.size())
0074               continue;
0075 
0076             bool expectValid(((j - framesBeforeFirstPacket) % eventLength) < packetLength);
0077             if (expectValid) {
0078               if (not chanData.at(j).valid)
0079                 throw std::runtime_error("Frame " + std::to_string(j) + " on channel " +
0080                                          std::to_string(indices.at(tmuxIndex)) +
0081                                          " is invalid, but expected valid frame (path='" + path + "')");
0082             } else if (chanData.at(j).valid)
0083               throw std::runtime_error("Frame " + std::to_string(j) + " on channel " +
0084                                        std::to_string(indices.at(tmuxIndex)) +
0085                                        " is valid, but expected invalid frame (path='" + path + "')");
0086           }
0087         }
0088       }
0089 
0090       // 3) Extract the data for each event
0091       bool eventIncomplete(false);
0092       for (size_t eventIndex = 0;; eventIndex++) {
0093         EventData eventData;
0094 
0095         for (const auto& [id, value] : channelMap) {
0096           const auto& [spec, indices] = value;
0097           const auto& chanData = boardData.at(indices.at(eventIndex % (spec.tmux / boardTMUX_)));
0098 
0099           // Extract the frames for this event
0100           const size_t framesBeforeEvent(eventIndex * boardTMUX_ * framesPerBX_ + emptyFramesAtStart_ + spec.offset);
0101           const size_t packetLength(spec.tmux * framesPerBX_ - spec.interpacketGap);
0102 
0103           if (chanData.size() < (framesBeforeEvent + spec.tmux * framesPerBX_)) {
0104             eventIncomplete = true;
0105             break;
0106           }
0107 
0108           std::vector<ap_uint<64>> chanEventData(packetLength);
0109           for (size_t j = 0; j < packetLength; j++)
0110             chanEventData.at(j) = chanData.at(framesBeforeEvent + j).data;
0111           eventData.add(id, chanEventData);
0112         }
0113 
0114         if (eventIncomplete)
0115           break;
0116 
0117         events_.push_back(eventData);
0118       }
0119     }
0120 
0121     eventIt_ = events_.begin();
0122   }
0123 
0124   BoardDataReader::BoardDataReader(FileFormat format,
0125                                    const std::vector<std::string>& fileNames,
0126                                    const size_t framesPerBX,
0127                                    const size_t tmux,
0128                                    const size_t emptyFramesAtStart,
0129                                    const std::map<LinkId, std::vector<size_t>>& channelMap,
0130                                    const std::map<std::string, ChannelSpec>& channelSpecs)
0131       : BoardDataReader(format, fileNames, framesPerBX, tmux, emptyFramesAtStart, mergeMaps(channelMap, channelSpecs)) {
0132   }
0133 
0134   EventData BoardDataReader::getNextEvent() {
0135     if (eventIt_ == events_.end())
0136       throw std::runtime_error("Board data reader ran out of events");
0137 
0138     return *(eventIt_++);
0139   }
0140 
0141   BoardDataReader::ChannelMap_t BoardDataReader::mergeMaps(const std::map<LinkId, std::vector<size_t>>& indexMap,
0142                                                            const std::map<std::string, ChannelSpec>& specMap) {
0143     ChannelMap_t channelMap;
0144     for (const auto& x : indexMap)
0145       channelMap.at(x.first) = {specMap.at(x.first.interface), x.second};
0146     return channelMap;
0147   }
0148 
0149 }  // namespace l1t::demo