Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-10 01:53:56

0001 #include "L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/tkinput_ref.h"
0002 #include "L1Trigger/Phase2L1ParticleFlow/interface/dbgPrintf.h"
0003 
0004 #include <cmath>
0005 #include <cassert>
0006 #include <cstdio>
0007 
0008 #ifdef CMSSW_GIT_HASH
0009 #include <cstdint>
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011 #include "FWCore/Utilities/interface/Exception.h"
0012 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0013 
0014 namespace {
0015   l1ct::TrackInputEmulator::Region parseRegion(const std::string &str) {
0016     if (str == "barrel")
0017       return l1ct::TrackInputEmulator::Region::Barrel;
0018     else if (str == "endcap")
0019       return l1ct::TrackInputEmulator::Region::Endcap;
0020     else if (str == "any")
0021       return l1ct::TrackInputEmulator::Region::Any;
0022     else
0023       throw cms::Exception("Configuration", "TrackInputEmulator: Unsupported region '" + str + "'\n");
0024   }
0025   l1ct::TrackInputEmulator::Encoding parseEncoding(const std::string &str) {
0026     if (str == "stepping")
0027       return l1ct::TrackInputEmulator::Encoding::Stepping;
0028     else if (str == "biased")
0029       return l1ct::TrackInputEmulator::Encoding::Biased;
0030     else if (str == "unbised")
0031       return l1ct::TrackInputEmulator::Encoding::Unbiased;
0032     else
0033       throw cms::Exception("Configuration", "TrackInputEmulator: Unsupported track word encoding '" + str + "'\n");
0034   }
0035 }  // namespace
0036 
0037 l1ct::TrackInputEmulator::TrackInputEmulator(const edm::ParameterSet &iConfig)
0038     : TrackInputEmulator(parseRegion(iConfig.getParameter<std::string>("region")),
0039                          parseEncoding(iConfig.getParameter<std::string>("trackWordEncoding")),
0040                          iConfig.getParameter<bool>("bitwiseAccurate")) {
0041   if (region_ != Region::Endcap && region_ != Region::Barrel) {
0042     edm::LogError("TrackInputEmulator") << "region '" << iConfig.getParameter<std::string>("region")
0043                                         << "' is not yet supported";
0044   }
0045   debug_ = iConfig.getUntrackedParameter<bool>("debug", false);
0046   configPt(iConfig.getParameter<uint32_t>("ptLUTBits"));
0047   configEta(iConfig.getParameter<uint32_t>("etaLUTBits"),
0048             iConfig.getParameter<int32_t>("etaPreOffs"),
0049             iConfig.getParameter<uint32_t>("etaShift"),
0050             iConfig.getParameter<int32_t>("etaPostOffs"),
0051             iConfig.getParameter<bool>("etaSigned"),
0052             region_ == Region::Endcap);
0053   configPhi(iConfig.getParameter<uint32_t>("phiBits"));
0054   configZ0(iConfig.getParameter<uint32_t>("z0Bits"));
0055   if (region_ == Region::Barrel) {
0056     configDEtaBarrel(iConfig.getParameter<uint32_t>("dEtaBarrelBits"),
0057                      iConfig.getParameter<uint32_t>("dEtaBarrelZ0PreShift"),
0058                      iConfig.getParameter<uint32_t>("dEtaBarrelZ0PostShift"),
0059                      iConfig.getParameter<double>("dEtaBarrelFloatOffs"));
0060     configDPhiBarrel(iConfig.getParameter<uint32_t>("dPhiBarrelBits"),
0061                      iConfig.getParameter<uint32_t>("dPhiBarrelRInvPreShift"),
0062                      iConfig.getParameter<uint32_t>("dPhiBarrelRInvPostShift"),
0063                      iConfig.getParameter<double>("dPhiBarrelFloatOffs"));
0064   }
0065   if (region_ == Region::Endcap) {
0066     configDEtaHGCal(iConfig.getParameter<uint32_t>("dEtaHGCalBits"),
0067                     iConfig.getParameter<uint32_t>("dEtaHGCalZ0PreShift"),
0068                     iConfig.getParameter<uint32_t>("dEtaHGCalRInvPreShift"),
0069                     iConfig.getParameter<uint32_t>("dEtaHGCalLUTBits"),
0070                     iConfig.getParameter<uint32_t>("dEtaHGCalLUTShift"),
0071                     iConfig.getParameter<double>("dEtaHGCalFloatOffs"));
0072     configDPhiHGCal(iConfig.getParameter<uint32_t>("dPhiHGCalBits"),
0073                     iConfig.getParameter<uint32_t>("dPhiHGCalZ0PreShift"),
0074                     iConfig.getParameter<uint32_t>("dPhiHGCalZ0PostShift"),
0075                     iConfig.getParameter<uint32_t>("dPhiHGCalRInvShift"),
0076                     iConfig.getParameter<uint32_t>("dPhiHGCalTanlInvShift"),
0077                     iConfig.getParameter<uint32_t>("dPhiHGCalTanlLUTBits"),
0078                     iConfig.getParameter<double>("dPhiHGCalFloatOffs"));
0079   }
0080 }
0081 
0082 #endif
0083 
0084 l1ct::TrackInputEmulator::TrackInputEmulator(Region region, Encoding encoding, bool bitwise)
0085     : region_(region),
0086       encoding_(encoding),
0087       bitwise_(bitwise),
0088       rInvToPt_(31199.5),
0089       phiScale_(0.00038349520),
0090       z0Scale_(0.00999469),
0091       dEtaBarrelParamZ0_(0.31735),
0092       dPhiBarrelParamC_(0.0056535),
0093       dEtaHGCalParamZ0_(-0.00655),
0094       dEtaHGCalParamRInv2C_(+0.66),
0095       dEtaHGCalParamRInv2ITanl1_(-0.72),
0096       dEtaHGCalParamRInv2ITanl2_(-0.38),
0097       dPhiHGCalParamZ0_(0.00171908),
0098       dPhiHGCalParamC_(56.5354),
0099       debug_(false) {}
0100 
0101 std::pair<l1ct::TkObjEmu, bool> l1ct::TrackInputEmulator::decodeTrack(ap_uint<96> tkword,
0102                                                                       const l1ct::PFRegionEmu &sector,
0103                                                                       bool bitwise) const {
0104   l1ct::TkObjEmu ret;
0105   ret.clear();
0106   auto z0 = signedZ0(tkword);
0107   auto tanl = signedTanl(tkword);
0108   auto Rinv = signedRinv(tkword);
0109   auto phi = signedPhi(tkword);
0110 
0111   bool okprop = false, oksel = false;
0112   switch (region_) {
0113     case Region::Barrel:
0114       okprop = withinBarrel(tanl);
0115       break;
0116     case Region::Endcap:
0117       okprop = mayReachHGCal(tanl) && withinTracker(tanl);
0118       break;
0119     case Region::Any:
0120       okprop = withinTracker(tanl);
0121       break;
0122   }
0123 
0124   if (valid(tkword) && okprop) {
0125     ret.hwQuality = tkword(2, 0);
0126     ret.hwCharge = charge(tkword);
0127 
0128     if (bitwise) {
0129       ret.hwPt = convPt(Rinv);
0130 
0131       l1ct::glbeta_t vtxEta = convEta(tanl);
0132       l1ct::phi_t vtxPhi = convPhi(phi);
0133 
0134       // track propagation
0135       if (region_ == Region::Barrel) {
0136         ret.hwDEta = calcDEtaBarrel(z0, Rinv, tanl);
0137         ret.hwDPhi = calcDPhiBarrel(z0, Rinv, tanl);
0138       }
0139 
0140       if (region_ == Region::Endcap) {
0141         ret.hwDEta = calcDEtaHGCal(z0, Rinv, tanl);
0142         ret.hwDPhi = calcDPhiHGCal(z0, Rinv, tanl);
0143       }
0144 
0145       ret.hwEta = vtxEta - ret.hwDEta;
0146       ret.hwPhi = vtxPhi - ret.hwDPhi * ret.intCharge();
0147       ret.hwZ0 = convZ0(z0);
0148     } else {
0149       ret.hwPt = l1ct::Scales::makePtFromFloat(floatPt(Rinv));
0150 
0151       float fvtxEta = floatEta(tanl) / l1ct::Scales::ETAPHI_LSB;
0152       float fvtxPhi = floatPhi(phi) / l1ct::Scales::ETAPHI_LSB;
0153 
0154       // track propagation
0155       float fDEta = 0, fDPhi = 0;  // already in layer-1 units
0156       if (region_ == Region::Barrel) {
0157         fDEta = floatDEtaBarrel(z0, Rinv, tanl);
0158         fDPhi = floatDPhiBarrel(z0, Rinv, tanl);
0159       }
0160 
0161       if (region_ == Region::Endcap) {
0162         fDEta = floatDEtaHGCal(z0, Rinv, tanl);
0163         fDPhi = floatDPhiHGCal(z0, Rinv, tanl);
0164       }
0165 
0166       ret.hwDPhi = std::round(fDPhi);
0167       ret.hwDEta = std::round(fDEta);
0168       ret.hwPhi = std::round(fvtxPhi - fDPhi * ret.intCharge());
0169       ret.hwEta = glbeta_t(std::round(fvtxEta)) - ret.hwDEta - sector.hwEtaCenter;
0170 
0171       ret.hwZ0 = l1ct::Scales::makeZ0(floatZ0(z0));
0172     }
0173 
0174     oksel = ret.hwQuality != 0;
0175   }
0176   return std::make_pair(ret, oksel);
0177 }
0178 
0179 float l1ct::TrackInputEmulator::floatPt(ap_int<15> Rinv) const { return rInvToPt_ / std::abs(toFloat_(Rinv)); }
0180 
0181 l1ct::pt_t l1ct::TrackInputEmulator::convPt(ap_int<15> Rinv) const {
0182   ap_uint<14> absRinv = (Rinv >= 0 ? ap_uint<14>(Rinv) : ap_uint<14>(-Rinv));
0183   unsigned int index = absRinv.to_int() >> ptLUTShift_;
0184   if (index >= ptLUT_.size()) {
0185     dbgPrintf("WARN: Rinv %d, absRinv %d, index %d, size %lu, shift %d\n",
0186               Rinv.to_int(),
0187               absRinv.to_int(),
0188               index,
0189               ptLUT_.size(),
0190               ptLUTShift_);
0191     index = ptLUT_.size() - 1;
0192   }
0193   return ptLUT_[index];
0194 }
0195 
0196 void l1ct::TrackInputEmulator::configPt(int lutBits) {
0197   ptLUTShift_ = 14 - lutBits;
0198   ptLUT_.resize(1 << lutBits);
0199   for (unsigned int u = 0, n = ptLUT_.size(); u < n; ++u) {
0200     int iRinv = std::round((u + 0.5) * (1 << ptLUTShift_));
0201     ptLUT_[u] = l1ct::Scales::makePtFromFloat(floatPt(iRinv));
0202   }
0203 }
0204 
0205 float l1ct::TrackInputEmulator::floatEta(ap_int<16> tanl) const {
0206   float lam = std::atan(floatTanl(tanl));
0207   float theta = M_PI / 2 - lam;
0208   return -std::log(std::tan(0.5 * theta));
0209 }
0210 
0211 l1ct::glbeta_t l1ct::TrackInputEmulator::convEta(ap_int<16> tanl) const {
0212   unsigned int index;
0213   if (tanlLUTSigned_) {
0214     index = std::max(0, std::abs(tanl.to_int()) - tanlLUTPreOffs_) >> tanlLUTShift_;
0215   } else {
0216     ap_uint<16> unsTanl = tanl(15, 0);
0217     index = unsTanl.to_int() >> tanlLUTShift_;
0218   }
0219   if (index >= tanlLUT_.size()) {
0220     dbgPrintf(
0221         "WARN: tanl %d, index %d, size %lu (signed %d)\n", tanl.to_int(), index, tanlLUT_.size(), int(tanlLUTSigned_));
0222     index = tanlLUT_.size() - 1;
0223   }
0224   int ret = tanlLUT_[index] + tanlLUTPostOffs_;
0225   if (tanlLUTSigned_ && tanl < 0)
0226     ret = -ret;
0227   if (debug_)
0228     dbgPrintf("convEta: itanl = %+8d -> index %8d, LUT %8d, ret %+8d\n", tanl.to_int(), index, tanlLUT_[index], ret);
0229   return ret;
0230 }
0231 
0232 void l1ct::TrackInputEmulator::configEta(
0233     int lutBits, int preOffs, int shift, int postOffs, bool lutSigned, bool endcap) {
0234   tanlLUTSigned_ = lutSigned;
0235   tanlLUTPreOffs_ = preOffs;
0236   tanlLUTPostOffs_ = postOffs;
0237   tanlLUTShift_ = shift;
0238   tanlLUT_.resize(1 << lutBits);
0239   int etaCenter = lutSigned ? l1ct::Scales::makeGlbEtaRoundEven(2.5).to_int() / 2 : 0;
0240   int etamin = 1, etamax = -1;
0241   for (unsigned int u = 0, n = tanlLUT_.size(), h = n / 2; u < n; ++u) {
0242     int i = (tanlLUTSigned_ || (u < h)) ? int(u) : int(u) - int(n);
0243     ap_int<16> tanl = std::min<int>(i * (1 << shift) + preOffs, (1 << 16) - 1);
0244     int eta = l1ct::Scales::makeGlbEta(floatEta(tanl)).to_int() - etaCenter - tanlLUTPostOffs_;
0245     bool valid = endcap ? (mayReachHGCal(tanl) && withinTracker(tanl)) : withinBarrel(tanl);
0246     if (valid) {
0247       tanlLUT_[u] = eta;
0248       if (etamin > etamax) {
0249         etamin = eta;
0250         etamax = eta;
0251       } else {
0252         etamin = std::min(etamin, eta);
0253         etamax = std::max(etamax, eta);
0254       }
0255     } else {
0256       tanlLUT_[u] = 0;
0257     }
0258   }
0259   if (debug_)
0260     dbgPrintf(
0261         "Configured with glbEtaCenter = %d, bits %d, preOffs %d, shift %d, postOffs %d, lutmin = %d, lutmax = %d\n",
0262         etaCenter,
0263         lutBits,
0264         preOffs,
0265         shift,
0266         postOffs,
0267         etamin,
0268         etamax);
0269 }
0270 
0271 float l1ct::TrackInputEmulator::floatPhi(ap_int<12> phi) const { return phiScale_ * toFloat_(phi); }
0272 
0273 l1ct::phi_t l1ct::TrackInputEmulator::convPhi(ap_int<12> phi) const {
0274   int offs = phi >= 0 ? vtxPhiOffsPos_ : vtxPhiOffsNeg_;
0275   return (phi.to_int() * vtxPhiMult_ + offs) >> vtxPhiBitShift_;
0276 }
0277 
0278 void l1ct::TrackInputEmulator::configPhi(int bits) {
0279   float scale = phiScale_ / l1ct::Scales::ETAPHI_LSB;
0280   vtxPhiBitShift_ = bits;
0281   vtxPhiMult_ = std::round(scale * (1 << bits));
0282   switch (encoding_) {
0283     case Encoding::Stepping:
0284       vtxPhiOffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0285       vtxPhiOffsNeg_ = std::round(-scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0286       break;
0287     case Encoding::Biased:
0288       vtxPhiOffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0289       vtxPhiOffsNeg_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0290       break;
0291     case Encoding::Unbiased:
0292       vtxPhiOffsPos_ = (1 << (bits - 1));
0293       vtxPhiOffsNeg_ = (1 << (bits - 1));
0294       break;
0295   }
0296   if (debug_)
0297     dbgPrintf("Configured vtxPhi with scale %d [to_cmssw %.8f, to_l1ct %.8f, %d bits], offsets %+d (pos), %+d (neg)\n",
0298               vtxPhiMult_,
0299               phiScale_,
0300               scale,
0301               bits,
0302               vtxPhiOffsPos_,
0303               vtxPhiOffsNeg_);
0304 }
0305 
0306 float l1ct::TrackInputEmulator::floatZ0(ap_int<12> z0) const { return z0Scale_ * toFloat_(z0); }
0307 
0308 l1ct::z0_t l1ct::TrackInputEmulator::convZ0(ap_int<12> z0) const {
0309   int offs = z0 >= 0 ? z0OffsPos_ : z0OffsNeg_;
0310   return (z0.to_int() * z0Mult_ + offs) >> z0BitShift_;
0311 }
0312 
0313 void l1ct::TrackInputEmulator::configZ0(int bits) {
0314   float scale = z0Scale_ / l1ct::Scales::Z0_LSB;
0315   z0BitShift_ = bits;
0316   z0Mult_ = std::round(scale * (1 << bits));
0317   switch (encoding_) {
0318     case Encoding::Stepping:
0319       z0OffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0320       z0OffsNeg_ = std::round(-scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0321       break;
0322     case Encoding::Biased:
0323       z0OffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0324       z0OffsNeg_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0325       break;
0326     case Encoding::Unbiased:
0327       z0OffsPos_ = (1 << (bits - 1));
0328       z0OffsNeg_ = (1 << (bits - 1));
0329       break;
0330   }
0331 
0332   if (debug_)
0333     dbgPrintf("Configured z0 with scale %d [to_cmssw %.8f, to_l1ct %.8f, %d bits], offsets %+d (pos), %+d (neg)\n",
0334               z0Mult_,
0335               z0Scale_,
0336               scale,
0337               bits,
0338               z0OffsPos_,
0339               z0OffsNeg_);
0340 }
0341 
0342 float l1ct::TrackInputEmulator::floatDEtaBarrel(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0343   float ret = floatEta(tanl) - floatEta(tanl + z0.to_float() * dEtaBarrelParamZ0_);
0344   if (debug_) {
0345     dbgPrintf(
0346         "flt deta for z0 %+6d Rinv %+6d tanl %+6d:  eta(calo) %+8.2f  eta(vtx)  %+8.3f  ret  "
0347         "%+8.2f\n",
0348         z0.to_int(),
0349         Rinv.to_int(),
0350         tanl.to_int(),
0351         floatEta(tanl + z0.to_float() * dEtaBarrelParamZ0_),
0352         floatEta(tanl),
0353         ret);
0354   }
0355   return ret / l1ct::Scales::ETAPHI_LSB;
0356 }
0357 
0358 l1ct::tkdeta_t l1ct::TrackInputEmulator::calcDEtaBarrel(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0359   int vtxEta = convEta(tanl);
0360 
0361   ap_uint<14> absZ0 = z0 >= 0 ? ap_uint<14>(z0) : ap_uint<14>(-z0);
0362   int preSum = ((absZ0 >> dEtaBarrelZ0PreShift_) * dEtaBarrelZ0_) >> dEtaBarrelZ0PostShift_;
0363 
0364   int caloEta = convEta(tanl + (z0 > 0 ? 1 : -1) * ((preSum + dEtaBarrelOffs_) >> dEtaBarrelBits_));
0365 
0366   int ret = vtxEta - caloEta;
0367   if (debug_) {
0368     dbgPrintf(
0369         "int deta for z0 %+6d Rinv %+6d tanl %+6d:  preSum %+8.2f  eta(calo) %+8.2f  eta(vtx)  %+8.3f  ret  "
0370         "%+8.2f\n",
0371         z0.to_int(),
0372         Rinv.to_int(),
0373         tanl.to_int(),
0374         preSum,
0375         caloEta,
0376         vtxEta,
0377         ret);
0378   }
0379   return ret;
0380 }
0381 
0382 //use eta LUTs
0383 void l1ct::TrackInputEmulator::configDEtaBarrel(int dEtaBarrelBits,
0384                                                 int dEtaBarrelZ0PreShift,
0385                                                 int dEtaBarrelZ0PostShift,
0386                                                 float offs) {
0387   dEtaBarrelBits_ = dEtaBarrelBits;
0388 
0389   dEtaBarrelZ0PreShift_ = dEtaBarrelZ0PreShift;
0390   dEtaBarrelZ0PostShift_ = dEtaBarrelZ0PostShift;
0391   dEtaBarrelZ0_ =
0392       std::round(dEtaBarrelParamZ0_ * (1 << (dEtaBarrelZ0PreShift + dEtaBarrelZ0PostShift + dEtaBarrelBits)));
0393 
0394   int finalShift = dEtaBarrelBits_;
0395   dEtaBarrelOffs_ = std::round((1 << finalShift) * (0.5 + offs));
0396 
0397   if (debug_)
0398     dbgPrintf("Configured deta with %d bits: preshift %8d  postshift %8d, offset %8d\n",
0399               dEtaBarrelBits,
0400               dEtaBarrelZ0PreShift_,
0401               dEtaBarrelZ0PostShift_,
0402               offs);
0403 
0404   assert(finalShift >= 0);
0405 }
0406 
0407 float l1ct::TrackInputEmulator::floatDPhiBarrel(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0408   float ret = dPhiBarrelParamC_ * std::abs(Rinv.to_int());
0409   //ret = atan(ret / sqrt(1-ret*ret)); //use linear approx for now
0410   if (debug_) {
0411     dbgPrintf("flt dphi for z0 %+6d Rinv %+6d tanl %+6d:  Rinv/1k  %8.2f   ret  %8.2f\n",
0412               z0.to_int(),
0413               Rinv.to_int(),
0414               tanl.to_int(),
0415               std::abs(Rinv.to_int()) / 1024.0,
0416               ret);
0417   }
0418   return ret;
0419 }
0420 
0421 l1ct::tkdphi_t l1ct::TrackInputEmulator::calcDPhiBarrel(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0422   ap_uint<14> absRinv = Rinv >= 0 ? ap_uint<14>(Rinv) : ap_uint<14>(-Rinv);
0423   int preSum = ((absRinv >> dPhiBarrelRInvPreShift_) * dPhiBarrelC_) >> dPhiBarrelRInvPostShift_;
0424 
0425   if (debug_) {
0426     dbgPrintf("int dphi for z0 %+6d Rinv %+6d tanl %+6d:  ret  %8.2f\n",
0427               z0.to_int(),
0428               Rinv.to_int(),
0429               tanl.to_int(),
0430               (preSum + dPhiBarrelOffs_) >> dPhiBarrelBits_);
0431   }
0432 
0433   return (preSum + dPhiBarrelOffs_) >> dPhiBarrelBits_;
0434 }
0435 
0436 //using DSPs
0437 void l1ct::TrackInputEmulator::configDPhiBarrel(int dPhiBarrelBits,
0438                                                 int dPhiBarrelRInvPreShift,
0439                                                 int dPhiBarrelRInvPostShift,
0440                                                 float offs) {
0441   dPhiBarrelBits_ = dPhiBarrelBits;
0442 
0443   dPhiBarrelRInvPreShift_ = dPhiBarrelRInvPreShift;
0444   dPhiBarrelRInvPostShift_ = dPhiBarrelRInvPostShift;
0445   dPhiBarrelC_ =
0446       std::round(dPhiBarrelParamC_ * (1 << (dPhiBarrelRInvPreShift + dPhiBarrelRInvPostShift + dPhiBarrelBits)));
0447 
0448   int finalShift = dPhiBarrelBits_;
0449   dPhiBarrelOffs_ = std::round((1 << finalShift) * (0.5 + offs));
0450 
0451   if (debug_)
0452     dbgPrintf("Configured dphi with %d bits: preshift %8d  postshift %8d, offset %8d\n",
0453               dPhiBarrelBits,
0454               dPhiBarrelRInvPreShift_,
0455               dPhiBarrelRInvPostShift_,
0456               offs);
0457 
0458   assert(finalShift >= 0);
0459 }
0460 
0461 float l1ct::TrackInputEmulator::floatDEtaHGCal(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0462   float RinvScaled = Rinv.to_float() / (16 * 1024.0), RinvScaled2 = RinvScaled * RinvScaled;
0463   float invtanlScaled = (32 * 1024.0) / std::abs(tanl.to_float()), invtanlScaled2 = invtanlScaled * invtanlScaled;
0464   float tanlTerm = (tanl > 0 ? 1 : -1) * (dEtaHGCalParamRInv2C_ + dEtaHGCalParamRInv2ITanl1_ * invtanlScaled +
0465                                           dEtaHGCalParamRInv2ITanl2_ * invtanlScaled2);
0466   float ret = dEtaHGCalParamZ0_ * z0.to_float() + tanlTerm * RinvScaled2;
0467   if (debug_) {
0468     dbgPrintf(
0469         "flt deta for z0 %+6d Rinv %+6d tanl %+6d:  z0term %+8.2f  rinv2u %.4f tanlterm  %+8.3f (pre: %+8.2f)  ret  "
0470         "%+8.2f\n",
0471         z0.to_int(),
0472         Rinv.to_int(),
0473         tanl.to_int(),
0474         dEtaHGCalParamZ0_ * z0.to_float(),
0475         RinvScaled2,
0476         tanlTerm * RinvScaled2,
0477         tanlTerm,
0478         ret);
0479   }
0480   return ret;
0481 }
0482 
0483 l1ct::tkdeta_t l1ct::TrackInputEmulator::calcDEtaHGCal(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0484   int z0Term = dEtaHGCalZ0_ * (z0 >> dEtaHGCalZ0PreShift_);
0485 
0486   int rinvShift = Rinv.to_int() >> dEtaHGCalRInvPreShift_, rinvShift2 = rinvShift * rinvShift;
0487 
0488   ap_uint<16> unsTanl = tanl(15, 0);
0489   unsigned int tanlIdx = (unsTanl.to_int()) >> dEtaHGCalTanlShift_;
0490   assert(tanlIdx < dEtaHGCalLUT_.size());
0491   int tanlTerm = (rinvShift2 * dEtaHGCalLUT_[tanlIdx] + dEtaHGCalTanlTermOffs_) >> dEtaHGCalTanlTermShift_;
0492 
0493   int ret0 = z0Term + tanlTerm + dEtaHGCalOffs_;
0494   if (debug_) {
0495     dbgPrintf(
0496         "int deta for z0 %+6d Rinv %+6d tanl %+6d:  z0term %+8.2f  rinv2u %.4f tanlterm  %+8.2f (pre: %+8.2f)  ret  "
0497         "%+8.2f\n",
0498         z0.to_int(),
0499         Rinv.to_int(),
0500         tanl.to_int(),
0501         float(z0Term) / (1 << dEtaHGCalBits_),
0502         float(rinvShift2) / (1 << (28 - 2 * dEtaHGCalRInvPreShift_)),
0503         float(tanlTerm) / (1 << dEtaHGCalBits_),
0504         float(dEtaHGCalLUT_[tanlIdx]) / (1 << (dEtaHGCalBits_ - dEtaHGCalLUTShift_)),
0505         float(ret0) / (1 << dEtaHGCalBits_));
0506   }
0507   return (ret0 + (1 << (dEtaHGCalBits_ - 1))) >> dEtaHGCalBits_;
0508 }
0509 
0510 void l1ct::TrackInputEmulator::configDEtaHGCal(int dEtaHGCalBits,
0511                                                int dEtaHGCalZ0PreShift,
0512                                                int dEtaHGCalRInvPreShift,
0513                                                int dEtaHGCalLUTBits,
0514                                                int dEtaHGCalLUTShift,
0515                                                float offs) {
0516   dEtaHGCalBits_ = dEtaHGCalBits;
0517   float scale = (1 << dEtaHGCalBits);
0518 
0519   dEtaHGCalZ0PreShift_ = dEtaHGCalZ0PreShift;
0520   dEtaHGCalZ0_ = std::round(dEtaHGCalParamZ0_ * scale * (1 << dEtaHGCalZ0PreShift));
0521 
0522   dEtaHGCalRInvPreShift_ = dEtaHGCalRInvPreShift;
0523 
0524   dEtaHGCalTanlShift_ = 16 - dEtaHGCalLUTBits;
0525   dEtaHGCalLUT_.resize((1 << dEtaHGCalLUTBits));
0526   dEtaHGCalLUTShift_ = dEtaHGCalLUTShift;
0527 
0528   dEtaHGCalTanlTermShift_ = 28 - 2 * dEtaHGCalRInvPreShift_ - dEtaHGCalLUTShift_;
0529   dEtaHGCalTanlTermOffs_ = std::round(0.5 * (1 << dEtaHGCalTanlTermShift_));
0530   int lutmin = 1, lutmax = -1;
0531   float lutScale = scale / (1 << dEtaHGCalLUTShift);
0532   for (unsigned int u = 0, n = dEtaHGCalLUT_.size(), h = n / 2; u < n; ++u) {
0533     int i = (u < h) ? int(u) : int(u) - int(n);
0534     float tanl = (i + 0.5) * (1 << dEtaHGCalTanlShift_);
0535     float sign = tanl >= 0 ? 1 : -1;
0536     float invtanlScaled = 32 * 1024.0 / std::abs(tanl), invtanlScaled2 = invtanlScaled * invtanlScaled;
0537     float term = sign * (dEtaHGCalParamRInv2C_ + dEtaHGCalParamRInv2ITanl1_ * invtanlScaled +
0538                          dEtaHGCalParamRInv2ITanl2_ * invtanlScaled2);
0539     int iterm = std::round(lutScale * term);
0540     bool valid = mayReachHGCal(tanl);
0541     if (valid) {
0542       dEtaHGCalLUT_[u] = iterm;
0543       if (lutmin > lutmax) {
0544         lutmin = iterm;
0545         lutmax = iterm;
0546       } else {
0547         lutmin = std::min(lutmin, iterm);
0548         lutmax = std::max(lutmax, iterm);
0549       }
0550     } else {
0551       dEtaHGCalLUT_[u] = 0;
0552     }
0553   }
0554 
0555   dEtaHGCalOffs_ = std::round(scale * offs);
0556 
0557   if (debug_)
0558     dbgPrintf(
0559         "Configured deta with %d bits: z0 %8d [%8.2f], lutmin = %d, lutmax = %d, lutshift %d, rinvShift %d, "
0560         "tanlTermShift %d\n",
0561         dEtaHGCalBits,
0562         dEtaHGCalZ0_,
0563         dEtaHGCalZ0_ / float(scale),
0564         lutmin,
0565         lutmax,
0566         dEtaHGCalLUTShift,
0567         dEtaHGCalRInvPreShift_,
0568         dEtaHGCalTanlTermShift_);
0569 }
0570 
0571 float l1ct::TrackInputEmulator::floatDPhiHGCal(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0572   int dzsign = tanl >= 0 ? +1 : -1;
0573   float ret =
0574       (dPhiHGCalParamC_ - dPhiHGCalParamZ0_ * z0 * dzsign) * std::abs(Rinv.to_int()) / std::abs(tanl.to_float());
0575   if (debug_) {
0576     dbgPrintf(
0577         "flt dphi for z0 %+6d Rinv %+6d tanl %+6d:  preSum %+9.4f  Rinv/1k  %8.2f   1k/tanl  %8.5f   ret  %8.2f\n",
0578         z0.to_int(),
0579         Rinv.to_int(),
0580         tanl.to_int(),
0581         dPhiHGCalParamC_ - dPhiHGCalParamZ0_ * z0 * dzsign,
0582         std::abs(Rinv.to_int()) / 1024.0,
0583         1024.0 / std::abs(tanl.to_float()),
0584         ret);
0585   }
0586   return ret;
0587 }
0588 
0589 l1ct::tkdphi_t l1ct::TrackInputEmulator::calcDPhiHGCal(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0590   int dzsign = tanl >= 0 ? +1 : -1;
0591   int preSum = (((z0 >> dPhiHGCalZ0PreShift_) * dPhiHGCalZ0_) >> dPhiHGCalZ0PostShift_) * dzsign + dPhiHGCalPreOffs_;
0592 
0593   ap_uint<14> absRinv = Rinv >= 0 ? ap_uint<14>(Rinv) : ap_uint<14>(-Rinv);
0594   int rinvShifted = absRinv.to_int() >> dPhiHGCalRInvShift_;
0595 
0596   ap_uint<15> absTanl = tanl >= 0 ? ap_uint<15>(tanl) : ap_uint<15>(-tanl);
0597   unsigned int tanlIdx = absTanl.to_int() >> dPhiHGCalTanlShift_;
0598   assert(tanlIdx < dPhiHGCalTanlLUT_.size());
0599   int tanlTerm = dPhiHGCalTanlLUT_[tanlIdx];
0600 
0601   int finalShift = dPhiHGCalBits_ + dPhiHGCalTanlInvShift_ - dPhiHGCalRInvShift_;
0602   if (debug_) {
0603     dbgPrintf(
0604         "int dphi for z0 %+6d Rinv %+6d tanl %+6d:  preSum %+9.4f  Rinv/1k  %8.2f   1k/tanl  %8.5f   ret  %8.2f: int "
0605         "preSum %8d  rivShift %8d  tanlTerm %8d\n",
0606         z0.to_int(),
0607         Rinv.to_int(),
0608         tanl.to_int(),
0609         float(preSum) / (1 << dPhiHGCalBits_),
0610         (rinvShifted << dPhiHGCalRInvShift_) / 1024.0,
0611         tanlTerm * 1024.0 / (1 << dPhiHGCalTanlInvShift_),
0612         float(preSum * rinvShifted * tanlTerm) / (1 << finalShift),
0613         preSum,
0614         rinvShifted,
0615         tanlTerm);
0616   }
0617 
0618   return (preSum * rinvShifted * tanlTerm + dPhiHGCalOffs_) >> finalShift;
0619 }
0620 
0621 void l1ct::TrackInputEmulator::configDPhiHGCal(int dPhiHGCalBits,
0622                                                int dPhiHGCalZ0PreShift,
0623                                                int dPhiHGCalZ0PostShift,
0624                                                int dPhiHGCalRInvShift,
0625                                                int dPhiHGCalTanlInvShift,
0626                                                int dPhiHGCalTanlLUTBits,
0627                                                float offs) {
0628   dPhiHGCalBits_ = dPhiHGCalBits;
0629 
0630   dPhiHGCalZ0PreShift_ = dPhiHGCalZ0PreShift;
0631   dPhiHGCalZ0PostShift_ = dPhiHGCalZ0PostShift;
0632   dPhiHGCalZ0_ = -std::round(dPhiHGCalParamZ0_ * (1 << (dPhiHGCalZ0PreShift + dPhiHGCalZ0PostShift + dPhiHGCalBits)));
0633 
0634   dPhiHGCalPreOffs_ = std::round(dPhiHGCalParamC_ * (1 << dPhiHGCalBits));
0635 
0636   dPhiHGCalRInvShift_ = dPhiHGCalRInvShift;
0637 
0638   dPhiHGCalTanlInvShift_ = dPhiHGCalTanlInvShift;
0639   dPhiHGCalTanlShift_ = 15 - dPhiHGCalTanlLUTBits;
0640   dPhiHGCalTanlLUT_.resize((1 << dPhiHGCalTanlLUTBits));
0641   int lutmin = 1, lutmax = -1;
0642   for (unsigned int u = 0, n = dPhiHGCalTanlLUT_.size(); u < n; ++u) {
0643     float tanl = (u + 0.5) * (1 << dPhiHGCalTanlShift_);
0644     int iterm = std::round((1 << dPhiHGCalTanlInvShift_) / tanl);
0645     bool valid = mayReachHGCal(tanl);
0646     if (valid) {
0647       dPhiHGCalTanlLUT_[u] = iterm;
0648       if (lutmin > lutmax) {
0649         lutmin = iterm;
0650         lutmax = iterm;
0651       } else {
0652         lutmin = std::min(lutmin, iterm);
0653         lutmax = std::max(lutmax, iterm);
0654       }
0655     } else {
0656       dPhiHGCalTanlLUT_[u] = 0;
0657     }
0658   }
0659 
0660   int finalShift = dPhiHGCalBits_ + dPhiHGCalTanlInvShift_ - dPhiHGCalRInvShift_;
0661   dPhiHGCalOffs_ = std::round((1 << finalShift) * (0.5 + offs));
0662 
0663   if (debug_)
0664     dbgPrintf(
0665         "Configured dphi with %d bits: z0 %8d [%8.2f], preoffs %8d [%8.2f], final shift %d, lutmin = %d, lutmax = %d\n",
0666         dPhiHGCalBits,
0667         dPhiHGCalZ0_,
0668         dPhiHGCalZ0_ / float(1 << (dPhiHGCalZ0PostShift + dPhiHGCalBits)),
0669         dPhiHGCalPreOffs_,
0670         dPhiHGCalPreOffs_ / float(1 << dPhiHGCalBits),
0671         finalShift,
0672         lutmin,
0673         lutmax);
0674 
0675   assert(finalShift >= 0);
0676 }