File indexing completed on 2025-06-03 00:12:13
0001 #include "L1Trigger/TrackerDTC/interface/DTC.h"
0002
0003 #include <vector>
0004 #include <iterator>
0005 #include <algorithm>
0006 #include <numeric>
0007
0008 namespace trackerDTC {
0009
0010 DTC::DTC(const tt::Setup* setup,
0011 const trackerTFP::DataFormats* dataFormats,
0012 const LayerEncoding* layerEncoding,
0013 int dtcId,
0014 const std::vector<std::vector<TTStubRef>>& stubsDTC)
0015 : setup_(setup),
0016 dataFormats_(dataFormats),
0017 region_(dtcId / setup->numDTCsPerRegion()),
0018 board_(dtcId % setup->numDTCsPerRegion()),
0019 modules_(setup->dtcModules(dtcId)),
0020 input_(setup->dtcNumRoutingBlocks(), Stubss(setup->dtcNumModulesPerRoutingBlock())),
0021 lost_(setup->numOverlappingRegions()) {
0022
0023 auto acc = [](int sum, const std::vector<TTStubRef>& stubsModule) { return sum + stubsModule.size(); };
0024 const int nStubs = std::accumulate(stubsDTC.begin(), stubsDTC.end(), 0, acc);
0025 stubs_.reserve(nStubs);
0026
0027 for (int modId = 0; modId < setup->numModulesPerDTC(); modId++) {
0028 const std::vector<TTStubRef>& ttStubRefs = stubsDTC[modId];
0029 if (ttStubRefs.empty())
0030 continue;
0031
0032 const tt::SensorModule* module = modules_.at(modId);
0033
0034 const int blockId = modId / setup->dtcNumModulesPerRoutingBlock();
0035
0036 const int channelId = modId % setup->dtcNumModulesPerRoutingBlock();
0037
0038 Stubs& stubs = input_[blockId][channelId];
0039 for (const TTStubRef& ttStubRef : ttStubRefs) {
0040 stubs_.emplace_back(setup, dataFormats, layerEncoding, module, ttStubRef);
0041 Stub& stub = stubs_.back();
0042 if (stub.valid())
0043
0044 stubs.push_back(&stub);
0045 }
0046
0047 std::sort(stubs.begin(), stubs.end(), [](Stub* lhs, Stub* rhs) {
0048 return std::abs(lhs->bend()) < std::abs(rhs->bend());
0049 });
0050
0051 if (!setup_->enableTruncation() || (int)stubs.size() <= setup->numFramesFE())
0052 continue;
0053
0054 const auto limit = std::next(stubs.begin(), setup->numFramesFE());
0055
0056 for (int region = 0; region < setup->numOverlappingRegions(); region++)
0057 std::copy_if(limit, stubs.end(), std::back_inserter(lost_[region]), [region](Stub* stub) {
0058 return stub->inRegion(region);
0059 });
0060
0061 stubs.erase(limit, stubs.end());
0062 }
0063 }
0064
0065
0066 void DTC::produce(TTDTC& productAccepted, TTDTC& productLost) {
0067
0068 Stubs lost;
0069 Stubss blockStubs(setup_->dtcNumRoutingBlocks());
0070 for (int routingBlock = 0; routingBlock < setup_->dtcNumRoutingBlocks(); routingBlock++)
0071 merge(input_[routingBlock], blockStubs[routingBlock], lost);
0072
0073 for (int region = 0; region < setup_->numOverlappingRegions(); region++) {
0074 auto inRegion = [region](Stub* stub) { return stub->inRegion(region); };
0075 std::copy_if(lost.begin(), lost.end(), std::back_inserter(lost_[region]), inRegion);
0076 }
0077
0078 Stubss regionStubs(setup_->numOverlappingRegions());
0079 split(blockStubs, regionStubs);
0080
0081 produce(regionStubs, productAccepted);
0082 produce(lost_, productLost);
0083 }
0084
0085
0086 void DTC::merge(Stubss& inputs, Stubs& output, Stubs& lost) {
0087
0088 Stubss stacks(inputs.size());
0089
0090 while (!std::all_of(inputs.begin(), inputs.end(), [](const Stubs& channel) { return channel.empty(); }) ||
0091 !std::all_of(stacks.begin(), stacks.end(), [](const Stubs& channel) { return channel.empty(); })) {
0092
0093 for (int iInput = 0; iInput < static_cast<int>(inputs.size()); iInput++) {
0094 Stubs& input = inputs[iInput];
0095 Stubs& stack = stacks[iInput];
0096 if (input.empty())
0097 continue;
0098 Stub* stub = pop_front(input);
0099 if (stub) {
0100 if (setup_->enableTruncation() && static_cast<int>(stack.size()) == setup_->dtcDepthMemory() - 1)
0101
0102 lost.push_back(pop_front(stack));
0103 stack.push_back(stub);
0104 }
0105 }
0106
0107 bool nothingToRoute(true);
0108 for (int iInput = inputs.size() - 1; iInput >= 0; iInput--) {
0109 Stubs& stack = stacks[iInput];
0110 if (stack.empty())
0111 continue;
0112 nothingToRoute = false;
0113 output.push_back(pop_front(stack));
0114
0115 break;
0116 }
0117
0118 if (nothingToRoute)
0119 output.push_back(nullptr);
0120 }
0121
0122 if (setup_->enableTruncation() && (int)output.size() > setup_->numFramesIOHigh()) {
0123 const auto limit = std::next(output.begin(), setup_->numFramesIOHigh());
0124 std::copy_if(limit, output.end(), std::back_inserter(lost), [](Stub* stub) { return stub; });
0125 output.erase(limit, output.end());
0126 }
0127
0128 for (auto it = output.end(); it != output.begin();)
0129 it = (*--it) ? output.begin() : output.erase(it);
0130 }
0131
0132
0133 void DTC::split(Stubss& inputs, Stubss& outputs) {
0134 int region(0);
0135 auto regionMask = [®ion](Stub* stub) { return stub && stub->inRegion(region) ? stub : nullptr; };
0136 for (Stubs& output : outputs) {
0137
0138 Stubss streams(inputs.size());
0139 int i(0);
0140 for (Stubs& input : inputs) {
0141 Stubs& stream = streams[i++];
0142 std::transform(input.begin(), input.end(), back_inserter(stream), regionMask);
0143 for (auto it = stream.end(); it != stream.begin();)
0144 it = (*--it) ? stream.begin() : stream.erase(it);
0145 }
0146 merge(streams, output, lost_[region++]);
0147 }
0148 }
0149
0150
0151 void DTC::produce(const Stubss& stubss, TTDTC& product) {
0152 int channel(0);
0153 auto toFrame = [&channel](Stub* stub) { return stub ? stub->frame(channel) : tt::FrameStub(); };
0154 for (const Stubs& stubs : stubss) {
0155 tt::StreamStub stream;
0156 stream.reserve(stubs.size());
0157 std::transform(stubs.begin(), stubs.end(), std::back_inserter(stream), toFrame);
0158 product.setStream(region_, board_, channel++, stream);
0159 }
0160 }
0161
0162
0163 Stub* DTC::pop_front(Stubs& deque) {
0164 Stub* stub = deque.front();
0165 deque.pop_front();
0166 return stub;
0167 }
0168
0169 }