Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:22:05

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 countsel = 0;
0247 
0248   unsigned int countteall = 0;
0249   unsigned int stubpairs = 0;
0250 
0251   unsigned int ninnerstubs = 0;
0252 
0253   //Actual implemenation starts here
0254 
0255   //Reset the tebuffer
0256   std::get<0>(tebuffer_).reset();
0257   std::get<1>(tebuffer_) = 0;
0258   std::get<2>(tebuffer_) = std::get<3>(tebuffer_);
0259 
0260   //Reset the teunits
0261   for (auto& teunit : teunits_) {
0262     teunit.reset();
0263   }
0264 
0265   TEData tedata;
0266   TEData tedata__;
0267   TEData tedata___;
0268   bool goodtedata = false;
0269   bool goodtedata__ = false;
0270   bool goodtedata___ = false;
0271 
0272   bool tebuffernearfull;
0273 
0274   for (unsigned int istep = 0; istep < maxStep_; istep++) {
0275     // These print statements are not on by defaul but can be enabled for the
0276     // comparison with HLS code to track differences.
0277     if (print) {
0278       CircularBuffer<TEData>& tedatabuffer = std::get<0>(tebuffer_);
0279       unsigned int& istub = std::get<1>(tebuffer_);
0280       unsigned int& imem = std::get<2>(tebuffer_);
0281       cout << "istep=" << istep << " TEBuffer: " << istub << " " << imem << " " << tedatabuffer.rptr() << " "
0282            << tedatabuffer.wptr();
0283       int k = -1;
0284       for (auto& teunit : teunits_) {
0285         k++;
0286         cout << " [" << k << " " << teunit.rptr() << " " << teunit.wptr() << " " << teunit.idle() << "]";
0287       }
0288       cout << endl;
0289     }
0290 
0291     CircularBuffer<TEData>& tedatabuffer = std::get<0>(tebuffer_);
0292     tebuffernearfull = tedatabuffer.nearfull();
0293 
0294     //
0295     // First block here checks if there is a teunit with data that should should be used
0296     // to calculate the tracklet parameters
0297     //
0298 
0299     TrackletEngineUnit* teunitptr = nullptr;
0300 
0301     for (auto& teunit : teunits_) {
0302       teunit.setNearFull();
0303       if (!teunit.empty()) {
0304         teunitptr = &teunit;
0305       }
0306     }
0307 
0308     if (teunitptr != nullptr) {
0309       auto stubpair = teunitptr->read();
0310       stubpairs++;
0311 
0312       if (trackletpars_->nTracklets() >= settings_.ntrackletmax()) {
0313         edm::LogVerbatim("Tracklet") << "Will break on too many tracklets in " << getName();
0314         break;
0315       }
0316       const Stub* innerFPGAStub = stubpair.first;
0317       const L1TStub* innerStub = innerFPGAStub->l1tstub();
0318 
0319       const Stub* outerFPGAStub = stubpair.second;
0320       const L1TStub* outerStub = outerFPGAStub->l1tstub();
0321 
0322       if (settings_.debugTracklet()) {
0323         edm::LogVerbatim("Tracklet") << "TrackletProcessor execute " << getName() << "[" << iSector_ << "]";
0324       }
0325 
0326       bool accept = false;
0327 
0328       if (iSeed_ == Seed::L1L2 || iSeed_ == Seed::L2L3 || iSeed_ == Seed::L3L4 || iSeed_ == Seed::L5L6) {
0329         accept = barrelSeeding(innerFPGAStub, innerStub, outerFPGAStub, outerStub);
0330       } else if (iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4) {
0331         accept = diskSeeding(innerFPGAStub, innerStub, outerFPGAStub, outerStub);
0332       } else {
0333         accept = overlapSeeding(outerFPGAStub, outerStub, innerFPGAStub, innerStub);
0334       }
0335 
0336       if (accept)
0337         countsel++;
0338 
0339       if (trackletpars_->nTracklets() >= settings_.ntrackletmax()) {
0340         edm::LogVerbatim("Tracklet") << "Will break on number of tracklets in " << getName();
0341         assert(0);
0342         break;
0343       }
0344 
0345       if (settings_.debugTracklet()) {
0346         edm::LogVerbatim("Tracklet") << "TrackletProcessor execute done";
0347       }
0348     }
0349 
0350     //
0351     // The second block fills the teunit if data in buffer and process TEUnit step
0352     //
0353     //
0354 
0355     bool notemptytebuffer = !tedatabuffer.empty();
0356 
0357     int ite = -1;
0358     for (auto& teunit : teunits_) {
0359       ite++;
0360       if (teunit.idle()) {
0361         if (notemptytebuffer) {
0362           teunit.init(std::get<0>(tebuffer_).read());
0363           notemptytebuffer = false;  //prevent initialzing another TE unit
0364         }
0365       }
0366       teunit.step(print, istep, ite);
0367     }
0368 
0369     //
0370     // The third block here checks if we have input stubs to process
0371     //
0372     //
0373 
0374     if (goodtedata___)
0375       tedatabuffer.store(tedata___);
0376 
0377     goodtedata = false;
0378 
0379     unsigned int& istub = std::get<1>(tebuffer_);
0380     unsigned int& imem = std::get<2>(tebuffer_);
0381     unsigned int imemend = std::get<4>(tebuffer_);
0382 
0383     if ((!tebuffernearfull) && imem < imemend && istub < innerallstubs_[imem]->nStubs()) {
0384       ninnerstubs++;
0385 
0386       const Stub* stub = innerallstubs_[imem]->getStub(istub);
0387 
0388       if (settings_.debugTracklet()) {
0389         edm::LogVerbatim("Tracklet") << getName() << " Have stub in " << innerallstubs_[imem]->getName();
0390       }
0391 
0392       bool negdisk = (stub->disk().value() < 0);  //FIXME stub needs to contain bit for +/- z disk
0393 
0394       FPGAWord phicorr = stub->phicorr();
0395       int innerfinephi = phicorr.bits(phicorr.nbits() - nbitsfinephi_, nbitsfinephi_);
0396       FPGAWord innerbend = stub->bend();
0397 
0398       //Take the top nbitszfinebintable_ bits of the z coordinate
0399       int indexz = (stub->z().value() >> (stub->z().nbits() - nbitszfinebintable_)) & ((1 << nbitszfinebintable_) - 1);
0400       int indexr = -1;
0401       if (layerdisk1_ > (N_LAYER - 1)) {
0402         if (negdisk) {
0403           indexz = ((1 << nbitszfinebintable_) - 1) - indexz;
0404         }
0405         indexr = stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_);
0406       } else {  //Take the top nbitsfinebintable_ bits of the z coordinate
0407         indexr = (stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_)) & ((1 << nbitsrfinebintable_) - 1);
0408       }
0409 
0410       int lutval = -1;
0411       if (iSeed_ < 6) {  //FIXME should only be one table - but will need coordination with HLS code.
0412         lutval = innerTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
0413       } else {
0414         lutval = innerOverlapTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
0415       }
0416 
0417       if (lutval != -1) {
0418         unsigned int lutwidth = settings_.lutwidthtab(0, iSeed_);
0419         FPGAWord lookupbits(lutval, lutwidth, true, __LINE__, __FILE__);
0420 
0421         int rzfinebinfirst = lookupbits.bits(0, NFINERZBITS);       //finerz
0422         int next = lookupbits.bits(NFINERZBITS, 1);                 //use next r/z bin
0423         int start = lookupbits.bits(NFINERZBITS + 1, nbitsrzbin_);  //rz bin
0424         int rzdiffmax = lookupbits.bits(NFINERZBITS + 1 + nbitsrzbin_, NFINERZBITS);
0425 
0426         if ((iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4) && negdisk) {  //TODO - need to store negative disk
0427           start += (1 << nbitsrzbin_);
0428         }
0429         int last = start + next;
0430 
0431         int nbins = (1 << N_RZBITS);
0432 
0433         unsigned int useregindex = (innerfinephi << innerbend.nbits()) + innerbend.value();
0434         if (iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4 || iSeed_ == Seed::L1D1 || iSeed_ == Seed::L2D1) {
0435           //FIXME If the lookupbits were rationally organized this would be much simpler
0436           unsigned int nrbits = 3;
0437           int ir = ((start & ((1 << (nrbits - 1)) - 1)) << 1) + (rzfinebinfirst >> (NFINERZBITS - 1));
0438           useregindex = (useregindex << nrbits) + ir;
0439         }
0440 
0441         unsigned int usereg = useregiontable_.lookup(useregindex);
0442 
0443         tedata.regions_.clear();
0444         tedata.stub_ = stub;
0445         tedata.rzbinfirst_ = rzfinebinfirst;
0446         tedata.start_ = start;
0447         tedata.innerfinephi_ = innerfinephi;
0448         tedata.rzdiffmax_ = rzdiffmax;
0449         tedata.innerbend_ = innerbend;
0450 
0451         std::string mask = "";
0452 
0453         for (int ibin = start; ibin <= last; ibin++) {
0454           for (unsigned int ireg = 0; ireg < settings_.nvmte(1, iSeed_); ireg++) {
0455             if (!(usereg & (1 << ireg))) {
0456               mask = "0" + mask;
0457               continue;
0458             }
0459 
0460             if (settings_.debugTracklet()) {
0461               edm::LogVerbatim("Tracklet") << getName() << " looking for matching stub in bin " << ibin << " with "
0462                                            << outervmstubs_->nVMStubsBinned(ireg * nbins + ibin) << " stubs";
0463             }
0464             assert(ireg * nbins + ibin < outervmstubs_->nBin());
0465             int nstubs = outervmstubs_->nVMStubsBinned(ireg * nbins + ibin);
0466 
0467             if (nstubs > 0) {
0468               mask = "1" + mask;
0469               tedata.regions_.emplace_back(tuple<int, int, int>(ibin - start, ireg, nstubs));
0470               countteall += nstubs;
0471             } else {
0472               mask = "0" + mask;
0473             }
0474           }
0475         }
0476 
0477         if (!tedata.regions_.empty()) {
0478           goodtedata = true;
0479         }
0480       }
0481       istub++;
0482       if (istub >= innerallstubs_[imem]->nStubs()) {
0483         istub = 0;
0484         imem++;
0485       }
0486     } else if ((!tebuffernearfull) && imem < imemend && istub == 0) {
0487       imem++;
0488     }
0489 
0490     goodtedata___ = goodtedata__;
0491     goodtedata__ = goodtedata;
0492 
0493     tedata___ = tedata__;
0494     tedata__ = tedata;
0495 
0496     //
0497     // stop looping over istep if done
0498     //
0499 
0500     bool done = true;
0501 
0502     if (imem < imemend || (!tedatabuffer.empty())) {
0503       done = false;
0504     }
0505 
0506     for (auto& teunit : teunits_) {
0507       if (!(teunit.idle() && teunit.empty()))
0508         done = false;
0509     }
0510 
0511     if (done) {
0512       donecount++;
0513     }
0514 
0515     //FIXME This should be done cleaner... Not too hard, but need to check fully the TEBuffer and TEUnit buffer.
0516     if (donecount > 4) {
0517       break;
0518     }
0519   }
0520 
0521   //
0522   // Done with processing - collect performance statistics
0523   //
0524 
0525   if (settings_.writeMonitorData("TP")) {
0526     globals_->ofstream("trackletprocessor.txt") << getName() << " " << ninnerstubs   //# inner stubs
0527                                                 << " " << outervmstubs_->nVMStubs()  //# outer stubs
0528                                                 << " " << countteall                 //# pairs tried in TE
0529                                                 << " " << stubpairs                  //# stubs pairs
0530                                                 << " " << countsel                   //# tracklets found
0531                                                 << endl;
0532   }
0533 }