Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:27

0001 #ifndef tdr_regionizer_elements_ref_h
0002 #define tdr_regionizer_elements_ref_h
0003 
0004 #include "DataFormats/L1TParticleFlow/interface/layer1_emulator.h"
0005 
0006 #include <vector>
0007 #include <map>
0008 #include <deque>
0009 #include <cassert>
0010 #include <algorithm>
0011 
0012 #include "L1Trigger/Phase2L1ParticleFlow/interface/dbgPrintf.h"
0013 
0014 namespace l1ct {
0015   namespace tdr_regionizer {
0016 
0017     inline int phi_wrap(int local_phi) {
0018       if (local_phi > l1ct::Scales::INTPHI_PI)
0019         local_phi -= l1ct::Scales::INTPHI_TWOPI;
0020       else if (local_phi <= -l1ct::Scales::INTPHI_PI)
0021         local_phi += l1ct::Scales::INTPHI_TWOPI;
0022       return local_phi;
0023     }
0024 
0025     /// corresponds to level1_to_2_pipe_t in firmware
0026     template <typename T>
0027     class PipeEntry {
0028     public:
0029       PipeEntry() : obj_(), sr_(-1) {}
0030       PipeEntry(const T& obj, int sr, int glbeta, int glbphi) : obj_(obj), sr_(sr), glbeta_(glbeta), glbphi_(glbphi) {}
0031 
0032       int sr() const { return sr_; }
0033 
0034       // Note, this returns a copy so you can modify
0035       T obj() const { return obj_; }
0036 
0037       bool valid() const { return sr_ >= 0; }
0038 
0039       void setInvalid() { sr_ = -1; }
0040 
0041       int pt() const { return obj_.intPt(); }
0042       int glbPhi() const { return glbphi_; }
0043       int glbEta() const { return glbeta_; }
0044 
0045     private:
0046       T obj_;
0047       /// the SR linearized indices (can index regionmap_) where this object needs to go; -1 means invalid
0048       int sr_;
0049       /// The global eta and phi of the object (hard to get with duplicates)
0050       int glbeta_, glbphi_;
0051     };
0052 
0053     /// The pipe, with multiple inputs and one output
0054     template <typename T>
0055     class Pipe {
0056     public:
0057       /// if using the default constructor, have to call setTaps before use
0058       Pipe() : pipe_() {}
0059 
0060       Pipe(size_t ntaps) : pipe_(ntaps) {}
0061 
0062       void setTaps(size_t taps) { pipe_.resize(taps); }
0063 
0064       /// check if the entry is valid (i.e. already has data)
0065       bool valid(size_t idx) const { return pipe_.at(idx).valid(); }
0066 
0067       /// should check if valid before adding an entry
0068       void addEntry(size_t idx, const PipeEntry<T>& entry) { pipe_[idx] = entry; }
0069 
0070       /// perform one tick, shifting all the entries to higher indices, and returning the last
0071       PipeEntry<T> popEntry();
0072 
0073       void reset();
0074 
0075       size_t size() const { return pipe_.size(); }
0076 
0077       /// for debug
0078       const PipeEntry<T>& entry(size_t idx) const { return pipe_[idx]; }
0079 
0080     private:
0081       std::vector<PipeEntry<T>> pipe_;
0082     };
0083 
0084     /// The pipe, with multiple inputs and one output
0085     template <typename T>
0086     class Pipes {
0087     public:
0088       /// the number of pipes
0089       Pipes(size_t nregions) : pipes_(nregions / SRS_PER_RAM) {}
0090 
0091       /// set the number of taps in each pipe
0092       void setTaps(size_t taps);
0093 
0094       /// check if the entry is valid (i.e. already has data)
0095       bool valid(int sr, size_t logicBufIdx) const { return pipes_[pipeIndex(sr)].valid(logicBufIdx); }
0096 
0097       /// should check if valid before adding an entry
0098       void addEntry(int sr, size_t logicBufIdx, const PipeEntry<T>& entry) {
0099         pipes_[pipeIndex(sr)].addEntry(logicBufIdx, entry);
0100       }
0101 
0102       /// perform one tick, shifting all the entries to higher indices, and returning the last
0103       PipeEntry<T> popEntry(size_t pipe) { return pipes_[pipe].popEntry(); };
0104 
0105       void reset();
0106 
0107       size_t size() const { return pipes_.size(); }
0108 
0109       size_t numTaps() const { return pipes_.at(0).size(); }
0110 
0111       /// for debug
0112       const PipeEntry<T>& entry(size_t pipe, size_t tap) const { return pipes_[pipe].entry(tap); }
0113 
0114     private:
0115       /// SRs share RAMs (and hardware pipes)
0116       static size_t constexpr SRS_PER_RAM = 2;
0117 
0118       /// Because some SRs share pipes, this determines the pipe index for a linearize SR index
0119       /// (This is based on the VHDL function, get_target_pipe_index_subindex)
0120       size_t pipeIndex(int sr) const { return sr / SRS_PER_RAM; }
0121 
0122       std::vector<Pipe<T>> pipes_;
0123     };
0124 
0125     /// the components that make up the L1 regionizer buffer
0126     template <typename T>
0127     class BufferEntry {
0128     public:
0129       BufferEntry() {}
0130       BufferEntry(const T& obj, std::vector<size_t> srIndices, int glbeta, int glbphi, unsigned int clk);
0131 
0132       unsigned int clock() const { return linkobjclk_; }
0133       int nextSR() const { return (objcount_ < srIndices_.size()) ? srIndices_[objcount_] : -1; }
0134       void incSR() { objcount_++; }
0135       int pt() const { return obj_.intPt(); }
0136       int glbPhi() const { return glbphi_; }
0137       int glbEta() const { return glbeta_; }
0138 
0139       //T obj() { return obj_; }
0140       const T& obj() const { return obj_; }
0141 
0142     private:
0143       T obj_;
0144       /// the SR linearized indices (can index regionmap_) where this object needs to go
0145       std::vector<size_t> srIndices_;
0146       /// The global eta and phi of the object (hard to get with duplicates)
0147       int glbeta_, glbphi_;
0148       unsigned int linkobjclk_, objcount_;
0149     };
0150 
0151     /// The L1 regionizer buffer (corresponding to level1_fifo_buffer.vhd)
0152     template <typename T>
0153     class Buffer {
0154     public:
0155       Buffer() : clkindex360_(INIT360), clkindex240_(INIT240), timeOfNextObject_(-1) {}
0156 
0157       void addEntry(
0158           const T& obj, std::vector<size_t> srs, int glbeta, int glbphi, unsigned int dupNum, unsigned int ndup);
0159 
0160       BufferEntry<T>& front() { return data_.front(); }
0161       const BufferEntry<T>& front() const { return data_.front(); }
0162 
0163       /// sets the next time something is taken from this buffer
0164       void updateNextObjectTime(int currentTime);
0165 
0166       /// delete the front element
0167       void pop() { data_.pop_front(); }
0168 
0169       // mostly for debug
0170       unsigned int clock(unsigned int index = 0) const { return data_[index].clock(); }
0171       int pt(unsigned int index = 0) const { return data_[index].pt(); }
0172       int glbPhi(unsigned int index = 0) const { return data_[index].glbPhi(); }
0173       int glbEta(unsigned int index = 0) const { return data_[index].glbEta(); }
0174 
0175       unsigned int numEntries() const { return data_.size(); }
0176 
0177       /// pop the first entry, formatted for inclusion in pipe
0178       PipeEntry<T> popEntry(int currTime, bool debug);
0179 
0180       int timeOfNextObject() const { return timeOfNextObject_; }
0181 
0182       void reset() {
0183         clkindex360_ = INIT360;
0184         clkindex240_ = INIT240;
0185         data_.clear();
0186         timeOfNextObject_ = -1;
0187       }
0188 
0189     private:
0190       // used when building up the linkobjclk_ entries for the BufferEntries
0191       unsigned int nextObjClk(unsigned int ndup);
0192 
0193       // transient--used only during event construction, not used after
0194       // Counts in 1.39ns increments (i.e. 360 increments by 2, 240 by 3)
0195       unsigned int clkindex360_;
0196       unsigned int clkindex240_;
0197 
0198       static unsigned int constexpr INIT360 = 1;
0199       static unsigned int constexpr INIT240 = 0;
0200 
0201       /// The actual data
0202       std::deque<BufferEntry<T>> data_;
0203 
0204       /// the time of the next object in the buffer (-1 if none)
0205       int timeOfNextObject_;
0206     };
0207 
0208     template <typename T>
0209     class Regionizer {
0210     public:
0211       Regionizer() = delete;
0212       Regionizer(unsigned int neta,
0213                  unsigned int nphi,  //the number of eta and phi SRs in a big region (board)
0214                  unsigned int maxobjects,
0215                  int bigRegionMin,
0216                  int bigRegionMax,  // the phi range covered by this board
0217                  unsigned int nclocks,
0218                  unsigned int ndup = 1,  // how much one duplicates the inputs (to increase processing bandwidth)
0219                  bool debug = false);
0220 
0221       void initSectors(const std::vector<DetectorSector<T>>& sectors);
0222       void initSectors(const DetectorSector<T>& sector);
0223       void initRegions(const std::vector<PFInputRegion>& regions);
0224 
0225       void fillBuffers(const std::vector<DetectorSector<T>>& sectors);
0226       void fillBuffers(const DetectorSector<T>& sector);
0227 
0228       void run();
0229 
0230       void reset();
0231 
0232       /// Return a map of of the SRs indexed by SR index (covering only those from board)
0233       std::map<size_t, std::vector<T>> fillRegions(bool doSort);
0234 
0235       void printDebug(int count) const;
0236 
0237     private:
0238       /// is the given small region in the big region
0239       bool isInBigRegion(const PFRegionEmu& reg) const;
0240 
0241       /// Does the given region fit in the big region, taking into account overlaps?
0242       bool isInBigRegionLoose(const PFRegionEmu& reg) const;
0243 
0244       unsigned int numBuffers() const { return buffers_.size(); }
0245       unsigned int numEntries(unsigned int bufferIndex) const { return buffers_[bufferIndex].numEntries(); }
0246 
0247       std::vector<size_t> getSmallRegions(int glbeta, int glbphi) const;
0248 
0249       void addToBuffer(const T& obj, unsigned int index, unsigned int dupNum);
0250       void setBuffer(const std::vector<T>& objvec, unsigned int index);
0251       void setBuffers(const std::vector<std::vector<T>>&& objvecvec);
0252 
0253       /// This retruns the linearized small region associated with the given item (-1 is throwout)
0254       int nextSR(unsigned int linknum, unsigned int index = 0) { return buffers_[linknum].nextSR(index); }
0255 
0256       /// 'put' object in small region
0257       void addToSmallRegion(PipeEntry<T>&&);
0258 
0259       /// returns 2D arrays, sectors (links) first dimension, objects second
0260       std::vector<std::vector<T>> fillLinks(const std::vector<DetectorSector<T>>& sectors) const;
0261       std::vector<std::vector<T>> fillLinks(const DetectorSector<T>& sector) const;
0262 
0263       // this function is for sorting small regions first in phi and then in eta.
0264       // It takes regions_ indices
0265       bool sortRegionsRegular(size_t a, size_t b) const;
0266 
0267       bool sortSectors(size_t a, size_t b) const;
0268 
0269       bool sortRegionsHelper(int etaa, int etab, int phia, int phib) const;
0270 
0271       /// get the index in regions_ for a particular SR.
0272       size_t regionIndex(int sr) const { return regionmap_.at(sr); }
0273 
0274       /// get the logical buffer index (i.e. the index in the order in the firmware)
0275       size_t logicBuffIndex(size_t bufIdx) const;
0276 
0277       /// The numbers of eta and phi in a big region (board)
0278       unsigned int neta_, nphi_;
0279       /// The maximum number of objects to output per small region
0280       unsigned int maxobjects_;
0281       /// The number of input sectors for this type of device
0282       unsigned int nsectors_;
0283       /// the minimumum phi of this board
0284       int bigRegionMin_;
0285       /// the maximum phi of this board
0286       int bigRegionMax_;
0287       /// the number of clocks to receive one event
0288       unsigned int nclocks_;
0289       /// How many buffers per link (default 1)
0290       unsigned int ndup_;
0291 
0292       /// the region information assopciated with each input sector
0293       std::vector<l1ct::PFRegionEmu> sectors_;
0294 
0295       /// the region information associated with each SR
0296       std::vector<l1ct::PFRegionEmu> regions_;
0297 
0298       /// indices of regions that are in the big region (board)
0299       std::vector<size_t> regionmap_;
0300 
0301       /// indices maps the sectors from the way they appear in the software to the order they are done in the regionizer
0302       std::vector<size_t> sectormap_;
0303 
0304       /// the inverse mapping of sectormap_ (only used for debug printing)
0305       std::vector<size_t> invsectormap_;
0306 
0307       /// The buffers. There are ndup_ buffers per link/sector
0308       std::vector<Buffer<T>> buffers_;
0309 
0310       /// The pipes, one per ram (see SRS_PER_RAM)
0311       Pipes<T> pipes_;
0312 
0313       /// The objects in each small region handled in board; Indexing corresponds to that in regionmap_
0314       std::vector<std::vector<T>> smallRegionObjects_;
0315 
0316       /// Whether this is the first event (since timing is a bit different then)
0317       bool firstEvent_;
0318 
0319       /// This is the delay (only applied after first event) before processing starts
0320       static unsigned int constexpr DELAY_TO_START = 10;
0321 
0322       bool debug_;
0323     };
0324 
0325   }  // namespace  tdr_regionizer
0326 }  // namespace l1ct
0327 
0328 #endif