Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-07-07 22:33:40

0001 #include "L1Trigger/TrackFindingTracklet/interface/TrackletProcessor.h"
0002 #include "L1Trigger/TrackFindingTracklet/interface/Settings.h"
0003 #include "L1Trigger/TrackFindingTracklet/interface/Globals.h"
0004 #include "L1Trigger/TrackFindingTracklet/interface/AllStubsMemory.h"
0005 #include "L1Trigger/TrackFindingTracklet/interface/AllInnerStubsMemory.h"
0006 #include "L1Trigger/TrackFindingTracklet/interface/Util.h"
0007 #include "L1Trigger/TrackFindingTracklet/interface/IMATH_TrackletCalculator.h"
0008 
0009 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0010 #include "FWCore/Utilities/interface/Exception.h"
0011 #include "DataFormats/Math/interface/deltaPhi.h"
0012 
0013 #include <utility>
0014 #include <tuple>
0015 
0016 using namespace std;
0017 using namespace trklet;
0018 
0019 TrackletProcessor::TrackletProcessor(string name, Settings const& settings, Globals* globals)
0020     : TrackletCalculatorBase(name, settings, globals),
0021       tebuffer_(CircularBuffer<TEData>(3), 0, 0, 0, 0),
0022       pttableinner_(settings),
0023       pttableouter_(settings),
0024       useregiontable_(settings),
0025       innerTable_(settings),
0026       innerOverlapTable_(settings) {
0027   iAllStub_ = -1;
0028 
0029   for (unsigned int ilayer = 0; ilayer < N_LAYER; ilayer++) {
0030     vector<TrackletProjectionsMemory*> tmp(settings_.nallstubs(ilayer), nullptr);
0031     trackletprojlayers_.push_back(tmp);
0032   }
0033 
0034   for (unsigned int idisk = 0; idisk < N_DISK; idisk++) {
0035     vector<TrackletProjectionsMemory*> tmp(settings_.nallstubs(idisk + N_LAYER), nullptr);
0036     trackletprojdisks_.push_back(tmp);
0037   }
0038 
0039   outervmstubs_ = nullptr;
0040 
0041   initLayerDisksandISeed(layerdisk1_, layerdisk2_, iSeed_);
0042 
0043   double rmin = -1.0;
0044   double rmax = -1.0;
0045 
0046   if (iSeed_ == Seed::L1L2 || iSeed_ == Seed::L2L3 || iSeed_ == Seed::L3L4 || iSeed_ == Seed::L5L6) {
0047     rmin = settings_.rmean(layerdisk1_);
0048     rmax = settings_.rmean(layerdisk2_);
0049   } else {
0050     if (iSeed_ == Seed::L1D1) {
0051       rmax = settings_.rmaxdiskl1overlapvm();
0052       rmin = settings_.rmean(layerdisk1_);
0053     } else if (iSeed_ == Seed::L2D1) {
0054       rmax = settings_.rmaxdiskvm();
0055       rmin = settings_.rmean(layerdisk1_);
0056     } else {
0057       rmax = settings_.rmaxdiskvm();
0058       rmin = rmax * settings_.zmean(layerdisk2_ - N_LAYER - 1) / settings_.zmean(layerdisk2_ - N_LAYER);
0059     }
0060   }
0061 
0062   double dphimax = asin(0.5 * settings_.maxrinv() * rmax) - asin(0.5 * settings_.maxrinv() * rmin);
0063 
0064   //number of fine phi bins in sector
0065   int nfinephibins =
0066       settings_.nallstubs(layerdisk2_) * settings_.nvmte(1, iSeed_) * (1 << settings_.nfinephi(1, iSeed_));
0067   double dfinephi = settings_.dphisectorHG() / nfinephibins;
0068 
0069   nbitsfinephi_ = settings_.nbitsallstubs(layerdisk2_) + settings_.nbitsvmte(1, iSeed_) + settings_.nfinephi(1, iSeed_);
0070 
0071   int nbins = 2.0 * (dphimax / dfinephi + 1.0);
0072 
0073   nbitsfinephidiff_ = log(nbins) / log(2.0) + 1;
0074 
0075   nbitszfinebintable_ = settings_.vmrlutzbits(layerdisk1_);
0076   nbitsrfinebintable_ = settings_.vmrlutrbits(layerdisk1_);
0077 
0078   nbitsrzbin_ = N_RZBITS;
0079   if (iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4)
0080     nbitsrzbin_ = 2;
0081 
0082   innerphibits_ = settings_.nfinephi(0, iSeed_);
0083   outerphibits_ = settings_.nfinephi(1, iSeed_);
0084 
0085   if (layerdisk1_ == LayerDisk::L1 || layerdisk1_ == LayerDisk::L2 || layerdisk1_ == LayerDisk::L3 ||
0086       layerdisk1_ == LayerDisk::L5 || layerdisk1_ == LayerDisk::D1 || layerdisk1_ == LayerDisk::D3) {
0087     innerTable_.initVMRTable(layerdisk1_, TrackletLUT::VMRTableType::inner);  //projection to next layer/disk
0088   }
0089 
0090   if (layerdisk1_ == LayerDisk::L1 || layerdisk1_ == LayerDisk::L2) {
0091     innerOverlapTable_.initVMRTable(layerdisk1_,
0092                                     TrackletLUT::VMRTableType::inneroverlap);  //projection to disk from layer
0093   }
0094 
0095   // set TC index
0096   iTC_ = name_[7] - 'A';
0097   assert(iTC_ >= 0 && iTC_ < 14);
0098 
0099   TCIndex_ = (iSeed_ << 4) + iTC_;
0100   assert(TCIndex_ >= 0 && TCIndex_ <= (int)settings_.ntrackletmax());
0101 
0102   maxStep_ = settings_.maxStep("TP");
0103 }
0104 
0105 void TrackletProcessor::addOutputProjection(TrackletProjectionsMemory*& outputProj, MemoryBase* memory) {
0106   outputProj = dynamic_cast<TrackletProjectionsMemory*>(memory);
0107   assert(outputProj != nullptr);
0108 }
0109 
0110 void TrackletProcessor::addOutput(MemoryBase* memory, string output) {
0111   if (settings_.writetrace()) {
0112     edm::LogVerbatim("Tracklet") << "In " << name_ << " adding output to " << memory->getName() << " to output "
0113                                  << output;
0114   }
0115   if (output == "trackpar") {
0116     auto* tmp = dynamic_cast<TrackletParametersMemory*>(memory);
0117     assert(tmp != nullptr);
0118     trackletpars_ = tmp;
0119     return;
0120   }
0121 
0122   if (output.substr(0, 7) == "projout") {
0123     //output is on the form 'projoutL2PHIC' or 'projoutD3PHIB'
0124     auto* tmp = dynamic_cast<TrackletProjectionsMemory*>(memory);
0125     assert(tmp != nullptr);
0126 
0127     unsigned int layerdisk = output[8] - '1';   //layer or disk counting from 0
0128     unsigned int phiregion = output[12] - 'A';  //phiregion counting from 0
0129 
0130     if (output[7] == 'L') {
0131       assert(layerdisk < N_LAYER);
0132       assert(phiregion < trackletprojlayers_[layerdisk].size());
0133       //check that phiregion not already initialized
0134       assert(trackletprojlayers_[layerdisk][phiregion] == nullptr);
0135       trackletprojlayers_[layerdisk][phiregion] = tmp;
0136       return;
0137     }
0138 
0139     if (output[7] == 'D') {
0140       assert(layerdisk < N_DISK);
0141       assert(phiregion < trackletprojdisks_[layerdisk].size());
0142       //check that phiregion not already initialized
0143       assert(trackletprojdisks_[layerdisk][phiregion] == nullptr);
0144       trackletprojdisks_[layerdisk][phiregion] = tmp;
0145       return;
0146     }
0147   }
0148 
0149   throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find output : " << output;
0150 }
0151 
0152 void TrackletProcessor::addInput(MemoryBase* memory, string input) {
0153   if (settings_.writetrace()) {
0154     edm::LogVerbatim("Tracklet") << "In " << name_ << " adding input from " << memory->getName() << " to input "
0155                                  << input;
0156   }
0157 
0158   if (input == "outervmstubin") {
0159     auto* tmp = dynamic_cast<VMStubsTEMemory*>(memory);
0160     assert(tmp != nullptr);
0161     outervmstubs_ = tmp;
0162     iAllStub_ = tmp->getName()[11] - 'A';
0163     if (iSeed_ == Seed::L2L3)
0164       iAllStub_ = tmp->getName()[11] - 'I';
0165     if (iSeed_ == Seed::L1D1 || iSeed_ == Seed::L2D1) {
0166       if (tmp->getName()[11] == 'X')
0167         iAllStub_ = 0;
0168       if (tmp->getName()[11] == 'Y')
0169         iAllStub_ = 1;
0170       if (tmp->getName()[11] == 'Z')
0171         iAllStub_ = 2;
0172       if (tmp->getName()[11] == 'W')
0173         iAllStub_ = 3;
0174     }
0175 
0176     unsigned int iTP = getName()[7] - 'A';
0177 
0178     pttableinner_.initTPlut(true, iSeed_, layerdisk1_, layerdisk2_, nbitsfinephidiff_, iTP);
0179     pttableouter_.initTPlut(false, iSeed_, layerdisk1_, layerdisk2_, nbitsfinephidiff_, iTP);
0180 
0181     //need iAllStub_ set before building the table
0182 
0183     useregiontable_.initTPregionlut(
0184         iSeed_, layerdisk1_, layerdisk2_, iAllStub_, nbitsfinephidiff_, nbitsfinephi_, pttableinner_, iTP);
0185 
0186     TrackletEngineUnit teunit(&settings_,
0187                               nbitsfinephi_,
0188                               layerdisk1_,
0189                               layerdisk2_,
0190                               iSeed_,
0191                               nbitsfinephidiff_,
0192                               iAllStub_,
0193                               &pttableinner_,
0194                               &pttableouter_,
0195                               outervmstubs_);
0196 
0197     teunits_.resize(settings_.teunits(iSeed_), teunit);
0198 
0199     return;
0200   }
0201 
0202   if (input == "innerallstubin") {
0203     auto* tmp = dynamic_cast<AllInnerStubsMemory*>(memory);
0204     assert(tmp != nullptr);
0205     if (innerallstubs_.size() == 2) {  //FIXME this should be done with better logic with reading the input stubs
0206       innerallstubs_.insert(innerallstubs_.begin(), tmp);
0207     } else {
0208       innerallstubs_.push_back(tmp);
0209     }
0210 
0211     //FIXME should be done once after all inputs are added
0212     tebuffer_ = tuple<CircularBuffer<TEData>, unsigned int, unsigned int, unsigned int, unsigned int>(
0213         CircularBuffer<TEData>(3), 0, 0, 0, innerallstubs_.size());
0214 
0215     return;
0216   }
0217   if (input == "outerallstubin") {
0218     auto* tmp = dynamic_cast<AllStubsMemory*>(memory);
0219     assert(tmp != nullptr);
0220     outerallstubs_.push_back(tmp);
0221     return;
0222   }
0223   throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find input : " << input;
0224 }
0225 
0226 void TrackletProcessor::execute(unsigned int iSector, double phimin, double phimax) {
0227   bool print = (iSector == 3) && (getName() == "TP_L1L2D");
0228   print = false;
0229 
0230   phimin_ = phimin;
0231   phimax_ = phimax;
0232   iSector_ = iSector;
0233 
0234   if (!settings_.useSeed(iSeed_))
0235     return;
0236 
0237   //Not most elegant solution; but works
0238   int donecount = 0;
0239 
0240   //Consistency checks
0241   assert(iAllStub_ >= 0);
0242   assert(iAllStub_ < (int)settings_.nallstubs(layerdisk2_));
0243   assert(outervmstubs_ != nullptr);
0244 
0245   //used to collect performance data
0246   unsigned int countall = 0;
0247   unsigned int countsel = 0;
0248 
0249   unsigned int countteall = 0;
0250   unsigned int stubpairs = 0;
0251 
0252   unsigned int ntedata = 0;
0253 
0254   unsigned int ninnerstubs = 0;
0255 
0256   //Actual implemenation starts here
0257 
0258   //Reset the tebuffer
0259   std::get<0>(tebuffer_).reset();
0260   std::get<1>(tebuffer_) = 0;
0261   std::get<2>(tebuffer_) = std::get<3>(tebuffer_);
0262 
0263   //Reset the teunits
0264   for (auto& teunit : teunits_) {
0265     teunit.reset();
0266   }
0267 
0268   TEData tedata;
0269   TEData tedata__;
0270   TEData tedata___;
0271   bool goodtedata = false;
0272   bool goodtedata__ = false;
0273   bool goodtedata___ = false;
0274 
0275   bool tebuffernearfull;
0276 
0277   for (unsigned int istep = 0; istep < maxStep_; istep++) {
0278     // These print statements are not on by defaul but can be enabled for the
0279     // comparison with HLS code to track differences.
0280     if (print) {
0281       CircularBuffer<TEData>& tedatabuffer = std::get<0>(tebuffer_);
0282       unsigned int& istub = std::get<1>(tebuffer_);
0283       unsigned int& imem = std::get<2>(tebuffer_);
0284       cout << "istep=" << istep << " TEBuffer: " << istub << " " << imem << " " << tedatabuffer.rptr() << " "
0285            << tedatabuffer.wptr();
0286       int k = -1;
0287       for (auto& teunit : teunits_) {
0288         k++;
0289         cout << " [" << k << " " << teunit.rptr() << " " << teunit.wptr() << " " << teunit.idle() << "]";
0290       }
0291       cout << endl;
0292     }
0293 
0294     CircularBuffer<TEData>& tedatabuffer = std::get<0>(tebuffer_);
0295     tebuffernearfull = tedatabuffer.nearfull();
0296 
0297     //
0298     // First block here checks if there is a teunit with data that should should be used
0299     // to calculate the tracklet parameters
0300     //
0301 
0302     TrackletEngineUnit* teunitptr = nullptr;
0303 
0304     for (auto& teunit : teunits_) {
0305       teunit.setNearFull();
0306       if (!teunit.empty()) {
0307         teunitptr = &teunit;
0308       }
0309     }
0310 
0311     if (teunitptr != nullptr) {
0312       auto stubpair = teunitptr->read();
0313       stubpairs++;
0314 
0315       if (trackletpars_->nTracklets() >= settings_.ntrackletmax()) {
0316         edm::LogVerbatim("Tracklet") << "Will break on too many tracklets in " << getName();
0317         break;
0318       }
0319       countall++;
0320       const Stub* innerFPGAStub = stubpair.first;
0321       const L1TStub* innerStub = innerFPGAStub->l1tstub();
0322 
0323       const Stub* outerFPGAStub = stubpair.second;
0324       const L1TStub* outerStub = outerFPGAStub->l1tstub();
0325 
0326       if (settings_.debugTracklet()) {
0327         edm::LogVerbatim("Tracklet") << "TrackletProcessor execute " << getName() << "[" << iSector_ << "]";
0328       }
0329 
0330       bool accept = false;
0331 
0332       if (iSeed_ == Seed::L1L2 || iSeed_ == Seed::L2L3 || iSeed_ == Seed::L3L4 || iSeed_ == Seed::L5L6) {
0333         accept = barrelSeeding(innerFPGAStub, innerStub, outerFPGAStub, outerStub);
0334       } else if (iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4) {
0335         accept = diskSeeding(innerFPGAStub, innerStub, outerFPGAStub, outerStub);
0336       } else {
0337         accept = overlapSeeding(outerFPGAStub, outerStub, innerFPGAStub, innerStub);
0338       }
0339 
0340       if (accept)
0341         countsel++;
0342 
0343       if (trackletpars_->nTracklets() >= settings_.ntrackletmax()) {
0344         edm::LogVerbatim("Tracklet") << "Will break on number of tracklets in " << getName();
0345         assert(0);
0346         break;
0347       }
0348 
0349       if (settings_.debugTracklet()) {
0350         edm::LogVerbatim("Tracklet") << "TrackletProcessor execute done";
0351       }
0352     }
0353 
0354     //
0355     // The second block fills the teunit if data in buffer and process TEUnit step
0356     //
0357     //
0358 
0359     bool notemptytebuffer = !tedatabuffer.empty();
0360 
0361     int ite = -1;
0362     for (auto& teunit : teunits_) {
0363       ite++;
0364       if (teunit.idle()) {
0365         if (notemptytebuffer) {
0366           teunit.init(std::get<0>(tebuffer_).read());
0367           notemptytebuffer = false;  //prevent initialzing another TE unit
0368         }
0369       }
0370       teunit.step(print, istep, ite);
0371     }
0372 
0373     //
0374     // The third block here checks if we have input stubs to process
0375     //
0376     //
0377 
0378     if (goodtedata___)
0379       tedatabuffer.store(tedata___);
0380 
0381     goodtedata = false;
0382 
0383     unsigned int& istub = std::get<1>(tebuffer_);
0384     unsigned int& imem = std::get<2>(tebuffer_);
0385     unsigned int imemend = std::get<4>(tebuffer_);
0386 
0387     if ((!tebuffernearfull) && imem < imemend && istub < innerallstubs_[imem]->nStubs()) {
0388       ninnerstubs++;
0389 
0390       const Stub* stub = innerallstubs_[imem]->getStub(istub);
0391 
0392       if (settings_.debugTracklet()) {
0393         edm::LogVerbatim("Tracklet") << getName() << " Have stub in " << innerallstubs_[imem]->getName();
0394       }
0395 
0396       bool negdisk = (stub->disk().value() < 0);  //FIXME stub needs to contain bit for +/- z disk
0397 
0398       FPGAWord phicorr = stub->phicorr();
0399       int innerfinephi = phicorr.bits(phicorr.nbits() - nbitsfinephi_, nbitsfinephi_);
0400       FPGAWord innerbend = stub->bend();
0401 
0402       //Take the top nbitszfinebintable_ bits of the z coordinate
0403       int indexz = (stub->z().value() >> (stub->z().nbits() - nbitszfinebintable_)) & ((1 << nbitszfinebintable_) - 1);
0404       int indexr = -1;
0405       if (layerdisk1_ > (N_LAYER - 1)) {
0406         if (negdisk) {
0407           indexz = ((1 << nbitszfinebintable_) - 1) - indexz;
0408         }
0409         indexr = stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_);
0410       } else {  //Take the top nbitsfinebintable_ bits of the z coordinate
0411         indexr = (stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_)) & ((1 << nbitsrfinebintable_) - 1);
0412       }
0413 
0414       int lutval = -1;
0415       if (iSeed_ < 6) {  //FIXME should only be one table - but will need coordination with HLS code.
0416         lutval = innerTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
0417       } else {
0418         lutval = innerOverlapTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
0419       }
0420 
0421       if (lutval != -1) {
0422         unsigned int lutwidth = settings_.lutwidthtab(0, iSeed_);
0423         FPGAWord lookupbits(lutval, lutwidth, true, __LINE__, __FILE__);
0424 
0425         int rzfinebinfirst = lookupbits.bits(0, NFINERZBITS);       //finerz
0426         int next = lookupbits.bits(NFINERZBITS, 1);                 //use next r/z bin
0427         int start = lookupbits.bits(NFINERZBITS + 1, nbitsrzbin_);  //rz bin
0428         int rzdiffmax = lookupbits.bits(NFINERZBITS + 1 + nbitsrzbin_, NFINERZBITS);
0429 
0430         if ((iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4) && negdisk) {  //TODO - need to store negative disk
0431           start += (1 << nbitsrzbin_);
0432         }
0433         int last = start + next;
0434 
0435         int nbins = (1 << N_RZBITS);
0436 
0437         unsigned int useregindex = (innerfinephi << innerbend.nbits()) + innerbend.value();
0438         if (iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4 || iSeed_ == Seed::L1D1 || iSeed_ == Seed::L2D1) {
0439           //FIXME If the lookupbits were rationally organized this would be much simpler
0440           unsigned int nrbits = 3;
0441           int ir = ((start & ((1 << (nrbits - 1)) - 1)) << 1) + (rzfinebinfirst >> (NFINERZBITS - 1));
0442           useregindex = (useregindex << nrbits) + ir;
0443         }
0444 
0445         unsigned int usereg = useregiontable_.lookup(useregindex);
0446 
0447         tedata.regions_.clear();
0448         tedata.stub_ = stub;
0449         tedata.rzbinfirst_ = rzfinebinfirst;
0450         tedata.start_ = start;
0451         tedata.innerfinephi_ = innerfinephi;
0452         tedata.rzdiffmax_ = rzdiffmax;
0453         tedata.innerbend_ = innerbend;
0454 
0455         std::string mask = "";
0456 
0457         for (int ibin = start; ibin <= last; ibin++) {
0458           for (unsigned int ireg = 0; ireg < settings_.nvmte(1, iSeed_); ireg++) {
0459             if (!(usereg & (1 << ireg))) {
0460               mask = "0" + mask;
0461               continue;
0462             }
0463 
0464             if (settings_.debugTracklet()) {
0465               edm::LogVerbatim("Tracklet") << getName() << " looking for matching stub in bin " << ibin << " with "
0466                                            << outervmstubs_->nVMStubsBinned(ireg * nbins + ibin) << " stubs";
0467             }
0468             assert(ireg * nbins + ibin < outervmstubs_->nBin());
0469             int nstubs = outervmstubs_->nVMStubsBinned(ireg * nbins + ibin);
0470 
0471             if (nstubs > 0) {
0472               mask = "1" + mask;
0473               tedata.regions_.emplace_back(tuple<int, int, int>(ibin - start, ireg, nstubs));
0474               countteall += nstubs;
0475             } else {
0476               mask = "0" + mask;
0477             }
0478           }
0479         }
0480 
0481         if (!tedata.regions_.empty()) {
0482           ntedata++;
0483           goodtedata = true;
0484         }
0485       }
0486       istub++;
0487       if (istub >= innerallstubs_[imem]->nStubs()) {
0488         istub = 0;
0489         imem++;
0490       }
0491     } else if ((!tebuffernearfull) && imem < imemend && istub == 0) {
0492       imem++;
0493     }
0494 
0495     goodtedata___ = goodtedata__;
0496     goodtedata__ = goodtedata;
0497 
0498     tedata___ = tedata__;
0499     tedata__ = tedata;
0500 
0501     //
0502     // stop looping over istep if done
0503     //
0504 
0505     bool done = true;
0506 
0507     if (imem < imemend || (!tedatabuffer.empty())) {
0508       done = false;
0509     }
0510 
0511     for (auto& teunit : teunits_) {
0512       if (!(teunit.idle() && teunit.empty()))
0513         done = false;
0514     }
0515 
0516     if (done) {
0517       donecount++;
0518     }
0519 
0520     //FIXME This should be done cleaner... Not too hard, but need to check fully the TEBuffer and TEUnit buffer.
0521     if (donecount > 4) {
0522       break;
0523     }
0524   }
0525 
0526   //
0527   // Done with processing - collect performance statistics
0528   //
0529 
0530   if (settings_.writeMonitorData("TP")) {
0531     globals_->ofstream("trackletprocessor.txt") << getName() << " " << ninnerstubs   //# inner stubs
0532                                                 << " " << outervmstubs_->nVMStubs()  //# outer stubs
0533                                                 << " " << countteall                 //# pairs tried in TE
0534                                                 << " " << stubpairs                  //# stubs pairs
0535                                                 << " " << countsel                   //# tracklets found
0536                                                 << endl;
0537   }
0538 }