diff --git a/L1Trigger/TrackFindingTracklet/interface/Settings.h b/L1Trigger/TrackFindingTracklet/interface/Settings.h index 6d4abf30d37a7..9675d6ae85dbe 100644 --- a/L1Trigger/TrackFindingTracklet/interface/Settings.h +++ b/L1Trigger/TrackFindingTracklet/interface/Settings.h @@ -158,6 +158,7 @@ namespace trklet { } unsigned int teunits(unsigned int iSeed) const { return teunits_[iSeed]; } + unsigned int trpunits(unsigned int iSeed) const { return trpunits_[iSeed]; } unsigned int NTC(int seed) const { return ntc_[seed]; } @@ -666,7 +667,8 @@ namespace trklet { int chisqphifactbits_{14}; int chisqzfactbits_{14}; - std::array teunits_{{5, 2, 5, 3, 3, 2, 3, 2, 0, 0, 0, 0}}; //teunits used by seed + std::array teunits_{{5, 2, 5, 3, 3, 2, 3, 2, 0, 0, 0, 0}}; //teunits used by seed + std::array trpunits_{{0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10}}; //trpunits used by seed std::array vmrlutzbits_{ {7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3}}; // zbits used by LUT in VMR diff --git a/L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h b/L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h index 6cf8abd6e714a..7f0f3a38c647c 100644 --- a/L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h +++ b/L1Trigger/TrackFindingTracklet/interface/TrackletProcessorDisplaced.h @@ -6,9 +6,9 @@ #include "L1Trigger/TrackFindingTracklet/interface/TrackletCalculatorDisplaced.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h" #include "L1Trigger/TrackFindingTracklet/interface/CircularBuffer.h" -#include "L1Trigger/TrackFindingTracklet/interface/TrackletEngineUnit.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletParametersMemory.h" #include "L1Trigger/TrackFindingTracklet/interface/TrackletProjectionsMemory.h" +#include "L1Trigger/TrackFindingTracklet/interface/TripletEngineUnit.h" #include #include @@ -40,6 +40,10 @@ namespace trklet { private: int iTC_; + unsigned int maxStep_; + + std::tuple, unsigned int, unsigned int, unsigned int, unsigned int> trpbuffer_; + std::vector trpunits_; unsigned int layerdisk1_; unsigned int layerdisk2_; diff --git a/L1Trigger/TrackFindingTracklet/interface/TripletEngineUnit.h b/L1Trigger/TrackFindingTracklet/interface/TripletEngineUnit.h new file mode 100644 index 0000000000000..4f75a3a39bc3c --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/interface/TripletEngineUnit.h @@ -0,0 +1,94 @@ +#ifndef L1Trigger_TrackFindingTracklet_interface_TripletEngineUnit_h +#define L1Trigger_TrackFindingTracklet_interface_TripletEngineUnit_h + +#include "L1Trigger/TrackFindingTracklet/interface/VMStubsTEMemory.h" +#include "L1Trigger/TrackFindingTracklet/interface/CircularBuffer.h" +#include "L1Trigger/TrackFindingTracklet/interface/TrackletLUT.h" + +#include +#include + +namespace trklet { + + class Settings; + class Stub; + class L1TStub; + + struct TrpEData { + const Stub* stub_; + int start_out_; + int start_in_; + int rzbinfirst_out_; + int rzdiffmax_out_; + std::vector > projbin_out_; // next z/r bin; outer stub mem; nstub + std::vector > projbin_in_; // next z/r bin; inner stub mem; nstub + }; + + class TripletEngineUnit { + public: + TripletEngineUnit(const Settings* const settings, + unsigned int layerdisk1, + unsigned int layerdisk2, + unsigned int layerdisk3, + unsigned int iSeed, + std::vector innervmstubs, + std::vector outervmstubs); + + ~TripletEngineUnit() = default; + + void init(const TrpEData& trpdata); + + bool getGoodTriplet() { return goodtriplet__; } + + bool empty() const { return candtriplets_.empty(); } + + const std::tuple& read() { return candtriplets_.read(); } + + const std::tuple& peek() const { return candtriplets_.peek(); } + + bool idle() const { return idle_; } + + void setNearFull() { nearfull_ = candtriplets_.nearfull(); } + + void reset(); + + void step(); + + const Stub* innerStub() const { return trpdata_.stub_; } + + private: + std::vector innervmstubs_; + std::vector outervmstubs_; + TrpEData trpdata_; + const Settings* settings_; + unsigned int layerdisk1_; + unsigned int layerdisk2_; + unsigned int layerdisk3_; + unsigned int iSeed_; + bool nearfull_; //initialized at start of each processing step + + //unsigned int memory slot + unsigned int nmem_out_; + unsigned int nmem_in_; + unsigned int istub_out_; + unsigned int istub_in_; + unsigned int next_out_; + unsigned int next_in_; + unsigned int nstub_out_; + unsigned int nstub_in_; + unsigned int outmem_; + unsigned int inmem_; + unsigned int nproj_out_; + unsigned int nproj_in_; + + bool idle_; + + std::tuple candtriplet_, candtriplet__; + bool goodtriplet_, goodtriplet__; + + //save the candidate matches + CircularBuffer > candtriplets_; + }; // TripletEngineUnit + +}; // namespace trklet +#endif diff --git a/L1Trigger/TrackFindingTracklet/src/TrackletProcessorDisplaced.cc b/L1Trigger/TrackFindingTracklet/src/TrackletProcessorDisplaced.cc index 903c62cf0a124..0c8a1424264e0 100644 --- a/L1Trigger/TrackFindingTracklet/src/TrackletProcessorDisplaced.cc +++ b/L1Trigger/TrackFindingTracklet/src/TrackletProcessorDisplaced.cc @@ -23,10 +23,13 @@ using namespace trklet; // This module takes in collections of stubs within a phi region and a // displaced seed name and tries to create that displaced seed out of the stubs // -// Update: Claire Savard, Oct. 2024 +// Update: Claire Savard, Nov. 2024 TrackletProcessorDisplaced::TrackletProcessorDisplaced(string name, Settings const& settings, Globals* globals) - : TrackletCalculatorDisplaced(name, settings, globals), innerTable_(settings), innerThirdTable_(settings) { + : TrackletCalculatorDisplaced(name, settings, globals), + trpbuffer_(CircularBuffer(3), 0, 0, 0, 0), + innerTable_(settings), + innerThirdTable_(settings) { innerallstubs_.clear(); middleallstubs_.clear(); outerallstubs_.clear(); @@ -58,10 +61,9 @@ TrackletProcessorDisplaced::TrackletProcessorDisplaced(string name, Settings con // set TC index iTC_ = region; - constexpr int TCIndexMin = 128; - constexpr int TCIndexMax = 191; - TCIndex_ = (iSeed_ << 4) + iTC_; - assert(TCIndex_ >= TCIndexMin && TCIndex_ < TCIndexMax); + TCIndex_ = (iSeed_ << settings.nbitsseed()) + iTC_; + + maxStep_ = settings_.maxStep("TPD"); } void TrackletProcessorDisplaced::addOutputProjection(TrackletProjectionsMemory*& outputProj, MemoryBase* memory) { @@ -156,177 +158,249 @@ void TrackletProcessorDisplaced::addInput(MemoryBase* memory, string input) { } void TrackletProcessorDisplaced::execute(unsigned int iSector, double phimin, double phimax) { - unsigned int countall = 0; - unsigned int countsel = 0; - phimin_ = phimin; phimax_ = phimax; iSector_ = iSector; - // loop over the middle stubs in the potential seed - for (unsigned int midmem = 0; midmem < middleallstubs_.size(); midmem++) { - for (unsigned int i = 0; i < middleallstubs_[midmem]->nStubs(); i++) { - const Stub* midallstub = middleallstubs_[midmem]->getStub(i); + unsigned int countall = 0; + unsigned int countsel = 0; + int donecount = 0; + + // set the triplet engine units and buffer + TripletEngineUnit trpunit(&settings_, layerdisk1_, layerdisk2_, layerdisk3_, iSeed_, innervmstubs_, outervmstubs_); + trpunits_.resize(settings_.trpunits(iSeed_), trpunit); + trpbuffer_ = tuple, unsigned int, unsigned int, unsigned int, unsigned int>( + CircularBuffer(3), 0, 0, 0, middleallstubs_.size()); + + // reset the trpunits + for (auto& trpunit : trpunits_) { + trpunit.reset(); + } + + // reset the tebuffer + std::get<0>(trpbuffer_).reset(); + std::get<1>(trpbuffer_) = 0; + std::get<2>(trpbuffer_) = std::get<3>(trpbuffer_); + + TrpEData trpdata; + TrpEData trpdata__; + TrpEData trpdata___; + bool goodtrpdata = false; + bool goodtrpdata__ = false; + bool goodtrpdata___ = false; + + bool trpbuffernearfull; + for (unsigned int istep = 0; istep < maxStep_; istep++) { + CircularBuffer& trpdatabuffer = std::get<0>(trpbuffer_); + trpbuffernearfull = trpdatabuffer.nearfull(); + + // + // First block here checks if there is a trpunit with data that should be used + // to calculate the tracklet parameters + // + + // set pointer to the last filled trpunit + TripletEngineUnit* trpunitptr = nullptr; + for (auto& trpunit : trpunits_) { + trpunit.setNearFull(); + if (!trpunit.empty()) { + trpunitptr = &trpunit; + } + } + + if (trpunitptr != nullptr) { + auto stubtriplet = trpunitptr->read(); + + countall++; + + const Stub* innerFPGAStub = std::get<0>(stubtriplet); + const Stub* middleFPGAStub = std::get<1>(stubtriplet); + const Stub* outerFPGAStub = std::get<2>(stubtriplet); + + const L1TStub* innerStub = innerFPGAStub->l1tstub(); + const L1TStub* middleStub = middleFPGAStub->l1tstub(); + const L1TStub* outerStub = outerFPGAStub->l1tstub(); + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "TrackletProcessorDisplaced execute " << getName() << "[" << iSector_ << "]"; + } + + // check if the seed made from the 3 stubs is valid + bool accept = false; + if (iSeed_ == Seed::L2L3L4 || iSeed_ == Seed::L4L5L6) + accept = LLLSeeding(innerFPGAStub, innerStub, middleFPGAStub, middleStub, outerFPGAStub, outerStub); + else if (iSeed_ == Seed::L2L3D1) + accept = LLDSeeding(innerFPGAStub, innerStub, middleFPGAStub, middleStub, outerFPGAStub, outerStub); + else if (iSeed_ == Seed::D1D2L2) + accept = DDLSeeding(innerFPGAStub, innerStub, middleFPGAStub, middleStub, outerFPGAStub, outerStub); + + if (accept) + countsel++; + + if (trackletpars_->nTracklets() >= settings_.ntrackletmax()) { + edm::LogVerbatim("Tracklet") << "Will break on number of tracklets in " << getName(); + assert(0); + break; + } + + if (settings_.debugTracklet()) { + edm::LogVerbatim("Tracklet") << "TrackletProcessor execute done"; + } + } + + // + // The second block fills the trpunit if data in buffer and process TripletEngineUnit step + // + // + + bool notemptytrpbuffer = !trpdatabuffer.empty(); + for (auto& trpunit : trpunits_) { + if (trpunit.idle() && notemptytrpbuffer) { // only fill one idle unit every step + trpunit.init(std::get<0>(trpbuffer_).read()); + notemptytrpbuffer = false; //prevent initializing another triplet engine unit + } + trpunit.step(); + } + + // + // The third block here checks if we have input stubs to process + // + // + + if (goodtrpdata___) + trpdatabuffer.store(trpdata___); + goodtrpdata = false; + + unsigned int& istub = std::get<1>(trpbuffer_); + unsigned int& midmem = std::get<2>(trpbuffer_); + unsigned int midmemend = std::get<4>(trpbuffer_); + + if ((!trpbuffernearfull) && midmem < midmemend && istub < middleallstubs_[midmem]->nStubs()) { + const Stub* stub = middleallstubs_[midmem]->getStub(istub); if (settings_.debugTracklet()) { edm::LogVerbatim("Tracklet") << "In " << getName() << " have middle stub"; } // get r/z index of the middle stub - int indexz = (((1 << (midallstub->z().nbits() - 1)) + midallstub->z().value()) >> - (midallstub->z().nbits() - nbitszfinebintable_)); + int indexz = (((1 << (stub->z().nbits() - 1)) + stub->z().value()) >> (stub->z().nbits() - nbitszfinebintable_)); int indexr = -1; - bool negdisk = (midallstub->disk().value() < 0); // check if disk in negative z region - if (layerdisk1_ >= LayerDisk::D1) { // if a disk + bool negdisk = (stub->disk().value() < 0); // check if disk in negative z region + if (layerdisk1_ >= LayerDisk::D1) { // if a disk if (negdisk) indexz = (1 << nbitszfinebintable_) - indexz; - indexr = midallstub->r().value(); - if (midallstub->isPSmodule()) { - indexr = midallstub->r().value() >> (midallstub->r().nbits() - nbitsrfinebintable_); + indexr = stub->r().value(); + if (stub->isPSmodule()) { + indexr = stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_); } } else { // else a layer - indexr = (((1 << (midallstub->r().nbits() - 1)) + midallstub->r().value()) >> - (midallstub->r().nbits() - nbitsrfinebintable_)); + indexr = (((1 << (stub->r().nbits() - 1)) + stub->r().value()) >> (stub->r().nbits() - nbitsrfinebintable_)); } - assert(indexz >= 0); - assert(indexr >= 0); - assert(indexz < (1 << nbitszfinebintable_)); - assert(indexr < (1 << nbitsrfinebintable_)); - // create lookupbits that define projections from middle stub - unsigned int lutwidth = settings_.lutwidthtabextended(0, iSeed_); int lutval = -1; const auto& lutshift = innerTable_.nbits(); lutval = innerTable_.lookup((indexz << nbitsrfinebintable_) + indexr); int lutval2 = innerThirdTable_.lookup((indexz << nbitsrfinebintable_) + indexr); if (lutval != -1 && lutval2 != -1) lutval += (lutval2 << lutshift); - if (lutval == -1) - continue; - FPGAWord lookupbits(lutval, lutwidth, true, __LINE__, __FILE__); - - // get r/z bins for projection into outer layer/disk - int nbitsrzbin = N_RZBITS; - if (iSeed_ == Seed::D1D2L2) - nbitsrzbin--; - int rzbinfirst = lookupbits.bits(0, NFINERZBITS); - int next = lookupbits.bits(NFINERZBITS, 1); - int rzdiffmax = lookupbits.bits(NFINERZBITS + 1 + nbitsrzbin, NFINERZBITS); - - int start = lookupbits.bits(NFINERZBITS + 1, nbitsrzbin); // first rz bin projection - if (iSeed_ == Seed::D1D2L2 && negdisk) // if projecting into disk - start += (1 << nbitsrzbin); - int last = start + next; // last rz bin projection - - if (settings_.debugTracklet()) { - edm::LogVerbatim("Tracklet") << "Will look in r/z bins for outer stub " << start << " to " << last << endl; - } - // loop over outer stubs that the middle stub can project to - for (int ibin = start; ibin <= last; ibin++) { - for (unsigned int outmem = 0; outmem < outervmstubs_.size(); outmem++) { - for (unsigned int j = 0; j < outervmstubs_[outmem]->nVMStubsBinned(ibin); j++) { - if (settings_.debugTracklet()) - edm::LogVerbatim("Tracklet") << "In " << getName() << " have outer stub" << endl; - - const VMStubTE& outvmstub = outervmstubs_[outmem]->getVMStubTEBinned(ibin, j); - - // check if r/z of outer stub is within projection range - int rzbin = (outvmstub.vmbits().value() & (settings_.NLONGVMBINS() - 1)); - if (start != ibin) - rzbin += 8; - if (rzbin < rzbinfirst || rzbin - rzbinfirst > rzdiffmax) { - if (settings_.debugTracklet()) { - edm::LogVerbatim("Tracklet") << "Outer stub rejected because of wrong r/z bin"; - } - continue; - } - - // get r/z bins for projection into third layer/disk - int nbitsrzbin_ = N_RZBITS; - int next_ = lookupbits.bits(lutshift + NFINERZBITS, 1); - - int start_ = lookupbits.bits(lutshift + NFINERZBITS + 1, nbitsrzbin_); // first rz bin projection - if (iSeed_ == Seed::D1D2L2 && negdisk) // if projecting from disk into layer - start_ = settings_.NLONGVMBINS() - 1 - start_ - next_; - int last_ = start_ + next_; // last rz bin projection - - if (settings_.debugTracklet()) { - edm::LogVerbatim("Tracklet") - << "Will look in rz bins for inner stub " << start_ << " to " << last_ << endl; - } - - // loop over inner stubs that the middle stub can project to - for (int ibin_ = start_; ibin_ <= last_; ibin_++) { - for (unsigned int inmem = 0; inmem < innervmstubs_.size(); inmem++) { - for (unsigned int k = 0; k < innervmstubs_[inmem]->nVMStubsBinned(ibin_); k++) { - if (settings_.debugTracklet()) - edm::LogVerbatim("Tracklet") << "In " << getName() << " have inner stub" << endl; - - const VMStubTE& invmstub = innervmstubs_[inmem]->getVMStubTEBinned(ibin_, k); - - countall++; - - const Stub* innerFPGAStub = invmstub.stub(); - const Stub* middleFPGAStub = midallstub; - const Stub* outerFPGAStub = outvmstub.stub(); - - const L1TStub* innerStub = innerFPGAStub->l1tstub(); - const L1TStub* middleStub = middleFPGAStub->l1tstub(); - const L1TStub* outerStub = outerFPGAStub->l1tstub(); - - if (settings_.debugTracklet()) { - edm::LogVerbatim("Tracklet") - << "triplet seeding\n" - << innerFPGAStub->strbare() << middleFPGAStub->strbare() << outerFPGAStub->strbare() - << innerStub->stubword() << middleStub->stubword() << outerStub->stubword() - << innerFPGAStub->layerdisk() << middleFPGAStub->layerdisk() << outerFPGAStub->layerdisk(); - edm::LogVerbatim("Tracklet") - << "TrackletCalculatorDisplaced execute " << getName() << "[" << iSector_ << "]"; - } - - // check if the seed made from the 3 stubs is valid - bool accept = false; - if (iSeed_ == Seed::L2L3L4 || iSeed_ == Seed::L4L5L6) - accept = LLLSeeding(innerFPGAStub, innerStub, middleFPGAStub, middleStub, outerFPGAStub, outerStub); - else if (iSeed_ == Seed::L2L3D1) - accept = LLDSeeding(innerFPGAStub, innerStub, middleFPGAStub, middleStub, outerFPGAStub, outerStub); - else if (iSeed_ == Seed::D1D2L2) - accept = DDLSeeding(innerFPGAStub, innerStub, middleFPGAStub, middleStub, outerFPGAStub, outerStub); - - if (accept) - countsel++; - - if (settings_.debugTracklet()) { - edm::LogVerbatim("Tracklet") << "TrackletCalculatorDisplaced execute done"; - } - if (countall >= settings_.maxStep("TPD")) - break; - } - if (countall >= settings_.maxStep("TPD")) - break; - } - if (countall >= settings_.maxStep("TPD")) - break; - } - if (countall >= settings_.maxStep("TPD")) - break; + if (lutval != -1) { + unsigned int lutwidth = settings_.lutwidthtabextended(0, iSeed_); + FPGAWord lookupbits(lutval, lutwidth, true, __LINE__, __FILE__); + + // get r/z bins for projection into outer layer/disk + int nbitsrzbin_out = N_RZBITS; + if (iSeed_ == Seed::D1D2L2) + nbitsrzbin_out--; + int rzbinfirst_out = lookupbits.bits(0, NFINERZBITS); + int rzdiffmax_out = lookupbits.bits(NFINERZBITS + 1 + nbitsrzbin_out, NFINERZBITS); + int start_out = lookupbits.bits(NFINERZBITS + 1, nbitsrzbin_out); // first rz bin projection + int next_out = lookupbits.bits(NFINERZBITS, 1); + if (iSeed_ == Seed::D1D2L2 && negdisk) // if projecting into disk + start_out += (1 << nbitsrzbin_out); + int last_out = start_out + next_out; // last rz bin projection + + // get r/z bins for projection into third (inner) layer/disk + int nbitsrzbin_in = N_RZBITS; + int start_in = lookupbits.bits(lutshift + NFINERZBITS + 1, nbitsrzbin_in); // first rz bin projection + int next_in = lookupbits.bits(lutshift + NFINERZBITS, 1); + if (iSeed_ == Seed::D1D2L2 && negdisk) // if projecting from disk into layer + start_in = settings_.NLONGVMBINS() - 1 - start_in - next_in; + int last_in = start_in + next_in; // last rz bin projection + + // fill trpdata with projection info of middle stub + trpdata.stub_ = stub; + trpdata.rzbinfirst_out_ = rzbinfirst_out; + trpdata.rzdiffmax_out_ = rzdiffmax_out; + trpdata.start_out_ = start_out; + trpdata.start_in_ = start_in; + + // fill projection bins info for single engine unit + trpdata.projbin_out_.clear(); + trpdata.projbin_in_.clear(); + for (int ibin_out = start_out; ibin_out <= last_out; ibin_out++) { + for (unsigned int outmem = 0; outmem < outervmstubs_.size(); outmem++) { + int nstubs_out = outervmstubs_[outmem]->nVMStubsBinned(ibin_out); + if (nstubs_out > 0) + trpdata.projbin_out_.emplace_back(tuple(ibin_out - start_out, outmem, nstubs_out)); + } + } + for (int ibin_in = start_in; ibin_in <= last_in; ibin_in++) { + for (unsigned int inmem = 0; inmem < innervmstubs_.size(); inmem++) { + int nstubs_in = innervmstubs_[inmem]->nVMStubsBinned(ibin_in); + if (nstubs_in > 0) + trpdata.projbin_in_.emplace_back(tuple(ibin_in - start_in, inmem, nstubs_in)); } - if (countall >= settings_.maxStep("TPD")) - break; } - if (countall >= settings_.maxStep("TPD")) - break; + + if (!trpdata.projbin_in_.empty() && !trpdata.projbin_out_.empty()) { + goodtrpdata = true; + } } - if (countall >= settings_.maxStep("TPD")) - break; + + istub++; + if (istub >= middleallstubs_[midmem]->nStubs()) { + istub = 0; + midmem++; + } + + } else if ((!trpbuffernearfull) && midmem < midmemend && istub == 0) + midmem++; + + goodtrpdata___ = goodtrpdata__; + goodtrpdata__ = goodtrpdata; + + trpdata___ = trpdata__; + trpdata__ = trpdata; + + // + // stop looping over istep if done + // + + bool done = true; + + if (midmem < midmemend || (!trpdatabuffer.empty())) { + done = false; + } + + for (auto& trpunit : trpunits_) { + if (!(trpunit.idle() && trpunit.empty())) + done = false; } - if (countall >= settings_.maxStep("TPD")) + + if (done) { + donecount++; + } + + //FIXME This should be done cleaner... Not too hard, but need to check fully the TEBuffer and TEUnit buffer. + if (donecount > 4) { break; + } } if (settings_.writeMonitorData("TPD")) { - globals_->ofstream("trackletprocessordisplaced.txt") << getName() << " " << countall << " " << countsel << endl; + globals_->ofstream("trackletprocessordisplaced.txt") + << getName() << " " << countall << " " << countsel << std::endl; } } diff --git a/L1Trigger/TrackFindingTracklet/src/TripletEngineUnit.cc b/L1Trigger/TrackFindingTracklet/src/TripletEngineUnit.cc new file mode 100644 index 0000000000000..709cf34bfd468 --- /dev/null +++ b/L1Trigger/TrackFindingTracklet/src/TripletEngineUnit.cc @@ -0,0 +1,112 @@ +#include "L1Trigger/TrackFindingTracklet/interface/TripletEngineUnit.h" +#include "L1Trigger/TrackFindingTracklet/interface/Settings.h" + +using namespace trklet; + +// TripletEngineUnit +// +// This script sets a processing unit for the TrackletProcessorDisplaced +// based on information from the middle stub and its projections in and out, +// and a new triplet seed is checked and created for each processing step +// +// Author: Claire Savard, Nov. 2024 + +TripletEngineUnit::TripletEngineUnit(const Settings* const settings, + unsigned int layerdisk1, + unsigned int layerdisk2, + unsigned int layerdisk3, + unsigned int iSeed, + std::vector innervmstubs, + std::vector outervmstubs) + : settings_(settings), candtriplets_(3) { + idle_ = true; + layerdisk1_ = layerdisk1; + layerdisk2_ = layerdisk2; + layerdisk3_ = layerdisk3; + iSeed_ = iSeed; + innervmstubs_ = innervmstubs; + outervmstubs_ = outervmstubs; +} + +void TripletEngineUnit::init(const TrpEData& trpdata) { + trpdata_ = trpdata; + istub_out_ = 0; + istub_in_ = 0; + nproj_out_ = 0; + nproj_in_ = 0; + idle_ = false; + + assert(!trpdata_.projbin_out_.empty() && !trpdata_.projbin_in_.empty()); + std::tie(next_out_, outmem_, nstub_out_) = trpdata_.projbin_out_[0]; + std::tie(next_in_, inmem_, nstub_in_) = trpdata_.projbin_in_[0]; +} + +void TripletEngineUnit::reset() { + idle_ = true; + goodtriplet_ = false; + goodtriplet__ = false; + candtriplets_.reset(); +} + +void TripletEngineUnit::step() { + if (goodtriplet__) { + candtriplets_.store(candtriplet__); + } + + goodtriplet__ = goodtriplet_; + candtriplet__ = candtriplet_; + + goodtriplet_ = false; + + if (idle_ || nearfull_) { + return; + } + + // get inner and outer projected stub for certain next value + int ibin_out = trpdata_.start_out_ + next_out_; + int ibin_in = trpdata_.start_in_ + next_in_; + const VMStubTE& outervmstub = outervmstubs_[outmem_]->getVMStubTEBinned(ibin_out, istub_out_); + const VMStubTE& innervmstub = innervmstubs_[inmem_]->getVMStubTEBinned(ibin_in, istub_in_); + + // check if r/z of outer stub is within projection range + int rzbin = (outervmstub.vmbits().value() & (settings_->NLONGVMBINS() - 1)); + if (trpdata_.start_out_ != ibin_out) + rzbin += 8; + if (rzbin < trpdata_.rzbinfirst_out_ || rzbin - trpdata_.rzbinfirst_out_ > trpdata_.rzdiffmax_out_) { + if (settings_->debugTracklet()) { + edm::LogVerbatim("Tracklet") << "Outer stub rejected because of wrong r/z bin"; + } + } else { + candtriplet_ = + std::tuple(innervmstub.stub(), trpdata_.stub_, outervmstub.stub()); + goodtriplet_ = true; + } + + // go to next projection (looping through all inner stubs for each outer stub) + istub_in_++; + if (istub_in_ >= nstub_in_) { // if gone through all in stubs, move to next in proj bin + nproj_in_++; + istub_in_ = 0; + if (nproj_in_ >= trpdata_.projbin_in_.size()) { // if gone through all in proj bins, move to next out stub + istub_out_++; + nproj_in_ = 0; + if (istub_out_ >= nstub_out_) { // if gone through all out stubs, move to next out proj bin + nproj_out_++; + istub_out_ = 0; + if (nproj_out_ >= + trpdata_.projbin_out_.size()) { // if gone through all out proj bins, reset everything and stop engine unit + istub_in_ = 0; + istub_out_ = 0; + nproj_in_ = 0; + nproj_out_ = 0; + idle_ = true; + return; + } + // get next out proj bin + std::tie(next_out_, outmem_, nstub_out_) = trpdata_.projbin_out_[nproj_out_]; + } + } + // get next in proj bin + std::tie(next_in_, inmem_, nstub_in_) = trpdata_.projbin_in_[nproj_in_]; + } +}