Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-03 00:12:16

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 namespace trackerTFP {
0010 
0011   GeometricProcessor::GeometricProcessor(const tt::Setup* setup,
0012                                          const DataFormats* dataFormats,
0013                                          const LayerEncoding* layerEncoding,
0014                                          std::vector<StubGP>& stubs)
0015       : setup_(setup), dataFormats_(dataFormats), layerEncoding_(layerEncoding), stubs_(stubs) {
0016     numChannelIn_ = dataFormats_->numChannel(Process::pp);
0017     numChannelOut_ = dataFormats_->numChannel(Process::gp);
0018   }
0019 
0020   // fill output products
0021   void GeometricProcessor::produce(const std::vector<std::vector<StubPP*>>& streamsIn,
0022                                    std::vector<std::deque<StubGP*>>& streamsOut) {
0023     for (int channelOut = 0; channelOut < numChannelOut_; channelOut++) {
0024       // helper
0025       const int phiT = channelOut % setup_->gpNumBinsPhiT() - setup_->gpNumBinsPhiT() / 2;
0026       const int zT = channelOut / setup_->gpNumBinsPhiT() - setup_->gpNumBinsZT() / 2;
0027       auto valid = [phiT, zT](StubPP* stub) {
0028         const bool phiTValid = stub && phiT >= stub->phiTMin() && phiT <= stub->phiTMax();
0029         const bool zTValid = stub && zT >= stub->zTMin() && zT <= stub->zTMax();
0030         return (phiTValid && zTValid) ? stub : nullptr;
0031       };
0032       // input streams of stubs
0033       std::vector<std::deque<StubPP*>> inputs(numChannelIn_);
0034       for (int channelIn = 0; channelIn < numChannelIn_; channelIn++) {
0035         const std::vector<StubPP*>& streamIn = streamsIn[channelIn];
0036         std::transform(streamIn.begin(), streamIn.end(), std::back_inserter(inputs[channelIn]), valid);
0037       }
0038       // fifo for each stream
0039       std::vector<std::deque<StubGP*>> stacks(streamsIn.size());
0040       // output stream
0041       std::deque<StubGP*>& output = streamsOut[channelOut];
0042       // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick
0043       while (
0044           !std::all_of(inputs.begin(), inputs.end(), [](const std::deque<StubPP*>& stubs) { return stubs.empty(); }) ||
0045           !std::all_of(stacks.begin(), stacks.end(), [](const std::deque<StubGP*>& stubs) { return stubs.empty(); })) {
0046         // fill input fifos
0047         for (int channelIn = 0; channelIn < numChannelIn_; channelIn++) {
0048           std::deque<StubGP*>& stack = stacks[channelIn];
0049           StubPP* stub = pop_front(inputs[channelIn]);
0050           if (stub) {
0051             // convert stub
0052             StubGP* stubGP = produce(*stub, phiT, zT);
0053             // buffer overflow
0054             if (setup_->enableTruncation() && static_cast<int>(stack.size()) == setup_->gpDepthMemory() - 1)
0055               pop_front(stack);
0056             stack.push_back(stubGP);
0057           }
0058         }
0059         // merge input fifos to one stream, prioritizing higher input channel over lower channel
0060         bool nothingToRoute(true);
0061         for (int channelIn = 0; channelIn < numChannelIn_; channelIn++) {
0062           StubGP* stub = pop_front(stacks[channelIn]);
0063           if (stub) {
0064             nothingToRoute = false;
0065             output.push_back(stub);
0066             break;
0067           }
0068         }
0069         if (nothingToRoute)
0070           output.push_back(nullptr);
0071       }
0072       // truncate if desired
0073       if (setup_->enableTruncation() && static_cast<int>(output.size()) > setup_->numFramesHigh())
0074         output.resize(setup_->numFramesHigh());
0075       // remove all gaps between end and last stub
0076       for (auto it = output.end(); it != output.begin();)
0077         it = (*--it) ? output.begin() : output.erase(it);
0078     }
0079   }
0080 
0081   // convert stub
0082   StubGP* GeometricProcessor::produce(const StubPP& stub, int phiT, int zT) {
0083     const DataFormat& dfPhiT = dataFormats_->format(Variable::phiT, Process::gp);
0084     const DataFormat& dfZT = dataFormats_->format(Variable::zT, Process::gp);
0085     const DataFormat& dfCot = dataFormats_->format(Variable::cot, Process::gp);
0086     const DataFormat& dfR = dataFormats_->format(Variable::r, Process::gp);
0087     const DataFormat& dfL = dataFormats_->format(Variable::layer, Process::gp);
0088     const double cot = dfCot.digi(dfZT.floating(zT) / setup_->chosenRofZ());
0089     // determine kf layer id
0090     const std::vector<int>& le = layerEncoding_->layerEncoding(zT);
0091     const int layerId = setup_->layerId(stub.frame().first);
0092     const auto it = std::find(le.begin(), le.end(), layerId);
0093     const int kfLayerId = std::min(static_cast<int>(std::distance(le.begin(), it)), setup_->numLayers() - 1);
0094     // create data fields
0095     const double r = stub.r();
0096     const double phi = stub.phi() - dfPhiT.floating(phiT);
0097     const double z = stub.z() - (stub.r() + dfR.digi(setup_->chosenRofPhi())) * cot;
0098     TTBV layer(kfLayerId, dfL.width());
0099     if (stub.layer()[4]) {  // barrel
0100       layer.set(5);
0101       if (stub.layer()[3])  // psTilt
0102         layer.set(3);
0103       if (stub.layer().val(3) < 3)  // layerId < 3
0104         layer.set(4);
0105     } else if (stub.layer()[3])  // psTilt
0106       layer.set(4);
0107     const int inv2RMin = stub.inv2RMin();
0108     const int inv2RMax = stub.inv2RMax();
0109     stubs_.emplace_back(stub, r, phi, z, layer, inv2RMin, inv2RMax);
0110     return &stubs_.back();
0111   }
0112 
0113   // remove and return first element of deque, returns nullptr if empty
0114   template <class T>
0115   T* GeometricProcessor::pop_front(std::deque<T*>& ts) const {
0116     T* t = nullptr;
0117     if (!ts.empty()) {
0118       t = ts.front();
0119       ts.pop_front();
0120     }
0121     return t;
0122   }
0123 
0124 }  // namespace trackerTFP