Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-06-04 04:35:09

0001 #include "L1Trigger/Phase2L1ParticleFlow/interface/L1TCorrelatorLayer1PatternFileWriter.h"
0002 #include "L1Trigger/Phase2L1ParticleFlow/interface/regionizer/middle_buffer_multififo_regionizer_ref.h"
0003 #include "FWCore/Utilities/interface/Exception.h"
0004 #include "FWCore/ParameterSet/interface/allowedValues.h"
0005 #include <iostream>
0006 
0007 L1TCorrelatorLayer1PatternFileWriter::L1TCorrelatorLayer1PatternFileWriter(const edm::ParameterSet& iConfig,
0008                                                                            const l1ct::Event& eventTemplate)
0009     : partition_(parsePartition(iConfig.getParameter<std::string>("partition"))),
0010       tmuxFactor_(iConfig.getParameter<uint32_t>("tmuxFactor")),
0011       writeInputs_(!iConfig.getParameter<std::string>("inputFileName").empty()),
0012       writeOutputs_(!iConfig.getParameter<std::string>("outputFileName").empty()),
0013       tfTimeslices_(std::max(1u, tfTmuxFactor_ / tmuxFactor_)),
0014       hgcTimeslices_(std::max(1u, hgcTmuxFactor_ / tmuxFactor_)),
0015       gctTimeslices_(std::max(1u, gctTmuxFactor_ / tmuxFactor_)),
0016       gmtTimeslices_(std::max(1u, gmtTmuxFactor_ / tmuxFactor_)),
0017       gttTimeslices_(std::max(1u, gttTmuxFactor_ / tmuxFactor_)),
0018       outputBoard_(-1),
0019       outputLinkEgamma_(-1),
0020       fileFormat_(iConfig.getParameter<std::string>("fileFormat")),
0021       eventsPerFile_(iConfig.getParameter<uint32_t>("eventsPerFile")),
0022       eventIndex_(0) {
0023   if (writeInputs_) {
0024     nInputFramesPerBX_ = iConfig.getParameter<uint32_t>("nInputFramesPerBX");
0025 
0026     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0027       configTimeSlices(iConfig, "tf", eventTemplate.raw.track.size(), tfTimeslices_, tfLinksFactor_);
0028       channelSpecsInput_["tf"] = {tfTmuxFactor_, tfTimeslices_};
0029     }
0030     if (partition_ == Partition::Barrel) {
0031       auto sectorConfig = iConfig.getParameter<std::vector<edm::ParameterSet>>("gctSectors");
0032       gctLinksEcal_ = iConfig.getParameter<uint32_t>("gctNLinksEcal");
0033       gctLinksHad_ = iConfig.getParameter<uint32_t>("gctNLinksHad");
0034       gctSingleLink_ = false;
0035       bool gctHasMultiLink = false;
0036       if (sectorConfig.size() != gctSectors_)
0037         throw cms::Exception("Configuration", "Bad number of GCT sectors");
0038       for (unsigned int iS = 0; iS < gctSectors_; ++iS) {
0039         auto linksEcal = sectorConfig[iS].getParameter<std::vector<int32_t>>("gctLinksEcal");
0040         auto linksHad = sectorConfig[iS].getParameter<std::vector<int32_t>>("gctLinksHad");
0041         if (linksEcal.size() != gctLinksEcal_ || linksHad.size() != gctLinksHad_)
0042           throw cms::Exception("Configuration", "Bad number of GCT links");
0043         unsigned int iLink = 0;
0044         if (!(gctLinksEcal_ == 1 && gctLinksHad_ == 1 && linksEcal[0] == linksHad[0] && linksEcal[0] != -1)) {
0045           for (unsigned int i = 0; i < gctLinksHad_; ++i, ++iLink) {
0046             if (linksHad[i] != -1)
0047               channelIdsInput_[l1t::demo::LinkId{"gct", iLink + 10 * iS}].push_back(linksHad[i]);
0048           }
0049           for (unsigned int i = 0; i < gctLinksEcal_; ++i) {
0050             if (linksEcal[i] != -1)
0051               channelIdsInput_[l1t::demo::LinkId{"gct", iLink + 10 * iS}].push_back(linksEcal[i]);
0052           }
0053           gctHasMultiLink = true;
0054         } else {  // single link combining ecal and hcal
0055           channelIdsInput_[l1t::demo::LinkId{"gct", 10 * iS}].push_back(linksEcal[0]);
0056           gctSingleLink_ = true;
0057         }
0058         channelSpecsInput_["gct"] = {tmuxFactor_ * gctTimeslices_, 0};
0059       }
0060       if (gctSingleLink_ && gctHasMultiLink)
0061         throw cms::Exception("Configuration", "Some GCT sectors have a single link, others have multiple.");
0062     }
0063     if (partition_ == Partition::HGCal || partition_ == Partition::HGCalNoTk) {
0064       configTimeSlices(iConfig, "hgc", eventTemplate.raw.hgcalcluster.size(), hgcTimeslices_, hgcLinksFactor_);
0065       channelSpecsInput_["hgc"] = {tmuxFactor_ * hgcTimeslices_, hgcTimeslices_};
0066     }
0067     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal || partition_ == Partition::HGCalNoTk) {
0068       configTimeSlices(iConfig, "gmt", 1, gmtTimeslices_, gmtLinksFactor_);
0069       gmtNumberOfMuons_ = iConfig.getParameter<uint32_t>("gmtNumberOfMuons");
0070       channelSpecsInput_["gmt"] = {tmuxFactor_ * gmtTimeslices_,
0071                                    gmtTimeslices_ * nInputFramesPerBX_ * tmuxFactor_ - gmtNumberOfMuons_};
0072     }
0073     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0074       configTimeSlices(iConfig, "gtt", 1, gttTimeslices_, gttLinksFactor_);
0075       gttLatency_ = iConfig.getParameter<uint32_t>("gttLatency");
0076       gttNumberOfPVs_ = iConfig.getParameter<uint32_t>("gttNumberOfPVs");
0077       channelSpecsInput_["gtt"] = l1t::demo::ChannelSpec{tmuxFactor_ * gttTimeslices_, 1, gttLatency_};
0078     }
0079     inputFileWriter_ =
0080         std::make_unique<l1t::demo::BoardDataWriter>(l1t::demo::parseFileFormat(fileFormat_),
0081                                                      iConfig.getParameter<std::string>("inputFileName"),
0082                                                      iConfig.getParameter<std::string>("inputFileExtension"),
0083                                                      nInputFramesPerBX_,
0084                                                      tmuxFactor_,
0085                                                      iConfig.getParameter<uint32_t>("maxLinesPerInputFile"),
0086                                                      channelIdsInput_,
0087                                                      channelSpecsInput_);
0088   }
0089 
0090   if (writeOutputs_) {
0091     nOutputFramesPerBX_ = iConfig.getParameter<uint32_t>("nOutputFramesPerBX");
0092 
0093     outputRegions_ = iConfig.getParameter<std::vector<uint32_t>>("outputRegions");
0094     outputLinksPuppi_ = iConfig.getParameter<std::vector<uint32_t>>("outputLinksPuppi");
0095     for (unsigned int i = 0; i < outputLinksPuppi_.size(); ++i) {
0096       channelIdsOutput_[l1t::demo::LinkId{"puppi", i}].push_back(outputLinksPuppi_[i]);
0097     }
0098     channelSpecsOutput_["puppi"] = {tmuxFactor_, 0};
0099     nPuppiFramesPerRegion_ = (nOutputFramesPerBX_ * tmuxFactor_) / outputRegions_.size();
0100     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0101       outputLinkEgamma_ = iConfig.getParameter<int32_t>("outputLinkEgamma");
0102       nEgammaObjectsOut_ = iConfig.getParameter<uint32_t>("nEgammaObjectsOut");
0103       if (outputLinkEgamma_ != -1) {
0104         channelIdsOutput_[l1t::demo::LinkId{"egamma", 0}].push_back(outputLinkEgamma_);
0105         if (tmuxFactor_ == 18) {
0106           // the format is different, as we put together multiple endcaps or slices
0107           unsigned int nboards = (partition_ == Partition::Barrel) ? 3 : 2;
0108           channelSpecsOutput_["egamma"] = {tmuxFactor_,
0109                                            nOutputFramesPerBX_ * tmuxFactor_ / nboards - 3 * nEgammaObjectsOut_};
0110         } else {
0111           outputBoard_ = iConfig.getParameter<int32_t>("outputBoard");
0112           channelSpecsOutput_["egamma"] = {tmuxFactor_, nOutputFramesPerBX_ * tmuxFactor_ - 3 * nEgammaObjectsOut_};
0113         }
0114       }
0115     }
0116     outputFileWriter_ =
0117         std::make_unique<l1t::demo::BoardDataWriter>(l1t::demo::parseFileFormat(fileFormat_),
0118                                                      iConfig.getParameter<std::string>("outputFileName"),
0119                                                      iConfig.getParameter<std::string>("outputFileExtension"),
0120                                                      nOutputFramesPerBX_,
0121                                                      tmuxFactor_,
0122                                                      iConfig.getParameter<uint32_t>("maxLinesPerOutputFile"),
0123                                                      channelIdsOutput_,
0124                                                      channelSpecsOutput_);
0125   }
0126 }
0127 
0128 L1TCorrelatorLayer1PatternFileWriter::~L1TCorrelatorLayer1PatternFileWriter() {}
0129 
0130 edm::ParameterSetDescription L1TCorrelatorLayer1PatternFileWriter::getParameterSetDescription() {
0131   edm::ParameterSetDescription description;
0132   description.add<std::string>("inputFileName", "");
0133   description.add<std::string>("inputFileExtension", "txt.gz");
0134   description.add<uint32_t>("maxLinesPerInputFile", 1024u);
0135   description.add<uint32_t>("nInputFramesPerBX", 9u);
0136   description.add<std::string>("outputFileName", "");
0137   description.add<std::string>("outputFileExtension", "txt.gz");
0138   description.add<uint32_t>("maxLinesPerOutputFile", 1024u);
0139   description.add<uint32_t>("nOutputFramesPerBX", 9u);
0140   description.add<uint32_t>("tmuxFactor", 6u);
0141   description.add<uint32_t>("eventsPerFile", 12u);
0142   description.add<std::string>("fileFormat");
0143 
0144   description.ifValue(edm::ParameterDescription<std::string>("partition", "Barrel", true),
0145                       "Barrel" >> (describeTF() and describeGCT() and describeGTT() and describeGMT() and
0146                                    describePuppi() and describeEG()) or
0147                           "HGCal" >> (describeTF() and describeHGC() and describeGTT() and describeGMT() and
0148                                       describePuppi() and describeEG()) or
0149                           "HGCalNoTk" >> (describeHGC() and describeGMT() and describePuppi()) or
0150                           "HF" >> (describePuppi()));
0151   return description;
0152 }
0153 
0154 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeTF() {
0155   return describeTimeSlices("tf");
0156 }
0157 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeGCT() {
0158   edm::ParameterSetDescription gctSectorPSD;
0159   gctSectorPSD.add<std::vector<int32_t>>("gctLinksEcal");
0160   gctSectorPSD.add<std::vector<int32_t>>("gctLinksHad");
0161   return std::make_unique<edm::ParameterDescription<std::vector<edm::ParameterSet>>>(
0162              "gctSectors", gctSectorPSD, true) and
0163          edm::ParameterDescription<uint32_t>("gctNLinksEcal", 1, true) and
0164          edm::ParameterDescription<uint32_t>("gctNLinksHad", 2, true);
0165 }
0166 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeHGC() {
0167   return describeTimeSlices("hgc");
0168 }
0169 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeGMT() {
0170   return describeTimeSlices("gmt") and edm::ParameterDescription<uint32_t>("gmtNumberOfMuons", 12, true);
0171 }
0172 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeGTT() {
0173   return describeTimeSlices("gtt") and
0174          edm::ParameterDescription<uint32_t>("gttLatency", 162, true) and  // minimal latency is 18 BX
0175          edm::ParameterDescription<uint32_t>("gttNumberOfPVs", 10, true);
0176 }
0177 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describePuppi() {
0178   return edm::ParameterDescription<std::vector<uint32_t>>("outputRegions", std::vector<uint32_t>(), true) and
0179          edm::ParameterDescription<std::vector<uint32_t>>("outputLinksPuppi", std::vector<uint32_t>(), true);
0180 }
0181 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeEG() {
0182   return edm::ParameterDescription<int32_t>("outputLinkEgamma", -1, true) and
0183          edm::ParameterDescription<uint32_t>("nEgammaObjectsOut", 16, true) and
0184          edm::ParameterDescription<int32_t>("outputBoard", -1, true);
0185 }
0186 
0187 void L1TCorrelatorLayer1PatternFileWriter::write(const l1ct::Event& event) {
0188   if (writeInputs_) {
0189     l1t::demo::EventData inputs;
0190     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0191       writeTF(event, inputs);
0192     }
0193     if (partition_ == Partition::Barrel) {
0194       writeBarrelGCT(event, inputs);
0195     }
0196     if (partition_ == Partition::HGCal || partition_ == Partition::HGCalNoTk) {
0197       writeHGC(event, inputs);
0198     }
0199     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal || partition_ == Partition::HGCalNoTk) {
0200       writeGMT(event, inputs);
0201     }
0202     if (partition_ == Partition::Barrel || partition_ == Partition::HGCal) {
0203       writeGTT(event, inputs);
0204     }
0205     inputFileWriter_->addEvent(inputs);
0206   }
0207 
0208   if (writeOutputs_) {
0209     l1t::demo::EventData outputs;
0210     writePuppi(event, outputs);
0211     if (outputLinkEgamma_ != -1)
0212       writeEgamma(event, outputs);
0213     outputFileWriter_->addEvent(outputs);
0214   }
0215 
0216   eventIndex_++;
0217   if (eventIndex_ % eventsPerFile_ == 0) {
0218     if (writeInputs_)
0219       inputFileWriter_->flush();
0220     if (writeOutputs_)
0221       outputFileWriter_->flush();
0222   }
0223 }
0224 
0225 L1TCorrelatorLayer1PatternFileWriter::Partition L1TCorrelatorLayer1PatternFileWriter::parsePartition(
0226     const std::string& partition) {
0227   if (partition == "Barrel")
0228     return Partition::Barrel;
0229   if (partition == "HGCal")
0230     return Partition::HGCal;
0231   if (partition == "HGCalNoTk")
0232     return Partition::HGCalNoTk;
0233   if (partition == "HF")
0234     return Partition::HF;
0235   throw cms::Exception("Configuration", "Unsupported partition_ '" + partition + "'\n");
0236 }
0237 
0238 void L1TCorrelatorLayer1PatternFileWriter::configTimeSlices(const edm::ParameterSet& iConfig,
0239                                                             const std::string& prefix,
0240                                                             unsigned int nSectors,
0241                                                             unsigned int nTimeSlices,
0242                                                             unsigned int linksFactor) {
0243   if (nTimeSlices > 1) {
0244     auto timeSliceConfig = iConfig.getParameter<std::vector<edm::ParameterSet>>(prefix + "TimeSlices");
0245     if (timeSliceConfig.size() != nTimeSlices)
0246       throw cms::Exception("Configuration")
0247           << "Mismatched number of " << prefix << "TimeSlices, expected " << nTimeSlices << std::endl;
0248     for (unsigned int iT = 0; iT < nTimeSlices; ++iT) {
0249       configSectors(timeSliceConfig[iT], prefix, nSectors, linksFactor);
0250     }
0251   } else {
0252     configSectors(iConfig, prefix, nSectors, linksFactor);
0253   }
0254 }
0255 
0256 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeTimeSlices(
0257     const std::string& prefix) {
0258   edm::ParameterSetDescription timeslicesPSD;
0259   timeslicesPSD.addNode(describeSectors(prefix));
0260   return edm::ParameterDescription<std::vector<edm::ParameterSet>>(prefix + "TimeSlices", timeslicesPSD, true) xor
0261          describeSectors(prefix);
0262 }
0263 
0264 void L1TCorrelatorLayer1PatternFileWriter::configSectors(const edm::ParameterSet& iConfig,
0265                                                          const std::string& prefix,
0266                                                          unsigned int nSectors,
0267                                                          unsigned int linksFactor) {
0268   if (nSectors > 1) {
0269     auto sectorConfig = iConfig.getParameter<std::vector<edm::ParameterSet>>(prefix + "Sectors");
0270     if (sectorConfig.size() != nSectors)
0271       throw cms::Exception("Configuration")
0272           << "Mismatched number of " << prefix << "Sectors, expected " << nSectors << std::endl;
0273     for (unsigned int iS = 0; iS < nSectors; ++iS) {
0274       configLinks(sectorConfig[iS], prefix, linksFactor, linksFactor > 1 ? iS * 10 : iS);
0275     }
0276   } else {
0277     configLinks(iConfig, prefix, linksFactor, 0);
0278   }
0279 }
0280 
0281 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeSectors(
0282     const std::string& prefix) {
0283   edm::ParameterSetDescription sectorsPSD;
0284   sectorsPSD.addNode(describeLinks(prefix));
0285   return edm::ParameterDescription<std::vector<edm::ParameterSet>>(prefix + "Sectors", sectorsPSD, true) xor
0286          describeLinks(prefix);
0287 }
0288 
0289 void L1TCorrelatorLayer1PatternFileWriter::configLinks(const edm::ParameterSet& iConfig,
0290                                                        const std::string& prefix,
0291                                                        unsigned int linksFactor,
0292                                                        unsigned int offset) {
0293   if (linksFactor > 1) {
0294     auto links = iConfig.getParameter<std::vector<int32_t>>(prefix + "Links");
0295     if (links.size() != linksFactor)
0296       throw cms::Exception("Configuration")
0297           << "Mismatched number of " << prefix << "Links, expected " << linksFactor << std::endl;
0298     for (unsigned int i = 0; i < linksFactor; ++i) {
0299       if (links[i] != -1) {
0300         channelIdsInput_[l1t::demo::LinkId{prefix, i + offset}].push_back(links[i]);
0301       }
0302     }
0303   } else {
0304     auto link = iConfig.getParameter<int32_t>(prefix + "Link");
0305     if (link != -1) {
0306       channelIdsInput_[l1t::demo::LinkId{prefix, offset}].push_back(link);
0307     }
0308   }
0309 }
0310 
0311 std::unique_ptr<edm::ParameterDescriptionNode> L1TCorrelatorLayer1PatternFileWriter::describeLinks(
0312     const std::string& prefix) {
0313   return edm::ParameterDescription<int32_t>(prefix + "Link", true) xor
0314          edm::ParameterDescription<std::vector<int32_t>>(prefix + "Links", true);
0315 }
0316 
0317 void L1TCorrelatorLayer1PatternFileWriter::writeTF(const l1ct::Event& event, l1t::demo::EventData& out) {
0318   for (unsigned int iS = 0, nS = event.raw.track.size(); iS < nS; ++iS) {
0319     l1t::demo::LinkId key{"tf", iS};
0320     if (channelIdsInput_.count(key) == 0)
0321       continue;
0322     std::vector<ap_uint<64>> ret;
0323     std::vector<ap_uint<96>> tracks = event.raw.track[iS].obj;
0324     if (tracks.empty())
0325       tracks.emplace_back(0);
0326     for (unsigned int i = 0, n = tracks.size(); i < n; ++i) {
0327       const ap_uint<96>& packedtk = tracks[i];
0328       if (i % 2 == 0) {
0329         ret.emplace_back(packedtk(63, 0));
0330         ret.emplace_back(0);
0331         ret.back()(31, 0) = packedtk(95, 64);
0332       } else {
0333         ret.back()(63, 32) = packedtk(31, 0);
0334         ret.emplace_back(packedtk(95, 32));
0335       }
0336     }
0337     out.add(key, ret);
0338   }
0339 }
0340 
0341 void L1TCorrelatorLayer1PatternFileWriter::writeHGC(const l1ct::Event& event, l1t::demo::EventData& out) {
0342   assert(hgcLinksFactor_ == 4);  // this piece of code won't really work otherwise
0343   std::vector<ap_uint<64>> ret[hgcLinksFactor_];
0344   for (unsigned int iS = 0, nS = event.raw.hgcalcluster.size(); iS < nS; ++iS) {
0345     l1t::demo::LinkId key0{"hgc", iS * 10};
0346     if (channelIdsInput_.count(key0) == 0)
0347       continue;
0348     for (unsigned int il = 0; il < hgcLinksFactor_; ++il) {
0349       // put header word and (dummy) towers
0350       ret[il].resize(31);
0351       ap_uint<64>& head64 = ret[il][0];
0352       head64(63, 48) = 0xABC0;                                        // Magic
0353       head64(47, 38) = 0;                                             // Opaque
0354       head64(39, 32) = (eventIndex_ % hgcTimeslices_) * tmuxFactor_;  // TM slice
0355       head64(31, 24) = iS;                                            // Sector
0356       head64(23, 16) = il;                                            // link
0357       head64(15, 0) = eventIndex_ % 3564;                             // BX
0358       for (unsigned int j = 0; j < 30; ++j) {
0359         ret[il][j + 1] = 4 * j + il;
0360       }
0361     }
0362     for (auto clust : event.raw.hgcalcluster[iS].obj) {
0363       for (unsigned int il = 0; il < hgcLinksFactor_; ++il) {
0364         ret[il].push_back(clust(64 * il + 63, 64 * il));
0365       }
0366     }
0367     for (unsigned int il = 0; il < hgcLinksFactor_; ++il) {
0368       out.add(l1t::demo::LinkId{"hgc", iS * 10 + il}, ret[il]);
0369     }
0370   }
0371 }
0372 
0373 void L1TCorrelatorLayer1PatternFileWriter::writeBarrelGCT(const l1ct::Event& event, l1t::demo::EventData& out) {
0374   std::vector<ap_uint<64>> ret;
0375   for (unsigned int iS = 0; iS < gctSectors_; ++iS) {
0376     l1t::demo::LinkId key0{"gct", iS * 10};
0377     if (channelIdsInput_.count(key0) == 0)
0378       continue;
0379     const auto& had = event.decoded.hadcalo[iS];
0380     const auto& ecal = event.decoded.emcalo[iS];
0381     if (!gctSingleLink_) {
0382       unsigned int iLink = 0, nHad = had.size(), nEcal = ecal.size();
0383       for (unsigned int i = 0; i < gctLinksHad_; ++i, ++iLink) {
0384         ret.clear();
0385         for (unsigned int iHad = i; iHad < nHad; iHad += gctLinksHad_) {
0386           ret.emplace_back(had[iHad].pack());
0387         }
0388         if (ret.empty())
0389           ret.emplace_back(0);
0390         out.add(l1t::demo::LinkId{"gct", iS * 10 + iLink}, ret);
0391       }
0392       for (unsigned int i = 0; i < gctLinksEcal_; ++i, ++iLink) {
0393         ret.clear();
0394         for (unsigned int iEcal = i; iEcal < nEcal; iEcal += gctLinksEcal_) {
0395           ret.emplace_back(ecal[iEcal].pack());
0396         }
0397         if (ret.empty())
0398           ret.emplace_back(0);
0399         out.add(l1t::demo::LinkId{"gct", iS * 10 + iLink}, ret);
0400       }
0401     } else {
0402       const unsigned int NCLK_EM = 54, NCLK_TOT = 3 * NCLK_EM;
0403       l1ct::HadCaloObjEmu tmp;
0404       ret.resize(std::min(NCLK_EM + had.size(), NCLK_TOT));
0405       for (unsigned int iclock = 0, nem = ecal.size(); iclock < NCLK_EM; ++iclock) {
0406         if (iclock < nem) {
0407           l1ct::MiddleBufferMultififoRegionizerEmulator::encode(ecal[iclock], tmp);
0408           ret[iclock] = tmp.pack();
0409         } else {
0410           ret[iclock] = 0;
0411         }
0412       }
0413       for (unsigned int ihad = 0, iclock = NCLK_EM, nhad = had.size(); iclock < NCLK_TOT && ihad < nhad;
0414            ++iclock, ++ihad) {
0415         l1ct::MiddleBufferMultififoRegionizerEmulator::encode(had[ihad], tmp);
0416         ret[iclock] = tmp.pack();
0417       }
0418       out.add(l1t::demo::LinkId{"gct", iS * 10}, ret);
0419     }
0420   }
0421 }
0422 
0423 void L1TCorrelatorLayer1PatternFileWriter::writeGMT(const l1ct::Event& event, l1t::demo::EventData& out) {
0424   l1t::demo::LinkId key{"gmt", 0};
0425   if (channelIdsInput_.count(key) == 0)
0426     return;
0427   std::vector<ap_uint<64>> muons = event.raw.muon.obj;
0428   muons.resize(gmtNumberOfMuons_, ap_uint<64>(0));
0429   out.add(key, muons);
0430 }
0431 
0432 void L1TCorrelatorLayer1PatternFileWriter::writeGTT(const l1ct::Event& event, l1t::demo::EventData& out) {
0433   l1t::demo::LinkId key{"gtt", 0};
0434   if (channelIdsInput_.count(key) == 0)
0435     return;
0436   std::vector<ap_uint<64>> pvs = event.pvs_emu;
0437   pvs.resize(gttNumberOfPVs_, ap_uint<64>(0));
0438   out.add(key, pvs);
0439 }
0440 
0441 void L1TCorrelatorLayer1PatternFileWriter::writePuppi(const l1ct::Event& event, l1t::demo::EventData& out) {
0442   unsigned int n = outputLinksPuppi_.size();
0443   std::vector<std::vector<ap_uint<64>>> links(n);
0444   for (auto ir : outputRegions_) {
0445     auto puppi = event.out[ir].puppi;
0446     unsigned int npuppi = puppi.size();
0447     for (unsigned int i = 0; i < n * nPuppiFramesPerRegion_; ++i) {
0448       links[i / nPuppiFramesPerRegion_].push_back(i < npuppi ? puppi[i].pack() : ap_uint<l1ct::PuppiObj::BITWIDTH>(0));
0449     }
0450   }
0451   for (unsigned int i = 0; i < n; ++i) {
0452     out.add(l1t::demo::LinkId{"puppi", i}, links[i]);
0453   }
0454 }
0455 
0456 void L1TCorrelatorLayer1PatternFileWriter::writeEgamma(const l1ct::OutputBoard& egboard,
0457                                                        std::vector<ap_uint<64>>& ret) {
0458   unsigned int s0 = ret.size();
0459   const auto& pho = egboard.egphoton;
0460   const auto& ele = egboard.egelectron;
0461   ret.reserve(s0 + 3 * nEgammaObjectsOut_);
0462   for (const auto& p : pho) {
0463     ret.emplace_back(p.pack());
0464   }
0465   ret.resize(s0 + nEgammaObjectsOut_, ap_uint<64>(0));
0466   for (const auto& p : ele) {
0467     ap_uint<128> dword = p.pack();
0468     ret.push_back(dword(63, 0));
0469     ret.push_back(dword(127, 64));
0470   }
0471   ret.resize(s0 + 3 * nEgammaObjectsOut_, ap_uint<64>(0));
0472 }
0473 
0474 void L1TCorrelatorLayer1PatternFileWriter::writeEgamma(const l1ct::Event& event, l1t::demo::EventData& out) {
0475   std::vector<ap_uint<64>> ret;
0476   if (tmuxFactor_ == 18) {
0477     // the format is different, as we put together all boards
0478     unsigned int nboards = event.board_out.size();
0479     unsigned int npad = nOutputFramesPerBX_ * tmuxFactor_ / nboards;
0480     for (unsigned int board = 0; board < nboards; ++board) {
0481       ret.resize(board * npad, ap_uint<64>(0));
0482       writeEgamma(event.board_out[board], ret);
0483     }
0484   } else {
0485     writeEgamma(event.board_out[outputBoard_], ret);
0486   }
0487   out.add(l1t::demo::LinkId{"egamma", 0}, ret);
0488 }
0489 
0490 void L1TCorrelatorLayer1PatternFileWriter::flush() {
0491   if (inputFileWriter_)
0492     inputFileWriter_->flush();
0493   if (outputFileWriter_)
0494     outputFileWriter_->flush();
0495 }