Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "L1Trigger/TrackerTFP/interface/GeometricProcessor.h"
0002 
0003 #include <numeric>
0004 #include <algorithm>
0005 #include <iterator>
0006 #include <deque>
0007 #include <vector>
0008 
0009 using namespace std;
0010 using namespace edm;
0011 using namespace tt;
0012 
0013 namespace trackerTFP {
0014 
0015   GeometricProcessor::GeometricProcessor(const ParameterSet& iConfig,
0016                                          const Setup* setup,
0017                                          const DataFormats* dataFormats,
0018                                          int region)
0019       : enableTruncation_(iConfig.getParameter<bool>("EnableTruncation")),
0020         setup_(setup),
0021         dataFormats_(dataFormats),
0022         region_(region),
0023         input_(dataFormats_->numChannel(Process::gp), vector<deque<StubPP*>>(dataFormats_->numChannel(Process::pp))) {}
0024 
0025   // read in and organize input product (fill vector input_)
0026   void GeometricProcessor::consume(const TTDTC& ttDTC) {
0027     auto validFrame = [](int sum, const FrameStub& frame) { return sum + (frame.first.isNonnull() ? 1 : 0); };
0028     int nStubsPP(0);
0029     for (int channel = 0; channel < dataFormats_->numChannel(Process::pp); channel++) {
0030       const StreamStub& stream = ttDTC.stream(region_, channel);
0031       nStubsPP += accumulate(stream.begin(), stream.end(), 0, validFrame);
0032     }
0033     stubsPP_.reserve(nStubsPP);
0034     for (int channel = 0; channel < dataFormats_->numChannel(Process::pp); channel++) {
0035       for (const FrameStub& frame : ttDTC.stream(region_, channel)) {
0036         StubPP* stub = nullptr;
0037         if (frame.first.isNonnull()) {
0038           stubsPP_.emplace_back(frame, dataFormats_);
0039           stub = &stubsPP_.back();
0040         }
0041         for (int sector = 0; sector < dataFormats_->numChannel(Process::gp); sector++)
0042           // adding gaps (nullptr) if no stub available or not in sector to emulate f/w
0043           input_[sector][channel].push_back(stub && stub->inSector(sector) ? stub : nullptr);
0044       }
0045     }
0046     // remove all gaps between end and last stub
0047     for (vector<deque<StubPP*>>& input : input_)
0048       for (deque<StubPP*>& stubs : input)
0049         for (auto it = stubs.end(); it != stubs.begin();)
0050           it = (*--it) ? stubs.begin() : stubs.erase(it);
0051     auto validStub = [](int sum, StubPP* stub) { return sum + (stub ? 1 : 0); };
0052     int nStubsGP(0);
0053     for (const vector<deque<StubPP*>>& sector : input_)
0054       for (const deque<StubPP*>& channel : sector)
0055         nStubsGP += accumulate(channel.begin(), channel.end(), 0, validStub);
0056     stubsGP_.reserve(nStubsGP);
0057   }
0058 
0059   // fill output products
0060   void GeometricProcessor::produce(StreamsStub& accepted, StreamsStub& lost) {
0061     for (int sector = 0; sector < dataFormats_->numChannel(Process::gp); sector++) {
0062       vector<deque<StubPP*>>& inputs = input_[sector];
0063       vector<deque<StubGP*>> stacks(dataFormats_->numChannel(Process::pp));
0064       const int sectorPhi = sector % setup_->numSectorsPhi();
0065       const int sectorEta = sector / setup_->numSectorsPhi();
0066       auto size = [](int sum, const deque<StubPP*>& stubs) { return sum + stubs.size(); };
0067       const int nStubs = accumulate(inputs.begin(), inputs.end(), 0, size);
0068       vector<StubGP*> acceptedSector;
0069       vector<StubGP*> lostSector;
0070       acceptedSector.reserve(nStubs);
0071       lostSector.reserve(nStubs);
0072       // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick
0073       while (!all_of(inputs.begin(), inputs.end(), [](const deque<StubPP*>& stubs) { return stubs.empty(); }) or
0074              !all_of(stacks.begin(), stacks.end(), [](const deque<StubGP*>& stubs) { return stubs.empty(); })) {
0075         // fill input fifos
0076         for (int channel = 0; channel < dataFormats_->numChannel(Process::pp); channel++) {
0077           deque<StubGP*>& stack = stacks[channel];
0078           StubPP* stub = pop_front(inputs[channel]);
0079           if (stub) {
0080             stubsGP_.emplace_back(*stub, sectorPhi, sectorEta);
0081             if (enableTruncation_ && (int)stack.size() == setup_->gpDepthMemory() - 1)
0082               lostSector.push_back(pop_front(stack));
0083             stack.push_back(&stubsGP_.back());
0084           }
0085         }
0086         // merge input fifos to one stream, prioritizing higher input channel over lower channel
0087         bool nothingToRoute(true);
0088         for (int channel = dataFormats_->numChannel(Process::pp) - 1; channel >= 0; channel--) {
0089           StubGP* stub = pop_front(stacks[channel]);
0090           if (stub) {
0091             nothingToRoute = false;
0092             acceptedSector.push_back(stub);
0093             break;
0094           }
0095         }
0096         if (nothingToRoute)
0097           acceptedSector.push_back(nullptr);
0098       }
0099       // truncate if desired
0100       if (enableTruncation_ && (int)acceptedSector.size() > setup_->numFrames()) {
0101         const auto limit = next(acceptedSector.begin(), setup_->numFrames());
0102         copy_if(limit, acceptedSector.end(), back_inserter(lostSector), [](const StubGP* stub) { return stub; });
0103         acceptedSector.erase(limit, acceptedSector.end());
0104       }
0105       // remove all gaps between end and last stub
0106       for (auto it = acceptedSector.end(); it != acceptedSector.begin();)
0107         it = (*--it) ? acceptedSector.begin() : acceptedSector.erase(it);
0108       // fill products
0109       auto put = [](const vector<StubGP*>& stubs, StreamStub& stream) {
0110         auto toFrame = [](StubGP* stub) { return stub ? stub->frame() : FrameStub(); };
0111         stream.reserve(stubs.size());
0112         transform(stubs.begin(), stubs.end(), back_inserter(stream), toFrame);
0113       };
0114       const int index = region_ * dataFormats_->numChannel(Process::gp) + sector;
0115       put(acceptedSector, accepted[index]);
0116       put(lostSector, lost[index]);
0117     }
0118   }
0119 
0120   // remove and return first element of deque, returns nullptr if empty
0121   template <class T>
0122   T* GeometricProcessor::pop_front(deque<T*>& ts) const {
0123     T* t = nullptr;
0124     if (!ts.empty()) {
0125       t = ts.front();
0126       ts.pop_front();
0127     }
0128     return t;
0129   }
0130 
0131 }  // namespace trackerTFP