From f44c1f19d1c6ca3c590348e1478c5a4a28141d50 Mon Sep 17 00:00:00 2001 From: Louise Skinnari Date: Fri, 7 May 2021 17:08:27 +0200 Subject: [PATCH] MP updates (fixed) (#81) * Updates to MatchProcessor so that we can get full agreement with HLS version * Fix to LUT for adding stub in VMStubsTEMemory when running extendted tracking Co-authored-by: Anders Ryd --- .../interface/MatchEngineUnit.h | 19 +- .../interface/TrackletLUT.h | 2 + .../src/MatchEngineUnit.cc | 94 ++++- .../src/MatchProcessor.cc | 354 ++++++++++-------- .../src/VMStubsTEMemory.cc | 17 +- 5 files changed, 313 insertions(+), 173 deletions(-) diff --git a/L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h b/L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h index 7dfaa3503736e..6c62b694f502d 100644 --- a/L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h +++ b/L1Trigger/TrackFindingTracklet/interface/MatchEngineUnit.h @@ -35,10 +35,13 @@ namespace trklet { bool usesecondMinus, bool usesecondPlus, bool isPSseed, - Tracklet* proj); + Tracklet* proj, + bool print); bool empty() const { return candmatches_.empty(); } + int TCID() const; + std::pair read() { return candmatches_.read(); } std::pair peek() const { return candmatches_.peek(); } @@ -47,8 +50,16 @@ namespace trklet { bool idle() const { return idle_; } + bool active() const { return !idle_||goodpair_||goodpair__||!empty(); } + + bool have_() const { return havepair_; } + bool have__() const { return havepair__; } + void reset(); + unsigned int rptr() const { return candmatches_.rptr(); } + unsigned int wptr() const { return candmatches_.wptr(); } + void step(bool print); private: @@ -77,7 +88,11 @@ namespace trklet { //LUT for bend consistency with rinv const TrackletLUT& luttable_; - + //Pipeline variables + std::pair tmppair_, tmppair__; + bool goodpair_, goodpair__; + bool havepair_, havepair__; + //save the candidate matches CircularBuffer> candmatches_; }; diff --git a/L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h b/L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h index 7e7392d372e3a..d730d1270e9ec 100644 --- a/L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h +++ b/L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h @@ -59,6 +59,8 @@ namespace trklet { int lookup(unsigned int index) const; + unsigned int size() const { return table_.size(); } + private: int getphiCorrValue(unsigned int layerdisk, unsigned int ibend, unsigned int irbin, diff --git a/L1Trigger/TrackFindingTracklet/src/MatchEngineUnit.cc b/L1Trigger/TrackFindingTracklet/src/MatchEngineUnit.cc index 2b89f436be2fc..20c8ab9e1b329 100644 --- a/L1Trigger/TrackFindingTracklet/src/MatchEngineUnit.cc +++ b/L1Trigger/TrackFindingTracklet/src/MatchEngineUnit.cc @@ -4,10 +4,14 @@ using namespace std; using namespace trklet; -MatchEngineUnit::MatchEngineUnit(bool barrel, unsigned int layerdisk, const TrackletLUT& luttable) : luttable_(luttable), candmatches_(5) { +MatchEngineUnit::MatchEngineUnit(bool barrel, unsigned int layerdisk, const TrackletLUT& luttable) : luttable_(luttable), candmatches_(3) { idle_ = true; barrel_ = barrel; layerdisk_ = layerdisk; + goodpair_ = false; + goodpair__ = false; + havepair_ = false; + havepair__ = false; } void MatchEngineUnit::init(VMStubsMEMemory* vmstubsmemory, @@ -23,7 +27,8 @@ void MatchEngineUnit::init(VMStubsMEMemory* vmstubsmemory, bool usesecondMinus, bool usesecondPlus, bool isPSseed, - Tracklet* proj) { + Tracklet* proj, + bool) { vmstubsmemory_ = vmstubsmemory; idle_ = false; nrzbins_ = nrzbins; @@ -39,22 +44,53 @@ void MatchEngineUnit::init(VMStubsMEMemory* vmstubsmemory, if (usefirstMinus) { use_.emplace_back(0, 0); } - if (usefirstPlus) { - use_.emplace_back(0, 1); - } if (usesecondMinus) { use_.emplace_back(1, 0); } + if (usefirstPlus) { + use_.emplace_back(0, 1); + } if (usesecondPlus) { use_.emplace_back(1, 1); } assert(use_.size() != 0); isPSseed_ = isPSseed; proj_ = proj; + + //Even when you init a new projection you need to process the pipeline + //This should be fixed to be done more cleanly - but require synchronizaton + //with the HLS code + if (goodpair__) { + candmatches_.store(tmppair__); + } + + havepair__ = havepair_; + goodpair__ = goodpair_; + tmppair__ = tmppair_; + + havepair_ = false; + goodpair_ = false; + + } -void MatchEngineUnit::step(bool print) { - if (idle() || candmatches_.almostfull()) +void MatchEngineUnit::step(bool) { + + bool almostfull = candmatches_.nearfull(); + + if (goodpair__) { + assert(havepair__); + candmatches_.store(tmppair__); + } + + havepair__ = havepair_; + goodpair__ = goodpair_; + tmppair__ = tmppair_; + + havepair_ = false; + goodpair_ = false; + + if (idle() || almostfull) return; unsigned int slot = (phibin_ + use_[iuse_].second) * nrzbins_ + rzbin_ + use_[iuse_].first; @@ -106,16 +142,21 @@ void MatchEngineUnit::step(bool print) { } } - if (print) - cout << "MEU TrkId stubindex : " << 128 * proj_->TCIndex() + proj_->trackletIndex() << " " - << vmstub.stubindex().value() << " " << ((pass && dphicut) && luttable_.lookup(index)) << " index=" << index - << " projrinv bend : " << projrinv_ << " " << vmstub.bend().value() << " shift_ isPSseed_ :" << shift_ << " " - << isPSseed_ << " slot=" << slot << endl; + // Detailed printout for comparison with HLS code + //if (print) + // cout << "MEU TrkId stubindex : " << 128 * proj_->TCIndex() + proj_->trackletIndex() << " " + // << vmstub.stubindex().value() << " " << ((pass && dphicut) && luttable_.lookup(index)) << " index=" << index + // << " projrinv bend : " << projrinv_ << " " << vmstub.bend().value() << " shift_ isPSseed_ :" << shift_ << " " + // << isPSseed_ << " slot=" << slot << endl; //Check if stub bend and proj rinv consistent - if ((pass && dphicut) && luttable_.lookup(index)) { - std::pair tmp(proj_, vmstub.stub()); - candmatches_.store(tmp); + + goodpair_ = (pass && dphicut) && luttable_.lookup(index); + havepair_ = true; + + if (havepair_) { + std::pair tmppair(proj_, vmstub.stub()); + tmppair_ = tmppair; } istub_++; @@ -133,4 +174,27 @@ void MatchEngineUnit::reset() { candmatches_.reset(); idle_ = true; istub_ = 0; + goodpair_ = false; + goodpair__ = false; + havepair_ = false; + havepair__ = false; +} + +int MatchEngineUnit::TCID() const { + + if (!empty()) { + return peek().first->TCID(); + } + + if (idle_&&!havepair_&&!havepair__) { + return 16383; + } + if (havepair__) { + return tmppair__.first->TCID(); + } + if (havepair_) { + return tmppair_.first->TCID(); + } + return proj_->TCID(); + } diff --git a/L1Trigger/TrackFindingTracklet/src/MatchProcessor.cc b/L1Trigger/TrackFindingTracklet/src/MatchProcessor.cc index 4eca2ff1c4569..5723a4dcce56c 100644 --- a/L1Trigger/TrackFindingTracklet/src/MatchProcessor.cc +++ b/L1Trigger/TrackFindingTracklet/src/MatchProcessor.cc @@ -125,6 +125,7 @@ void MatchProcessor::addInput(MemoryBase* memory, string input) { } void MatchProcessor::execute(unsigned int iSector, double phimin) { + assert(vmstubs_.size() == 1); /* @@ -154,6 +155,11 @@ void MatchProcessor::execute(unsigned int iSector, double phimin) { unsigned int countinputproj = 0; unsigned int iprojmem = 0; + while (iprojmemnTracklets()==0) { + iprojmem++; + } + + unsigned int iproj = 0; inputProjBuffer_.reset(); @@ -166,135 +172,80 @@ void MatchProcessor::execute(unsigned int iSector, double phimin) { matchengine.reset(); } + + ProjectionTemp tmpProj_, tmpProj__; + bool good_ = false; + bool good__ = false; + for (unsigned int istep = 0; istep < settings_.maxStep("MP"); istep++) { + + bool projBuffNearFull=inputProjBuffer_.nearfull(); + + // This print statement is useful for detailed comparison with the HLS code + // It prints out detailed status information for each clock step + /* + if (print) { + cout << "istep = "<nTracklets() == 0) { - iprojmem++; - } else if (iproj < projMem->nTracklets()) { - if (!inputProjBuffer_.almostfull()) { - if (settings_.debugTracklet()) { - edm::LogVerbatim("Tracklet") << getName() << " have projection in memory : " << projMem->getName(); - } - - Tracklet* proj = projMem->getTracklet(iproj); - - FPGAWord fpgaphi = proj->proj(layerdisk_).fpgaphiproj(); - - unsigned int iphi = (fpgaphi.value() >> (fpgaphi.nbits() - nvmbits_)) & (nvmbins_ - 1); - - int nextrabits = 2; - int overlapbits = nvmbits_ + nextrabits; - - unsigned int extrabits = fpgaphi.bits(fpgaphi.nbits() - overlapbits, nextrabits); - - unsigned int ivmPlus = iphi; - - int shift = 0; - - if (extrabits == ((1U << nextrabits) - 1) && iphi != ((1U << settings_.nbitsvmme(layerdisk_)) - 1)) { - shift = 1; - ivmPlus++; - } - unsigned int ivmMinus = iphi; - if (extrabits == 0 && iphi != 0) { - shift = -1; - ivmMinus--; - } - - int projrinv = -1; - if (barrel_) { - FPGAWord phider = proj->proj(layerdisk_).fpgaphiprojder(); - projrinv = (1 << (nrinv_ - 1)) - 1 - (phider.value() >> (phider.nbits() - nrinv_)); - } else { - //The next lines looks up the predicted bend based on: - // 1 - r projections - // 2 - phi derivative - // 3 - the sign - i.e. if track is forward or backward - - int rindex = (proj->proj(layerdisk_).fpgarzproj().value() >> - (proj->proj(layerdisk_).fpgarzproj().nbits() - nrbits_)) & - ((1 << nrbits_) - 1); - - int phiderindex = (proj->proj(layerdisk_).fpgaphiprojder().value() >> - (proj->proj(layerdisk_).fpgaphiprojder().nbits() - nphiderbits_)) & - ((1 << nphiderbits_) - 1); - - int signindex = proj->proj(layerdisk_).fpgarzprojder().value() < 0; - - int bendindex = (signindex << (nphiderbits_ + nrbits_)) + (rindex << (nphiderbits_)) + phiderindex; - - projrinv = rinvbendlut_.lookup(bendindex); - - proj->proj(layerdisk_).setBendIndex(projrinv); - } - assert(projrinv >= 0); - - unsigned int slot = proj->proj(layerdisk_).fpgarzbin1projvm().value(); - bool second = proj->proj(layerdisk_).fpgarzbin2projvm().value(); - - unsigned int projfinephi = (fpgaphi.value() >> (fpgaphi.nbits() - (nvmbits_ + NFINEPHIBITS))) & ((1<proj(layerdisk_).fpgafinerzvm().value(); - - bool isPSseed = proj->PSseed(); - - int nbins = (1 << N_RZBITS); - if (layerdisk_ >= N_LAYER) { - nbins*=2; //twice as many bins in disks (since there are two disks) - } - - VMStubsMEMemory* stubmem = vmstubs_[0]; - bool usefirstMinus = stubmem->nStubsBin(ivmMinus * nbins + slot) != 0; - bool usesecondMinus = (second && (stubmem->nStubsBin(ivmMinus * nbins + slot + 1) != 0)); - bool usefirstPlus = ivmPlus != ivmMinus && stubmem->nStubsBin(ivmPlus * nbins + slot) != 0; - bool usesecondPlus = - ivmPlus != ivmMinus && (second && (stubmem->nStubsBin(ivmPlus * nbins + slot + 1) != 0)); - - bool useProj = usefirstPlus || usesecondPlus || usefirstMinus || usesecondMinus; - - if (useProj) { - ProjectionTemp tmpProj(proj, - slot, - projrinv, - projfinerz, - projfinephi, - ivmMinus, - shift, - usefirstMinus, - usefirstPlus, - usesecondMinus, - usesecondPlus, - isPSseed); - inputProjBuffer_.store(tmpProj); - } - - iproj++; - if (iproj == projMem->nTracklets()) { - iproj = 0; - iprojmem++; - } - } - } - } else { - projdone = true; + //Step 3 + //Check if we have candidate match to process + + unsigned int iMEbest = 0; + int bestTCID = matchengines_[0].TCID(); + bool meactive = matchengines_[0].active(); + for (unsigned int iME = 1; iME < nMatchEngines_; iME++) { + meactive = meactive || matchengines_[iME].active(); + int tcid=matchengines_[iME].TCID(); + if (tcid candmatch = matchengines_[iMEbest].read(); + + const Stub* fpgastub = candmatch.second; + Tracklet* tracklet = candmatch.first; + + if (oldTracklet != nullptr) { + //allow equal here since we can have more than one cadidate match per tracklet projection + //cout << "old new : "<TCID()<<" "<TCID()<<" "<TCID() <= tracklet->TCID()); + } + oldTracklet = tracklet; + + bool match = matchCalculator(tracklet, fpgastub, print, istep); + + if (settings_.debugTracklet() && match) { + edm::LogVerbatim("Tracklet") << getName() << " have match"; + } + + countall++; + if (match) + countsel++; + } + //Step 2 //Check if we have ME that can process projection - + bool addedProjection = false; for (unsigned int iME = 0; iME < nMatchEngines_; iME++) { if (!matchengines_[iME].idle()) countme++; - matchengines_[iME].step(print); //if match engine empty and we have queued projections add to match engine if ((!addedProjection) && matchengines_[iME].idle() && (!inputProjBuffer_.empty())) { ProjectionTemp tmpProj = inputProjBuffer_.read(); @@ -322,54 +273,151 @@ void MatchProcessor::execute(unsigned int iSector, double phimin) { tmpProj.use(1, 0), tmpProj.use(1, 1), tmpProj.isPSseed(), - tmpProj.proj()); + tmpProj.proj(), + print&&(iME==0)); addedProjection = true; + } else { + matchengines_[iME].step(print&&iME==0); } + } - //Step 3 - //Check if we have candidate match to process - unsigned int iMEbest = nMatchEngines_; - int bestTCID = -1; - bool bestInPipeline = false; - for (unsigned int iME = 0; iME < nMatchEngines_; iME++) { - bool empty = matchengines_[iME].empty(); - medone = medone && (empty && matchengines_[iME].idle()); - if (empty && matchengines_[iME].idle()) - continue; - int currentTCID = empty ? matchengines_[iME].currentProj()->TCID() : matchengines_[iME].peek().first->TCID(); - if ((iMEbest == nMatchEngines_) || (currentTCID < bestTCID)) { - iMEbest = iME; - bestTCID = currentTCID; - bestInPipeline = empty; - } - } - if (iMEbest != nMatchEngines_ && (!bestInPipeline)) { - std::pair candmatch = matchengines_[iMEbest].read(); - - const Stub* fpgastub = candmatch.second; - Tracklet* tracklet = candmatch.first; + //Step 1 + //First step here checks if we have more input projections to put into + //the input puffer for projections - if (oldTracklet != nullptr) { - //allow equal here since we can have more than one cadidate match per tracklet projection - assert(oldTracklet->TCID() <= tracklet->TCID()); - } - oldTracklet = tracklet; + if (good__) { + inputProjBuffer_.store(tmpProj__); + } - bool match = matchCalculator(tracklet, fpgastub, print, istep); + good__ = good_; + tmpProj__ = tmpProj_; - if (settings_.debugTracklet() && match) { - edm::LogVerbatim("Tracklet") << getName() << " have match"; + good_ = false; + + if (istep < settings_.maxStep("MP")) { + if (iprojmem < inputprojs_.size()) { + TrackletProjectionsMemory* projMem = inputprojs_[iprojmem]; + if (!projBuffNearFull) { + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << getName() << " have projection in memory : " << projMem->getName(); + } + + Tracklet* proj = projMem->getTracklet(iproj); + + FPGAWord fpgaphi = proj->proj(layerdisk_).fpgaphiproj(); + + unsigned int iphi = (fpgaphi.value() >> (fpgaphi.nbits() - nvmbits_)) & (nvmbins_ - 1); + + int nextrabits = 2; + int overlapbits = nvmbits_ + nextrabits; + + unsigned int extrabits = fpgaphi.bits(fpgaphi.nbits() - overlapbits, nextrabits); + + unsigned int ivmPlus = iphi; + + int shift = 0; + + if (extrabits == ((1U << nextrabits) - 1) && iphi != ((1U << settings_.nbitsvmme(layerdisk_)) - 1)) { + shift = 1; + ivmPlus++; + } + unsigned int ivmMinus = iphi; + if (extrabits == 0 && iphi != 0) { + shift = -1; + ivmMinus--; + } + + int projrinv = -1; + if (barrel_) { + FPGAWord phider = proj->proj(layerdisk_).fpgaphiprojder(); + projrinv = (1 << (nrinv_ - 1)) - 1 - (phider.value() >> (phider.nbits() - nrinv_)); + } else { + //The next lines looks up the predicted bend based on: + // 1 - r projections + // 2 - phi derivative + // 3 - the sign - i.e. if track is forward or backward + + int rindex = (proj->proj(layerdisk_).fpgarzproj().value() >> + (proj->proj(layerdisk_).fpgarzproj().nbits() - nrbits_)) & + ((1 << nrbits_) - 1); + + int phiderindex = (proj->proj(layerdisk_).fpgaphiprojder().value() >> + (proj->proj(layerdisk_).fpgaphiprojder().nbits() - nphiderbits_)) & + ((1 << nphiderbits_) - 1); + + int signindex = proj->proj(layerdisk_).fpgarzprojder().value() < 0; + + int bendindex = (signindex << (nphiderbits_ + nrbits_)) + (rindex << (nphiderbits_)) + phiderindex; + + projrinv = rinvbendlut_.lookup(bendindex); + + proj->proj(layerdisk_).setBendIndex(projrinv); + } + assert(projrinv >= 0); + + unsigned int slot = proj->proj(layerdisk_).fpgarzbin1projvm().value(); + bool second = proj->proj(layerdisk_).fpgarzbin2projvm().value(); + + unsigned int projfinephi = (fpgaphi.value() >> (fpgaphi.nbits() - (nvmbits_ + NFINEPHIBITS))) & ((1<proj(layerdisk_).fpgafinerzvm().value(); + + bool isPSseed = proj->PSseed(); + + int nbins = (1 << N_RZBITS); + if (layerdisk_ >= N_LAYER) { + nbins*=2; //twice as many bins in disks (since there are two disks) + } + + VMStubsMEMemory* stubmem = vmstubs_[0]; + bool usefirstMinus = stubmem->nStubsBin(ivmMinus * nbins + slot) != 0; + bool usesecondMinus = (second && (stubmem->nStubsBin(ivmMinus * nbins + slot + 1) != 0)); + bool usefirstPlus = ivmPlus != ivmMinus && stubmem->nStubsBin(ivmPlus * nbins + slot) != 0; + bool usesecondPlus = + ivmPlus != ivmMinus && (second && (stubmem->nStubsBin(ivmPlus * nbins + slot + 1) != 0)); + + good_ = usefirstPlus || usesecondPlus || usefirstMinus || usesecondMinus; + + if (good_) { + ProjectionTemp tmpProj(proj, + slot, + projrinv, + projfinerz, + projfinephi, + ivmMinus, + shift, + usefirstMinus, + usefirstPlus, + usesecondMinus, + usesecondPlus, + isPSseed); + tmpProj_ = tmpProj; + } + + iproj++; + if (iproj == projMem->nTracklets()) { + iproj = 0; + do { + iprojmem++; + } while (iprojmemnTracklets()==0); + } + } + + } else { + projdone = true && !good_ && !good__; } - - countall++; - if (match) - countsel++; } - if ((projdone && medone) || (istep == settings_.maxStep("MP") - 1)) { + + // + // Check if done + // + // + // + + if ((projdone && !meactive) || (istep == settings_.maxStep("MP") - 1)) { if (settings_.writeMonitorData("MP")) { globals_->ofstream("matchprocessor.txt") << getName() << " " << istep << " " << countall << " " << countsel << " " << countme << " " << countinputproj << endl; diff --git a/L1Trigger/TrackFindingTracklet/src/VMStubsTEMemory.cc b/L1Trigger/TrackFindingTracklet/src/VMStubsTEMemory.cc index 9d8ccae586cf0..4d7ac21ad4373 100644 --- a/L1Trigger/TrackFindingTracklet/src/VMStubsTEMemory.cc +++ b/L1Trigger/TrackFindingTracklet/src/VMStubsTEMemory.cc @@ -70,8 +70,13 @@ bool VMStubsTEMemory::addVMStub(VMStubTE vmstub, int bin) { return true; } - bool pass = bendtable_.lookup(vmstub.bend().value()); - + bool pass = false; + if (settings_.extended()&&bendtable_.size()==0) { + pass = true ; + } else { + pass = bendtable_.lookup(vmstub.bend().value()); + } + if (!pass) { if (settings_.debugTracklet()) edm::LogVerbatim("Tracklet") << getName() << " Stub failed bend cut. bend = " @@ -132,8 +137,14 @@ bool VMStubsTEMemory::addVMStub(VMStubTE vmstub) { //If the pt of the stub is consistent with the allowed pt of tracklets //in that can be formed in this VM and the other VM used in the TE. - bool pass = bendtable_.lookup(vmstub.bend().value()); + bool pass = false; + if (settings_.extended()&&bendtable_.size()==0) { + pass = true ; + } else { + pass = bendtable_.lookup(vmstub.bend().value()); + } + if (!pass) { if (settings_.debugTracklet()) edm::LogVerbatim("Tracklet") << getName() << " Stub failed bend cut. bend = "