diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.h b/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.h index c31755a0fb0e9..2c1866adf0a6f 100644 --- a/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.h +++ b/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -13,7 +14,7 @@ namespace l1ct { namespace tdr_regionizer { - inline int dphi_wrap(int local_phi) { + inline int phi_wrap(int local_phi) { if (local_phi > l1ct::Scales::INTPHI_PI) local_phi -= l1ct::Scales::INTPHI_TWOPI; else if (local_phi <= -l1ct::Scales::INTPHI_PI) @@ -21,151 +22,260 @@ namespace l1ct { return local_phi; } - // These are done per-sector (= per-input link) + /// corresponds to level1_to_2_pipe_t in firmware template - class PipeObject { + class PipeEntry { public: - PipeObject() {} - PipeObject(const T& obj, std::vector srIndices, int glbphi, int glbeta, unsigned int clk); - - unsigned int getClock() const { return linkobjclk_; } - void setClock(unsigned int clock) { linkobjclk_ = clock; } - const std::vector& getSRIndices() const { return srIndices_; } - size_t getNextSRIndex() const { return srIndices_.at(objcount_); } - unsigned int getCount() const { return objcount_; } - void incCount() { objcount_++; } - int getPt() const { return obj_.hwPt.to_int(); } - int getGlbPhi() const { return glbphi_; } - int getGlbEta() const { return glbeta_; } - - T& getRawObj() { return obj_; } - const T& getRawObj() const { return obj_; } + PipeEntry() : obj_(), sr_(-1) {} + PipeEntry(const T& obj, int sr, int glbeta, int glbphi) : obj_(obj), sr_(sr), glbeta_(glbeta), glbphi_(glbphi) {} + + int sr() const { return sr_; } + + // Note, this returns a copy so you can modify + T obj() const { return obj_; } + + bool valid() const { return sr_ >= 0; } + + void setInvalid() { sr_ = -1; } + + int pt() const { return obj_.intPt(); } + int glbPhi() const { return glbphi_; } + int glbEta() const { return glbeta_; } + + private: + T obj_; + /// the SR linearized indices (can index regionmap_) where this object needs to go; -1 means invalid + int sr_; + /// The global eta and phi of the object (hard to get with duplicates) + int glbeta_, glbphi_; + }; + + /// The pipe, with multiple inputs and one output + template + class Pipe { + public: + /// if using the default constructor, have to call setTaps before use + Pipe() : pipe_() {} + + Pipe(size_t ntaps) : pipe_(ntaps) {} + + void setTaps(size_t taps) { pipe_.resize(taps); } + + /// check if the entry is valid (i.e. already has data) + bool valid(size_t idx) const { return pipe_.at(idx).valid(); } + + /// should check if valid before adding an entry + void addEntry(size_t idx, const PipeEntry& entry) { pipe_[idx] = entry; } + + /// perform one tick, shifting all the entries to higher indices, and returning the last + PipeEntry popEntry(); + + void reset(); + + size_t size() const { return pipe_.size(); } + + /// for debug + const PipeEntry& entry(size_t idx) const { return pipe_[idx]; } + + private: + std::vector> pipe_; + }; + + /// The pipe, with multiple inputs and one output + template + class Pipes { + public: + /// the number of pipes + Pipes(size_t nregions) : pipes_(nregions / SRS_PER_RAM) {} + + /// set the number of taps in each pipe + void setTaps(size_t taps); + + /// check if the entry is valid (i.e. already has data) + bool valid(int sr, size_t logicBufIdx) const { return pipes_[pipeIndex(sr)].valid(logicBufIdx); } + + /// should check if valid before adding an entry + void addEntry(int sr, size_t logicBufIdx, const PipeEntry& entry) { + pipes_[pipeIndex(sr)].addEntry(logicBufIdx, entry); + } + + /// perform one tick, shifting all the entries to higher indices, and returning the last + PipeEntry popEntry(size_t pipe) { return pipes_[pipe].popEntry(); }; + + void reset(); + + size_t size() const { return pipes_.size(); } + + size_t numTaps() const { return pipes_.at(0).size(); } + + /// for debug + const PipeEntry& entry(size_t pipe, size_t tap) const { return pipes_[pipe].entry(tap); } + + private: + /// SRs share RAMs (and hardware pipes) + static size_t constexpr SRS_PER_RAM = 2; + + /// Because some SRs share pipes, this determines the pipe index for a linearize SR index + /// (This is based on the VHDL function, get_target_pipe_index_subindex) + size_t pipeIndex(int sr) const { return sr / SRS_PER_RAM; } + + std::vector> pipes_; + }; + + /// the components that make up the L1 regionizer buffer + template + class BufferEntry { + public: + BufferEntry() {} + BufferEntry(const T& obj, std::vector srIndices, int glbeta, int glbphi, unsigned int clk); + + unsigned int clock() const { return linkobjclk_; } + int nextSR() const { return (objcount_ < srIndices_.size()) ? srIndices_[objcount_] : -1; } + void incSR() { objcount_++; } + int pt() const { return obj_.intPt(); } + int glbPhi() const { return glbphi_; } + int glbEta() const { return glbeta_; } + + //T obj() { return obj_; } + const T& obj() const { return obj_; } private: T obj_; /// the SR linearized indices (can index regionmap_) where this object needs to go std::vector srIndices_; - /// The global eta and phi of the object (somewhat redundant with obj_) + /// The global eta and phi of the object (hard to get with duplicates) int glbeta_, glbphi_; unsigned int linkobjclk_, objcount_; }; + /// The L1 regionizer buffer (corresponding to level1_fifo_buffer.vhd) template - class Pipe { + class Buffer { public: - Pipe(unsigned int nphi = 9) : clkindex_(0), nphi_(nphi) {} + Buffer() : clkindex360_(INIT360), clkindex240_(INIT240), timeOfNextObject_(-1) {} + + void addEntry( + const T& obj, std::vector srs, int glbeta, int glbphi, unsigned int dupNum, unsigned int ndup); + + BufferEntry& front() { return data_.front(); } + const BufferEntry& front() const { return data_.front(); } - void addObj(T obj, std::vector srs, int glbeta, int glbphi); + /// sets the next time something is taken from this buffer + void updateNextObjectTime(int currentTime); - PipeObject& getObj(unsigned int index = 0) { return data_[index]; } - const PipeObject& getObj(unsigned int index = 0) const { return data_[index]; } + /// delete the front element + void pop() { data_.pop_front(); } - unsigned int getClock(unsigned int index = 0) const { return getObj(index).getClock(); } - void setClock(unsigned int clock, unsigned int index = 0) { return getObj(index).setClock(clock); } - unsigned int getCount(unsigned int index = 0) const { return getObj(index).getCount(); } - void incCount(unsigned int index = 0) { getObj(index).incCount(); } - void erase(unsigned int index = 0) { data_.erase(data_.begin() + index); } - int getPt(unsigned int index = 0) const { return getObj(index).getPt(); } - int getGlbPhi(unsigned int index = 0) const { return getObj(index).getGlbPhi(); } - int getGlbEta(unsigned int index = 0) const { return getObj(index).getGlbEta(); } + // mostly for debug + unsigned int clock(unsigned int index = 0) const { return data_[index].clock(); } + int pt(unsigned int index = 0) const { return data_[index].pt(); } + int glbPhi(unsigned int index = 0) const { return data_[index].glbPhi(); } + int glbEta(unsigned int index = 0) const { return data_[index].glbEta(); } - int getClosedIndexForObject(unsigned int index = 0); - /// This returns the hardware pipe index (since there are one per SR pair) - size_t getPipeIndexForObject(unsigned int index = 0); + unsigned int numEntries() const { return data_.size(); } - unsigned int getPipeSize() const { return data_.size(); } + /// pop the first entry, formatted for inclusion in pipe + PipeEntry popEntry(int currTime, bool debug); + + int timeOfNextObject() const { return timeOfNextObject_; } void reset() { - clkindex_ = 0; + clkindex360_ = INIT360; + clkindex240_ = INIT240; data_.clear(); + timeOfNextObject_ = -1; } private: - unsigned int clkindex_, nphi_; - std::vector> data_; + // used when building up the linkobjclk_ entries for the BufferEntries + unsigned int nextObjClk(unsigned int ndup); + + // transient--used only during event construction, not used after + // Counts in 1.39ns increments (i.e. 360 increments by 2, 240 by 3) + unsigned int clkindex360_; + unsigned int clkindex240_; + + static unsigned int constexpr INIT360 = 1; + static unsigned int constexpr INIT240 = 0; + + /// The actual data + std::deque> data_; + + /// the time of the next object in the buffer (-1 if none) + int timeOfNextObject_; }; template class Regionizer { public: - Regionizer() {} + Regionizer() = delete; Regionizer(unsigned int neta, - unsigned int nphi, //the number of eta and phi SRs in a big region (board) - unsigned int nregions, // The total number of small regions in the full barrel + unsigned int nphi, //the number of eta and phi SRs in a big region (board) unsigned int maxobjects, int bigRegionMin, int bigRegionMax, // the phi range covered by this board - int nclocks); + unsigned int nclocks, + unsigned int ndup = 1, // how much one duplicates the inputs (to increase processing bandwidth) + bool debug = false); void initSectors(const std::vector>& sectors); void initSectors(const DetectorSector& sector); void initRegions(const std::vector& regions); - // is the given small region in the big region - bool isInBigRegion(const PFRegionEmu& reg) const; + void fillBuffers(const std::vector>& sectors); + void fillBuffers(const DetectorSector& sector); - unsigned int getSize() const { return pipes_.size(); } - unsigned int getPipeSize(unsigned int linkIndex) const { return pipes_[linkIndex].getPipeSize(); } + void run(); - std::vector getSmallRegions(int glbeta, int glbphi) const; + void reset(); - void addToPipe(const T& obj, unsigned int index); - void setPipe(const std::vector& objvec, unsigned int index); - void setPipes(const std::vector>& objvecvec); + /// Return a map of of the SRs indexed by SR index (covering only those from board) + std::map> fillRegions(bool doSort); - // linkIndex == sector - int getPipeTime(int linkIndex, int linkTimeOfObject, int linkAlgoClockRunningTime); + void printDebug(int count) const; - /// This either removes the next object on the link or inrements the count; It returns the next time - int popLinkObject(int linkIndex, int currentTimeOfObject); - int timeNextFromIndex(unsigned int linkIndex, int time) { - return getPipeTime(linkIndex, pipes_[linkIndex].getClock(), time); - } + private: + /// is the given small region in the big region + bool isInBigRegion(const PFRegionEmu& reg) const; - void initTimes(); + /// Does the given region fit in the big region, taking into account overlaps? + bool isInBigRegionLoose(const PFRegionEmu& reg) const; - int getClosedIndexForObject(unsigned int linknum, unsigned int index = 0) { - return pipes_[linknum].getClosedIndexForObject(index); - } + unsigned int numBuffers() const { return buffers_.size(); } + unsigned int numEntries(unsigned int bufferIndex) const { return buffers_[bufferIndex].numEntries(); } - /// This retruns the linearized small region associated with the given item - size_t getPipeIndexForObject(unsigned int linknum, unsigned int index = 0) { - return pipes_[linknum].getPipeIndexForObject(index); - } + std::vector getSmallRegions(int glbeta, int glbphi) const; - /// This returns the hardware pipe number of the item. Generally two SRs share a pipe - size_t getHardwarePipeIndexForObject(unsigned int linknum, unsigned int index = 0) { - return getHardwarePipeIndex(getPipeIndexForObject(linknum, index)); - } + void addToBuffer(const T& obj, unsigned int index, unsigned int dupNum); + void setBuffer(const std::vector& objvec, unsigned int index); + void setBuffers(const std::vector>&& objvecvec); - /// 'put' object in small region - void addToSmallRegion(unsigned int linkNum, unsigned int index = 0); + /// This retruns the linearized small region associated with the given item (-1 is throwout) + int nextSR(unsigned int linknum, unsigned int index = 0) { return buffers_[linknum].nextSR(index); } - void run(bool debug = false); + /// 'put' object in small region + void addToSmallRegion(PipeEntry&&); - void reset(); + /// returns 2D arrays, sectors (links) first dimension, objects second + std::vector> fillLinks(const std::vector>& sectors) const; + std::vector> fillLinks(const DetectorSector& sector) const; - /// Return a map of of the SRs indexed by SR index (covering only those from board) - std::map> fillRegions(bool doSort); + // this function is for sorting small regions first in phi and then in eta. + // It takes regions_ indices + bool sortRegionsRegular(size_t a, size_t b) const; - void printDebug(int count) const; + bool sortSectors(size_t a, size_t b) const; - private: - /// SRs share RAMs (and hardware pipes) - static size_t constexpr SRS_PER_RAM = 2; + bool sortRegionsHelper(int etaa, int etab, int phia, int phib) const; - /// Because some SRs share pipes, this determines the pipe index for a linearize SR index - /// (This is based on the VHDL function, get_target_pipe_index_subindex) - size_t getHardwarePipeIndex(size_t srIndex) const { return srIndex / SRS_PER_RAM; } + /// get the index in regions_ for a particular SR. + size_t regionIndex(int sr) const { return regionmap_.at(sr); } - // this function is for sorting small regions first in phi and then in eta. - // It takes regions_ indices - bool sortRegionsRegular(size_t a, size_t b) const; + /// get the logical buffer index (i.e. the index in the order in the firmware) + size_t logicBuffIndex(size_t bufIdx) const; /// The numbers of eta and phi in a big region (board) unsigned int neta_, nphi_; - /// The total number of small regions in the barrel (not just in the board) - unsigned int nregions_; /// The maximum number of objects to output per small region unsigned int maxobjects_; /// The number of input sectors for this type of device @@ -175,7 +285,9 @@ namespace l1ct { /// the maximum phi of this board int bigRegionMax_; /// the number of clocks to receive one event - int nclocks_; + unsigned int nclocks_; + /// How many buffers per link (default 1) + unsigned int ndup_; /// the region information assopciated with each input sector std::vector sectors_; @@ -186,13 +298,28 @@ namespace l1ct { /// indices of regions that are in the big region (board) std::vector regionmap_; - /// One pipe per each sector (link). These do not correspond to the firmware pipes - std::vector> pipes_; - /// One entry per sector (= link = pipe). If the pipe is empty, this is always -1 - std::vector timeOfNextObject_; + /// indices maps the sectors from the way they appear in the software to the order they are done in the regionizer + std::vector sectormap_; + + /// the inverse mapping of sectormap_ (only used for debug printing) + std::vector invsectormap_; + + /// The buffers. There are ndup_ buffers per link/sector + std::vector> buffers_; + + /// The pipes, one per ram (see SRS_PER_RAM) + Pipes pipes_; /// The objects in each small region handled in board; Indexing corresponds to that in regionmap_ std::vector> smallRegionObjects_; + + /// Whether this is the first event (since timing is a bit different then) + bool firstEvent_; + + /// This is the delay (only applied after first event) before processing starts + static unsigned int constexpr DELAY_TO_START = 10; + + bool debug_; }; } // namespace tdr_regionizer diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.icc b/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.icc index a2699b086e0b8..6456c5712b483 100644 --- a/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.icc +++ b/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.icc @@ -1,77 +1,235 @@ +#include +#include "L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_elements_ref.h" +// PIPE ENTRY AND BUFFER template -l1ct::tdr_regionizer::PipeObject::PipeObject( - const T& obj, std::vector srIndices, int glbphi, int glbeta, unsigned int clk) +l1ct::tdr_regionizer::PipeEntry l1ct::tdr_regionizer::Pipe::popEntry() { + assert(pipe_.size() > 0); + auto last = pipe_.back(); + // shift one over + for (size_t i = pipe_.size() - 1; i > 0; --i) { + pipe_[i] = pipe_[i - 1]; + } + pipe_[0].setInvalid(); + return last; +} + +template +void l1ct::tdr_regionizer::Pipe::reset() { + for (auto& pe : pipe_) { + pe.setInvalid(); + } +} + +template +void l1ct::tdr_regionizer::Pipes::reset() { + for (auto& pipe : pipes_) { + pipe.reset(); + } +} + +template +void l1ct::tdr_regionizer::Pipes::setTaps(size_t taps) { + for (auto& pipe : pipes_) { + pipe.setTaps(taps); + } +} + +// BUFFER ENTRY AND BUFFER +template +l1ct::tdr_regionizer::BufferEntry::BufferEntry( + const T& obj, std::vector srIndices, int glbeta, int glbphi, unsigned int clk) : obj_(obj), srIndices_(srIndices), glbeta_(glbeta), glbphi_(glbphi), linkobjclk_(clk) { objcount_ = 0; } template -void l1ct::tdr_regionizer::Pipe::addObj(T obj, std::vector srIndices, int glbeta, int glbphi) { - data_.emplace_back(obj, srIndices, glbeta, glbphi, clkindex_++); +inline void l1ct::tdr_regionizer::Buffer::addEntry( + const T& obj, std::vector srIndices, int glbeta, int glbphi, unsigned int dupNum, unsigned int ndup) { + // dupNum is the duplicate number of this buffer (int range 0 to ndup_-1) + auto objClk = nextObjClk(ndup); + data_.emplace_back(obj, srIndices, glbeta, glbphi, objClk); + if (timeOfNextObject_ < 0) { + timeOfNextObject_ = objClk; + } +} + +template +void l1ct::tdr_regionizer::Buffer::updateNextObjectTime(int currTime) { + if (data_.size() > 0) { + timeOfNextObject_ = std::max(front().clock(), static_cast(currTime + 1)); + } else { + timeOfNextObject_ = -1; + } +} + +template +inline unsigned int l1ct::tdr_regionizer::Buffer::nextObjClk(unsigned int ndup) { + unsigned int nextVal = std::max(clkindex360_, clkindex240_) / 3; + + clkindex360_ += 2 * ndup; + clkindex240_ += 3; + + return nextVal; } -//explicit for tracker to handle clocking + +// explicit for tracks template <> -inline void l1ct::tdr_regionizer::Pipe::addObj(l1ct::TkObjEmu obj, - std::vector srIndices, - int glbeta, - int glbphi) { - data_.emplace_back(obj, srIndices, glbeta, glbphi, clkindex_++); - if (clkindex_ % 3 == 2) - clkindex_++; //this is for tracker, could I get this generically maybe? +inline unsigned int l1ct::tdr_regionizer::Buffer::nextObjClk(unsigned int ndup) { + if (ndup != 1) { + throw std::invalid_argument("Only ndup==1 is currently supported for the TkObjEmu buffers."); + } + + unsigned int nextVal = std::max(clkindex360_, clkindex240_) / 3; + + clkindex360_ += 2; + if ((clkindex360_ - INIT360) % 6 == 4) { + clkindex360_ += 2; + } + + clkindex240_ += 3; + + return nextVal; } template -size_t l1ct::tdr_regionizer::Pipe::getPipeIndexForObject(unsigned int index) { - return getObj(index).getNextSRIndex(); +l1ct::tdr_regionizer::PipeEntry l1ct::tdr_regionizer::Buffer::popEntry(int currTime, bool debug) { + if (front().nextSR() < 0) { + // throwout + pop(); + if (debug) { + dbgCout() << "updating time clock = " << front().clock() << ", currTime = " << currTime << std::endl; + } + updateNextObjectTime(currTime); + return l1ct::tdr_regionizer::PipeEntry(); + } + + auto pipeEntry = + l1ct::tdr_regionizer::PipeEntry(front().obj(), front().nextSR(), front().glbEta(), front().glbPhi()); + front().incSR(); + if (front().nextSR() < 0) { + // no more SRs for current front + pop(); + } else { + if (debug) { + dbgCout() << "Remain on same object, nextSR = " << front().nextSR() << std::endl; + } + // this is a processing_stall, but throwouts that follow can still be dropped + // due to the pipeline have to look two ticks back + if (numEntries() > 1 && data_[1].nextSR() == -1 && static_cast(data_[1].clock()) == currTime + 2) { + if (debug) { + dbgCout() << "removing a following throwout with time " << data_[1].clock() << std::endl; + } + data_.erase(data_.begin() + 1); + } else if (numEntries() > 2 && data_[2].nextSR() == -1 && static_cast(data_[2].clock()) <= currTime + 2) { + if (debug) { + dbgCout() << "removing the two-back throwout with time " << data_[2].clock() << std::endl; + } + data_.erase(data_.begin() + 2); + } + } + if (debug) { + dbgCout() << "updating time clock = " << front().clock() << ", currTime = " << currTime << std::endl; + } + + updateNextObjectTime(currTime); + return pipeEntry; } +// REGIONIZER template l1ct::tdr_regionizer::Regionizer::Regionizer(unsigned int neta, unsigned int nphi, - unsigned int nregions, unsigned int maxobjects, int bigRegionMin, int bigRegionMax, - int nclocks) + unsigned int nclocks, + unsigned int ndup, + bool debug) : neta_(neta), nphi_(nphi), - nregions_(nregions), maxobjects_(maxobjects), nsectors_(0), bigRegionMin_(bigRegionMin), bigRegionMax_(bigRegionMax), - nclocks_(nclocks) { - smallRegionObjects_.resize(neta_ * nphi_); -} + nclocks_(nclocks), + ndup_(ndup), + pipes_(neta * nphi), + smallRegionObjects_(neta * nphi), + firstEvent_(true), + debug_(debug) {} template void l1ct::tdr_regionizer::Regionizer::initSectors(const std::vector>& sectors) { assert(nsectors_ == 0); - nsectors_ = sectors.size(); - sectors_.resize(nsectors_); - pipes_.resize(nsectors_); - for (unsigned int i = 0; i < nsectors_; ++i) { - sectors_[i] = sectors[i].region; + + // we need a mapping of physical (what's in the sectors variable) to logical, + // but it's easier to create the inverse, first + + for (const auto& sector : sectors) { + if (isInBigRegionLoose(sector.region)) { + invsectormap_.push_back(sectors_.size()); + sectors_.push_back(sector.region); + } } + nsectors_ = sectors_.size(); + buffers_.resize(nsectors_ * ndup_); + if (debug_) { + dbgCout() << "Number of sectors: " << nsectors_ << std::endl; + } + + std::sort(invsectormap_.begin(), invsectormap_.end(), [this](size_t a, size_t b) { return this->sortSectors(a, b); }); + + // now invert the invsectormap_ + sectormap_.resize(invsectormap_.size()); + for (size_t i = 0; i < invsectormap_.size(); ++i) { + sectormap_[invsectormap_[i]] = i; + } + + pipes_.setTaps(nsectors_ * ndup_); } template void l1ct::tdr_regionizer::Regionizer::initSectors(const DetectorSector& sector) { assert(nsectors_ == 0); nsectors_ = 1; - sectors_.resize(1, sector.region); - pipes_.resize(nsectors_); + sectors_.push_back(sector.region); + sectormap_.push_back(0); + buffers_.resize(nsectors_ * ndup_); + if (debug_) { + dbgCout() << "Number of sectors: " << nsectors_ << std::endl; + } + pipes_.setTaps(nsectors_ * ndup_); } -// this function is for sorting small regions first +template +void l1ct::tdr_regionizer::Regionizer::fillBuffers(const std::vector>& sectors) { + setBuffers(fillLinks(sectors)); +} + +template +void l1ct::tdr_regionizer::Regionizer::fillBuffers(const DetectorSector& sector) { + setBuffers(fillLinks(sector)); +} + +// this function is for sorting small regions // in eta first, then in phi template bool l1ct::tdr_regionizer::Regionizer::sortRegionsRegular(size_t a, size_t b) const { // first do eta auto etaa = regions_[a].intEtaCenter(); auto etab = regions_[b].intEtaCenter(); + auto phia = regions_[a].intPhiCenter(); + auto phib = regions_[b].intPhiCenter(); + return sortRegionsHelper(etaa, etab, phia, phib); +} + +// this function is for sorting small regions +// in eta first, then in phi +template +bool l1ct::tdr_regionizer::Regionizer::sortRegionsHelper(int etaa, int etab, int phia, int phib) const { + // first do eta if (etaa < etab) { return true; } else if (etaa > etab) { @@ -79,8 +237,6 @@ bool l1ct::tdr_regionizer::Regionizer::sortRegionsRegular(size_t a, size_t b) } // if here, then etaa == etab, move to phi - auto phia = regions_[a].intPhiCenter(); - auto phib = regions_[b].intPhiCenter(); if (bigRegionMax_ < bigRegionMin_) { // the wraparound case if (phia > bigRegionMin_ && phib < bigRegionMax_) { @@ -97,16 +253,30 @@ bool l1ct::tdr_regionizer::Regionizer::sortRegionsRegular(size_t a, size_t b) } } +// this function is for sorting the sectors +// in eta first, then in phi +template +bool l1ct::tdr_regionizer::Regionizer::sortSectors(size_t a, size_t b) const { + // first do eta + auto etaa = sectors_[a].intEtaCenter(); + auto etab = sectors_[b].intEtaCenter(); + auto phia = sectors_[a].intPhiCenter(); + auto phib = sectors_[b].intPhiCenter(); + return sortRegionsHelper(etaa, etab, phia, phib); +} + template void l1ct::tdr_regionizer::Regionizer::initRegions(const std::vector& regions) { regions_.resize(regions.size()); for (unsigned int i = 0; i < regions.size(); ++i) { regions_[i] = regions[i].region; - // dbgCout() << "region eta/phi: " << regions_[i].intEtaCenter() << " " << regions_[i].intPhiCenter() - // << ", eta half width = " << regions_[i].hwEtaHalfWidth.to_int() - // << ", phi half width = " << regions_[i].hwPhiHalfWidth.to_int() - // << ", eta extra = " << regions_[i].hwEtaExtra.to_int() - // << ", phi extra = " << regions_[i].hwPhiExtra.to_int() << std::endl; + if (debug_) { + dbgCout() << "region eta/phi: " << regions_[i].intEtaCenter() << " " << regions_[i].intPhiCenter() + << ", eta half width = " << regions_[i].hwEtaHalfWidth.to_int() + << ", phi half width = " << regions_[i].hwPhiHalfWidth.to_int() + << ", eta extra = " << regions_[i].hwEtaExtra.to_int() + << ", phi extra = " << regions_[i].hwPhiExtra.to_int() << std::endl; + } if (isInBigRegion(regions_[i])) { regionmap_.push_back(i); } @@ -128,207 +298,290 @@ bool l1ct::tdr_regionizer::Regionizer::isInBigRegion(const PFRegionEmu& reg) } } +template +bool l1ct::tdr_regionizer::Regionizer::isInBigRegionLoose(const PFRegionEmu& reg) const { + auto phi = reg.intPhiCenter(); + auto brmax = phi_wrap(bigRegionMax_ + reg.hwPhiHalfWidth.to_int() + reg.hwPhiExtra.to_int()); + auto brmin = phi_wrap(bigRegionMin_ - reg.hwPhiHalfWidth.to_int() - reg.hwPhiExtra.to_int()); + if (brmax < brmin) { + // the wraparound case + return phi > brmin || phi < brmax; + } else { + // the normal case + return phi > brmin && phi < brmax; + } +} + +template <> +inline bool l1ct::tdr_regionizer::Regionizer::isInBigRegionLoose(const PFRegionEmu& reg) const { + auto phi = reg.intPhiCenter(); + auto brmax = phi_wrap(bigRegionMax_ + 2 * reg.hwPhiHalfWidth.to_int()); + auto brmin = phi_wrap(bigRegionMin_ - 2 * reg.hwPhiHalfWidth.to_int()); + if (brmax < brmin) { + // the wraparound case + return phi > brmin || phi < brmax; + } else { + // the normal case + return phi > brmin && phi < brmax; + } +} + template std::vector l1ct::tdr_regionizer::Regionizer::getSmallRegions(int glbeta, int glbphi) const { std::vector srIndices; // the signal regions this object should go into // only iterate over regions covered by board for (size_t i = 0; i < regionmap_.size(); i++) { - auto regionidx = regionmap_[i]; - int regphi = dphi_wrap(glbphi - regions_[regionidx].intPhiCenter()); + auto regionidx = regionIndex(i); + int regphi = phi_wrap(glbphi - regions_[regionidx].intPhiCenter()); int regeta = glbeta - regions_[regionidx].intEtaCenter(); - if (regions_[regionidx].isInside(regeta, regphi)) { + // add a special check to not have 3 eta regions + if (regions_[regionidx].isInside(regeta, regphi) && + !((glbeta == 57 && regeta == -115) || (glbeta == -57 && regeta == 115))) { srIndices.push_back(i); } } + + // In a silly convention, the order of these nneds to be modified if there are 4. + if (srIndices.size() == 4) { + auto ent1 = srIndices[1]; + srIndices[1] = srIndices[2]; + srIndices[2] = ent1; + } return srIndices; } template -void l1ct::tdr_regionizer::Regionizer::addToPipe(const T& obj, unsigned int sector) { - assert(sector < getSize()); +void l1ct::tdr_regionizer::Regionizer::addToBuffer(const T& obj, unsigned int buffer, unsigned int dupNum) { + assert(buffer < numBuffers()); + const unsigned int sector = buffer / ndup_; auto glbphi = sectors_[sector].hwGlbPhiOf(obj).to_int(); auto glbeta = sectors_[sector].hwGlbEtaOf(obj).to_int(); // get the SR indices that this object should go into - std::vector srIndices = getSmallRegions(glbeta, glbphi); - if (!srIndices.empty()) { - pipes_[sector].addObj(obj, srIndices, glbeta, glbphi); - } + buffers_[buffer].addEntry(obj, getSmallRegions(glbeta, glbphi), glbeta, glbphi, dupNum, ndup_); } template -void l1ct::tdr_regionizer::Regionizer::setPipe(const std::vector& objvec, unsigned int sector) { - assert(sector < getSize()); - pipes_[sector].reset(); - for (unsigned int i = 0; i < objvec.size(); i++) { - addToPipe(objvec[i], sector); +void l1ct::tdr_regionizer::Regionizer::setBuffer(const std::vector& objvec, unsigned int buffer) { + assert(buffer < numBuffers()); + buffers_[buffer].reset(); + unsigned int dupNum = buffer % ndup_; + for (unsigned int i = dupNum; i < objvec.size(); i += ndup_) { + // if (debug_) { + // dbgCout() << "Buffer " << buffer << " dupNum " << dupNum << ": add obj, index " << i << " with pt = " << objvec[i].intPt() << std::endl; + // } + addToBuffer(objvec[i], buffer, dupNum); } } template -void l1ct::tdr_regionizer::Regionizer::setPipes(const std::vector>& objvecvec) { - assert(getSize() == objvecvec.size()); - for (unsigned int sector = 0; sector < getSize(); sector++) { - setPipe(objvecvec[sector], sector); +void l1ct::tdr_regionizer::Regionizer::setBuffers(const std::vector>&& objvecvec) { + assert(numBuffers() == objvecvec.size() * ndup_); + for (unsigned int buffer = 0; buffer < numBuffers(); buffer++) { + setBuffer(objvecvec[buffer / ndup_], buffer); } } -// NEED TO CHECK CONSTANTS HERE template -int l1ct::tdr_regionizer::Regionizer::getPipeTime(int linkIndex, - int linkTimeOfObject, - int linkAlgoClockRunningTime) { - const int LINK_TO_ALGO_CLK_OFFSET = 2; //13; // in units of algo clock - int linkObjectArrival = (nsectors_ - 1 - linkIndex) + LINK_TO_ALGO_CLK_OFFSET + linkTimeOfObject; +void l1ct::tdr_regionizer::Regionizer::addToSmallRegion(l1ct::tdr_regionizer::PipeEntry&& pipeEntry) { + if (pipeEntry.valid()) { + auto rawObj = pipeEntry.obj(); - return (linkAlgoClockRunningTime < 0 || linkObjectArrival > linkAlgoClockRunningTime + 4) - ? linkObjectArrival - : (linkAlgoClockRunningTime + 4); -} + // in small region, the relative eta and phi are based on a different center, so need to update + auto realRegIdx = regionIndex(pipeEntry.sr()); + auto etaC = regions_[realRegIdx].intEtaCenter(); + auto phiC = regions_[realRegIdx].intPhiCenter(); -template -int l1ct::tdr_regionizer::Regionizer::popLinkObject(int linkIndex, int currentTimeOfObject) { - auto& obj = pipes_[linkIndex].getObj(); - obj.incCount(); - if (obj.getCount() < obj.getSRIndices().size()) { - // Continue working on the same object, since it goes in multiple SRs due to overlaps - return currentTimeOfObject + 1; - } else { - // move on to next item in pipe - pipes_[linkIndex].erase(); - //get time of next object - if (getPipeSize(linkIndex)) { - return getPipeTime(linkIndex, pipes_[linkIndex].getClock(), currentTimeOfObject); - } else { //no more objects on link - return -1; - } - } -} + int locEta = pipeEntry.glbEta() - etaC; + int locPhi = phi_wrap(pipeEntry.glbPhi() - phiC); -template -void l1ct::tdr_regionizer::Regionizer::initTimes() { - for (unsigned int sector = 0; sector < getSize(); ++sector) { - if (getPipeSize(sector)) { - timeOfNextObject_.push_back(timeNextFromIndex(sector, -1)); - } else { - timeOfNextObject_.push_back(-1); - } - } -} + rawObj.hwEta = locEta; + rawObj.hwPhi = locPhi; -template -void l1ct::tdr_regionizer::Regionizer::addToSmallRegion(unsigned int linkNum, unsigned int index) { - auto pipeObj = pipes_[linkNum].getObj(index); - smallRegionObjects_[pipeObj.getNextSRIndex()].push_back(pipeObj.getRawObj()); + smallRegionObjects_[pipeEntry.sr()].push_back(rawObj); + } } template -void l1ct::tdr_regionizer::Regionizer::run(bool debug) { - unsigned int loopCount = 0; - if (debug) - printDebug(loopCount); - while (loopCount < 972) { //this is the max allowable if nothing ever blocks - //init min time, pipe, and link index - // to find the target pipe currently with action - int minPipeIndex = -1; - int minLinkIndex = -1; - int minTime = 0; - - //do pipe-full handling - for (unsigned int sector = 0; sector < getSize(); ++sector) { - if (timeOfNextObject_[sector] >= 0 && smallRegionObjects_[getPipeIndexForObject(sector)].size() == maxobjects_) { - //pipe is full so proceed to next object - //'remove' the selected object from its link - timeOfNextObject_[sector] = popLinkObject(sector, timeOfNextObject_[sector]); - } //end pipe-full handling loop - } - - //do find object handling - for (unsigned int sector = 0; sector < getSize(); ++sector) { - // dbgCout() << "secotor = " << sector << ", timeOfNextObject_[sector] = " << timeOfNextObject_[sector] - // << ", minLinkIndex = " << minLinkIndex << ", minTime = " << minTime << ", minPipeIndex = " << minPipeIndex << std::endl; - if (timeOfNextObject_[sector] >= 0 && (minLinkIndex == -1 || timeOfNextObject_[sector] < minTime)) { - //found new 'selected' link object and pipe - minPipeIndex = getHardwarePipeIndexForObject(sector); - minTime = timeOfNextObject_[sector]; - minLinkIndex = sector; - } else if (getPipeSize(sector) && minLinkIndex >= 0 && - minPipeIndex == static_cast(getHardwarePipeIndexForObject(sector)) && - timeOfNextObject_[sector] == minTime) { - //have pipe conflict, so need to wait a clock - ++timeOfNextObject_[sector]; +void l1ct::tdr_regionizer::Regionizer::run() { + if (debug_) + printDebug(-1); + + // first event doesn't have a delayed start + int startTime = firstEvent_ ? 0 : DELAY_TO_START; + firstEvent_ = false; + + for (int currTime = startTime; currTime < 972 + startTime; + currTime++) { //this is the max allowable if nothing ever blocks + // not positive where 972 comes from. It seems to be 162 * 6 + + // to exit early + bool processedAll = true; // to be overwritten if not the case + + // handle the fifo buffers + for (size_t bufIdx = 0; bufIdx < buffers_.size(); ++bufIdx) { + auto& buffer = buffers_[bufIdx]; + if (buffer.timeOfNextObject() >= 0) { + processedAll = false; + } + if (buffer.timeOfNextObject() == currTime) { + // time to handle the buffer entry + const auto nextSR = buffer.front().nextSR(); + if (debug_) { + dbgCout() << "Current time " << currTime << ", handling bufIdx " << bufIdx << " object with SR = " << nextSR + << ", pt = " << buffer.pt() << ", glbeta = " << buffer.glbEta() << ", glbphi = " << buffer.glbPhi() + << std::endl; + } + if (nextSR < 0 || buffer.pt() == 0 || smallRegionObjects_[nextSR].size() == maxobjects_) { + // throwout or SR full, just get rid of object + buffer.popEntry(currTime, debug_); + } else { + const auto logicBufIdx = logicBuffIndex(bufIdx); + if (pipes_.valid(nextSR, logicBufIdx)) { + // The pipe already has an entry, so wait till space is available + buffer.updateNextObjectTime(currTime); + } else { + // put the value in the pipe + pipes_.addEntry(nextSR, logicBufIdx, buffer.popEntry(currTime, debug_)); + } + } } } - // dbgCout() << " After, minLinkIndex = " << minLinkIndex << ", minTime = " << minTime << ", minPipeIndex = " << minPipeIndex << std::endl; + if (debug_) + printDebug(currTime); - if (minLinkIndex < 0) - break; //exit case - - //'put' object in small region - addToSmallRegion(minLinkIndex); + // add the small regions + for (size_t i = 0; i < pipes_.size(); i++) { + addToSmallRegion(pipes_.popEntry(i)); + } - //'remove' the selected object from its link - int nextTime = popLinkObject(minLinkIndex, timeOfNextObject_[minLinkIndex]); - if (nextTime > nclocks_) { + // check ot see if you have processed all + if (processedAll) { + // first clear the pipes + for (size_t tap = 0; tap < pipes_.numTaps(); tap++) { + // add the small regions + for (size_t i = 0; i < pipes_.size(); i++) { + addToSmallRegion(pipes_.popEntry(i)); + } + } + if (debug_) + printDebug(2000); break; } - timeOfNextObject_[minLinkIndex] = nextTime; - ++loopCount; } //end main loop - - if (debug) - printDebug(loopCount); } template void l1ct::tdr_regionizer::Regionizer::reset() { - for (auto& pipe : pipes_) { - pipe.reset(); + for (auto& buffer : buffers_) { + buffer.reset(); } - timeOfNextObject_.clear(); + pipes_.reset(); for (auto& smallRegionObject : smallRegionObjects_) { smallRegionObject.clear(); } + firstEvent_ = true; } template std::map> l1ct::tdr_regionizer::Regionizer::fillRegions(bool doSort) { std::map> srMap; for (size_t sr = 0; sr < smallRegionObjects_.size(); sr++) { - srMap[regionmap_[sr]] = smallRegionObjects_[sr]; + srMap[regionIndex(sr)] = smallRegionObjects_[sr]; if (doSort) { - std::sort(srMap[regionmap_[sr]].begin(), srMap[regionmap_[sr]].end(), std::greater<>()); + std::sort(srMap[regionIndex(sr)].begin(), srMap[regionIndex(sr)].end(), std::greater<>()); } } return srMap; } +template +size_t l1ct::tdr_regionizer::Regionizer::logicBuffIndex(size_t bufIdx) const { + const unsigned int sector = bufIdx / ndup_; + auto logSector = sectormap_[sector]; + return logSector * ndup_ + bufIdx % ndup_; +} + template void l1ct::tdr_regionizer::Regionizer::printDebug(int count) const { - dbgCout() << "PIPES, (for " << getSize() << " sectors)" << std::endl; - dbgCout() << count << "\tsector\titem\tpt\teta\tphi" << std::endl; - for (unsigned int sector = 0; sector < getSize(); sector++) { - for (unsigned int j = 0; j < getPipeSize(sector); j++) { - dbgCout() << "\t" << sector << "\t" << j << "\t" << pipes_[sector].getPt(j) << "\t" << pipes_[sector].getGlbEta(j) - << "\t" << pipes_[sector].getGlbPhi(j) << std::endl; + dbgCout() << "BUFFERS, (for " << numBuffers() << " buffers)" << std::endl; + dbgCout() << count << "\tbuffer\tlogical\titem\tpt\teta\tphi\tclock" << std::endl; + for (auto sector : invsectormap_) { + for (unsigned int dup = 0; dup < ndup_; dup++) { + const unsigned int buffer = sector * ndup_ + dup; + for (unsigned int j = 0; j < numEntries(buffer); j++) { + dbgCout() << "\t" << buffer << "\t" << logicBuffIndex(buffer) << "\t" << j << "\t" << buffers_[buffer].pt(j) + << "\t" << buffers_[buffer].glbEta(j) << "\t" << buffers_[buffer].glbPhi(j) << "\t" + << buffers_[buffer].clock(j) << std::endl; + } + dbgCout() << "-------------------------------" << std::endl; + } + } + dbgCout() << "PIPES, (for " << pipes_.size() << " pipes)" << std::endl; + dbgCout() << count << "\tpipe\ttap\tsr\tpt\teta\tphi" << std::endl; + for (size_t pipe = 0; pipe < pipes_.size(); pipe++) { + for (size_t tap = 0; tap < pipes_.numTaps(); tap++) { + auto entry = pipes_.entry(pipe, tap); + dbgCout() << "\t" << pipe << "\t" << tap << "\t" << entry.sr() << "\t" << entry.pt() << "\t" << entry.glbEta() + << "\t" << entry.glbPhi() << std::endl; } dbgCout() << "-------------------------------" << std::endl; } + dbgCout() << "SMALL REGIONS" << std::endl; for (unsigned int region = 0; region < neta_ * nphi_; region++) { - dbgCout() << count << "\tregion\titem\tpt\tloceta\tlocphi" << std::endl; + dbgCout() << count << "\tregion\t\titem\tpt\tloceta\tlocphi" << std::endl; + auto realRegIdx = regionIndex(region); + auto etaC = regions_[realRegIdx].intEtaCenter(); + auto phiC = regions_[realRegIdx].intPhiCenter(); for (unsigned int j = 0; j < smallRegionObjects_[region].size(); j++) { - dbgCout() << "\t" << region << " " << j << "\t" << smallRegionObjects_[region][j].hwPt.to_int() << "\t" - << smallRegionObjects_[region][j].hwEta.to_int() << "\t" - << smallRegionObjects_[region][j].hwPhi.to_int() << std::endl; + dbgCout() << "\t" << region << " (" << etaC << ", " << phiC << ")\t" << j << "\t" + << smallRegionObjects_[region][j].intPt() << "\t" << smallRegionObjects_[region][j].intEta() << "\t" + << smallRegionObjects_[region][j].intPhi() << std::endl; } dbgCout() << "-------------------------------" << std::endl; } dbgCout() << "TIMES" << std::endl; - for (unsigned int i = 0; i < timeOfNextObject_.size(); i++) { - dbgCout() << " " << timeOfNextObject_[i]; + for (unsigned int i = 0; i < numBuffers(); i++) { + dbgCout() << " " << buffers_[i].timeOfNextObject(); } dbgCout() << "\n-------------------------------" << std::endl; } + +// returns 2D arrays, sectors (links) first dimension, objects second +template +std::vector> l1ct::tdr_regionizer::Regionizer::fillLinks( + const std::vector>& sectors) const { + std::vector> links; + + if (maxobjects_ == 0) { + return links; + } + //one link per sector + for (const auto& sector : sectors) { + if (isInBigRegionLoose(sector.region)) { + links.emplace_back(); + for (unsigned int io = 0; io < sector.size() && io < nclocks_; io++) { + links.back().push_back(sector[io]); + } + } + } + return links; +} + +template +std::vector> l1ct::tdr_regionizer::Regionizer::fillLinks(const DetectorSector& sector) const { + std::vector> links; + + if (maxobjects_ == 0) { + return links; + } + + links.emplace_back(); + for (unsigned int io = 0; io < sector.size() && io < nclocks_; io++) { + links.back().push_back(sector[io]); + } + return links; +} diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_ref.h b/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_ref.h index 7e7b24afce177..f486902602ac9 100644 --- a/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_ref.h +++ b/L1Trigger/Phase2L1ParticleFlow/interface/regionizer/tdr_regionizer_ref.h @@ -15,7 +15,7 @@ namespace l1ct { uint32_t ncalo, uint32_t nem, uint32_t nmu, - int32_t nclocks, + uint32_t nclocks, std::vector bigRegionEdges, bool dosort); @@ -29,18 +29,12 @@ namespace l1ct { void run(const RegionizerDecodedInputs& in, std::vector& out) override; private: - // link emulation from decoded inputs (for simulation) - void fillLinks(const RegionizerDecodedInputs& in, std::vector>& links); - void fillLinks(const RegionizerDecodedInputs& in, std::vector>& links); - void fillLinks(const RegionizerDecodedInputs& in, std::vector>& links); - void fillLinks(const RegionizerDecodedInputs& in, std::vector>& links); - /// The nubmer of barrel big regions (boards) uint32_t nBigRegions_; /// The maximum number of objects of each type to output per small region uint32_t ntk_, ncalo_, nem_, nmu_; /// The number of clocks to receive all data of an event (TMUX18 = 162) - int32_t nclocks_; + uint32_t nclocks_; /// The phi edges of the big regions (boards); one greater than the number of boards std::vector bigRegionEdges_; @@ -49,13 +43,6 @@ namespace l1ct { /// The number of eta and phi small regions in a big region (board) uint32_t netaInBR_, nphiInBR_; - /// The total number of small regions in barrel (not just in board) - uint32_t nregions_; - - uint32_t MAX_TK_OBJ_; - uint32_t MAX_EMCALO_OBJ_; - uint32_t MAX_HADCALO_OBJ_; - uint32_t MAX_MU_OBJ_; bool init_; // has initialization happened diff --git a/L1Trigger/Phase2L1ParticleFlow/src/regionizer/tdr_regionizer_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/regionizer/tdr_regionizer_ref.cpp index e58ca482ced1c..8a654985ab2e0 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/regionizer/tdr_regionizer_ref.cpp +++ b/L1Trigger/Phase2L1ParticleFlow/src/regionizer/tdr_regionizer_ref.cpp @@ -11,7 +11,7 @@ l1ct::TDRRegionizerEmulator::TDRRegionizerEmulator(const edm::ParameterSet& iCon iConfig.getParameter("nCalo"), iConfig.getParameter("nEmCalo"), iConfig.getParameter("nMu"), - iConfig.getParameter("nClocks"), + iConfig.getParameter("nClocks"), iConfig.getParameter>("bigRegionEdges"), iConfig.getParameter("doSort")) { debug_ = iConfig.getUntrackedParameter("debug", false); @@ -22,7 +22,7 @@ l1ct::TDRRegionizerEmulator::TDRRegionizerEmulator(uint32_t ntk, uint32_t ncalo, uint32_t nem, uint32_t nmu, - int32_t nclocks, + uint32_t nclocks, std::vector bigRegionEdges, bool dosort) : RegionizerEmulator(), @@ -37,10 +37,6 @@ l1ct::TDRRegionizerEmulator::TDRRegionizerEmulator(uint32_t ntk, nphiInBR_(3), init_(false) { nBigRegions_ = bigRegionEdges_.size() - 1; - MAX_TK_OBJ_ = nclocks_ * 2 / 3; // 2 objects per 3 clocks - MAX_EMCALO_OBJ_ = nclocks_; // 1 object per clock - MAX_HADCALO_OBJ_ = nclocks_; // 1 object per clock - MAX_MU_OBJ_ = nclocks_; // 1 object per clock } l1ct::TDRRegionizerEmulator::~TDRRegionizerEmulator() {} @@ -52,17 +48,17 @@ void l1ct::TDRRegionizerEmulator::initSectorsAndRegions(const RegionizerDecodedI } assert(!init_); init_ = true; - nregions_ = out.size(); for (unsigned int i = 0; i < nBigRegions_; i++) { tkRegionizers_.emplace_back( - netaInBR_, nphiInBR_, nregions_, ntk_, bigRegionEdges_[i], bigRegionEdges_[i + 1], nclocks_); + netaInBR_, nphiInBR_, ntk_, bigRegionEdges_[i], bigRegionEdges_[i + 1], nclocks_, 1, false); + // duplicate input fibers to increase to increasee the throughput, since lots of data comes in per fiber hadCaloRegionizers_.emplace_back( - netaInBR_, nphiInBR_, nregions_, ncalo_, bigRegionEdges_[i], bigRegionEdges_[i + 1], nclocks_); + netaInBR_, nphiInBR_, ncalo_, bigRegionEdges_[i], bigRegionEdges_[i + 1], nclocks_, 2, false); emCaloRegionizers_.emplace_back( - netaInBR_, nphiInBR_, nregions_, nem_, bigRegionEdges_[i], bigRegionEdges_[i + 1], nclocks_); + netaInBR_, nphiInBR_, nem_, bigRegionEdges_[i], bigRegionEdges_[i + 1], nclocks_, 1, false); muRegionizers_.emplace_back( - netaInBR_, nphiInBR_, nregions_, nmu_, bigRegionEdges_[i], bigRegionEdges_[i + 1], nclocks_); + netaInBR_, nphiInBR_, nmu_, bigRegionEdges_[i], bigRegionEdges_[i + 1], nclocks_, 1, false); } dbgCout() << "in.track.size() = " << in.track.size() << std::endl; @@ -95,83 +91,6 @@ void l1ct::TDRRegionizerEmulator::initSectorsAndRegions(const RegionizerDecodedI } } -void l1ct::TDRRegionizerEmulator::fillLinks(const l1ct::RegionizerDecodedInputs& in, - std::vector>& links) { - if (ntk_ == 0) - return; - - links.clear(); - links.resize(in.track.size()); - - //one link per sector - for (unsigned int il = 0; il < in.track.size(); il++) { - const l1ct::DetectorSector& sec = in.track[il]; - for (unsigned int io = 0; io < sec.size(); io++) { - links[il].push_back(sec[io]); - if (links[il].size() == MAX_TK_OBJ_) { - break; - } - } - } -} - -void l1ct::TDRRegionizerEmulator::fillLinks(const l1ct::RegionizerDecodedInputs& in, - std::vector>& links) { - if (ncalo_ == 0) - return; - - links.clear(); - links.resize(in.hadcalo.size()); - - //one link per sector - for (unsigned int il = 0; il < in.hadcalo.size(); il++) { - const l1ct::DetectorSector& sec = in.hadcalo[il]; - for (unsigned int io = 0; io < sec.size(); io++) { - links[il].push_back(sec[io]); - if (links[il].size() == MAX_HADCALO_OBJ_) { - break; - } - } - } -} - -void l1ct::TDRRegionizerEmulator::fillLinks(const l1ct::RegionizerDecodedInputs& in, - std::vector>& links) { - if (nem_ == 0) - return; - - links.clear(); - links.resize(in.emcalo.size()); - - //one link per sector - for (unsigned int il = 0; il < in.emcalo.size(); il++) { - const l1ct::DetectorSector& sec = in.emcalo[il]; - for (unsigned int io = 0; io < sec.size(); io++) { - links[il].push_back(sec[io]); - if (links[il].size() == MAX_EMCALO_OBJ_) { - break; - } - } - } -} - -void l1ct::TDRRegionizerEmulator::fillLinks(const l1ct::RegionizerDecodedInputs& in, - std::vector>& links) { - if (nmu_ == 0) - return; - - links.clear(); - links.resize(1); //muons are global - - const l1ct::DetectorSector& sec = in.muon; - for (unsigned int io = 0; io < sec.size(); io++) { - links[0].push_back(sec[io]); - if (links[0].size() == MAX_MU_OBJ_) { - break; - } - } -} - void l1ct::TDRRegionizerEmulator::run(const RegionizerDecodedInputs& in, std::vector& out) { if (debug_) { dbgCout() << "TDRRegionizerEmulator::run called, out.size = " << out.size() << std::endl; @@ -181,51 +100,22 @@ void l1ct::TDRRegionizerEmulator::run(const RegionizerDecodedInputs& in, std::ve initSectorsAndRegions(in, out); } - // 2D arrays, sectors (links) first dimension, objects second - std::vector> tk_links_in; - std::vector> em_links_in; - std::vector> calo_links_in; - std::vector> mu_links_in; - - // read the inputs - fillLinks(in, tk_links_in); - fillLinks(in, em_links_in); - fillLinks(in, calo_links_in); - fillLinks(in, mu_links_in); - //this is overkill and could be improved, for now its ok (the sectors outside each board just wont do anything) - for (unsigned int ie = 0; ie < nBigRegions_; ie++) { //add objects from link tkRegionizers_[ie].reset(); - tkRegionizers_[ie].setPipes(tk_links_in); - tkRegionizers_[ie].initTimes(); - if (debug_) { - dbgCout() << "Big region: " << ie << " SECTORS/LINKS " << std::endl; - dbgCout() << "\tsector\titem\tpt\teta\tphi" << std::endl; - for (unsigned int sector = 0; sector < tk_links_in.size(); sector++) { - for (unsigned int j = 0; j < tk_links_in[sector].size(); j++) { - dbgCout() << "\t" << sector << "\t" << j << "\t " << tk_links_in[sector][j].hwPt.to_int() << "\t" - << tk_links_in[sector][j].hwEta.to_int() << "\t" << tk_links_in[sector][j].hwPhi.to_int() - << std::endl; - } - dbgCout() << "-------------------------------" << std::endl; - } - } - tkRegionizers_[ie].run(debug_); + tkRegionizers_[ie].fillBuffers(in.track); + tkRegionizers_[ie].run(); emCaloRegionizers_[ie].reset(); - emCaloRegionizers_[ie].setPipes(em_links_in); - emCaloRegionizers_[ie].initTimes(); + emCaloRegionizers_[ie].fillBuffers(in.emcalo); emCaloRegionizers_[ie].run(); hadCaloRegionizers_[ie].reset(); - hadCaloRegionizers_[ie].setPipes(calo_links_in); - hadCaloRegionizers_[ie].initTimes(); + hadCaloRegionizers_[ie].fillBuffers(in.hadcalo); hadCaloRegionizers_[ie].run(); muRegionizers_[ie].reset(); - muRegionizers_[ie].setPipes(mu_links_in); - muRegionizers_[ie].initTimes(); + muRegionizers_[ie].fillBuffers(in.muon); muRegionizers_[ie].run(); } diff --git a/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_cfg.py b/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_cfg.py index 2b0612daeb660..21d6d105095f9 100644 --- a/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_cfg.py +++ b/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_cfg.py @@ -89,7 +89,7 @@ nCalo = cms.uint32(15), nEmCalo = cms.uint32(12), nMu = cms.uint32(2), - nClocks = cms.int32(162), + nClocks = cms.uint32(162), doSort = cms.bool(False), bigRegionEdges = cms.vint32(-560, -80, 400, -560) )