Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:33

0001 #include "L1Trigger/Phase2L1ParticleFlow/interface/regionizer/middle_buffer_multififo_regionizer_ref.h"
0002 #include "L1Trigger/Phase2L1ParticleFlow/interface/dbgPrintf.h"
0003 #include "L1Trigger/Phase2L1ParticleFlow/interface/regionizer/multififo_regionizer_elements_ref.icc"
0004 
0005 #include <iostream>
0006 #include <memory>
0007 #include <stdexcept>
0008 
0009 #ifdef CMSSW_GIT_HASH
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0012 #include "FWCore/ParameterSet/interface/allowedValues.h"
0013 
0014 l1ct::MiddleBufferMultififoRegionizerEmulator::MiddleBufferMultififoRegionizerEmulator(const edm::ParameterSet& iConfig)
0015     : MiddleBufferMultififoRegionizerEmulator(iConfig.getParameter<uint32_t>("nClocks"),
0016                                               iConfig.getParameter<uint32_t>("nBuffers"),
0017                                               iConfig.getParameter<uint32_t>("etaBufferDepth"),
0018                                               iConfig.getParameter<uint32_t>("nTkLinks"),
0019                                               iConfig.getParameter<uint32_t>("nHCalLinks"),
0020                                               iConfig.getParameter<uint32_t>("nECalLinks"),
0021                                               iConfig.getParameter<uint32_t>("nTrack"),
0022                                               iConfig.getParameter<uint32_t>("nCalo"),
0023                                               iConfig.getParameter<uint32_t>("nEmCalo"),
0024                                               iConfig.getParameter<uint32_t>("nMu"),
0025                                               /*streaming=*/true,
0026                                               /*outii=*/2,
0027                                               /*pauseii=*/1,
0028                                               iConfig.getParameter<bool>("useAlsoVtxCoords")) {
0029   debug_ = iConfig.getUntrackedParameter<bool>("debug", false);
0030 }
0031 
0032 edm::ParameterSetDescription l1ct::MiddleBufferMultififoRegionizerEmulator::getParameterSetDescription() {
0033   edm::ParameterSetDescription description;
0034   description.add<uint32_t>("nClocks", 162);
0035   description.add<uint32_t>("nBuffers", 27);
0036   description.add<uint32_t>("etaBufferDepth", 54);
0037   description.add<uint32_t>("nTkLinks", 1);
0038   description.add<uint32_t>("nHCalLinks", 1);
0039   description.add<uint32_t>("nECalLinks", 0);
0040   description.add<uint32_t>("nTrack", 22);
0041   description.add<uint32_t>("nCalo", 15);
0042   description.add<uint32_t>("nEmCalo", 12);
0043   description.add<uint32_t>("nMu", 2);
0044   description.add<bool>("useAlsoVtxCoords", true);
0045   description.addUntracked<bool>("debug", false);
0046   return description;
0047 }
0048 
0049 #endif
0050 
0051 l1ct::MiddleBufferMultififoRegionizerEmulator::MiddleBufferMultififoRegionizerEmulator(unsigned int nclocks,
0052                                                                                        unsigned int nbuffers,
0053                                                                                        unsigned int etabufferDepth,
0054                                                                                        unsigned int ntklinks,
0055                                                                                        unsigned int nHCalLinks,
0056                                                                                        unsigned int nECalLinks,
0057                                                                                        unsigned int ntk,
0058                                                                                        unsigned int ncalo,
0059                                                                                        unsigned int nem,
0060                                                                                        unsigned int nmu,
0061                                                                                        bool streaming,
0062                                                                                        unsigned int outii,
0063                                                                                        unsigned int pauseii,
0064                                                                                        bool useAlsoVtxCoords)
0065     : RegionizerEmulator(useAlsoVtxCoords),
0066       NTK_SECTORS(9),
0067       NCALO_SECTORS(3),
0068       NTK_LINKS(ntklinks),
0069       HCAL_LINKS(nHCalLinks),
0070       ECAL_LINKS(nECalLinks),
0071       NMU_LINKS(1),
0072       nclocks_(nclocks),
0073       nbuffers_(nbuffers),
0074       etabuffer_depth_(etabufferDepth),
0075       ntk_(ntk),
0076       ncalo_(ncalo),
0077       nem_(nem),
0078       nmu_(nmu),
0079       outii_(outii),
0080       pauseii_(pauseii),
0081       nregions_pre_(27),
0082       nregions_post_(54),
0083       streaming_(streaming),
0084       init_(false),
0085       iclock_(0),
0086       tkRegionizerPre_(ntk, ntk, false, outii, pauseii, useAlsoVtxCoords),
0087       tkRegionizerPost_(ntk, (ntk + outii - 1) / outii, true, outii, pauseii, useAlsoVtxCoords),
0088       hadCaloRegionizerPre_(ncalo, ncalo, false, outii, pauseii),
0089       hadCaloRegionizerPost_(ncalo, (ncalo + outii - 1) / outii, true, outii, pauseii),
0090       emCaloRegionizerPre_(nem, nem, false, outii, pauseii),
0091       emCaloRegionizerPost_(nem, (nem + outii - 1) / outii, true, outii, pauseii),
0092       muRegionizerPre_(nmu, nmu, false, outii, pauseii),
0093       muRegionizerPost_(nmu, std::max(1u, (nmu + outii - 1) / outii), true, outii, pauseii),
0094       tkBuffers_(ntk ? nbuffers_ : 0),
0095       hadCaloBuffers_(ncalo ? nbuffers_ : 0),
0096       emCaloBuffers_(nem ? nbuffers_ : 0),
0097       muBuffers_(nmu ? nbuffers_ : 0) {
0098   assert(nbuffers_ == nregions_post_ || nbuffers_ == nregions_pre_);
0099   unsigned int phisectors = 9, etaslices = 3;
0100   for (unsigned int ietaslice = 0; ietaslice < etaslices && ntk > 0; ++ietaslice) {
0101     for (unsigned int ie = 0; ie < 2; ++ie) {  // 0 = negative, 1 = positive
0102       unsigned int nTFEtaSlices = ietaslice == 1 ? 2 : 1;
0103       if ((ietaslice == 0 && ie == 1) || (ietaslice == 2 && ie == 0))
0104         continue;
0105       unsigned int ireg0 = phisectors * ietaslice, il0 = 3 * NTK_LINKS * (nTFEtaSlices - 1) * ie;
0106       for (unsigned int is = 0; is < NTK_SECTORS; ++is) {  // 9 tf sectors
0107         for (unsigned int il = 0; il < NTK_LINKS; ++il) {  // max tracks per sector per clock
0108           unsigned int isp = (is + 1) % NTK_SECTORS, ism = (is + NTK_SECTORS - 1) % NTK_SECTORS;
0109           tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, is + ireg0, il0 + il);
0110           tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, isp + ireg0, il0 + il + NTK_LINKS);
0111           tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, ism + ireg0, il0 + il + 2 * NTK_LINKS);
0112         }
0113       }
0114     }
0115   }
0116   // calo
0117   for (unsigned int ie = 0; ie < etaslices; ++ie) {
0118     for (unsigned int is = 0; is < NCALO_SECTORS; ++is) {  // NCALO_SECTORS sectors
0119       for (unsigned int j = 0; j < 3; ++j) {               // 3 regions x sector
0120         for (unsigned int il = 0; il < HCAL_LINKS; ++il) {
0121           caloRoutes_.emplace_back(is, il, 3 * is + j + phisectors * ie, il);
0122           if (j) {
0123             caloRoutes_.emplace_back((is + 1) % 3, il, 3 * is + j + phisectors * ie, il + HCAL_LINKS);
0124           }
0125         }
0126         for (unsigned int il = 0; il < ECAL_LINKS; ++il) {
0127           emCaloRoutes_.emplace_back(is, il, 3 * is + j + phisectors * ie, il);
0128           if (j) {
0129             emCaloRoutes_.emplace_back((is + 1) % 3, il, 3 * is + j + phisectors * ie, il + ECAL_LINKS);
0130           }
0131         }
0132       }
0133     }
0134   }
0135   // mu
0136   for (unsigned int il = 0; il < NMU_LINKS && nmu > 0; ++il) {
0137     for (unsigned int j = 0; j < nregions_pre_; ++j) {
0138       muRoutes_.emplace_back(0, il, j, il);
0139     }
0140   }
0141 }
0142 
0143 l1ct::MiddleBufferMultififoRegionizerEmulator::~MiddleBufferMultififoRegionizerEmulator() {}
0144 
0145 void l1ct::MiddleBufferMultififoRegionizerEmulator::initSectorsAndRegions(const RegionizerDecodedInputs& in,
0146                                                                           const std::vector<PFInputRegion>& out) {
0147   assert(!init_);
0148   init_ = true;
0149   assert(out.size() == nregions_post_);
0150 
0151   std::vector<PFInputRegion> mergedRegions;
0152   unsigned int neta = 3, nphi = 9;
0153   mergedRegions.reserve(nregions_pre_);
0154   mergedRegions_.reserve(nregions_pre_);
0155   outputRegions_.reserve(nregions_post_);
0156   for (unsigned int ieta = 0; ieta < neta; ++ieta) {
0157     for (unsigned int iphi = 0; iphi < nphi; ++iphi) {
0158       const PFRegionEmu& reg0 = out[(2 * ieta + 0) * nphi + iphi].region;
0159       const PFRegionEmu& reg1 = out[(2 * ieta + 1) * nphi + iphi].region;
0160       assert(reg0.hwPhiCenter == reg1.hwPhiCenter);
0161       mergedRegions.emplace_back(reg0.floatEtaMin(),
0162                                  reg1.floatEtaMax(),
0163                                  reg0.floatPhiCenter(),
0164                                  reg0.floatPhiHalfWidth() * 2,
0165                                  reg0.floatEtaExtra(),
0166                                  reg0.floatPhiExtra());
0167       mergedRegions_.push_back(mergedRegions.back().region);
0168       outputRegions_.push_back(reg0);
0169       outputRegions_.push_back(reg1);
0170       if (debug_) {
0171         dbgCout() << "Created region with etaCenter " << mergedRegions.back().region.hwEtaCenter.to_int()
0172                   << ", halfWidth " << mergedRegions.back().region.hwEtaHalfWidth.to_int() << "\n";
0173       }
0174       if (nbuffers_ == nregions_post_) {
0175         for (int i = 0; i < 2; ++i) {
0176           unsigned int iout = (2 * ieta + i) * nphi + iphi;
0177           const l1ct::PFRegionEmu& from = mergedRegions.back().region;
0178           const l1ct::PFRegionEmu& to = out[iout].region;
0179           l1ct::glbeta_t etaMin = to.hwEtaCenter - to.hwEtaHalfWidth - to.hwEtaExtra - from.hwEtaCenter;
0180           l1ct::glbeta_t etaMax = to.hwEtaCenter + to.hwEtaHalfWidth + to.hwEtaExtra - from.hwEtaCenter;
0181           l1ct::glbeta_t etaShift = from.hwEtaCenter - to.hwEtaCenter;
0182           l1ct::glbphi_t phiMin = -to.hwPhiHalfWidth - to.hwPhiExtra;
0183           l1ct::glbphi_t phiMax = +to.hwPhiHalfWidth + to.hwPhiExtra;
0184           l1ct::glbphi_t phiShift = 0;
0185           if (ntk_ > 0)
0186             tkBuffers_[iout] = l1ct::multififo_regionizer::EtaPhiBuffer<l1ct::TkObjEmu>(
0187                 etabuffer_depth_, etaMin, etaMax, etaShift, phiMin, phiMax, phiShift);
0188           if (ncalo_ > 0)
0189             hadCaloBuffers_[iout] = l1ct::multififo_regionizer::EtaPhiBuffer<l1ct::HadCaloObjEmu>(
0190                 etabuffer_depth_, etaMin, etaMax, etaShift, phiMin, phiMax, phiShift);
0191           if (nem_ > 0)
0192             emCaloBuffers_[iout] = l1ct::multififo_regionizer::EtaPhiBuffer<l1ct::EmCaloObjEmu>(
0193                 etabuffer_depth_, etaMin, etaMax, etaShift, phiMin, phiMax, phiShift);
0194           if (nmu_ > 0)
0195             muBuffers_[iout] = l1ct::multififo_regionizer::EtaPhiBuffer<l1ct::MuObjEmu>(
0196                 etabuffer_depth_, etaMin, etaMax, etaShift, phiMin, phiMax, phiShift);
0197         }
0198       } else if (nbuffers_ == nregions_pre_) {
0199         unsigned int iout = ieta * nphi + iphi;
0200         if (ntk_ > 0)
0201           tkBuffers_[iout] = l1ct::multififo_regionizer::EtaPhiBuffer<l1ct::TkObjEmu>(etabuffer_depth_);
0202         if (ncalo_ > 0)
0203           hadCaloBuffers_[iout] = l1ct::multififo_regionizer::EtaPhiBuffer<l1ct::HadCaloObjEmu>(etabuffer_depth_);
0204         if (nem_ > 0)
0205           emCaloBuffers_[iout] = l1ct::multififo_regionizer::EtaPhiBuffer<l1ct::EmCaloObjEmu>(etabuffer_depth_);
0206         if (nmu_ > 0)
0207           muBuffers_[iout] = l1ct::multififo_regionizer::EtaPhiBuffer<l1ct::MuObjEmu>(etabuffer_depth_);
0208       }
0209     }
0210   }
0211   if (ntk_) {
0212     assert(in.track.size() == 2 * NTK_SECTORS);
0213     tkRegionizerPre_.initSectors(in.track);
0214     tkRegionizerPre_.initRegions(mergedRegions);
0215     tkRegionizerPre_.initRouting(tkRoutes_);
0216     tkRegionizerPost_.initRegions(out);
0217   }
0218   if (ncalo_) {
0219     assert(in.hadcalo.size() == NCALO_SECTORS);
0220     hadCaloRegionizerPre_.initSectors(in.hadcalo);
0221     hadCaloRegionizerPre_.initRegions(mergedRegions);
0222     hadCaloRegionizerPre_.initRouting(caloRoutes_);
0223     hadCaloRegionizerPost_.initRegions(out);
0224   }
0225   if (nem_) {
0226     assert(in.emcalo.size() == NCALO_SECTORS);
0227     emCaloRegionizerPre_.initSectors(in.emcalo);
0228     emCaloRegionizerPre_.initRegions(mergedRegions);
0229     if (ECAL_LINKS)
0230       emCaloRegionizerPre_.initRouting(emCaloRoutes_);
0231     emCaloRegionizerPost_.initRegions(out);
0232   }
0233   if (nmu_) {
0234     muRegionizerPre_.initSectors(in.muon);
0235     muRegionizerPre_.initRegions(mergedRegions);
0236     muRegionizerPre_.initRouting(muRoutes_);
0237     muRegionizerPost_.initRegions(out);
0238   }
0239 }
0240 
0241 bool l1ct::MiddleBufferMultififoRegionizerEmulator::step(bool newEvent,
0242                                                          const std::vector<l1ct::TkObjEmu>& links_tk,
0243                                                          const std::vector<l1ct::HadCaloObjEmu>& links_hadCalo,
0244                                                          const std::vector<l1ct::EmCaloObjEmu>& links_emCalo,
0245                                                          const std::vector<l1ct::MuObjEmu>& links_mu,
0246                                                          std::vector<l1ct::TkObjEmu>& out_tk,
0247                                                          std::vector<l1ct::HadCaloObjEmu>& out_hadCalo,
0248                                                          std::vector<l1ct::EmCaloObjEmu>& out_emCalo,
0249                                                          std::vector<l1ct::MuObjEmu>& out_mu,
0250                                                          bool /*unused*/) {
0251   iclock_ = (newEvent ? 0 : iclock_ + 1);
0252   bool newRead = iclock_ == 2 * etabuffer_depth_;
0253 
0254   std::vector<l1ct::TkObjEmu> pre_out_tk;
0255   std::vector<l1ct::HadCaloObjEmu> pre_out_hadCalo;
0256   std::vector<l1ct::EmCaloObjEmu> pre_out_emCalo;
0257   std::vector<l1ct::MuObjEmu> pre_out_mu;
0258   bool ret = false;
0259   if (ntk_)
0260     ret = tkRegionizerPre_.step(newEvent, links_tk, pre_out_tk, false);
0261   if (nmu_)
0262     ret = muRegionizerPre_.step(newEvent, links_mu, pre_out_mu, false);
0263   if (ncalo_)
0264     ret = hadCaloRegionizerPre_.step(newEvent, links_hadCalo, pre_out_hadCalo, false);
0265   if (nem_) {
0266     if (ECAL_LINKS) {
0267       ret = emCaloRegionizerPre_.step(newEvent, links_emCalo, pre_out_emCalo, false);
0268     } else if (ncalo_) {
0269       pre_out_emCalo.resize(pre_out_hadCalo.size());
0270       for (unsigned int i = 0, n = pre_out_hadCalo.size(); i < n; ++i) {
0271         decode(pre_out_hadCalo[i], pre_out_emCalo[i]);
0272       }
0273     }
0274   }
0275 
0276   // in the no-streaming case, we just output the pre-regionizer
0277   if (!streaming_) {
0278     out_tk.swap(pre_out_tk);
0279     out_mu.swap(pre_out_mu);
0280     out_hadCalo.swap(pre_out_hadCalo);
0281     out_emCalo.swap(pre_out_emCalo);
0282     return ret;
0283   }
0284 
0285   // otherwise, we push into the eta buffers
0286   if (newEvent) {
0287     for (auto& b : tkBuffers_)
0288       b.writeNewEvent();
0289     for (auto& b : hadCaloBuffers_)
0290       b.writeNewEvent();
0291     for (auto& b : emCaloBuffers_)
0292       b.writeNewEvent();
0293     for (auto& b : muBuffers_)
0294       b.writeNewEvent();
0295   }
0296   unsigned int neta = 3, nphi = 9;
0297   for (unsigned int ieta = 0; ieta < neta; ++ieta) {
0298     for (unsigned int iphi = 0; iphi < nphi; ++iphi) {
0299       unsigned int iin = ieta * nphi + iphi;
0300       for (int i = 0, n = nbuffers_ == nregions_pre_ ? 1 : 2; i < n; ++i) {
0301         unsigned int iout = (n * ieta + i) * nphi + iphi;
0302         if (ntk_)
0303           tkBuffers_[iout].maybe_push(pre_out_tk[iin]);
0304         if (ncalo_)
0305           hadCaloBuffers_[iout].maybe_push(pre_out_hadCalo[iin]);
0306         if (nem_)
0307           emCaloBuffers_[iout].maybe_push(pre_out_emCalo[iin]);
0308         if (nmu_)
0309           muBuffers_[iout].maybe_push(pre_out_mu[iin]);
0310       }
0311     }
0312   }
0313 
0314   // and we read from eta buffers into muxes
0315   if (newRead) {
0316     for (auto& b : tkBuffers_)
0317       b.readNewEvent();
0318     for (auto& b : hadCaloBuffers_)
0319       b.readNewEvent();
0320     for (auto& b : emCaloBuffers_)
0321       b.readNewEvent();
0322     for (auto& b : muBuffers_)
0323       b.readNewEvent();
0324   }
0325   std::vector<l1ct::TkObjEmu> bufferOut_tk(ntk_ ? nregions_post_ : 0);
0326   std::vector<l1ct::HadCaloObjEmu> bufferOut_hadCalo(ncalo_ ? nregions_post_ : 0);
0327   std::vector<l1ct::EmCaloObjEmu> bufferOut_emCalo(nem_ ? nregions_post_ : 0);
0328   std::vector<l1ct::MuObjEmu> bufferOut_mu(nmu_ ? nregions_post_ : 0);
0329   if (nbuffers_ == nregions_post_) {  // just copy directly
0330     for (unsigned int i = 0; i < nregions_post_; ++i) {
0331       if (ntk_)
0332         bufferOut_tk[i] = tkBuffers_[i].pop();
0333       if (ncalo_)
0334         bufferOut_hadCalo[i] = hadCaloBuffers_[i].pop();
0335       if (nem_)
0336         bufferOut_emCalo[i] = emCaloBuffers_[i].pop();
0337       if (nmu_)
0338         bufferOut_mu[i] = muBuffers_[i].pop();
0339     }
0340   } else if (nbuffers_ == nregions_pre_) {  // propagate and copy
0341     unsigned int neta = 3, nphi = 9;
0342     for (unsigned int ieta = 0; ieta < neta; ++ieta) {
0343       for (unsigned int iphi = 0; iphi < nphi; ++iphi) {
0344         unsigned int iin = ieta * nphi + iphi;
0345         const l1ct::PFRegionEmu& from = mergedRegions_[iin];
0346         l1ct::TkObjEmu tk = ntk_ ? tkBuffers_[iin].pop() : l1ct::TkObjEmu();
0347         l1ct::HadCaloObjEmu calo = ncalo_ ? hadCaloBuffers_[iin].pop() : l1ct::HadCaloObjEmu();
0348         l1ct::EmCaloObjEmu em = nem_ ? emCaloBuffers_[iin].pop() : l1ct::EmCaloObjEmu();
0349         l1ct::MuObjEmu mu = nmu_ ? muBuffers_[iin].pop() : l1ct::MuObjEmu();
0350         for (int i = 0; i < 2; ++i) {
0351           const l1ct::PFRegionEmu& to = outputRegions_[2 * iin + i];
0352           unsigned int iout = (2 * ieta + i) * nphi + iphi;
0353           l1ct::glbeta_t etaMin = to.hwEtaCenter - to.hwEtaHalfWidth - to.hwEtaExtra - from.hwEtaCenter;
0354           l1ct::glbeta_t etaMax = to.hwEtaCenter + to.hwEtaHalfWidth + to.hwEtaExtra - from.hwEtaCenter;
0355           l1ct::glbeta_t etaShift = from.hwEtaCenter - to.hwEtaCenter;
0356           l1ct::glbphi_t phiMin = -to.hwPhiHalfWidth - to.hwPhiExtra;
0357           l1ct::glbphi_t phiMax = +to.hwPhiHalfWidth + to.hwPhiExtra;
0358           if (tk.hwPt > 0 && l1ct::multififo_regionizer::local_eta_phi_window(tk, etaMin, etaMax, phiMin, phiMax)) {
0359             bufferOut_tk[iout] = tk;
0360             bufferOut_tk[iout].hwEta += etaShift;
0361           }
0362           if (calo.hwPt > 0 && l1ct::multififo_regionizer::local_eta_phi_window(calo, etaMin, etaMax, phiMin, phiMax)) {
0363             bufferOut_hadCalo[iout] = calo;
0364             bufferOut_hadCalo[iout].hwEta += etaShift;
0365           }
0366           if (em.hwPt > 0 && l1ct::multififo_regionizer::local_eta_phi_window(em, etaMin, etaMax, phiMin, phiMax)) {
0367             bufferOut_emCalo[iout] = em;
0368             bufferOut_emCalo[iout].hwEta += etaShift;
0369           }
0370           if (mu.hwPt > 0 && l1ct::multififo_regionizer::local_eta_phi_window(mu, etaMin, etaMax, phiMin, phiMax)) {
0371             bufferOut_mu[iout] = mu;
0372             bufferOut_mu[iout].hwEta += etaShift;
0373           }
0374         }
0375       }
0376     }
0377   }
0378   if (ntk_)
0379     tkRegionizerPost_.muxonly_step(newEvent, /*flush=*/true, bufferOut_tk, out_tk);
0380   if (ncalo_)
0381     hadCaloRegionizerPost_.muxonly_step(newEvent, /*flush=*/true, bufferOut_hadCalo, out_hadCalo);
0382   if (nem_)
0383     emCaloRegionizerPost_.muxonly_step(newEvent, /*flush=*/true, bufferOut_emCalo, out_emCalo);
0384   if (nmu_)
0385     muRegionizerPost_.muxonly_step(newEvent, /*flush=*/true, bufferOut_mu, out_mu);
0386 
0387   return newRead;
0388 }
0389 
0390 void l1ct::MiddleBufferMultififoRegionizerEmulator::fillLinks(unsigned int iclock,
0391                                                               const l1ct::RegionizerDecodedInputs& in,
0392                                                               std::vector<l1ct::TkObjEmu>& links,
0393                                                               std::vector<bool>& valid) {
0394   if (ntk_ == 0)
0395     return;
0396   assert(NTK_LINKS == 1);
0397   links.resize(NTK_SECTORS * NTK_LINKS * 2);
0398   valid.resize(links.size());
0399   // emulate reduced rate from 96b tracks on 64b links
0400   unsigned int itkclock = 2 * (iclock / 3) + (iclock % 3) - 1;  // will underflow for iclock == 0 but it doesn't matter
0401   for (unsigned int is = 0, idx = 0; is < 2 * NTK_SECTORS; ++is, ++idx) {  // tf sectors
0402     const l1ct::DetectorSector<l1ct::TkObjEmu>& sec = in.track[is];
0403     unsigned int ntracks = sec.size();
0404     unsigned int nw64 = (ntracks * 3 + 1) / 2;
0405     if (iclock % 3 == 0) {
0406       links[idx].clear();
0407       valid[idx] = (iclock == 0) || (iclock < nw64);
0408     } else if (itkclock < ntracks && itkclock < nclocks_ - 1) {
0409       links[idx] = sec[itkclock];
0410       valid[idx] = true;
0411     } else {
0412       links[idx].clear();
0413       valid[idx] = false;
0414     }
0415   }
0416 }
0417 
0418 template <typename T>
0419 void l1ct::MiddleBufferMultififoRegionizerEmulator::fillCaloLinks_(unsigned int iclock,
0420                                                                    const std::vector<DetectorSector<T>>& in,
0421                                                                    std::vector<T>& links,
0422                                                                    std::vector<bool>& valid) {
0423   unsigned int NLINKS = (typeid(T) == typeid(l1ct::HadCaloObjEmu) ? HCAL_LINKS : ECAL_LINKS);
0424   links.resize(NCALO_SECTORS * NLINKS);
0425   valid.resize(links.size());
0426   for (unsigned int is = 0, idx = 0; is < NCALO_SECTORS; ++is) {
0427     for (unsigned int il = 0; il < NLINKS; ++il, ++idx) {
0428       unsigned int ioffs = iclock * NLINKS + il;
0429       if (ioffs < in[is].size() && iclock < nclocks_ - 1) {
0430         links[idx] = in[is][ioffs];
0431         valid[idx] = true;
0432       } else {
0433         links[idx].clear();
0434         valid[idx] = false;
0435       }
0436     }
0437   }
0438 }
0439 void l1ct::MiddleBufferMultififoRegionizerEmulator::fillSharedCaloLinks(
0440     unsigned int iclock,
0441     const std::vector<l1ct::DetectorSector<l1ct::EmCaloObjEmu>>& em_in,
0442     const std::vector<l1ct::DetectorSector<l1ct::HadCaloObjEmu>>& had_in,
0443     std::vector<l1ct::HadCaloObjEmu>& links,
0444     std::vector<bool>& valid) {
0445   assert(ECAL_LINKS == 0 && HCAL_LINKS == 1 && ncalo_ != 0 && nem_ != 0);
0446   links.resize(NCALO_SECTORS);
0447   valid.resize(links.size());
0448   // for the moment we assume the first 54 clocks are for EM, the rest for HAD
0449   const unsigned int NCLK_EM = 54;
0450   for (unsigned int is = 0; is < NCALO_SECTORS; ++is) {
0451     links[is].clear();
0452     if (iclock < NCLK_EM) {
0453       valid[is] = true;
0454       if (iclock < em_in[is].size()) {
0455         encode(em_in[is][iclock], links[is]);
0456       }
0457     } else {
0458       if (iclock - NCLK_EM < had_in[is].size()) {
0459         encode(had_in[is][iclock - NCLK_EM], links[is]);
0460         valid[is] = true;
0461       } else {
0462         valid[is] = false;
0463       }
0464     }
0465   }  // sectors
0466 }
0467 
0468 void l1ct::MiddleBufferMultififoRegionizerEmulator::fillLinks(unsigned int iclock,
0469                                                               const l1ct::RegionizerDecodedInputs& in,
0470                                                               std::vector<l1ct::HadCaloObjEmu>& links,
0471                                                               std::vector<bool>& valid) {
0472   if (ncalo_ == 0)
0473     return;
0474   if (nem_ != 0 && ECAL_LINKS == 0 && HCAL_LINKS == 1)
0475     fillSharedCaloLinks(iclock, in.emcalo, in.hadcalo, links, valid);
0476   else
0477     fillCaloLinks_(iclock, in.hadcalo, links, valid);
0478 }
0479 
0480 void l1ct::MiddleBufferMultififoRegionizerEmulator::fillLinks(unsigned int iclock,
0481                                                               const l1ct::RegionizerDecodedInputs& in,
0482                                                               std::vector<l1ct::EmCaloObjEmu>& links,
0483                                                               std::vector<bool>& valid) {
0484   if (nem_ == 0)
0485     return;
0486   fillCaloLinks_(iclock, in.emcalo, links, valid);
0487 }
0488 
0489 void l1ct::MiddleBufferMultififoRegionizerEmulator::fillLinks(unsigned int iclock,
0490                                                               const l1ct::RegionizerDecodedInputs& in,
0491                                                               std::vector<l1ct::MuObjEmu>& links,
0492                                                               std::vector<bool>& valid) {
0493   if (nmu_ == 0)
0494     return;
0495   assert(NMU_LINKS == 1);
0496   links.resize(NMU_LINKS);
0497   valid.resize(links.size());
0498   if (iclock < in.muon.size() && iclock < nclocks_ - 1) {
0499     links[0] = in.muon[iclock];
0500     valid[0] = true;
0501   } else {
0502     links[0].clear();
0503     valid[0] = false;
0504   }
0505 }
0506 
0507 void l1ct::MiddleBufferMultififoRegionizerEmulator::destream(int iclock,
0508                                                              const std::vector<l1ct::TkObjEmu>& tk_out,
0509                                                              const std::vector<l1ct::EmCaloObjEmu>& em_out,
0510                                                              const std::vector<l1ct::HadCaloObjEmu>& calo_out,
0511                                                              const std::vector<l1ct::MuObjEmu>& mu_out,
0512                                                              PFInputRegion& out) {
0513   if (ntk_)
0514     tkRegionizerPost_.destream(iclock, tk_out, out.track);
0515   if (ncalo_)
0516     hadCaloRegionizerPost_.destream(iclock, calo_out, out.hadcalo);
0517   if (nem_)
0518     emCaloRegionizerPost_.destream(iclock, em_out, out.emcalo);
0519   if (nmu_)
0520     muRegionizerPost_.destream(iclock, mu_out, out.muon);
0521 }
0522 
0523 void l1ct::MiddleBufferMultififoRegionizerEmulator::reset() {
0524   tkRegionizerPre_.reset();
0525   emCaloRegionizerPre_.reset();
0526   hadCaloRegionizerPre_.reset();
0527   muRegionizerPre_.reset();
0528   tkRegionizerPost_.reset();
0529   emCaloRegionizerPost_.reset();
0530   hadCaloRegionizerPost_.reset();
0531   muRegionizerPost_.reset();
0532   for (auto& b : tkBuffers_)
0533     b.reset();
0534   for (auto& b : hadCaloBuffers_)
0535     b.reset();
0536   for (auto& b : emCaloBuffers_)
0537     b.reset();
0538   for (auto& b : muBuffers_)
0539     b.reset();
0540 }
0541 
0542 void l1ct::MiddleBufferMultififoRegionizerEmulator::run(const RegionizerDecodedInputs& in,
0543                                                         std::vector<PFInputRegion>& out) {
0544   assert(streaming_);  // doesn't make sense otherwise
0545   if (!init_)
0546     initSectorsAndRegions(in, out);
0547   reset();
0548   std::vector<l1ct::TkObjEmu> tk_links_in, tk_out;
0549   std::vector<l1ct::EmCaloObjEmu> em_links_in, em_out;
0550   std::vector<l1ct::HadCaloObjEmu> calo_links_in, calo_out;
0551   std::vector<l1ct::MuObjEmu> mu_links_in, mu_out;
0552 
0553   // read and sort the inputs
0554   for (unsigned int iclock = 0; iclock < nclocks_; ++iclock) {
0555     fillLinks(iclock, in, tk_links_in);
0556     fillLinks(iclock, in, em_links_in);
0557     fillLinks(iclock, in, calo_links_in);
0558     fillLinks(iclock, in, mu_links_in);
0559 
0560     bool newevt = (iclock == 0);
0561     step(newevt, tk_links_in, calo_links_in, em_links_in, mu_links_in, tk_out, calo_out, em_out, mu_out, true);
0562   }
0563 
0564   // set up an empty event
0565   for (auto& l : tk_links_in)
0566     l.clear();
0567   for (auto& l : em_links_in)
0568     l.clear();
0569   for (auto& l : calo_links_in)
0570     l.clear();
0571   for (auto& l : mu_links_in)
0572     l.clear();
0573 
0574   // read and put the inputs in the regions
0575   assert(out.size() == nregions_post_);
0576   for (unsigned int iclock = 0; iclock < nclocks_; ++iclock) {
0577     bool newevt = (iclock == 0);
0578     step(newevt, tk_links_in, calo_links_in, em_links_in, mu_links_in, tk_out, calo_out, em_out, mu_out, true);
0579 
0580     unsigned int ireg = (iclock / (outii_ + pauseii_));
0581     if ((iclock % (outii_ + pauseii_)) >= outii_)
0582       continue;
0583     if (ireg >= nregions_post_)
0584       break;
0585 
0586     if (streaming_) {
0587       destream(iclock, tk_out, em_out, calo_out, mu_out, out[ireg]);
0588     } else {
0589       if (iclock % outii_ == 0) {
0590         out[ireg].track = tk_out;
0591         out[ireg].emcalo = em_out;
0592         out[ireg].hadcalo = calo_out;
0593         out[ireg].muon = mu_out;
0594       }
0595     }
0596   }
0597 
0598   reset();
0599 }
0600 
0601 void l1ct::MiddleBufferMultififoRegionizerEmulator::encode(const l1ct::EmCaloObjEmu& from, l1ct::HadCaloObjEmu& to) {
0602   assert(!from.hwEmID[5]);
0603   to.hwPt = from.hwPt;
0604   to.hwEmPt = from.hwPtErr;
0605   to.hwEta = from.hwEta;
0606   to.hwPhi = from.hwPhi;
0607   to.hwEmID[5] = true;
0608   to.hwEmID(4, 0) = from.hwEmID(4, 0);
0609   to.src = from.src;
0610 }
0611 void l1ct::MiddleBufferMultififoRegionizerEmulator::encode(const l1ct::HadCaloObjEmu& from, l1ct::HadCaloObjEmu& to) {
0612   assert(!from.hwEmID[5]);
0613   to = from;
0614 }
0615 void l1ct::MiddleBufferMultififoRegionizerEmulator::decode(l1ct::HadCaloObjEmu& had, l1ct::EmCaloObjEmu& em) {
0616   if (had.hwPt && had.hwEmID[5]) {
0617     em.hwPt = had.hwPt;
0618     em.hwPtErr = had.hwEmPt;
0619     em.hwEta = had.hwEta;
0620     em.hwPhi = had.hwPhi;
0621     em.hwEmID[5] = 0;
0622     em.hwEmID(4, 0) = had.hwEmID(4, 0);
0623     em.hwSrrTot = 0;
0624     em.hwMeanZ = 0;
0625     em.hwHoe = 0;
0626     em.src = had.src;
0627     had.clear();
0628   } else {
0629     em.clear();
0630   }
0631 }