Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "L1Trigger/TrackerDTC/interface/DTC.h"
0002 
0003 #include <vector>
0004 #include <iterator>
0005 #include <algorithm>
0006 #include <numeric>
0007 
0008 using namespace std;
0009 using namespace edm;
0010 using namespace tt;
0011 
0012 namespace trackerDTC {
0013 
0014   DTC::DTC(const ParameterSet& iConfig,
0015            const Setup* setup,
0016            const LayerEncoding* layerEncoding,
0017            int dtcId,
0018            const std::vector<std::vector<TTStubRef>>& stubsDTC)
0019       : setup_(setup),
0020         enableTruncation_(iConfig.getParameter<bool>("EnableTruncation")),
0021         region_(dtcId / setup->numDTCsPerRegion()),
0022         board_(dtcId % setup->numDTCsPerRegion()),
0023         modules_(setup->dtcModules(dtcId)),
0024         input_(setup->dtcNumRoutingBlocks(), Stubss(setup->dtcNumModulesPerRoutingBlock())),
0025         lost_(setup->numOverlappingRegions()) {
0026     // count number of stubs on this dtc
0027     auto acc = [](int sum, const vector<TTStubRef>& stubsModule) { return sum + stubsModule.size(); };
0028     const int nStubs = accumulate(stubsDTC.begin(), stubsDTC.end(), 0, acc);
0029     stubs_.reserve(nStubs);
0030     // convert and assign Stubs to DTC routing block channel
0031     for (int modId = 0; modId < setup->numModulesPerDTC(); modId++) {
0032       const vector<TTStubRef>& ttStubRefs = stubsDTC[modId];
0033       if (ttStubRefs.empty())
0034         continue;
0035       // Module which produced this ttStubRefs
0036       SensorModule* module = modules_.at(modId);
0037       // DTC routing block id [0-1]
0038       const int blockId = modId / setup->dtcNumModulesPerRoutingBlock();
0039       // DTC routing blockc  channel id [0-35]
0040       const int channelId = modId % setup->dtcNumModulesPerRoutingBlock();
0041       // convert TTStubs and fill input channel
0042       Stubs& stubs = input_[blockId][channelId];
0043       for (const TTStubRef& ttStubRef : ttStubRefs) {
0044         stubs_.emplace_back(iConfig, setup, layerEncoding, module, ttStubRef);
0045         Stub& stub = stubs_.back();
0046         if (stub.valid())
0047           // passed pt and eta cut
0048           stubs.push_back(&stub);
0049       }
0050       // sort stubs by bend
0051       sort(stubs.begin(), stubs.end(), [](Stub* lhs, Stub* rhs) { return abs(lhs->bend()) < abs(rhs->bend()); });
0052       // truncate stubs if desired
0053       if (!enableTruncation_ || (int)stubs.size() <= setup->numFramesFE())
0054         continue;
0055       // begin of truncated stubs
0056       const auto limit = next(stubs.begin(), setup->numFramesFE());
0057       // copy truncated stubs into lost output channel
0058       for (int region = 0; region < setup->numOverlappingRegions(); region++)
0059         copy_if(
0060             limit, stubs.end(), back_inserter(lost_[region]), [region](Stub* stub) { return stub->inRegion(region); });
0061       // remove truncated stubs form input channel
0062       stubs.erase(limit, stubs.end());
0063     }
0064   }
0065 
0066   // board level routing in two steps and products filling
0067   void DTC::produce(TTDTC& productAccepted, TTDTC& productLost) {
0068     // router step 1: merges stubs of all modules connected to one routing block into one stream
0069     Stubs lost;
0070     Stubss blockStubs(setup_->dtcNumRoutingBlocks());
0071     for (int routingBlock = 0; routingBlock < setup_->dtcNumRoutingBlocks(); routingBlock++)
0072       merge(input_[routingBlock], blockStubs[routingBlock], lost);
0073     // copy lost stubs during merge into lost output channel
0074     for (int region = 0; region < setup_->numOverlappingRegions(); region++) {
0075       auto inRegion = [region](Stub* stub) { return stub->inRegion(region); };
0076       copy_if(lost.begin(), lost.end(), back_inserter(lost_[region]), inRegion);
0077     }
0078     // router step 2: merges stubs of all routing blocks and splits stubs into one stream per overlapping region
0079     Stubss regionStubs(setup_->numOverlappingRegions());
0080     split(blockStubs, regionStubs);
0081     // fill products
0082     produce(regionStubs, productAccepted);
0083     produce(lost_, productLost);
0084   }
0085 
0086   // router step 1: merges stubs of all modules connected to one routing block into one stream
0087   void DTC::merge(Stubss& inputs, Stubs& output, Stubs& lost) {
0088     // for each input one fifo
0089     Stubss stacks(inputs.size());
0090     // clock accurate firmware emulation, each while trip describes one clock tick
0091     while (!all_of(inputs.begin(), inputs.end(), [](const Stubs& channel) { return channel.empty(); }) or
0092            !all_of(stacks.begin(), stacks.end(), [](const Stubs& channel) { return channel.empty(); })) {
0093       // fill fifos
0094       for (int iInput = 0; iInput < (int)inputs.size(); iInput++) {
0095         Stubs& input = inputs[iInput];
0096         Stubs& stack = stacks[iInput];
0097         if (input.empty())
0098           continue;
0099         Stub* stub = pop_front(input);
0100         if (stub) {
0101           if (enableTruncation_ && (int)stack.size() == setup_->dtcDepthMemory() - 1)
0102             // kill current first stub when fifo overflows
0103             lost.push_back(pop_front(stack));
0104           stack.push_back(stub);
0105         }
0106       }
0107       // route stub from a fifo to output if possible
0108       bool nothingToRoute(true);
0109       for (int iInput = inputs.size() - 1; iInput >= 0; iInput--) {
0110         Stubs& stack = stacks[iInput];
0111         if (stack.empty())
0112           continue;
0113         nothingToRoute = false;
0114         output.push_back(pop_front(stack));
0115         // only one stub can be routed to output per clock tick
0116         break;
0117       }
0118       // each clock tick output will grow by one, if no stub is available then by a gap
0119       if (nothingToRoute)
0120         output.push_back(nullptr);
0121     }
0122     // truncate if desired
0123     if (enableTruncation_ && (int)output.size() > setup_->numFramesIO()) {
0124       const auto limit = next(output.begin(), setup_->numFramesIO());
0125       copy_if(limit, output.end(), back_inserter(lost), [](Stub* stub) { return stub; });
0126       output.erase(limit, output.end());
0127     }
0128     // remove all gaps between end and last stub
0129     for (auto it = output.end(); it != output.begin();)
0130       it = (*--it) ? output.begin() : output.erase(it);
0131   }
0132 
0133   // router step 2: merges stubs of all routing blocks and splits stubs into one stream per overlapping region
0134   void DTC::split(Stubss& inputs, Stubss& outputs) {
0135     int region(0);
0136     auto regionMask = [&region](Stub* stub) { return stub && stub->inRegion(region) ? stub : nullptr; };
0137     for (Stubs& output : outputs) {
0138       // copy of masked inputs for each output
0139       Stubss streams(inputs.size());
0140       int i(0);
0141       for (Stubs& input : inputs) {
0142         Stubs& stream = streams[i++];
0143         transform(input.begin(), input.end(), back_inserter(stream), regionMask);
0144         for (auto it = stream.end(); it != stream.begin();)
0145           it = (*--it) ? stream.begin() : stream.erase(it);
0146       }
0147       merge(streams, output, lost_[region++]);
0148     }
0149   }
0150 
0151   // conversion from Stubss to TTDTC
0152   void DTC::produce(const Stubss& stubss, TTDTC& product) {
0153     int channel(0);
0154     auto toFrame = [&channel](Stub* stub) {
0155       return stub ? make_pair(stub->ttStubRef(), stub->frame(channel)) : FrameStub();
0156     };
0157     for (const Stubs& stubs : stubss) {
0158       StreamStub stream;
0159       stream.reserve(stubs.size());
0160       transform(stubs.begin(), stubs.end(), back_inserter(stream), toFrame);
0161       product.setStream(region_, board_, channel++, stream);
0162     }
0163   }
0164 
0165   // pop_front function which additionally returns copy of deleted front
0166   Stub* DTC::pop_front(Stubs& deque) {
0167     Stub* stub = deque.front();
0168     deque.pop_front();
0169     return stub;
0170   }
0171 
0172 }  // namespace trackerDTC