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