Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-20 01:53:37

0001 #include "L1Trigger/Phase2L1ParticleFlow/interface/L1TCorrelatorLayer1PatternFileWriter.h"
0002 #include "L1Trigger/Phase2L1ParticleFlow/interface/regionizer/middle_buffer_multififo_regionizer_ref.h"
0003 #include "L1Trigger/Phase2L1ParticleFlow/interface/dbgPrintf.h"
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 #include "FWCore/ParameterSet/interface/allowedValues.h"
0006 #include <iostream>
0007 
0008 L1TCorrelatorLayer1PatternFileWriter::L1TCorrelatorLayer1PatternFileWriter(const edm::ParameterSet& iConfig,
0009                                                                            const l1ct::Event& eventTemplate)
0010     : partition_(parsePartition(iConfig.getParameter<std::string>("partition"))),
0011       tmuxFactor_(iConfig.getParameter<uint32_t>("tmuxFactor")),
0012       writeInputs_(!iConfig.getParameter<std::string>("inputFileName").empty()),
0013       writeOutputs_(!iConfig.getParameter<std::string>("outputFileName").empty()),
0014       writeDebugs_(!iConfig.getParameter<std::string>("debugFileName").empty()),
0015       tfTimeslices_(std::max(1u, tfTmuxFactor_ / tmuxFactor_)),
0016       hgcTimeslices_(std::max(1u, hgcTmuxFactor_ / tmuxFactor_)),
0017       gctEmTimeslices_(std::max(1u, gctEmTmuxFactor_ / tmuxFactor_)),
0018       gctHadTimeslices_(std::max(1u, gctHadTmuxFactor_ / tmuxFactor_)),
0019       gmtTimeslices_(std::max(1u, gmtTmuxFactor_ / tmuxFactor_)),
0020       gttTimeslices_(std::max(1u, gttTmuxFactor_ / tmuxFactor_)),
0021       outputBoard_(-1),
0022       outputLinkEgamma_(-1),
0023       nPFInTrack_(iConfig.getParameter<uint32_t>("nPFInTrack")),  // these are only for debugging
0024       nPFInEmCalo_(iConfig.getParameter<uint32_t>("nPFInEmCalo")),
0025       nPFInHadCalo_(iConfig.getParameter<uint32_t>("nPFInHadCalo")),
0026       nPFInMuon_(iConfig.getParameter<uint32_t>("nPFInMuon")),
0027       nPFOutCharged_(iConfig.getParameter<uint32_t>("nPFOutCharged")),  // these are only for debugging
0028       nPFOutPhoton_(iConfig.getParameter<uint32_t>("nPFOutPhoton")),
0029       nPFOutNeutral_(iConfig.getParameter<uint32_t>("nPFOutNeutral")),
0030       nPFOutMuon_(iConfig.getParameter<uint32_t>("nPFOutMuon")),
0031       fileFormat_(iConfig.getParameter<std::string>("fileFormat")),
0032       eventsPerFile_(iConfig.getParameter<uint32_t>("eventsPerFile")),
0033       eventIndex_(0) {
0034   if (writeInputs_) {
0035     nInputFramesPerBX_ = iConfig.getParameter<uint32_t>("nInputFramesPerBX");
0036 
0037     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0038       configTimeSlices(iConfig, "tf", eventTemplate.raw.track.size(), tfTimeslices_, tfLinksFactor_);
0039       tfNumberOfTracks_ = iConfig.getParameter<uint32_t>("tfNumberOfTracks");
0040       channelSpecsInput_["tf"] = {tfTmuxFactor_,
0041                                   tfTimeslices_ * nInputFramesPerBX_ * tmuxFactor_ - (tfNumberOfTracks_ * 3 / 2)};
0042     }
0043     if (partition_ == Partition::Barrel) {
0044       configTimeSlices(iConfig, "gctEm", eventTemplate.raw.gctEm.size(), gctEmTimeslices_, gctEmLinksFactor_);
0045       gctNumberOfEMs_ = iConfig.getParameter<uint32_t>("gctNumberOfEMs");
0046       channelSpecsInput_["gctEm"] = {tmuxFactor_ * gctEmTimeslices_,
0047                                      gctEmTimeslices_ * nInputFramesPerBX_ * tmuxFactor_ - gctNumberOfEMs_};
0048       configTimeSlices(iConfig, "gctHad", eventTemplate.raw.gctHad.size(), gctHadTimeslices_, gctHadLinksFactor_);
0049       gctNumberOfHads_ = iConfig.getParameter<uint32_t>("gctNumberOfHads");
0050       channelSpecsInput_["gctHad"] = {tmuxFactor_ * gctHadTimeslices_,
0051                                       gctHadTimeslices_ * nInputFramesPerBX_ * tmuxFactor_ - gctNumberOfHads_};
0052     }
0053     if (partition_ == Partition::HGCal || partition_ == Partition::HGCalNoTk) {
0054       configTimeSlices(iConfig, "hgc", eventTemplate.raw.hgcalcluster.size(), hgcTimeslices_, hgcLinksFactor_);
0055       channelSpecsInput_["hgc"] = {tmuxFactor_ * hgcTimeslices_, hgcTimeslices_};
0056     }
0057     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal || partition_ == Partition::HGCalNoTk) {
0058       configTimeSlices(iConfig, "gmt", 1, gmtTimeslices_, gmtLinksFactor_);
0059       gmtNumberOfMuons_ = iConfig.getParameter<uint32_t>("gmtNumberOfMuons");
0060       channelSpecsInput_["gmt"] = {tmuxFactor_ * gmtTimeslices_,
0061                                    gmtTimeslices_ * nInputFramesPerBX_ * tmuxFactor_ - gmtNumberOfMuons_};
0062     }
0063     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0064       configTimeSlices(iConfig, "gtt", 1, gttTimeslices_, gttLinksFactor_);
0065       gttLatency_ = iConfig.getParameter<uint32_t>("gttLatency");
0066       gttNumberOfPVs_ = iConfig.getParameter<uint32_t>("gttNumberOfPVs");
0067       channelSpecsInput_["gtt"] =
0068           l1t::demo::ChannelSpec{tmuxFactor_ * gttTimeslices_,
0069                                  gttTimeslices_ * nInputFramesPerBX_ * tmuxFactor_ - gttNumberOfPVs_,
0070                                  gttLatency_};
0071     }
0072     inputFileWriter_ =
0073         std::make_unique<l1t::demo::BoardDataWriter>(l1t::demo::parseFileFormat(fileFormat_),
0074                                                      iConfig.getParameter<std::string>("inputFileName"),
0075                                                      iConfig.getParameter<std::string>("inputFileExtension"),
0076                                                      nInputFramesPerBX_,
0077                                                      tmuxFactor_,
0078                                                      iConfig.getParameter<uint32_t>("maxLinesPerInputFile"),
0079                                                      channelIdsInput_,
0080                                                      channelSpecsInput_);
0081   }
0082 
0083   if (writeOutputs_) {
0084     nOutputFramesPerBX_ = iConfig.getParameter<uint32_t>("nOutputFramesPerBX");
0085 
0086     outputRegions_ = iConfig.getParameter<std::vector<uint32_t>>("outputRegions");
0087     outputLinksPuppi_ = iConfig.getParameter<std::vector<uint32_t>>("outputLinksPuppi");
0088     for (unsigned int i = 0; i < outputLinksPuppi_.size(); ++i) {
0089       channelIdsOutput_[l1t::demo::LinkId{"puppi", i}].push_back(outputLinksPuppi_[i]);
0090     }
0091     channelSpecsOutput_["puppi"] = {tmuxFactor_, 0};
0092     nPuppiFramesPerRegion_ = (nOutputFramesPerBX_ * tmuxFactor_) / outputRegions_.size();
0093     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0094       outputLinkEgamma_ = iConfig.getParameter<int32_t>("outputLinkEgamma");
0095       nEgammaObjectsOut_ = iConfig.getParameter<uint32_t>("nEgammaObjectsOut");
0096       if (outputLinkEgamma_ != -1) {
0097         channelIdsOutput_[l1t::demo::LinkId{"egamma", 0}].push_back(outputLinkEgamma_);
0098         if (tmuxFactor_ == 18) {
0099           // the format is different, as we put together multiple endcaps or slices
0100           unsigned int nboards = (partition_ == Partition::Barrel) ? 3 : 2;
0101           channelSpecsOutput_["egamma"] = {tmuxFactor_,
0102                                            nOutputFramesPerBX_ * tmuxFactor_ / nboards - 3 * nEgammaObjectsOut_};
0103         } else {
0104           outputBoard_ = iConfig.getParameter<int32_t>("outputBoard");
0105           channelSpecsOutput_["egamma"] = {tmuxFactor_, nOutputFramesPerBX_ * tmuxFactor_ - 3 * nEgammaObjectsOut_};
0106         }
0107       }
0108     }
0109     outputFileWriter_ =
0110         std::make_unique<l1t::demo::BoardDataWriter>(l1t::demo::parseFileFormat(fileFormat_),
0111                                                      iConfig.getParameter<std::string>("outputFileName"),
0112                                                      iConfig.getParameter<std::string>("outputFileExtension"),
0113                                                      nOutputFramesPerBX_,
0114                                                      tmuxFactor_,
0115                                                      iConfig.getParameter<uint32_t>("maxLinesPerOutputFile"),
0116                                                      channelIdsOutput_,
0117                                                      channelSpecsOutput_);
0118   }
0119 
0120   if (writeDebugs_) {
0121     // ouput internal signals for easier debugging
0122     nOutputFramesPerBX_ = iConfig.getParameter<uint32_t>("nOutputFramesPerBX");
0123 
0124     // Note:  the writers have a width of 64 very much hardcoded in the sizes. Therefore, send the bits as
0125     //        two separate "fibers"
0126     outputRegions_ = iConfig.getParameter<std::vector<uint32_t>>("outputRegions");
0127     int linkCount = 0;
0128     for (unsigned int i = 0; i < nPFInTrack_ * 2; ++i) {
0129       channelIdsOutput_[l1t::demo::LinkId{"pfin_track", i}].push_back(linkCount++);
0130     }
0131     for (unsigned int i = 0; i < nPFInEmCalo_ * 2; ++i) {
0132       channelIdsOutput_[l1t::demo::LinkId{"pfin_emcalo", i}].push_back(linkCount++);
0133     }
0134     for (unsigned int i = 0; i < nPFInHadCalo_ * 2; ++i) {
0135       channelIdsOutput_[l1t::demo::LinkId{"pfin_hadcalo", i}].push_back(linkCount++);
0136     }
0137     for (unsigned int i = 0; i < nPFInMuon_ * 2; ++i) {
0138       channelIdsOutput_[l1t::demo::LinkId{"pfin_muon", i}].push_back(linkCount++);
0139     }
0140     for (unsigned int i = 0; i < nPFOutCharged_ * 2; ++i) {
0141       channelIdsOutput_[l1t::demo::LinkId{"pfout_charged", i}].push_back(linkCount++);
0142     }
0143     for (unsigned int i = 0; i < nPFOutPhoton_ * 2; ++i) {
0144       channelIdsOutput_[l1t::demo::LinkId{"pfout_photon", i}].push_back(linkCount++);
0145     }
0146     for (unsigned int i = 0; i < nPFOutNeutral_ * 2; ++i) {
0147       channelIdsOutput_[l1t::demo::LinkId{"pfout_neutral", i}].push_back(linkCount++);
0148     }
0149     for (unsigned int i = 0; i < nPFOutMuon_ * 2; ++i) {
0150       channelIdsOutput_[l1t::demo::LinkId{"pfout_muon", i}].push_back(linkCount++);
0151     }
0152     channelSpecsOutput_["pfin_track"] = {tmuxFactor_, 0};
0153     channelSpecsOutput_["pfin_emcalo"] = {tmuxFactor_, 0};
0154     channelSpecsOutput_["pfin_hadcalo"] = {tmuxFactor_, 0};
0155     channelSpecsOutput_["pfin_muon"] = {tmuxFactor_, 0};
0156     channelSpecsOutput_["pfout_charged"] = {tmuxFactor_, 0};
0157     channelSpecsOutput_["pfout_photon"] = {tmuxFactor_, 0};
0158     channelSpecsOutput_["pfout_neutral"] = {tmuxFactor_, 0};
0159     channelSpecsOutput_["pfout_muon"] = {tmuxFactor_, 0};
0160 
0161     debugFileWriter_ =
0162         std::make_unique<l1t::demo::BoardDataWriter>(l1t::demo::parseFileFormat(fileFormat_),
0163                                                      iConfig.getParameter<std::string>("debugFileName"),
0164                                                      iConfig.getParameter<std::string>("debugFileExtension"),
0165                                                      nOutputFramesPerBX_,
0166                                                      tmuxFactor_,
0167                                                      iConfig.getParameter<uint32_t>("maxLinesPerOutputFile"),
0168                                                      channelIdsOutput_,
0169                                                      channelSpecsOutput_);
0170   }
0171 }
0172 
0173 L1TCorrelatorLayer1PatternFileWriter::~L1TCorrelatorLayer1PatternFileWriter() {}
0174 
0175 edm::ParameterSetDescription L1TCorrelatorLayer1PatternFileWriter::getParameterSetDescription() {
0176   edm::ParameterSetDescription description;
0177   description.add<std::string>("inputFileName", "");
0178   description.add<std::string>("inputFileExtension", "txt.gz");
0179   description.add<uint32_t>("maxLinesPerInputFile", 1024u);
0180   description.add<uint32_t>("nInputFramesPerBX", 9u);
0181   description.add<std::string>("outputFileName", "");
0182   description.add<std::string>("outputFileExtension", "txt.gz");
0183   description.add<uint32_t>("maxLinesPerOutputFile", 1024u);
0184   description.add<uint32_t>("nOutputFramesPerBX", 9u);
0185   description.add<uint32_t>("tmuxFactor", 6u);
0186   description.add<uint32_t>("eventsPerFile", 12u);
0187   description.add<std::string>("fileFormat");
0188 
0189   // these are for debugging internal values
0190   description.add<std::string>("debugFileName", "");
0191   description.add<std::string>("debugFileExtension", "txt.gz");
0192   description.add<uint32_t>("nPFInTrack", 0);  // A value of 0 turns off adding it to the output
0193   description.add<uint32_t>("nPFInEmCalo", 0);
0194   description.add<uint32_t>("nPFInHadCalo", 0);
0195   description.add<uint32_t>("nPFInMuon", 0);
0196   description.add<uint32_t>("nPFOutCharged", 0);
0197   description.add<uint32_t>("nPFOutPhoton", 0);
0198   description.add<uint32_t>("nPFOutNeutral", 0);
0199   description.add<uint32_t>("nPFOutMuon", 0);
0200 
0201   description.ifValue(edm::ParameterDescription<std::string>("partition", "Barrel", true),
0202                       "Barrel" >> (describeTF() and describeGCTEm() and describeGCTHad() and describeGTT() and
0203                                    describeGMT() and describePuppi() and describeEG()) or
0204                           "HGCal" >> (describeTF() and describeHGC() and describeGTT() and describeGMT() and
0205                                       describePuppi() and describeEG()) or
0206                           "HGCalNoTk" >> (describeHGC() and describeGMT() and describePuppi()) or
0207                           "HF" >> (describePuppi()));
0208   return description;
0209 }
0210 
0211 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeTF() {
0212   return describeTimeSlices("tf") and edm::ParameterDescription<uint32_t>(
0213                                           "tfNumberOfTracks", 108, true);  // need to change if Serenity needs variable
0214 }
0215 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeGCTEm() {
0216   return describeTimeSlices("gctEm") and edm::ParameterDescription<uint32_t>("gctNumberOfEMs", 32, true);
0217 }
0218 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeGCTHad() {
0219   return describeTimeSlices("gctHad") and edm::ParameterDescription<uint32_t>("gctNumberOfHads", 48, true);
0220 }
0221 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeHGC() {
0222   return describeTimeSlices("hgc");
0223 }
0224 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeGMT() {
0225   return describeTimeSlices("gmt") and edm::ParameterDescription<uint32_t>("gmtNumberOfMuons", 12, true);
0226 }
0227 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeGTT() {
0228   return describeTimeSlices("gtt") and
0229          edm::ParameterDescription<uint32_t>("gttLatency", 162, true) and  // minimal latency is 18 BX
0230          edm::ParameterDescription<uint32_t>("gttNumberOfPVs", 10, true);
0231 }
0232 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describePuppi() {
0233   return edm::ParameterDescription<std::vector<uint32_t>>("outputRegions", std::vector<uint32_t>(), true) and
0234          edm::ParameterDescription<std::vector<uint32_t>>("outputLinksPuppi", std::vector<uint32_t>(), true);
0235 }
0236 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeEG() {
0237   return edm::ParameterDescription<int32_t>("outputLinkEgamma", -1, true) and
0238          edm::ParameterDescription<uint32_t>("nEgammaObjectsOut", 16, true) and
0239          edm::ParameterDescription<int32_t>("outputBoard", -1, true);
0240 }
0241 
0242 void L1TCorrelatorLayer1PatternFileWriter::write(const l1ct::Event& event) {
0243   if (writeInputs_) {
0244     l1t::demo::EventData inputs;
0245     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0246       writeTF(event, inputs);
0247     }
0248     if (partition_ == Partition::Barrel) {
0249       writeGCTEm(event, inputs);
0250       writeGCTHad(event, inputs);
0251     }
0252     if (partition_ == Partition::HGCal || partition_ == Partition::HGCalNoTk) {
0253       writeHGC(event, inputs);
0254     }
0255     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal || partition_ == Partition::HGCalNoTk) {
0256       writeGMT(event, inputs);
0257     }
0258     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0259       writeGTT(event, inputs);
0260     }
0261     inputFileWriter_->addEvent(inputs);
0262   }
0263 
0264   if (writeOutputs_) {
0265     l1t::demo::EventData outputs;
0266     writePuppi(event, outputs);
0267     if (outputLinkEgamma_ != -1)
0268       writeEgamma(event, outputs);
0269     outputFileWriter_->addEvent(outputs);
0270   }
0271 
0272   if (writeDebugs_) {
0273     l1t::demo::EventData debugs;
0274     writeDebugs(event, debugs);
0275     debugFileWriter_->addEvent(debugs);
0276   }
0277 
0278   eventIndex_++;
0279   if (eventIndex_ % eventsPerFile_ == 0) {
0280     if (writeInputs_)
0281       inputFileWriter_->flush();
0282     if (writeOutputs_)
0283       outputFileWriter_->flush();
0284     if (writeDebugs_)
0285       debugFileWriter_->flush();
0286   }
0287 }
0288 
0289 L1TCorrelatorLayer1PatternFileWriter::Partition L1TCorrelatorLayer1PatternFileWriter::parsePartition(
0290     const std::string& partition) {
0291   if (partition == "Barrel")
0292     return Partition::Barrel;
0293   if (partition == "HGCal")
0294     return Partition::HGCal;
0295   if (partition == "HGCalNoTk")
0296     return Partition::HGCalNoTk;
0297   if (partition == "HF")
0298     return Partition::HF;
0299   throw cms::Exception("Configuration", "Unsupported partition_ '" + partition + "'\n");
0300 }
0301 
0302 void L1TCorrelatorLayer1PatternFileWriter::configTimeSlices(const edm::ParameterSet& iConfig,
0303                                                             const std::string& prefix,
0304                                                             unsigned int nSectors,
0305                                                             unsigned int nTimeSlices,
0306                                                             unsigned int linksFactor) {
0307   if (nTimeSlices > 1) {
0308     auto timeSliceConfig = iConfig.getParameter<std::vector<edm::ParameterSet>>(prefix + "TimeSlices");
0309     if (timeSliceConfig.size() != nTimeSlices)
0310       throw cms::Exception("Configuration")
0311           << "Mismatched number of " << prefix << "TimeSlices, expected " << nTimeSlices << std::endl;
0312     for (unsigned int iT = 0; iT < nTimeSlices; ++iT) {
0313       configSectors(timeSliceConfig[iT], prefix, nSectors, linksFactor);
0314     }
0315   } else {
0316     configSectors(iConfig, prefix, nSectors, linksFactor);
0317   }
0318 }
0319 
0320 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeTimeSlices(
0321     const std::string& prefix) {
0322   edm::ParameterSetDescription timeslicesPSD;
0323   timeslicesPSD.addNode(describeSectors(prefix));
0324   return edm::ParameterDescription<std::vector<edm::ParameterSet>>(prefix + "TimeSlices", timeslicesPSD, true) xor
0325          describeSectors(prefix);
0326 }
0327 
0328 void L1TCorrelatorLayer1PatternFileWriter::configSectors(const edm::ParameterSet& iConfig,
0329                                                          const std::string& prefix,
0330                                                          unsigned int nSectors,
0331                                                          unsigned int linksFactor) {
0332   if (nSectors > 1) {
0333     auto sectorConfig = iConfig.getParameter<std::vector<edm::ParameterSet>>(prefix + "Sectors");
0334     if (sectorConfig.size() != nSectors)
0335       throw cms::Exception("Configuration")
0336           << "Mismatched number of " << prefix << "Sectors, expected " << nSectors << std::endl;
0337     for (unsigned int iS = 0; iS < nSectors; ++iS) {
0338       configLinks(sectorConfig[iS], prefix, linksFactor, linksFactor > 1 ? iS * 10 : iS);
0339     }
0340   } else {
0341     configLinks(iConfig, prefix, linksFactor, 0);
0342   }
0343 }
0344 
0345 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeSectors(
0346     const std::string& prefix) {
0347   edm::ParameterSetDescription sectorsPSD;
0348   sectorsPSD.addNode(describeLinks(prefix));
0349   return edm::ParameterDescription<std::vector<edm::ParameterSet>>(prefix + "Sectors", sectorsPSD, true) xor
0350          describeLinks(prefix);
0351 }
0352 
0353 void L1TCorrelatorLayer1PatternFileWriter::configLinks(const edm::ParameterSet& iConfig,
0354                                                        const std::string& prefix,
0355                                                        unsigned int linksFactor,
0356                                                        unsigned int offset) {
0357   if (linksFactor > 1) {
0358     auto links = iConfig.getParameter<std::vector<int32_t>>(prefix + "Links");
0359     if (links.size() != linksFactor)
0360       throw cms::Exception("Configuration")
0361           << "Mismatched number of " << prefix << "Links, expected " << linksFactor << std::endl;
0362     for (unsigned int i = 0; i < linksFactor; ++i) {
0363       if (links[i] != -1) {
0364         channelIdsInput_[l1t::demo::LinkId{prefix, i + offset}].push_back(links[i]);
0365       }
0366     }
0367   } else {
0368     auto link = iConfig.getParameter<int32_t>(prefix + "Link");
0369     if (link != -1) {
0370       channelIdsInput_[l1t::demo::LinkId{prefix, offset}].push_back(link);
0371     }
0372   }
0373 }
0374 
0375 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeLinks(
0376     const std::string& prefix) {
0377   return edm::ParameterDescription<int32_t>(prefix + "Link", true) xor
0378          edm::ParameterDescription<std::vector<int32_t>>(prefix + "Links", true);
0379 }
0380 
0381 void L1TCorrelatorLayer1PatternFileWriter::writeTF(const l1ct::Event& event, l1t::demo::EventData& out) {
0382   for (unsigned int iS = 0, nS = event.raw.track.size(); iS < nS; ++iS) {
0383     l1t::demo::LinkId key{"tf", iS};
0384     if (channelIdsInput_.count(key) == 0)
0385       continue;
0386     std::vector<ap_uint<64>> ret;
0387     std::vector<ap_uint<96>> tracks = event.raw.track[iS].obj;
0388     if (tracks.empty())
0389       tracks.emplace_back(0);
0390     for (unsigned int i = 0, n = tracks.size(); i < n; ++i) {
0391       const ap_uint<96>& packedtk = tracks[i];
0392       if (i % 2 == 0) {
0393         ret.emplace_back(packedtk(63, 0));
0394         ret.emplace_back(0);
0395         ret.back()(31, 0) = packedtk(95, 64);
0396       } else {
0397         ret.back()(63, 32) = packedtk(31, 0);
0398         ret.emplace_back(packedtk(95, 32));
0399       }
0400     }
0401     ret.resize(tfNumberOfTracks_ * 3 / 2, ap_uint<64>(0));
0402     out.add(key, ret);
0403   }
0404 }
0405 
0406 void L1TCorrelatorLayer1PatternFileWriter::writeGCTEm(const l1ct::Event& event, l1t::demo::EventData& out) {
0407   for (unsigned int iS = 0, nS = event.raw.gctEm.size(); iS < nS; ++iS) {
0408     l1t::demo::LinkId key{"gctEm", iS};
0409     if (channelIdsInput_.count(key) == 0)
0410       continue;
0411     std::vector<ap_uint<64>> gctEm = event.raw.gctEm[iS].obj;
0412     gctEm.resize(gctNumberOfEMs_, ap_uint<64>(0));
0413     out.add(key, gctEm);
0414   }
0415 }
0416 
0417 void L1TCorrelatorLayer1PatternFileWriter::writeGCTHad(const l1ct::Event& event, l1t::demo::EventData& out) {
0418   for (unsigned int iS = 0, nS = event.raw.gctHad.size(); iS < nS; ++iS) {
0419     l1t::demo::LinkId key{"gctHad", iS};
0420     if (channelIdsInput_.count(key) == 0)
0421       continue;
0422     std::vector<ap_uint<64>> gctHad = event.raw.gctHad[iS].obj;
0423     gctHad.resize(gctNumberOfHads_, ap_uint<64>(0));
0424     out.add(key, gctHad);
0425   }
0426 }
0427 
0428 void L1TCorrelatorLayer1PatternFileWriter::writeHGC(const l1ct::Event& event, l1t::demo::EventData& out) {
0429   assert(hgcLinksFactor_ == 4);  // this piece of code won't really work otherwise
0430   std::vector<ap_uint<64>> ret[hgcLinksFactor_];
0431   for (unsigned int iS = 0, nS = event.raw.hgcalcluster.size(); iS < nS; ++iS) {
0432     l1t::demo::LinkId key0{"hgc", iS * 10};
0433     if (channelIdsInput_.count(key0) == 0)
0434       continue;
0435     for (unsigned int il = 0; il < hgcLinksFactor_; ++il) {
0436       // put header word and (dummy) towers
0437       ret[il].resize(31);
0438       ap_uint<64>& head64 = ret[il][0];
0439       head64(63, 48) = 0xABC0;                                        // Magic
0440       head64(47, 38) = 0;                                             // Opaque
0441       head64(39, 32) = (eventIndex_ % hgcTimeslices_) * tmuxFactor_;  // TM slice
0442       head64(31, 24) = iS;                                            // Sector
0443       head64(23, 16) = il;                                            // link
0444       head64(15, 0) = eventIndex_ % 3564;                             // BX
0445       for (unsigned int j = 0; j < 30; ++j) {
0446         ret[il][j + 1] = 4 * j + il;
0447       }
0448     }
0449     for (auto clust : event.raw.hgcalcluster[iS].obj) {
0450       for (unsigned int il = 0; il < hgcLinksFactor_; ++il) {
0451         ret[il].push_back(clust(64 * il + 63, 64 * il));
0452       }
0453     }
0454     for (unsigned int il = 0; il < hgcLinksFactor_; ++il) {
0455       out.add(l1t::demo::LinkId{"hgc", iS * 10 + il}, ret[il]);
0456     }
0457   }
0458 }
0459 
0460 void L1TCorrelatorLayer1PatternFileWriter::writeGMT(const l1ct::Event& event, l1t::demo::EventData& out) {
0461   l1t::demo::LinkId key{"gmt", 0};
0462   if (channelIdsInput_.count(key) == 0)
0463     return;
0464   std::vector<ap_uint<64>> muons = event.raw.muon.obj;
0465   muons.resize(gmtNumberOfMuons_, ap_uint<64>(0));
0466   out.add(key, muons);
0467 }
0468 
0469 void L1TCorrelatorLayer1PatternFileWriter::writeGTT(const l1ct::Event& event, l1t::demo::EventData& out) {
0470   l1t::demo::LinkId key{"gtt", 0};
0471   if (channelIdsInput_.count(key) == 0)
0472     return;
0473   std::vector<ap_uint<64>> pvs = event.pvs_emu;
0474   pvs.resize(gttNumberOfPVs_, ap_uint<64>(0));
0475   out.add(key, pvs);
0476 }
0477 
0478 // Debug functions output internal data for debugging purposes, mainly emulation/simulation comparison
0479 void L1TCorrelatorLayer1PatternFileWriter::writeDebugs(const l1ct::Event& event, l1t::demo::EventData& out) {
0480   // Note:  the writers have a width of 64 very much hardcoded in the sizes. Therefore, send the 73 bits as
0481   //        two separate "fibers"
0482 
0483   constexpr unsigned int MAX_BITWIDTH = 73;  // Should be the biggest object width (or greater)
0484 
0485   if (nPFInTrack_) {
0486     std::vector<std::vector<ap_uint<64>>> linksLow(nPFInTrack_);   // virtual links -- bits 63:0
0487     std::vector<std::vector<ap_uint<64>>> linksHigh(nPFInTrack_);  // virtual links -- bits MAX_BITWIDTH-1:64
0488     for (auto ir : outputRegions_) {
0489       auto pfvals = event.pfinputs[ir].track;
0490       unsigned int npfvals = pfvals.size();
0491       for (unsigned int i = 0; i < nPFInTrack_; ++i) {
0492         ap_uint<MAX_BITWIDTH> val = i < npfvals ? pfvals[i].pack() : ap_uint<l1ct::TkObjEmu::BITWIDTH>(0);
0493         linksHigh[i].push_back(val(MAX_BITWIDTH - 1, 64));
0494         linksLow[i].push_back(val(63, 0));
0495       }
0496     }
0497     for (unsigned int i = 0; i < linksLow.size(); ++i) {
0498       out.add(l1t::demo::LinkId{"pfin_track", 2 * i}, linksHigh[i]);
0499       out.add(l1t::demo::LinkId{"pfin_track", 2 * i + 1}, linksLow[i]);
0500     }
0501   }
0502   if (nPFInEmCalo_) {
0503     std::vector<std::vector<ap_uint<64>>> linksLow(nPFInEmCalo_);   // virtual links -- bits 63:0
0504     std::vector<std::vector<ap_uint<64>>> linksHigh(nPFInEmCalo_);  // virtual links -- bits MAX_BITWIDTH-1:64
0505     for (auto ir : outputRegions_) {
0506       auto pfvals = event.pfinputs[ir].emcalo;
0507       unsigned int npfvals = pfvals.size();
0508       for (unsigned int i = 0; i < nPFInEmCalo_; ++i) {
0509         ap_uint<MAX_BITWIDTH> val = i < npfvals ? pfvals[i].pack() : ap_uint<l1ct::EmCaloObjEmu::BITWIDTH>(0);
0510         linksHigh[i].push_back(val(MAX_BITWIDTH - 1, 64));
0511         linksLow[i].push_back(val(63, 0));
0512       }
0513     }
0514     for (unsigned int i = 0; i < linksLow.size(); ++i) {
0515       out.add(l1t::demo::LinkId{"pfin_emcalo", 2 * i}, linksHigh[i]);
0516       out.add(l1t::demo::LinkId{"pfin_emcalo", 2 * i + 1}, linksLow[i]);
0517     }
0518   }
0519   if (nPFInHadCalo_) {
0520     std::vector<std::vector<ap_uint<64>>> linksLow(nPFInHadCalo_);   // virtual links -- bits 63:0
0521     std::vector<std::vector<ap_uint<64>>> linksHigh(nPFInHadCalo_);  // virtual links -- bits MAX_BITWIDTH-1:64
0522     for (auto ir : outputRegions_) {
0523       auto pfvals = event.pfinputs[ir].hadcalo;
0524       unsigned int npfvals = pfvals.size();
0525       for (unsigned int i = 0; i < nPFInHadCalo_; ++i) {
0526         ap_uint<MAX_BITWIDTH> val = i < npfvals ? pfvals[i].pack() : ap_uint<l1ct::HadCaloObjEmu::BITWIDTH>(0);
0527         linksHigh[i].push_back(val(MAX_BITWIDTH - 1, 64));
0528         linksLow[i].push_back(val(63, 0));
0529       }
0530     }
0531     for (unsigned int i = 0; i < linksLow.size(); ++i) {
0532       out.add(l1t::demo::LinkId{"pfin_hadcalo", 2 * i}, linksHigh[i]);
0533       out.add(l1t::demo::LinkId{"pfin_hadcalo", 2 * i + 1}, linksLow[i]);
0534     }
0535   }
0536   if (nPFInMuon_) {
0537     std::vector<std::vector<ap_uint<64>>> linksLow(nPFInMuon_);   // virtual links -- bits 63:0
0538     std::vector<std::vector<ap_uint<64>>> linksHigh(nPFInMuon_);  // virtual links -- bits MAX_BITWIDTH-1:64
0539     for (auto ir : outputRegions_) {
0540       auto pfvals = event.pfinputs[ir].muon;
0541       unsigned int npfvals = pfvals.size();
0542       for (unsigned int i = 0; i < nPFInMuon_; ++i) {
0543         ap_uint<MAX_BITWIDTH> val = i < npfvals ? pfvals[i].pack() : ap_uint<l1ct::MuObjEmu::BITWIDTH>(0);
0544         linksHigh[i].push_back(val(MAX_BITWIDTH - 1, 64));
0545         linksLow[i].push_back(val(63, 0));
0546       }
0547     }
0548     for (unsigned int i = 0; i < linksLow.size(); ++i) {
0549       out.add(l1t::demo::LinkId{"pfin_muon", 2 * i}, linksHigh[i]);
0550       out.add(l1t::demo::LinkId{"pfin_muon", 2 * i + 1}, linksLow[i]);
0551     }
0552   }
0553 
0554   // the pf outoputs
0555 
0556   if (nPFOutCharged_) {
0557     std::vector<std::vector<ap_uint<64>>> linksLow(nPFOutCharged_);   // virtual links -- bits 63:0
0558     std::vector<std::vector<ap_uint<64>>> linksHigh(nPFOutCharged_);  // virtual links -- bits MAX_BITWIDTH-1:64
0559     for (auto ir : outputRegions_) {
0560       auto pfvals = event.out[ir].pfcharged;
0561       unsigned int npfvals = pfvals.size();
0562       for (unsigned int i = 0; i < nPFOutCharged_; ++i) {
0563         ap_uint<MAX_BITWIDTH> val = i < npfvals ? pfvals[i].pack() : ap_uint<l1ct::PFChargedObjEmu::BITWIDTH>(0);
0564         linksHigh[i].push_back(val(MAX_BITWIDTH - 1, 64));
0565         linksLow[i].push_back(val(63, 0));
0566       }
0567     }
0568     for (unsigned int i = 0; i < linksLow.size(); ++i) {
0569       out.add(l1t::demo::LinkId{"pfout_charged", 2 * i}, linksHigh[i]);
0570       out.add(l1t::demo::LinkId{"pfout_charged", 2 * i + 1}, linksLow[i]);
0571     }
0572   }
0573   if (nPFOutPhoton_) {
0574     std::vector<std::vector<ap_uint<64>>> linksLow(nPFOutPhoton_);   // virtual links -- bits 63:0
0575     std::vector<std::vector<ap_uint<64>>> linksHigh(nPFOutPhoton_);  // virtual links -- bits MAX_BITWIDTH-1:64
0576     for (auto ir : outputRegions_) {
0577       auto pfvals = event.out[ir].pfphoton;
0578       unsigned int npfvals = pfvals.size();
0579       for (unsigned int i = 0; i < nPFOutPhoton_; ++i) {
0580         ap_uint<MAX_BITWIDTH> val = i < npfvals ? pfvals[i].pack() : ap_uint<l1ct::PFNeutralObjEmu::BITWIDTH>(0);
0581         linksHigh[i].push_back(val(MAX_BITWIDTH - 1, 64));
0582         linksLow[i].push_back(val(63, 0));
0583       }
0584     }
0585     for (unsigned int i = 0; i < linksLow.size(); ++i) {
0586       out.add(l1t::demo::LinkId{"pfout_photon", 2 * i}, linksHigh[i]);
0587       out.add(l1t::demo::LinkId{"pfout_photon", 2 * i + 1}, linksLow[i]);
0588     }
0589   }
0590   if (nPFOutNeutral_) {
0591     std::vector<std::vector<ap_uint<64>>> linksLow(nPFOutNeutral_);   // virtual links -- bits 63:0
0592     std::vector<std::vector<ap_uint<64>>> linksHigh(nPFOutNeutral_);  // virtual links -- bits MAX_BITWIDTH-1:64
0593     for (auto ir : outputRegions_) {
0594       auto pfvals = event.out[ir].pfneutral;
0595       unsigned int npfvals = pfvals.size();
0596       for (unsigned int i = 0; i < nPFOutNeutral_; ++i) {
0597         ap_uint<MAX_BITWIDTH> val = i < npfvals ? pfvals[i].pack() : ap_uint<l1ct::PFNeutralObjEmu::BITWIDTH>(0);
0598         linksHigh[i].push_back(val(MAX_BITWIDTH - 1, 64));
0599         linksLow[i].push_back(val(63, 0));
0600       }
0601     }
0602     for (unsigned int i = 0; i < linksLow.size(); ++i) {
0603       out.add(l1t::demo::LinkId{"pfout_neutral", 2 * i}, linksHigh[i]);
0604       out.add(l1t::demo::LinkId{"pfout_neutral", 2 * i + 1}, linksLow[i]);
0605     }
0606   }
0607   if (nPFOutMuon_) {
0608     std::vector<std::vector<ap_uint<64>>> linksLow(nPFOutMuon_);   // virtual links -- bits 63:0
0609     std::vector<std::vector<ap_uint<64>>> linksHigh(nPFOutMuon_);  // virtual links -- bits MAX_BITWIDTH-1:64
0610     for (auto ir : outputRegions_) {
0611       auto pfvals = event.out[ir].pfmuon;
0612       unsigned int npfvals = pfvals.size();
0613       for (unsigned int i = 0; i < nPFOutMuon_; ++i) {
0614         ap_uint<MAX_BITWIDTH> val = i < npfvals ? pfvals[i].pack() : ap_uint<l1ct::PFChargedObjEmu::BITWIDTH>(0);
0615         linksHigh[i].push_back(val(MAX_BITWIDTH - 1, 64));
0616         linksLow[i].push_back(val(63, 0));
0617       }
0618     }
0619     for (unsigned int i = 0; i < linksLow.size(); ++i) {
0620       out.add(l1t::demo::LinkId{"pfout_muon", 2 * i}, linksHigh[i]);
0621       out.add(l1t::demo::LinkId{"pfout_muon", 2 * i + 1}, linksLow[i]);
0622     }
0623   }
0624 }
0625 
0626 void L1TCorrelatorLayer1PatternFileWriter::writePuppi(const l1ct::Event& event, l1t::demo::EventData& out) {
0627   unsigned int n = outputLinksPuppi_.size();
0628   std::vector<std::vector<ap_uint<64>>> links(n);
0629   for (auto ir : outputRegions_) {
0630     auto puppi = event.out[ir].puppi;
0631     unsigned int npuppi = puppi.size();
0632     for (unsigned int i = 0; i < n * nPuppiFramesPerRegion_; ++i) {
0633       links[i / nPuppiFramesPerRegion_].push_back(i < npuppi ? puppi[i].pack() : ap_uint<l1ct::PuppiObj::BITWIDTH>(0));
0634     }
0635   }
0636   for (unsigned int i = 0; i < n; ++i) {
0637     out.add(l1t::demo::LinkId{"puppi", i}, links[i]);
0638   }
0639 }
0640 
0641 void L1TCorrelatorLayer1PatternFileWriter::writeEgamma(const l1ct::OutputBoard& egboard,
0642                                                        std::vector<ap_uint<64>>& ret) {
0643   unsigned int s0 = ret.size();
0644   const auto& pho = egboard.egphoton;
0645   const auto& ele = egboard.egelectron;
0646   ret.reserve(s0 + 3 * nEgammaObjectsOut_);
0647   for (const auto& p : pho) {
0648     ret.emplace_back(p.pack());
0649   }
0650   ret.resize(s0 + nEgammaObjectsOut_, ap_uint<64>(0));
0651   for (const auto& p : ele) {
0652     ap_uint<128> dword = p.pack();
0653     ret.push_back(dword(63, 0));
0654     ret.push_back(dword(127, 64));
0655   }
0656   ret.resize(s0 + 3 * nEgammaObjectsOut_, ap_uint<64>(0));
0657 }
0658 
0659 void L1TCorrelatorLayer1PatternFileWriter::writeEgamma(const l1ct::Event& event, l1t::demo::EventData& out) {
0660   std::vector<ap_uint<64>> ret;
0661   if (tmuxFactor_ == 18) {
0662     // the format is different, as we put together all boards
0663     unsigned int nboards = event.board_out.size();
0664     unsigned int npad = nOutputFramesPerBX_ * tmuxFactor_ / nboards;
0665     for (unsigned int board = 0; board < nboards; ++board) {
0666       ret.resize(board * npad, ap_uint<64>(0));
0667       writeEgamma(event.board_out[board], ret);
0668     }
0669   } else {
0670     writeEgamma(event.board_out[outputBoard_], ret);
0671   }
0672   out.add(l1t::demo::LinkId{"egamma", 0}, ret);
0673 }
0674 
0675 void L1TCorrelatorLayer1PatternFileWriter::flush() {
0676   if (inputFileWriter_)
0677     inputFileWriter_->flush();
0678   if (outputFileWriter_)
0679     outputFileWriter_->flush();
0680   if (debugFileWriter_)
0681     debugFileWriter_->flush();
0682 }