Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-15 23:40:47

0001 #include "L1Trigger/TrackFindingTracklet/interface/VMRouterCM.h"
0002 #include "L1Trigger/TrackFindingTracklet/interface/Settings.h"
0003 #include "L1Trigger/TrackFindingTracklet/interface/Globals.h"
0004 #include "L1Trigger/TrackFindingTracklet/interface/VMStubTE.h"
0005 #include "L1Trigger/TrackFindingTracklet/interface/InputLinkMemory.h"
0006 #include "L1Trigger/TrackFindingTracklet/interface/AllStubsMemory.h"
0007 #include "L1Trigger/TrackFindingTracklet/interface/AllInnerStubsMemory.h"
0008 #include "L1Trigger/TrackFindingTracklet/interface/VMStubsMEMemory.h"
0009 #include "L1Trigger/TrackFindingTracklet/interface/VMStubsTEMemory.h"
0010 
0011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0012 #include "FWCore/Utilities/interface/Exception.h"
0013 
0014 using namespace std;
0015 using namespace trklet;
0016 
0017 VMRouterCM::VMRouterCM(string name, Settings const& settings, Globals* global)
0018     : ProcessBase(name, settings, global),
0019       meTable_(settings),
0020       diskTable_(settings),
0021       meTableOld_(settings),
0022       diskTableOld_(settings),
0023       innerTable_(settings),
0024       innerOverlapTable_(settings),
0025       innerThirdTable_(settings) {
0026   layerdisk_ = initLayerDisk(4);
0027 
0028   unsigned int region = name[9] - 'A';
0029   assert(region < settings_.nallstubs(layerdisk_));
0030 
0031   overlapbits_ = 7;
0032   nextrabits_ = overlapbits_ - (settings_.nbitsallstubs(layerdisk_) + settings_.nbitsvmme(layerdisk_));
0033 
0034   // The TrackletProcessorDisplaced currently uses the older LUTs that were
0035   // used with the non-combined modules. To maintain compatibility, we
0036   // initialize these older LUTs below, which are used for the triplet seeds in
0037   // the "execute" method. Once the TrackletProcessorDisplaced is updated,
0038   // these can be removed.
0039 
0040   meTable_.initVMRTable(layerdisk_, TrackletLUT::VMRTableType::me, region);            //used for ME and outer TE barrel
0041   meTableOld_.initVMRTable(layerdisk_, TrackletLUT::VMRTableType::me, region, false);  //used for ME and outer TE barrel
0042 
0043   if (layerdisk_ == LayerDisk::D1 || layerdisk_ == LayerDisk::D2 || layerdisk_ == LayerDisk::D4) {
0044     diskTable_.initVMRTable(layerdisk_, TrackletLUT::VMRTableType::disk, region);  //outer disk used by D1, D2, and D4
0045     diskTableOld_.initVMRTable(
0046         layerdisk_, TrackletLUT::VMRTableType::disk, region, false);  //outer disk used by D1, D2, and D4
0047   }
0048 
0049   if (layerdisk_ == LayerDisk::L1 || layerdisk_ == LayerDisk::L2 || layerdisk_ == LayerDisk::L3 ||
0050       layerdisk_ == LayerDisk::L5 || layerdisk_ == LayerDisk::D1 || layerdisk_ == LayerDisk::D3) {
0051     innerTable_.initVMRTable(
0052         layerdisk_, TrackletLUT::VMRTableType::inner, region, false);  //projection to next layer/disk
0053   }
0054 
0055   if (layerdisk_ == LayerDisk::L1 || layerdisk_ == LayerDisk::L2) {
0056     innerOverlapTable_.initVMRTable(
0057         layerdisk_, TrackletLUT::VMRTableType::inneroverlap, region, false);  //projection to disk from layer
0058   }
0059 
0060   if (layerdisk_ == LayerDisk::L2 || layerdisk_ == LayerDisk::L3 || layerdisk_ == LayerDisk::L5 ||
0061       layerdisk_ == LayerDisk::D1) {
0062     innerThirdTable_.initVMRTable(
0063         layerdisk_, TrackletLUT::VMRTableType::innerthird, region, false);  //projection to third layer/disk
0064   }
0065 
0066   nbitszfinebintable_ = settings_.vmrlutzbits(layerdisk_);
0067   nbitsrfinebintable_ = settings_.vmrlutrbits(layerdisk_);
0068 
0069   nvmmebins_ = settings_.NLONGVMBINS() * ((layerdisk_ >= N_LAYER) ? 2 : 1);  //number of long z/r bins in VM
0070 }
0071 
0072 void VMRouterCM::addOutput(MemoryBase* memory, string output) {
0073   if (settings_.writetrace()) {
0074     edm::LogVerbatim("Tracklet") << "In " << name_ << " adding output to " << memory->getName() << " to output "
0075                                  << output;
0076   }
0077 
0078   if (output == "allinnerstubout") {
0079     AllInnerStubsMemory* tmp = dynamic_cast<AllInnerStubsMemory*>(memory);
0080     assert(tmp != nullptr);
0081     char memtype = memory->getName().back();
0082     allinnerstubs_.emplace_back(memtype, tmp);
0083     return;
0084   }
0085 
0086   if (output.substr(0, 10) == "allstubout") {
0087     AllStubsMemory* tmp = dynamic_cast<AllStubsMemory*>(memory);
0088     allstubs_.push_back(tmp);
0089     return;
0090   }
0091 
0092   if (output.substr(0, 9) == "vmstubout") {
0093     if (memory->getName().substr(3, 2) == "TE") {
0094       VMStubsTEMemory* tmp = dynamic_cast<VMStubsTEMemory*>(memory);
0095       int i = output.find_last_of('_');
0096       unsigned int iseed = std::stoi(output.substr(i + 1));
0097       assert(iseed < N_SEED);
0098 
0099       // This flag is used to replicate the behavior of the old VMRouter for
0100       // the case of the triplet seeds.
0101       const bool isTripletSeed = (iseed >= L2L3L4);
0102 
0103       // seedtype, vmbin, and inner are only used in the case of the triplet
0104       // seeds.
0105       char seedtype = memory->getName().substr(11, 1)[0];
0106       unsigned int pos = 12;
0107       int vmbin = memory->getName().substr(pos, 1)[0] - '0';
0108       pos++;
0109       if (pos < memory->getName().size()) {
0110         if (memory->getName().substr(pos, 1)[0] != 'n') {
0111           vmbin = vmbin * 10 + memory->getName().substr(pos, 1)[0] - '0';
0112           pos++;
0113         }
0114       }
0115       unsigned int inner = 1;
0116       if (seedtype < 'I') {
0117         if (layerdisk_ == LayerDisk::L1 || layerdisk_ == LayerDisk::L3 || layerdisk_ == LayerDisk::L5 ||
0118             layerdisk_ == LayerDisk::D1 || layerdisk_ == LayerDisk::D3)
0119           inner = 0;
0120       } else if (seedtype < 'M') {
0121         if (layerdisk_ == LayerDisk::L2)
0122           inner = 0;
0123       } else if (seedtype <= 'Z') {
0124         if (layerdisk_ == LayerDisk::L1 || layerdisk_ == LayerDisk::L2)
0125           inner = 0;
0126       } else if (seedtype < 'o' && seedtype >= 'a') {
0127         if (layerdisk_ == LayerDisk::L2)
0128           inner = 0;
0129       } else if (seedtype > 'o' && seedtype <= 'z') {
0130         inner = 2;
0131       } else {
0132         throw cms::Exception("LogicError") << __FILE__ << " " << __LINE__ << " Invalid seeding!";
0133       }
0134 
0135       int seedindex = -1;
0136       for (unsigned int k = 0; k < vmstubsTEPHI_.size(); k++) {
0137         if (vmstubsTEPHI_[k].seednumber == iseed) {
0138           seedindex = k;
0139         }
0140       }
0141       if (seedindex == -1) {
0142         seedindex = vmstubsTEPHI_.size();
0143         vector<VMStubsTEMemory*> avectmp;
0144         vector<vector<VMStubsTEMemory*> > vectmp(!isTripletSeed ? 1 : settings_.nvmte(inner, iseed), avectmp);
0145         VMStubsTEPHICM atmp(iseed, inner, vectmp);
0146         vmstubsTEPHI_.push_back(atmp);
0147       }
0148       if (!isTripletSeed) {
0149         tmp->resize(settings_.NLONGVMBINS() * settings_.nvmte(1, iseed));
0150         vmstubsTEPHI_[seedindex].vmstubmem[0].push_back(tmp);
0151       } else {
0152         vmstubsTEPHI_[seedindex].vmstubmem[(vmbin - 1) & (settings_.nvmte(inner, iseed) - 1)].push_back(tmp);
0153       }
0154 
0155     } else if (memory->getName().substr(3, 2) == "ME") {
0156       VMStubsMEMemory* tmp = dynamic_cast<VMStubsMEMemory*>(memory);
0157       assert(tmp != nullptr);
0158       tmp->resize(nvmmebins_ * settings_.nvmme(layerdisk_));
0159       vmstubsMEPHI_.push_back(tmp);
0160     } else {
0161       throw cms::Exception("LogicError") << __FILE__ << " " << __LINE__ << " memory: " << memory->getName()
0162                                          << " => should never get here!";
0163     }
0164 
0165     return;
0166   }
0167 
0168   throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find output : " << output;
0169 }
0170 
0171 void VMRouterCM::addInput(MemoryBase* memory, string input) {
0172   if (settings_.writetrace()) {
0173     edm::LogVerbatim("Tracklet") << "In " << name_ << " adding input from " << memory->getName() << " to input "
0174                                  << input;
0175   }
0176   if (input == "stubin") {
0177     InputLinkMemory* tmp1 = dynamic_cast<InputLinkMemory*>(memory);
0178     assert(tmp1 != nullptr);
0179     if (tmp1 != nullptr) {
0180       stubinputs_.push_back(tmp1);
0181     }
0182     return;
0183   }
0184   throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find input : " << input;
0185 }
0186 
0187 void VMRouterCM::execute(unsigned int) {
0188   unsigned int allStubCounter = 0;
0189 
0190   //bool print = getName() == "VMR_D1PHIB" && iSector == 3;
0191   //print = false;
0192 
0193   //Loop over the input stubs
0194   for (auto& stubinput : stubinputs_) {
0195     for (unsigned int i = 0; i < stubinput->nStubs(); i++) {
0196       if (allStubCounter > settings_.maxStep("VMR"))
0197         continue;
0198       if (allStubCounter >= (1 << N_BITSMEMADDRESS))
0199         continue;
0200 
0201       Stub* stub = stubinput->getStub(i);
0202 
0203       //Note - below information is not part of the stub, but rather from which input memory
0204       //we are reading
0205       bool negdisk = (stub->disk().value() < 0);
0206 
0207       //use &127 to make sure we fit into the number of bits -
0208       //though we should have protected against overflows above
0209       FPGAWord allStubIndex(allStubCounter & ((1 << N_BITSMEMADDRESS) - 1), N_BITSMEMADDRESS, true, __LINE__, __FILE__);
0210 
0211       //TODO - should not be needed - but need to migrate some other pieces of code before removing
0212       stub->setAllStubIndex(allStubCounter);
0213       //TODO - should not be needed - but need to migrate some other pieces of code before removing
0214       stub->l1tstub()->setAllStubIndex(allStubCounter);
0215 
0216       allStubCounter++;
0217 
0218       for (auto& allstub : allstubs_) {
0219         allstub->addStub(stub);
0220         if (settings_.debugTracklet()) {
0221           edm::LogVerbatim("Tracklet") << getName() << " adding stub to " << allstub->getName();
0222         }
0223       }
0224 
0225       FPGAWord iphi = stub->phicorr();
0226       unsigned int iphipos = iphi.bits(iphi.nbits() - (settings_.nbitsallstubs(layerdisk_) + N_PHIBITS), N_PHIBITS);
0227 
0228       unsigned int phicutmax = 4;
0229       unsigned int phicutmin = 4;
0230 
0231       if (layerdisk_ != 0) {
0232         phicutmax = 6;
0233         phicutmin = 2;
0234       }
0235 
0236       //Fill inner allstubs memories - in HLS this is the same write to multiple memories
0237       for (auto& allstub : allinnerstubs_) {
0238         char memtype = allstub.first;
0239         if (memtype == 'R' && iphipos < phicutmax)
0240           continue;
0241         if (memtype == 'L' && iphipos >= phicutmin)
0242           continue;
0243         if (memtype == 'A' && iphipos < 4)
0244           continue;
0245         if (memtype == 'B' && iphipos >= 4)
0246           continue;
0247         if (memtype == 'E' && iphipos >= 4)
0248           continue;
0249         if (memtype == 'F' && iphipos < 4)
0250           continue;
0251         if (memtype == 'C' && iphipos >= 4)
0252           continue;
0253         if (memtype == 'D' && iphipos < 4)
0254           continue;
0255 
0256         int absz = std::abs(stub->z().value());
0257         if (layerdisk_ == LayerDisk::L2 && absz < VMROUTERCUTZL2 / settings_.kz(layerdisk_))
0258           continue;
0259         if ((layerdisk_ == LayerDisk::L3 || layerdisk_ == LayerDisk::L5) &&
0260             absz > VMROUTERCUTZL1L3L5 / settings_.kz(layerdisk_))
0261           continue;
0262         if ((layerdisk_ == LayerDisk::D1 || layerdisk_ == LayerDisk::D3) &&
0263             stub->r().value() > VMROUTERCUTRD1D3 / settings_.kr())
0264           continue;
0265         if ((layerdisk_ == LayerDisk::D1 || layerdisk_ == LayerDisk::D3) && stub->r().value() < 2 * int(N_DSS_MOD))
0266           continue;
0267         if (layerdisk_ == LayerDisk::L1) {
0268           if (memtype == 'M' || memtype == 'R' || memtype == 'L') {
0269             if (absz < VMROUTERCUTZL1 / settings_.kz(layerdisk_))
0270               continue;
0271           } else {
0272             if (absz > VMROUTERCUTZL1L3L5 / settings_.kz(layerdisk_))
0273               continue;
0274           }
0275         }
0276 
0277         if (settings_.debugTracklet()) {
0278           edm::LogVerbatim("Tracklet") << getName() << " adding stub to " << allstub.second->getName();
0279         }
0280 
0281         allstub.second->addStub(stub);
0282       }
0283 
0284       //Fill all the ME VM memories
0285       unsigned int ivm =
0286           iphi.bits(iphi.nbits() - (settings_.nbitsallstubs(layerdisk_) + settings_.nbitsvmme(layerdisk_)),
0287                     settings_.nbitsvmme(layerdisk_));
0288 
0289       //Calculate the z and r position for the vmstub
0290 
0291       //Take the top nbitszfinebintable_ bits of the z coordinate
0292       int indexz = (stub->z().value() >> (stub->z().nbits() - nbitszfinebintable_)) & ((1 << nbitszfinebintable_) - 1);
0293       int indexr = -1;
0294       if (layerdisk_ > (N_LAYER - 1)) {
0295         if (negdisk) {
0296           indexz = ((1 << nbitszfinebintable_) - 1) - indexz;
0297         }
0298         indexr = stub->r().value();
0299         if (stub->isPSmodule()) {
0300           indexr = stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_);
0301         }
0302       } else {
0303         //Take the top nbitsfinebintable_ bits of the z coordinate. The & is to handle the negative z values.
0304         indexr = (stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_)) & ((1 << nbitsrfinebintable_) - 1);
0305       }
0306 
0307       assert(indexz >= 0);
0308       assert(indexr >= 0);
0309       assert(indexz < (1 << nbitszfinebintable_));
0310       assert(indexr < (1 << nbitsrfinebintable_));
0311 
0312       int melut = meTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
0313 
0314       assert(melut >= 0);
0315 
0316       // The following indices are calculated in the same way as in the old
0317       // VMRouter and are only used for the triplet seeds.
0318       int indexzOld =
0319           (((1 << (stub->z().nbits() - 1)) + stub->z().value()) >> (stub->z().nbits() - nbitszfinebintable_));
0320       int indexrOld = -1;
0321       if (layerdisk_ > (N_LAYER - 1)) {
0322         if (negdisk) {
0323           indexzOld = (1 << nbitszfinebintable_) - indexzOld;
0324         }
0325         indexrOld = stub->r().value();
0326         if (stub->isPSmodule()) {
0327           indexrOld = stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_);
0328         }
0329       } else {
0330         //Take the top nbitsfinebintable_ bits of the z coordinate. The & is to handle the negative z values.
0331         indexrOld = (((1 << (stub->r().nbits() - 1)) + stub->r().value()) >> (stub->r().nbits() - nbitsrfinebintable_));
0332       }
0333 
0334       assert(indexzOld >= 0);
0335       assert(indexrOld >= 0);
0336       assert(indexzOld < (1 << nbitszfinebintable_));
0337       assert(indexrOld < (1 << nbitsrfinebintable_));
0338 
0339       int melutOld = meTableOld_.lookup((indexzOld << nbitsrfinebintable_) + indexrOld);
0340 
0341       assert(melutOld >= 0);
0342 
0343       int vmbin = melut >> NFINERZBITS;
0344       if (negdisk)
0345         vmbin += (1 << NFINERZBITS);
0346       int rzfine = melut & ((1 << NFINERZBITS) - 1);
0347 
0348       // pad disk PS bend word with a '0' in MSB so that all disk bends have 4 bits (for HLS compatibility)
0349       int nbendbits = stub->bend().nbits();
0350       if (layerdisk_ >= N_LAYER)
0351         nbendbits = settings_.nbendbitsmedisk();
0352 
0353       VMStubME vmstub(
0354           stub,
0355           stub->iphivmFineBins(settings_.nbitsallstubs(layerdisk_) + settings_.nbitsvmme(layerdisk_), NFINERZBITS),
0356           FPGAWord(rzfine, NFINERZBITS, true, __LINE__, __FILE__),
0357           FPGAWord(stub->bend().value(), nbendbits, true, __LINE__, __FILE__),
0358           allStubIndex);
0359 
0360       unsigned int nmems = vmstubsMEPHI_.size();
0361 
0362       for (unsigned int i = 0; i < nmems; i++) {  // allows multiple VMStubs to be written for duplicated MPs
0363         if (vmstubsMEPHI_[i] != nullptr)
0364           vmstubsMEPHI_[i]->addStub(vmstub, ivm * nvmmebins_ + vmbin);
0365       }
0366 
0367       for (auto& ivmstubTEPHI : vmstubsTEPHI_) {
0368         unsigned int iseed = ivmstubTEPHI.seednumber;
0369 
0370         // This flag is used to replicate the behavior of the old VMRouter for
0371         // the case of the triplet seeds.
0372         const bool isTripletSeed = (iseed >= L2L3L4);
0373 
0374         if (!isTripletSeed && layerdisk_ >= N_LAYER && (!stub->isPSmodule()))
0375           continue;
0376         unsigned int inner = (!isTripletSeed ? 1 : ivmstubTEPHI.stubposition);
0377         unsigned int lutwidth = settings_.lutwidthtab(inner, iseed);
0378         if (settings_.extended()) {
0379           lutwidth = settings_.lutwidthtabextended(inner, iseed);
0380         }
0381 
0382         int lutval = -999;
0383 
0384         if (inner > 0) {
0385           if (layerdisk_ < N_LAYER) {
0386             lutval = (!isTripletSeed ? melut : melutOld);
0387           } else {
0388             if (inner == 2 && iseed == Seed::L2L3D1) {
0389               lutval = 0;
0390               if (stub->r().value() < 10) {
0391                 lutval = 8 * (1 + (stub->r().value() >> 2));
0392               } else {
0393                 if (stub->r().value() < settings_.rmindiskl3overlapvm() / settings_.kr()) {
0394                   lutval = -1;
0395                 }
0396               }
0397             } else {
0398               lutval = (!isTripletSeed ? diskTable_.lookup((indexz << nbitsrfinebintable_) + indexr)
0399                                        : diskTableOld_.lookup((indexzOld << nbitsrfinebintable_) + indexrOld));
0400               if (lutval == 0)
0401                 continue;
0402             }
0403           }
0404           if (lutval == -1)
0405             continue;
0406         } else {
0407           if (iseed < Seed::L1D1 || iseed > Seed::L2D1) {
0408             lutval = innerTable_.lookup((indexzOld << nbitsrfinebintable_) + indexrOld);
0409           } else {
0410             lutval = innerOverlapTable_.lookup((indexzOld << nbitsrfinebintable_) + indexrOld);
0411           }
0412           if (lutval == -1)
0413             continue;
0414           if (settings_.extended() &&
0415               (iseed == Seed::L3L4 || iseed == Seed::L5L6 || iseed == Seed::D1D2 || iseed == Seed::L2L3D1)) {
0416             int lutval2 = innerThirdTable_.lookup((indexzOld << nbitsrfinebintable_) + indexrOld);
0417             if (lutval2 != -1) {
0418               const auto& lutshift = innerTable_.nbits();  // should be same for all inner tables
0419               lutval += (lutval2 << lutshift);
0420             }
0421           }
0422         }
0423 
0424         assert(lutval >= 0);
0425 
0426         FPGAWord binlookup(lutval, lutwidth, true, __LINE__, __FILE__);
0427 
0428         if (binlookup.value() < 0)
0429           continue;
0430 
0431         unsigned int ivmte =
0432             iphi.bits(iphi.nbits() - (settings_.nbitsallstubs(layerdisk_) + settings_.nbitsvmte(inner, iseed)),
0433                       settings_.nbitsvmte(inner, iseed));
0434 
0435         int bin = -1;
0436         if (inner != 0) {
0437           bin = binlookup.value() >> settings_.NLONGVMBITS();
0438           unsigned int tmp = binlookup.value() & (settings_.NLONGVMBINS() - 1);  //three bits in outer layers
0439           binlookup.set(tmp, settings_.NLONGVMBITS(), true, __LINE__, __FILE__);
0440         }
0441 
0442         FPGAWord finephi = stub->iphivmFineBins(settings_.nphireg(inner, iseed), settings_.nfinephi(inner, iseed));
0443 
0444         VMStubTE tmpstub(stub, finephi, stub->bend(), binlookup, allStubIndex);
0445 
0446         unsigned int nmem = ivmstubTEPHI.vmstubmem[!isTripletSeed ? 0 : ivmte].size();
0447         assert(nmem > 0);
0448 
0449         for (unsigned int l = 0; l < nmem; l++) {
0450           if (settings_.debugTracklet()) {
0451             edm::LogVerbatim("Tracklet") << getName() << " try adding stub to "
0452                                          << ivmstubTEPHI.vmstubmem[!isTripletSeed ? 0 : ivmte][l]->getName()
0453                                          << " bin=" << bin << " ivmte " << ivmte << " finephi " << finephi.value()
0454                                          << " regions bits " << settings_.nphireg(1, iseed) << " finephibits "
0455                                          << settings_.nfinephi(1, iseed);
0456           }
0457           if (!isTripletSeed)
0458             ivmstubTEPHI.vmstubmem[0][l]->addVMStub(tmpstub, bin, ivmte);
0459           else {
0460             if (inner == 0) {
0461               ivmstubTEPHI.vmstubmem[ivmte][l]->addVMStub(tmpstub);
0462             } else {
0463               ivmstubTEPHI.vmstubmem[ivmte][l]->addVMStub(tmpstub, bin, 0, false);
0464             }
0465           }
0466         }
0467       }
0468     }
0469   }
0470 }