Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-10 01:53:58

0001 #include "L1Trigger/Phase2L1ParticleFlow/interface/regionizer/multififo_regionizer_ref.h"
0002 #include "L1Trigger/Phase2L1ParticleFlow/interface/egamma/pfeginput_ref.h"
0003 #include "L1Trigger/Phase2L1ParticleFlow/interface/regionizer/multififo_regionizer_elements_ref.icc"
0004 
0005 #include <iostream>
0006 #include <memory>
0007 
0008 #ifdef CMSSW_GIT_HASH
0009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0010 
0011 l1ct::MultififoRegionizerEmulator::MultififoRegionizerEmulator(const edm::ParameterSet& iConfig)
0012     : MultififoRegionizerEmulator(iConfig.getParameter<uint32_t>("nEndcaps"),
0013                                   iConfig.getParameter<uint32_t>("nClocks"),
0014                                   iConfig.getParameter<uint32_t>("nTrack"),
0015                                   iConfig.getParameter<uint32_t>("nCalo"),
0016                                   iConfig.getParameter<uint32_t>("nEmCalo"),
0017                                   iConfig.getParameter<uint32_t>("nMu"),
0018                                   /*streaming=*/false,
0019                                   /*outii=*/1,
0020                                   iConfig.getParameter<bool>("useAlsoVtxCoords")) {
0021   debug_ = iConfig.getUntrackedParameter<bool>("debug", false);
0022   if (iConfig.existsAs<edm::ParameterSet>("egInterceptMode")) {
0023     const auto& emSelCfg = iConfig.getParameter<edm::ParameterSet>("egInterceptMode");
0024     setEgInterceptMode(emSelCfg.getParameter<bool>("afterFifo"), emSelCfg);
0025   }
0026 }
0027 #endif
0028 
0029 l1ct::MultififoRegionizerEmulator::MultififoRegionizerEmulator(unsigned int nendcaps,
0030                                                                unsigned int nclocks,
0031                                                                unsigned int ntk,
0032                                                                unsigned int ncalo,
0033                                                                unsigned int nem,
0034                                                                unsigned int nmu,
0035                                                                bool streaming,
0036                                                                unsigned int outii,
0037                                                                bool useAlsoVtxCoords)
0038     : RegionizerEmulator(useAlsoVtxCoords),
0039       NTK_SECTORS(9),
0040       NCALO_SECTORS(3),
0041       NTK_LINKS(2),
0042       NCALO_LINKS(2),
0043       HCAL_LINKS(0),
0044       ECAL_LINKS(0),
0045       NMU_LINKS(1),
0046       nendcaps_(nendcaps),
0047       nclocks_(nclocks),
0048       ntk_(ntk),
0049       ncalo_(ncalo),
0050       nem_(nem),
0051       nmu_(nmu),
0052       outii_(outii),
0053       pauseii_(0),
0054       streaming_(streaming),
0055       emInterceptMode_(noIntercept),
0056       init_(false),
0057       tkRegionizer_(ntk, streaming ? (ntk + outii - 1) / outii : ntk, streaming, outii, 0, useAlsoVtxCoords),
0058       hadCaloRegionizer_(ncalo, streaming ? (ncalo + outii - 1) / outii : ncalo, streaming, outii, 0),
0059       emCaloRegionizer_(nem, streaming ? (nem + outii - 1) / outii : nem, streaming, outii, 0),
0060       muRegionizer_(nmu, streaming ? std::max(1u, (nmu + outii - 1) / outii) : nmu, streaming, outii, 0) {
0061   // now we initialize the routes: track finder
0062   for (unsigned int ie = 0; ie < nendcaps && ntk > 0; ++ie) {
0063     for (unsigned int is = 0; is < NTK_SECTORS; ++is) {  // 9 tf sectors
0064       for (unsigned int il = 0; il < NTK_LINKS; ++il) {  // max tracks per sector per clock
0065         unsigned int isp = (is + 1) % NTK_SECTORS, ism = (is + NTK_SECTORS - 1) % NTK_SECTORS;
0066         tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, is + NTK_SECTORS * ie, il);
0067         tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, isp + NTK_SECTORS * ie, il + 2);
0068         tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, ism + NTK_SECTORS * ie, il + 4);
0069       }
0070     }
0071   }
0072   // hgcal
0073   assert(NCALO_SECTORS == 3 && NTK_SECTORS == 9);  // otherwise math below is broken, but it's hard to make it generic
0074   for (unsigned int ie = 0; ie < nendcaps; ++ie) {
0075     for (unsigned int is = 0; is < NCALO_SECTORS; ++is) {  // NCALO_SECTORS sectors
0076       for (unsigned int il = 0; il < NCALO_LINKS; ++il) {  // max clusters per sector per clock
0077         for (unsigned int j = 0; j < 3; ++j) {             // PF REGION
0078           caloRoutes_.emplace_back(is + 3 * ie, il, 3 * is + j + 9 * ie, il);
0079           if (j == 0 || j == 2) {
0080             int other = (j == 0) ? 2 : 1;  // pf region 0, takes from prev. pf region 2 takes from next
0081             //                       from sector      , from link, to region, to fifo
0082             caloRoutes_.emplace_back(
0083                 (is + other) % 3 + 3 * ie, il, 3 * is + j + 9 * ie, il + 2);  //last 2 = NCALOFIBERS
0084           }
0085         }
0086       }
0087     }
0088   }
0089   emCaloRoutes_ = caloRoutes_;  // in the endcaps there's only one calo
0090   // mu
0091   for (unsigned int il = 0; il < NMU_LINKS && nmu > 0; ++il) {  // max clusters per sector per clock
0092     for (unsigned int j = 0; j < NTK_SECTORS * nendcaps; ++j) {
0093       muRoutes_.emplace_back(0, il, j, il);
0094     }
0095   }
0096 }
0097 
0098 l1ct::MultififoRegionizerEmulator::MultififoRegionizerEmulator(BarrelSetup barrelSetup,
0099                                                                unsigned int nHCalLinks,
0100                                                                unsigned int nECalLinks,
0101                                                                unsigned int nclocks,
0102                                                                unsigned int ntk,
0103                                                                unsigned int ncalo,
0104                                                                unsigned int nem,
0105                                                                unsigned int nmu,
0106                                                                bool streaming,
0107                                                                unsigned int outii,
0108                                                                unsigned int pauseii,
0109                                                                bool useAlsoVtxCoords)
0110     : RegionizerEmulator(useAlsoVtxCoords),
0111       NTK_SECTORS((barrelSetup == BarrelSetup::Phi18 || barrelSetup == BarrelSetup::Phi9) ? 5 : 9),
0112       NCALO_SECTORS((barrelSetup == BarrelSetup::Phi18 || barrelSetup == BarrelSetup::Phi9) ? 2 : 3),
0113       NTK_LINKS(2),
0114       NCALO_LINKS(2),
0115       HCAL_LINKS(nHCalLinks),
0116       ECAL_LINKS(nECalLinks),
0117       NMU_LINKS(1),
0118       nendcaps_(0),
0119       nclocks_(nclocks),
0120       ntk_(ntk),
0121       ncalo_(ncalo),
0122       nem_(nem),
0123       nmu_(nmu),
0124       outii_(outii),
0125       pauseii_(pauseii),
0126       streaming_(streaming),
0127       emInterceptMode_(noIntercept),
0128       init_(false),
0129       tkRegionizer_(ntk, streaming ? (ntk + outii - 1) / outii : ntk, streaming, outii, pauseii, useAlsoVtxCoords),
0130       hadCaloRegionizer_(ncalo, streaming ? (ncalo + outii - 1) / outii : ncalo, streaming, outii, pauseii),
0131       emCaloRegionizer_(nem, streaming ? (nem + outii - 1) / outii : nem, streaming, outii, pauseii),
0132       muRegionizer_(nmu, streaming ? std::max(1u, (nmu + outii - 1) / outii) : nmu, streaming, outii, pauseii) {
0133   unsigned int nendcaps = 2, etaslices = 0;
0134   switch (barrelSetup) {
0135     case BarrelSetup::Full54:
0136       nregions_ = 54;
0137       etaslices = 6;
0138       break;
0139     case BarrelSetup::Full27:
0140       nregions_ = 27;
0141       etaslices = 3;
0142       break;
0143     case BarrelSetup::Central18:
0144       nregions_ = 18;
0145       etaslices = 2;
0146       break;
0147     case BarrelSetup::Central9:
0148       nregions_ = 9;
0149       etaslices = 1;
0150       break;
0151     case BarrelSetup::Phi18:
0152       nregions_ = 18;
0153       etaslices = 6;
0154       break;
0155     case BarrelSetup::Phi9:
0156       nregions_ = 9;
0157       etaslices = 3;
0158       break;
0159   }
0160   unsigned int phisectors = nregions_ / etaslices;
0161   // now we initialize the routes: track finder
0162   for (unsigned int ietaslice = 0; ietaslice < etaslices && ntk > 0; ++ietaslice) {
0163     for (unsigned int ie = 0; ie < nendcaps; ++ie) {  // 0 = negative, 1 = positive
0164       unsigned int nTFEtaSlices = 1;
0165       if (etaslices == 3) {
0166         if (ietaslice == 0 && ie == 1)
0167           continue;
0168         if (ietaslice == 2 && ie == 0)
0169           continue;
0170         if (ietaslice == 1)
0171           nTFEtaSlices = 2;
0172       } else if (etaslices == 6) {
0173         if (ietaslice <= 1 && ie == 1)
0174           continue;
0175         if (ietaslice >= 4 && ie == 0)
0176           continue;
0177         if (ietaslice == 2 || ietaslice == 3)
0178           nTFEtaSlices = 2;
0179       } else if (barrelSetup == BarrelSetup::Central18 || barrelSetup == BarrelSetup::Central9) {
0180         nTFEtaSlices = 2;
0181       }
0182       unsigned int ireg0 = phisectors * ietaslice, il0 = 6 * (nTFEtaSlices - 1) * ie;
0183       if (barrelSetup == BarrelSetup::Phi18 || barrelSetup == BarrelSetup::Phi9) {
0184         for (unsigned int iregphi = 0; iregphi < (nregions_ / etaslices); ++iregphi) {
0185           for (unsigned int il = 0; il < NTK_LINKS; ++il) {
0186             tkRoutes_.emplace_back((iregphi + 1) + NTK_SECTORS * ie, il, iregphi + ireg0, il0 + il);
0187             tkRoutes_.emplace_back((iregphi + 0) + NTK_SECTORS * ie, il, iregphi + ireg0, il0 + il + 2);
0188             tkRoutes_.emplace_back((iregphi + 2) + NTK_SECTORS * ie, il, iregphi + ireg0, il0 + il + 4);
0189           }
0190         }
0191       } else {
0192         for (unsigned int is = 0; is < NTK_SECTORS; ++is) {  // 9 tf sectors
0193           for (unsigned int il = 0; il < NTK_LINKS; ++il) {  // max tracks per sector per clock
0194             unsigned int isp = (is + 1) % NTK_SECTORS, ism = (is + NTK_SECTORS - 1) % NTK_SECTORS;
0195             tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, is + ireg0, il0 + il);
0196             tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, isp + ireg0, il0 + il + 2);
0197             tkRoutes_.emplace_back(is + NTK_SECTORS * ie, il, ism + ireg0, il0 + il + 4);
0198           }
0199         }
0200       }
0201     }
0202   }
0203   // calo
0204   unsigned int calo_sectors_to_loop = NCALO_SECTORS;
0205   if (barrelSetup == BarrelSetup::Phi18 || barrelSetup == BarrelSetup::Phi9) {
0206     calo_sectors_to_loop = 1;
0207     assert(NCALO_SECTORS == 2 && NTK_SECTORS == 5);  // otherwise math below is broken, but it's hard to make it generic
0208   } else {
0209     assert(NCALO_SECTORS == 3 && NTK_SECTORS == 9);  // otherwise math below is broken, but it's hard to make it generic
0210   }
0211   for (unsigned int ie = 0; ie < etaslices; ++ie) {
0212     for (unsigned int is = 0; is < calo_sectors_to_loop; ++is) {  // NCALO_SECTORS sectors
0213       for (unsigned int j = 0; j < 3; ++j) {                      // 3 regions x sector
0214         for (unsigned int il = 0; il < HCAL_LINKS; ++il) {
0215           caloRoutes_.emplace_back(is, il, 3 * is + j + phisectors * ie, il);
0216           if (j) {
0217             caloRoutes_.emplace_back((is + 1) % 3, il, 3 * is + j + phisectors * ie, il + HCAL_LINKS);
0218           }
0219         }
0220         for (unsigned int il = 0; il < ECAL_LINKS; ++il) {
0221           emCaloRoutes_.emplace_back(is, il, 3 * is + j + phisectors * ie, il);
0222           if (j) {
0223             emCaloRoutes_.emplace_back((is + 1) % 3, il, 3 * is + j + phisectors * ie, il + ECAL_LINKS);
0224           }
0225         }
0226       }
0227     }
0228   }
0229   // mu
0230   for (unsigned int il = 0; il < NMU_LINKS && nmu > 0; ++il) {
0231     for (unsigned int j = 0; j < nregions_; ++j) {
0232       muRoutes_.emplace_back(0, il, j, il);
0233     }
0234   }
0235 }
0236 
0237 l1ct::MultififoRegionizerEmulator::~MultififoRegionizerEmulator() {}
0238 
0239 void l1ct::MultififoRegionizerEmulator::setEgInterceptMode(bool afterFifo,
0240                                                            const l1ct::EGInputSelectorEmuConfig& interceptorConfig) {
0241   emInterceptMode_ = afterFifo ? interceptPostFifo : interceptPreFifo;
0242   interceptor_ = std::make_unique<EGInputSelectorEmulator>(interceptorConfig);
0243 }
0244 
0245 void l1ct::MultififoRegionizerEmulator::initSectorsAndRegions(const RegionizerDecodedInputs& in,
0246                                                               const std::vector<PFInputRegion>& out) {
0247   assert(!init_);
0248   init_ = true;
0249   if (nendcaps_ > 0) {
0250     assert(out.size() == NTK_SECTORS * nendcaps_);
0251   } else {
0252     assert(out.size() == nregions_);
0253   }
0254   nregions_ = out.size();
0255   if (ntk_) {
0256     assert(in.track.size() == NTK_SECTORS * (nendcaps_ ? nendcaps_ : 2));
0257     tkRegionizer_.initSectors(in.track);
0258     tkRegionizer_.initRegions(out);
0259     tkRegionizer_.initRouting(tkRoutes_);
0260   }
0261   if (ncalo_) {
0262     assert(in.hadcalo.size() == NCALO_SECTORS * (nendcaps_ ? nendcaps_ : 1));
0263     hadCaloRegionizer_.initSectors(in.hadcalo);
0264     hadCaloRegionizer_.initRegions(out);
0265     hadCaloRegionizer_.initRouting(caloRoutes_);
0266   }
0267   if (nem_) {
0268     assert(in.emcalo.size() == NCALO_SECTORS * (nendcaps_ ? nendcaps_ : 1));
0269     emCaloRegionizer_.initSectors(in.emcalo);
0270     emCaloRegionizer_.initRegions(out);
0271     emCaloRegionizer_.initRouting(emCaloRoutes_);
0272   }
0273   if (nmu_) {
0274     muRegionizer_.initSectors(in.muon);
0275     muRegionizer_.initRegions(out);
0276     muRegionizer_.initRouting(muRoutes_);
0277   }
0278 }
0279 
0280 // clock-cycle emulation
0281 bool l1ct::MultififoRegionizerEmulator::step(bool newEvent,
0282                                              const std::vector<l1ct::TkObjEmu>& links,
0283                                              std::vector<l1ct::TkObjEmu>& out,
0284                                              bool mux) {
0285   return ntk_ ? tkRegionizer_.step(newEvent, links, out, mux) : false;
0286 }
0287 
0288 bool l1ct::MultififoRegionizerEmulator::step(bool newEvent,
0289                                              const std::vector<l1ct::EmCaloObjEmu>& links,
0290                                              std::vector<l1ct::EmCaloObjEmu>& out,
0291                                              bool mux) {
0292   assert(emInterceptMode_ == noIntercept);  // otherwise the em & had calo can't be stepped independently
0293   return nem_ ? emCaloRegionizer_.step(newEvent, links, out, mux) : false;
0294 }
0295 
0296 bool l1ct::MultififoRegionizerEmulator::step(bool newEvent,
0297                                              const std::vector<l1ct::HadCaloObjEmu>& links,
0298                                              std::vector<l1ct::HadCaloObjEmu>& out,
0299                                              bool mux) {
0300   return ncalo_ ? hadCaloRegionizer_.step(newEvent, links, out, mux) : false;
0301 }
0302 
0303 bool l1ct::MultififoRegionizerEmulator::step(bool newEvent,
0304                                              const std::vector<l1ct::MuObjEmu>& links,
0305                                              std::vector<l1ct::MuObjEmu>& out,
0306                                              bool mux) {
0307   return nmu_ ? muRegionizer_.step(newEvent, links, out, mux) : false;
0308 }
0309 
0310 bool l1ct::MultififoRegionizerEmulator::step(bool newEvent,
0311                                              const std::vector<l1ct::TkObjEmu>& links_tk,
0312                                              const std::vector<l1ct::HadCaloObjEmu>& links_hadCalo,
0313                                              const std::vector<l1ct::EmCaloObjEmu>& links_emCalo,
0314                                              const std::vector<l1ct::MuObjEmu>& links_mu,
0315                                              std::vector<l1ct::TkObjEmu>& out_tk,
0316                                              std::vector<l1ct::HadCaloObjEmu>& out_hadCalo,
0317                                              std::vector<l1ct::EmCaloObjEmu>& out_emCalo,
0318                                              std::vector<l1ct::MuObjEmu>& out_mu,
0319                                              bool mux) {
0320   bool ret = false;
0321   if (ntk_)
0322     ret = tkRegionizer_.step(newEvent, links_tk, out_tk, mux);
0323   if (nmu_)
0324     ret = muRegionizer_.step(newEvent, links_mu, out_mu, mux);
0325   switch (emInterceptMode_) {
0326     case noIntercept:
0327       if (ncalo_)
0328         ret = hadCaloRegionizer_.step(newEvent, links_hadCalo, out_hadCalo, mux);
0329       if (nem_)
0330         ret = emCaloRegionizer_.step(newEvent, links_emCalo, out_emCalo, mux);
0331       break;
0332     case interceptPreFifo:
0333       // we actually intercept at the links, in the software it's equivalent and it's easier
0334       assert(nem_ > 0 && ncalo_ > 0 && !links_hadCalo.empty() && links_emCalo.empty());
0335       assert(interceptor_.get());
0336       {
0337         std::vector<l1ct::EmCaloObjEmu> intercepted_links;
0338         interceptor_->select_or_clear(links_hadCalo, intercepted_links);
0339         ret = hadCaloRegionizer_.step(newEvent, links_hadCalo, out_hadCalo, mux);
0340         emCaloRegionizer_.step(newEvent, intercepted_links, out_emCalo, mux);
0341       }
0342       break;
0343     case interceptPostFifo:
0344       assert(nem_ > 0 && ncalo_ > 0 && !links_hadCalo.empty() && links_emCalo.empty());
0345       assert(interceptor_.get());
0346       {
0347         if (mux) {
0348           std::vector<l1ct::HadCaloObjEmu> hadNoMux;
0349           hadCaloRegionizer_.step(newEvent, links_hadCalo, hadNoMux, /*mux=*/false);
0350           std::vector<l1ct::EmCaloObjEmu> emNoMux(hadNoMux.size());
0351           interceptor_->select_or_clear(hadNoMux, emNoMux);
0352           ret = hadCaloRegionizer_.muxonly_step(newEvent, /*flush=*/false, hadNoMux, out_hadCalo);
0353           emCaloRegionizer_.muxonly_step(newEvent, /*flush=*/true, emNoMux, out_emCalo);
0354         } else {
0355           ret = hadCaloRegionizer_.step(newEvent, links_hadCalo, out_hadCalo, /*mux=*/false);
0356           interceptor_->select_or_clear(out_hadCalo, out_emCalo);
0357         }
0358       }
0359       break;
0360   }
0361   return ret;
0362 }
0363 
0364 void l1ct::MultififoRegionizerEmulator::fillLinks(unsigned int iclock,
0365                                                   const l1ct::RegionizerDecodedInputs& in,
0366                                                   std::vector<l1ct::TkObjEmu>& links) {
0367   if (ntk_ == 0)
0368     return;
0369   links.resize(NTK_SECTORS * NTK_LINKS * (nendcaps_ ? nendcaps_ : 2));
0370   for (unsigned int is = 0, idx = 0; is < NTK_SECTORS * (nendcaps_ ? nendcaps_ : 2); ++is) {  // tf sectors
0371     const l1ct::DetectorSector<l1ct::TkObjEmu>& sec = in.track[is];
0372     for (unsigned int il = 0; il < NTK_LINKS; ++il, ++idx) {
0373       unsigned int ioffs = iclock * NTK_LINKS + il;
0374       if (ioffs < sec.size() && iclock < nclocks_ - 1) {
0375         links[idx] = sec[ioffs];
0376       } else {
0377         links[idx].clear();
0378       }
0379     }
0380   }
0381 }
0382 
0383 template <typename T>
0384 void l1ct::MultififoRegionizerEmulator::fillCaloLinks_(unsigned int iclock,
0385                                                        const std::vector<DetectorSector<T>>& in,
0386                                                        std::vector<T>& links) {
0387   unsigned int NLINKS =
0388       (nendcaps_ ? NCALO_LINKS : (typeid(T) == typeid(l1ct::HadCaloObjEmu) ? HCAL_LINKS : ECAL_LINKS));
0389   links.resize(NCALO_SECTORS * (nendcaps_ ? nendcaps_ : 1) * NLINKS);
0390   for (unsigned int is = 0, idx = 0; is < NCALO_SECTORS * (nendcaps_ ? nendcaps_ : 1); ++is) {
0391     for (unsigned int il = 0; il < NLINKS; ++il, ++idx) {
0392       unsigned int ioffs = iclock * NLINKS + il;
0393       if (ioffs < in[is].size() && iclock < nclocks_ - 1) {
0394         links[idx] = in[is][ioffs];
0395       } else {
0396         links[idx].clear();
0397       }
0398     }
0399   }
0400 }
0401 
0402 void l1ct::MultififoRegionizerEmulator::fillLinks(unsigned int iclock,
0403                                                   const l1ct::RegionizerDecodedInputs& in,
0404                                                   std::vector<l1ct::HadCaloObjEmu>& links) {
0405   if (ncalo_ == 0)
0406     return;
0407   fillCaloLinks_(iclock, in.hadcalo, links);
0408 }
0409 
0410 void l1ct::MultififoRegionizerEmulator::fillLinks(unsigned int iclock,
0411                                                   const l1ct::RegionizerDecodedInputs& in,
0412                                                   std::vector<l1ct::EmCaloObjEmu>& links) {
0413   if (nem_ == 0 || emInterceptMode_ != noIntercept)
0414     return;
0415   fillCaloLinks_(iclock, in.emcalo, links);
0416 }
0417 
0418 void l1ct::MultififoRegionizerEmulator::fillLinks(unsigned int iclock,
0419                                                   const l1ct::RegionizerDecodedInputs& in,
0420                                                   std::vector<l1ct::MuObjEmu>& links) {
0421   if (nmu_ == 0)
0422     return;
0423   assert(NMU_LINKS == 1);
0424   links.resize(NMU_LINKS);
0425   if (iclock < in.muon.size() && iclock < nclocks_ - 1) {
0426     links[0] = in.muon[iclock];
0427   } else {
0428     links[0].clear();
0429   }
0430 }
0431 
0432 void l1ct::MultififoRegionizerEmulator::toFirmware(const std::vector<l1ct::TkObjEmu>& emu,
0433                                                    TkObj fw[/*NTK_SECTORS][NTK_LINKS*/]) {
0434   if (ntk_ == 0)
0435     return;
0436   assert(emu.size() == NTK_SECTORS * NTK_LINKS * (nendcaps_ ? nendcaps_ : 2));
0437   for (unsigned int is = 0, idx = 0; is < NTK_SECTORS * (nendcaps_ ? nendcaps_ : 2); ++is) {  // tf sectors
0438     for (unsigned int il = 0; il < NTK_LINKS; ++il, ++idx) {
0439       fw[is * NTK_LINKS + il] = emu[idx];
0440     }
0441   }
0442 }
0443 void l1ct::MultififoRegionizerEmulator::toFirmware(const std::vector<l1ct::HadCaloObjEmu>& emu,
0444                                                    HadCaloObj fw[/*NCALO_SECTORS*NCALO_LINKS*/]) {
0445   if (ncalo_ == 0)
0446     return;
0447   unsigned int NLINKS = (nendcaps_ ? NCALO_LINKS * nendcaps_ : HCAL_LINKS);
0448   assert(emu.size() == NCALO_SECTORS * NLINKS);
0449   for (unsigned int is = 0, idx = 0; is < NCALO_SECTORS * (nendcaps_ ? nendcaps_ : 1); ++is) {  // calo sectors
0450     for (unsigned int il = 0; il < NLINKS; ++il, ++idx) {
0451       fw[is * NLINKS + il] = emu[idx];
0452     }
0453   }
0454 }
0455 
0456 void l1ct::MultififoRegionizerEmulator::toFirmware(const std::vector<l1ct::EmCaloObjEmu>& emu,
0457                                                    EmCaloObj fw[/*NCALO_SECTORS*NCALO_LINKS*/]) {
0458   if (nem_ == 0)
0459     return;
0460   unsigned int NLINKS = (nendcaps_ ? NCALO_LINKS * nendcaps_ : ECAL_LINKS);
0461   assert(emu.size() == NCALO_SECTORS * NLINKS);
0462   for (unsigned int is = 0, idx = 0; is < NCALO_SECTORS * (nendcaps_ ? nendcaps_ : 1); ++is) {  // calo sectors
0463     for (unsigned int il = 0; il < NLINKS; ++il, ++idx) {
0464       fw[is * NLINKS + il] = emu[idx];
0465     }
0466   }
0467 }
0468 
0469 void l1ct::MultififoRegionizerEmulator::toFirmware(const std::vector<l1ct::MuObjEmu>& emu, MuObj fw[/*NMU_LINKS*/]) {
0470   if (nmu_ == 0)
0471     return;
0472   assert(emu.size() == NMU_LINKS);
0473   for (unsigned int il = 0, idx = 0; il < NMU_LINKS; ++il, ++idx) {
0474     fw[il] = emu[idx];
0475   }
0476 }
0477 
0478 void l1ct::MultififoRegionizerEmulator::destream(int iclock,
0479                                                  const std::vector<l1ct::TkObjEmu>& tk_out,
0480                                                  const std::vector<l1ct::EmCaloObjEmu>& em_out,
0481                                                  const std::vector<l1ct::HadCaloObjEmu>& calo_out,
0482                                                  const std::vector<l1ct::MuObjEmu>& mu_out,
0483                                                  PFInputRegion& out) {
0484   if (ntk_)
0485     tkRegionizer_.destream(iclock, tk_out, out.track);
0486   if (ncalo_)
0487     hadCaloRegionizer_.destream(iclock, calo_out, out.hadcalo);
0488   if (nem_)
0489     emCaloRegionizer_.destream(iclock, em_out, out.emcalo);
0490   if (nmu_)
0491     muRegionizer_.destream(iclock, mu_out, out.muon);
0492 }
0493 
0494 void l1ct::MultififoRegionizerEmulator::run(const RegionizerDecodedInputs& in, std::vector<PFInputRegion>& out) {
0495   if (!init_)
0496     initSectorsAndRegions(in, out);
0497   tkRegionizer_.reset();
0498   emCaloRegionizer_.reset();
0499   hadCaloRegionizer_.reset();
0500   muRegionizer_.reset();
0501   std::vector<l1ct::TkObjEmu> tk_links_in, tk_out;
0502   std::vector<l1ct::EmCaloObjEmu> em_links_in, em_out;
0503   std::vector<l1ct::HadCaloObjEmu> calo_links_in, calo_out;
0504   std::vector<l1ct::MuObjEmu> mu_links_in, mu_out;
0505 
0506   // read and sort the inputs
0507   for (unsigned int iclock = 0; iclock < nclocks_; ++iclock) {
0508     fillLinks(iclock, in, tk_links_in);
0509     fillLinks(iclock, in, em_links_in);
0510     fillLinks(iclock, in, calo_links_in);
0511     fillLinks(iclock, in, mu_links_in);
0512 
0513     bool newevt = (iclock == 0), mux = true;
0514     step(newevt, tk_links_in, calo_links_in, em_links_in, mu_links_in, tk_out, calo_out, em_out, mu_out, mux);
0515   }
0516 
0517   // set up an empty event
0518   for (auto& l : tk_links_in)
0519     l.clear();
0520   for (auto& l : em_links_in)
0521     l.clear();
0522   for (auto& l : calo_links_in)
0523     l.clear();
0524   for (auto& l : mu_links_in)
0525     l.clear();
0526 
0527   // read and put the inputs in the regions
0528   assert(out.size() == nregions_);
0529   for (unsigned int iclock = 0; iclock < nclocks_; ++iclock) {
0530     bool newevt = (iclock == 0), mux = true;
0531     step(newevt, tk_links_in, calo_links_in, em_links_in, mu_links_in, tk_out, calo_out, em_out, mu_out, mux);
0532 
0533     unsigned int ireg = iclock / (outii_ + pauseii_);
0534     if ((iclock % (outii_ + pauseii_)) >= outii_)
0535       continue;
0536     if (ireg >= nregions_)
0537       break;
0538 
0539     if (streaming_) {
0540       destream(iclock, tk_out, em_out, calo_out, mu_out, out[ireg]);
0541     } else {
0542       if (iclock % outii_ == 0) {
0543         out[ireg].track = tk_out;
0544         out[ireg].emcalo = em_out;
0545         out[ireg].hadcalo = calo_out;
0546         out[ireg].muon = mu_out;
0547       }
0548     }
0549   }
0550 
0551   tkRegionizer_.reset();
0552   emCaloRegionizer_.reset();
0553   hadCaloRegionizer_.reset();
0554   muRegionizer_.reset();
0555 }