Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-20 01:53:35

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