Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-10-01 01:02:11

0001 #ifndef L1Trigger_Phase2L1ParticleFlow_L1SeedConePFJetEmulator_h
0002 #define L1Trigger_Phase2L1ParticleFlow_L1SeedConePFJetEmulator_h
0003 
0004 #include "DataFormats/L1TParticleFlow/interface/layer1_emulator.h"
0005 #include "DataFormats/L1TParticleFlow/interface/jets.h"
0006 
0007 #include <iostream>
0008 #include <vector>
0009 #include <numeric>
0010 #include <algorithm>
0011 
0012 #include "L1Trigger/Phase2L1ParticleFlow/interface/dbgPrintf.h"
0013 
0014 class L1SCJetEmu {
0015 public:
0016   // Data types and constants used in the FPGA and FPGA-optimized functions
0017   // This header file is also for use in the standalone FPGA-tools simulation
0018   // and thus contains no CMSSW/EDM specific content
0019   typedef l1ct::pt_t pt_t;
0020   typedef l1ct::glbeta_t etaphi_t;       // Type for eta & phi
0021   typedef ap_int<13> detaphi_t;          // Type for deta & dphi
0022   typedef ap_fixed<18, 23> detaphi2_t;   // Type for deta^2 & dphi^2
0023   typedef ap_fixed<22, 22> pt_etaphi_t;  // Type for product of pt with deta & dphi
0024   typedef l1ct::PuppiObjEmu Particle;
0025 
0026   class Jet : public l1ct::Jet {
0027   public:
0028     std::vector<l1ct::PuppiObjEmu> constituents;
0029   };
0030 
0031   L1SCJetEmu(bool debug, float coneSize, unsigned nJets);
0032 
0033   std::vector<Jet> emulateEvent(std::vector<Particle>& parts) const;
0034 
0035 private:
0036   // Configuration settings
0037   bool debug_;
0038   float coneSize_;
0039   unsigned nJets_;
0040   detaphi2_t rCone2_;
0041 
0042   // constants for the axis update
0043   typedef ap_ufixed<18, -2> inv_pt_t;
0044   static constexpr int N_table_inv_pt = 1024;
0045   inv_pt_t inv_pt_table_[N_table_inv_pt];
0046 
0047   static constexpr int ceillog2(int x) { return (x <= 2) ? 1 : 1 + ceillog2((x + 1) / 2); }
0048 
0049   static constexpr int floorlog2(int x) { return (x < 2) ? 0 : 1 + floorlog2(x / 2); }
0050 
0051   template <int B>
0052   static constexpr int pow(int x) {
0053     return x == 0 ? 1 : B * pow<B>(x - 1);
0054   }
0055 
0056   static constexpr int pow2(int x) { return pow<2>(x); }
0057 
0058   /* ---
0059   * Balanced tree reduce implementation.
0060   * Reduces an array of inputs to a single value using the template binary operator 'Op',
0061   * for example summing all elements with Op_add, or finding the maximum with Op_max
0062   * Use only when the input array is fully unrolled. Or, slice out a fully unrolled section
0063   * before applying and accumulate the result over the rolled dimension.
0064   * Required for emulation to guarantee equality of ordering.
0065   * --- */
0066   template <class T, class Op>
0067   static T reduce(std::vector<T> x, Op op) {
0068     int N = x.size();
0069     int leftN = pow2(floorlog2(N - 1)) > 0 ? pow2(floorlog2(N - 1)) : 0;
0070     //static constexpr int rightN = N - leftN > 0 ? N - leftN : 0;
0071     if (N == 1) {
0072       return x.at(0);
0073     } else if (N == 2) {
0074       return op(x.at(0), x.at(1));
0075     } else {
0076       std::vector<T> left(x.begin(), x.begin() + leftN);
0077       std::vector<T> right(x.begin() + leftN, x.end());
0078       return op(reduce<T, Op>(left, op), reduce<T, Op>(right, op));
0079     }
0080   }
0081 
0082   class OpPuppiObjMax {
0083   public:
0084     Particle operator()(Particle a, Particle b) { return a.hwPt >= b.hwPt ? a : b; }
0085   };
0086 
0087   static OpPuppiObjMax op_max;
0088 
0089   template <class data_T, int N>
0090   static inline float real_val_from_idx(unsigned i) {
0091     // Treat the index as the top N bits
0092     static constexpr int NB = ceillog2(N);  // number of address bits for table
0093     data_T x(0);
0094     // The MSB of 1 is implicit in the table
0095     x[x.width - 1] = 1;
0096     // So we can use the next NB bits for real data
0097     x(x.width - 2, x.width - NB - 1) = i;
0098     return (float)x;
0099   }
0100 
0101   template <class data_T, int N>
0102   static inline unsigned idx_from_real_val(data_T x) {
0103     // Slice the top N bits to get an index into the table
0104     static constexpr int NB = ceillog2(N);  // number of address bits for table
0105     // Slice the top-1 NB bits of the value
0106     // the MSB of '1' is implicit, so only slice below that
0107     ap_uint<NB> y = x(x.width - 2, x.width - NB - 1);
0108     return (unsigned)y(NB - 1, 0);
0109   }
0110 
0111   template <class data_T, class table_T, int N>
0112   static void init_invert_table(table_T table_out[N]) {
0113     // The template data_T is the data type used to address the table
0114     for (unsigned i = 0; i < N; i++) {
0115       float x = real_val_from_idx<data_T, N>(i);
0116       table_T inv_x = 1 / x;
0117       table_out[i] = inv_x;
0118     }
0119   }
0120 
0121   template <class in_t, class table_t, int N>
0122   static table_t invert_with_shift(const in_t in, const table_t inv_table[N], bool debug = false) {
0123     // find the first '1' in the denominator
0124     int msb = 0;
0125     for (int b = 0; b < in.width; b++) {
0126       if (in[b])
0127         msb = b;
0128     }
0129     // shift up the denominator such that the left-most bit (msb) is '1'
0130     in_t in_shifted = in << (in.width - msb - 1);
0131     // lookup the inverse of the shifted input
0132     int idx = idx_from_real_val<in_t, N>(in_shifted);
0133     table_t inv_in = inv_table[idx];
0134     // shift the output back
0135     table_t out = inv_in << (in.width - msb - 1);
0136     if (debug) {
0137       dbgCout() << "           x " << in << ", msb = " << msb << ", shift = " << (in.width - msb) << ", idx = " << idx
0138                 << std::endl;
0139       dbgCout() << "     pre 1 / " << in_shifted << " = " << inv_in << "(" << 1 / (float)in_shifted << ")" << std::endl;
0140       dbgCout() << "    post 1 / " << in << " = " << out << "(" << 1 / (float)in << ")" << std::endl;
0141     }
0142     return out;
0143   }
0144 
0145   static detaphi_t deltaPhi(Particle a, Particle b);
0146   bool inCone(Particle seed, Particle part) const;
0147   Jet makeJet_HW(const std::vector<Particle>& parts) const;
0148 
0149 };  // class L1SCJetEmu
0150 
0151 #endif