Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:30:39

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