Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-30 22:24:28

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     } else {
0205       ret.hwPt = l1ct::Scales::makePtFromFloat(floatPt(Rinv));
0206 
0207       float fvtxEta = floatEta(tanl) / l1ct::Scales::ETAPHI_LSB;
0208       float fvtxPhi = floatPhi(phi) / l1ct::Scales::ETAPHI_LSB;
0209 
0210       // track propagation
0211       float fDEta = 0, fDPhi = 0;  // already in layer-1 units
0212       if (region_ == Region::Barrel) {
0213         fDEta = floatDEtaBarrel(z0, Rinv, tanl);
0214         fDPhi = floatDPhiBarrel(z0, Rinv, tanl);
0215       }
0216 
0217       if (region_ == Region::Endcap) {
0218         fDEta = floatDEtaHGCal(z0, Rinv, tanl);
0219         fDPhi = floatDPhiHGCal(z0, Rinv, tanl);
0220       }
0221       ret.hwDPhi = std::round(fDPhi);
0222       ret.hwDEta = std::round(fDEta);
0223       ret.hwPhi = std::round(fvtxPhi - fDPhi * ret.intCharge());
0224       ret.hwEta = glbeta_t(std::round(fvtxEta)) - ret.hwDEta - sector.hwEtaCenter;
0225 
0226       ret.hwZ0 = l1ct::Scales::makeZ0(floatZ0(z0));
0227       ret.hwDxy = l1ct::Scales::makeDxy(floatDxy(dxy));  //floatDxy performs sqrt(abs(dxy))
0228     }
0229 
0230     if (!slim) {
0231       ap_uint<7> w_hitPattern = tkword(15, 9);
0232       ret.hwStubs = countSetBits(w_hitPattern);
0233       ret.hwRedChi2RZ = tkword(35, 32);
0234       ret.hwRedChi2RPhi = tkword(67, 64);
0235       ret.hwRedChi2Bend = tkword(18, 16);
0236     }
0237 
0238     oksel = ret.hwQuality != 0;
0239   }
0240   return std::make_pair(ret, oksel);
0241 }
0242 
0243 float l1ct::TrackInputEmulator::floatPt(ap_int<15> Rinv) const { return rInvToPt_ / std::abs(toFloat_(Rinv)); }
0244 
0245 l1ct::pt_t l1ct::TrackInputEmulator::convPt(ap_int<15> Rinv) const {
0246   ap_uint<14> absRinv = (Rinv >= 0 ? ap_uint<14>(Rinv) : ap_uint<14>(-Rinv));
0247   unsigned int index = absRinv.to_int() >> ptLUTShift_;
0248   if (index >= ptLUT_.size()) {
0249     dbgPrintf("WARN: Rinv %d, absRinv %d, index %d, size %lu, shift %d\n",
0250               Rinv.to_int(),
0251               absRinv.to_int(),
0252               index,
0253               ptLUT_.size(),
0254               ptLUTShift_);
0255     index = ptLUT_.size() - 1;
0256   }
0257   return ptLUT_[index];
0258 }
0259 
0260 void l1ct::TrackInputEmulator::configPt(int lutBits) {
0261   ptLUTShift_ = 14 - lutBits;
0262   ptLUT_.resize(1 << lutBits);
0263   for (unsigned int u = 0, n = ptLUT_.size(); u < n; ++u) {
0264     int iRinv = std::round((u + 0.5) * (1 << ptLUTShift_));
0265     ptLUT_[u] = l1ct::Scales::makePtFromFloat(floatPt(iRinv));
0266   }
0267 }
0268 
0269 float l1ct::TrackInputEmulator::floatEta(ap_int<16> tanl) const {
0270   float lam = std::atan(floatTanl(tanl));
0271   float theta = M_PI / 2 - lam;
0272   return -std::log(std::tan(0.5 * theta));
0273 }
0274 
0275 l1ct::glbeta_t l1ct::TrackInputEmulator::convEta(ap_int<16> tanl) const {
0276   unsigned int index;
0277   if (tanlLUTSigned_) {
0278     index = std::max(0, std::abs(tanl.to_int()) - tanlLUTPreOffs_) >> tanlLUTShift_;
0279   } else {
0280     ap_uint<16> unsTanl = tanl(15, 0);
0281     index = unsTanl.to_int() >> tanlLUTShift_;
0282   }
0283   if (index >= tanlLUT_.size()) {
0284     dbgPrintf(
0285         "WARN: tanl %d, index %d, size %lu (signed %d)\n", tanl.to_int(), index, tanlLUT_.size(), int(tanlLUTSigned_));
0286     index = tanlLUT_.size() - 1;
0287   }
0288   int ret = tanlLUT_[index] + tanlLUTPostOffs_;
0289   if (tanlLUTSigned_ && tanl < 0)
0290     ret = -ret;
0291   if (debug_)
0292     dbgPrintf("convEta: itanl = %+8d -> index %8d, LUT %8d, ret %+8d\n", tanl.to_int(), index, tanlLUT_[index], ret);
0293   return ret;
0294 }
0295 
0296 void l1ct::TrackInputEmulator::configEta(
0297     int lutBits, int preOffs, int shift, int postOffs, bool lutSigned, bool endcap) {
0298   tanlLUTSigned_ = lutSigned;
0299   tanlLUTPreOffs_ = preOffs;
0300   tanlLUTPostOffs_ = postOffs;
0301   tanlLUTShift_ = shift;
0302   tanlLUT_.resize(1 << lutBits);
0303   int etaCenter = lutSigned ? l1ct::Scales::makeGlbEtaRoundEven(2.5).to_int() / 2 : 0;
0304   int etamin = 1, etamax = -1;
0305   for (unsigned int u = 0, n = tanlLUT_.size(), h = n / 2; u < n; ++u) {
0306     int i = (tanlLUTSigned_ || (u < h)) ? int(u) : int(u) - int(n);
0307     ap_int<16> tanl = std::min<int>(i * (1 << shift) + preOffs, (1 << 16) - 1);
0308     int eta = l1ct::Scales::makeGlbEta(floatEta(tanl)).to_int() - etaCenter - tanlLUTPostOffs_;
0309     bool valid = endcap ? (mayReachHGCal(tanl) && withinTracker(tanl)) : withinBarrel(tanl);
0310     if (valid) {
0311       tanlLUT_[u] = eta;
0312       if (etamin > etamax) {
0313         etamin = eta;
0314         etamax = eta;
0315       } else {
0316         etamin = std::min(etamin, eta);
0317         etamax = std::max(etamax, eta);
0318       }
0319     } else {
0320       tanlLUT_[u] = 0;
0321     }
0322   }
0323   if (debug_)
0324     dbgPrintf(
0325         "Configured with glbEtaCenter = %d, bits %d, preOffs %d, shift %d, postOffs %d, lutmin = %d, lutmax = %d\n",
0326         etaCenter,
0327         lutBits,
0328         preOffs,
0329         shift,
0330         postOffs,
0331         etamin,
0332         etamax);
0333 }
0334 
0335 float l1ct::TrackInputEmulator::floatPhi(ap_int<12> phi) const { return phiScale_ * toFloat_(phi); }
0336 
0337 l1ct::phi_t l1ct::TrackInputEmulator::convPhi(ap_int<12> phi) const {
0338   int offs = phi >= 0 ? vtxPhiOffsPos_ : vtxPhiOffsNeg_;
0339   return (phi.to_int() * vtxPhiMult_ + offs) >> vtxPhiBitShift_;
0340 }
0341 
0342 void l1ct::TrackInputEmulator::configPhi(int bits) {
0343   float scale = phiScale_ / l1ct::Scales::ETAPHI_LSB;
0344   vtxPhiBitShift_ = bits;
0345   vtxPhiMult_ = std::round(scale * (1 << bits));
0346   switch (encoding_) {
0347     case Encoding::Stepping:
0348       vtxPhiOffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0349       vtxPhiOffsNeg_ = std::round(-scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0350       break;
0351     case Encoding::Biased:
0352       vtxPhiOffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0353       vtxPhiOffsNeg_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0354       break;
0355     case Encoding::Unbiased:
0356       vtxPhiOffsPos_ = (1 << (bits - 1));
0357       vtxPhiOffsNeg_ = (1 << (bits - 1));
0358       break;
0359   }
0360   if (debug_)
0361     dbgPrintf("Configured vtxPhi with scale %d [to_cmssw %.8f, to_l1ct %.8f, %d bits], offsets %+d (pos), %+d (neg)\n",
0362               vtxPhiMult_,
0363               phiScale_,
0364               scale,
0365               bits,
0366               vtxPhiOffsPos_,
0367               vtxPhiOffsNeg_);
0368 }
0369 
0370 float l1ct::TrackInputEmulator::floatZ0(ap_int<12> z0) const { return z0Scale_ * toFloat_(z0); }
0371 
0372 float l1ct::TrackInputEmulator::floatDxy(ap_int<13> dxy) const {
0373   float physcoord_ = dxyScale_ * toFloat_(dxy);
0374   physcoord_ = std::sqrt(std::abs(physcoord_));
0375   return physcoord_;
0376 }
0377 
0378 l1ct::z0_t l1ct::TrackInputEmulator::convZ0(ap_int<12> z0) const {
0379   int offs = z0 >= 0 ? z0OffsPos_ : z0OffsNeg_;
0380   return (z0.to_int() * z0Mult_ + offs) >> z0BitShift_;
0381 }
0382 
0383 l1ct::dxy_t l1ct::TrackInputEmulator::convDxy(ap_int<13> dxy) const {
0384   int offs = dxy >= 0 ? dxyOffsPos_ : dxyOffsNeg_;
0385   float physcoord_ = ((dxy.to_int() * dxyMult_ + offs) >> dxyBitShift_) * l1ct::Scales::DXY_LSB;
0386   physcoord_ = std::sqrt(std::abs(physcoord_));
0387   physcoord_ = physcoord_ / l1ct::Scales::DXYSQRT_LSB;
0388   l1ct::dxy_t ret = dxy_t(std::round(physcoord_));
0389   return ret;
0390 }
0391 
0392 void l1ct::TrackInputEmulator::configZ0(int bits) {
0393   float scale = z0Scale_ / l1ct::Scales::Z0_LSB;
0394   z0BitShift_ = bits;
0395   z0Mult_ = std::round(scale * (1 << bits));
0396   switch (encoding_) {
0397     case Encoding::Stepping:
0398       z0OffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0399       z0OffsNeg_ = std::round(-scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0400       break;
0401     case Encoding::Biased:
0402       z0OffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0403       z0OffsNeg_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0404       break;
0405     case Encoding::Unbiased:
0406       z0OffsPos_ = (1 << (bits - 1));
0407       z0OffsNeg_ = (1 << (bits - 1));
0408       break;
0409   }
0410 
0411   if (debug_)
0412     dbgPrintf("Configured z0 with scale %d [to_cmssw %.8f, to_l1ct %.8f, %d bits], offsets %+d (pos), %+d (neg)\n",
0413               z0Mult_,
0414               z0Scale_,
0415               scale,
0416               bits,
0417               z0OffsPos_,
0418               z0OffsNeg_);
0419 }
0420 
0421 void l1ct::TrackInputEmulator::configDxy(int bits) {
0422   // Function for setting Dxy conversion factors from bits to physical floating point coordinates
0423   // dxyScale_ = digitisation taken from track word (32/2**13)
0424   // dxyBitShift_ = total number of bits from track word
0425   // dxyMult_ = rescaling factor * 2**bits
0426   // dxyOffsPos_ = offset for positive dxy at bin boundary
0427   // dxyOffsNeg_ = offset for negative dxy at bin boundary
0428   float scale = dxyScale_ / l1ct::Scales::DXY_LSB;
0429   dxyBitShift_ = bits;
0430   dxyMult_ = std::round(scale * (1 << bits));
0431   switch (encoding_) {
0432     case Encoding::Stepping:
0433       dxyOffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0434       dxyOffsNeg_ = std::round(-scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0435       break;
0436     case Encoding::Biased:
0437       dxyOffsPos_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0438       dxyOffsNeg_ = std::round(+scale * 0.5 * (1 << bits) + 0.5 * (1 << bits));
0439       break;
0440     case Encoding::Unbiased:
0441       dxyOffsPos_ = (1 << (bits - 1));
0442       dxyOffsNeg_ = (1 << (bits - 1));
0443       break;
0444   }
0445   if (debug_)
0446     dbgPrintf("Configured dxy with scale %d [to_cmssw %.8f, to_l1ct %.8f, %d bits], offsets %+d (pos), %+d (neg)\n",
0447               dxyMult_,
0448               dxyScale_,
0449               scale,
0450               bits,
0451               dxyOffsPos_,
0452               dxyOffsNeg_);
0453 }
0454 
0455 float l1ct::TrackInputEmulator::floatDEtaBarrel(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0456   float ret = floatEta(tanl) - floatEta(tanl + z0.to_float() * dEtaBarrelParamZ0_);
0457   if (debug_) {
0458     dbgPrintf(
0459         "flt deta for z0 %+6d Rinv %+6d tanl %+6d:  eta(calo) %+8.2f  eta(vtx)  %+8.3f  ret  "
0460         "%+8.2f\n",
0461         z0.to_int(),
0462         Rinv.to_int(),
0463         tanl.to_int(),
0464         floatEta(tanl + z0.to_float() * dEtaBarrelParamZ0_),
0465         floatEta(tanl),
0466         ret);
0467   }
0468   return ret / l1ct::Scales::ETAPHI_LSB;
0469 }
0470 
0471 l1ct::tkdeta_t l1ct::TrackInputEmulator::calcDEtaBarrel(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0472   int vtxEta = convEta(tanl);
0473 
0474   ap_uint<14> absZ0 = z0 >= 0 ? ap_uint<14>(z0) : ap_uint<14>(-z0);
0475   int preSum = ((absZ0 >> dEtaBarrelZ0PreShift_) * dEtaBarrelZ0_) >> dEtaBarrelZ0PostShift_;
0476 
0477   int caloEta = convEta(tanl + (z0 > 0 ? 1 : -1) * ((preSum + dEtaBarrelOffs_) >> dEtaBarrelBits_));
0478 
0479   int ret = vtxEta - caloEta;
0480   if (debug_) {
0481     dbgPrintf(
0482         "int deta for z0 %+6d Rinv %+6d tanl %+6d:  preSum %+8.2f  eta(calo) %+8.2f  eta(vtx)  %+8.3f  ret  "
0483         "%+8.2f\n",
0484         z0.to_int(),
0485         Rinv.to_int(),
0486         tanl.to_int(),
0487         preSum,
0488         caloEta,
0489         vtxEta,
0490         ret);
0491   }
0492   return ret;
0493 }
0494 
0495 //use eta LUTs
0496 void l1ct::TrackInputEmulator::configDEtaBarrel(int dEtaBarrelBits,
0497                                                 int dEtaBarrelZ0PreShift,
0498                                                 int dEtaBarrelZ0PostShift,
0499                                                 float offs) {
0500   dEtaBarrelBits_ = dEtaBarrelBits;
0501 
0502   dEtaBarrelZ0PreShift_ = dEtaBarrelZ0PreShift;
0503   dEtaBarrelZ0PostShift_ = dEtaBarrelZ0PostShift;
0504   dEtaBarrelZ0_ =
0505       std::round(dEtaBarrelParamZ0_ * (1 << (dEtaBarrelZ0PreShift + dEtaBarrelZ0PostShift + dEtaBarrelBits)));
0506 
0507   int finalShift = dEtaBarrelBits_;
0508   dEtaBarrelOffs_ = std::round((1 << finalShift) * (0.5 + offs));
0509 
0510   if (debug_)
0511     dbgPrintf("Configured deta with %d bits: preshift %8d  postshift %8d, offset %8d\n",
0512               dEtaBarrelBits,
0513               dEtaBarrelZ0PreShift_,
0514               dEtaBarrelZ0PostShift_,
0515               offs);
0516 
0517   assert(finalShift >= 0);
0518 }
0519 
0520 float l1ct::TrackInputEmulator::floatDPhiBarrel(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0521   float ret = dPhiBarrelParamC_ * std::abs(Rinv.to_int());
0522   //ret = atan(ret / sqrt(1-ret*ret)); //use linear approx for now
0523   if (debug_) {
0524     dbgPrintf("flt dphi for z0 %+6d Rinv %+6d tanl %+6d:  Rinv/1k  %8.2f   ret  %8.2f\n",
0525               z0.to_int(),
0526               Rinv.to_int(),
0527               tanl.to_int(),
0528               std::abs(Rinv.to_int()) / 1024.0,
0529               ret);
0530   }
0531   return ret;
0532 }
0533 
0534 l1ct::tkdphi_t l1ct::TrackInputEmulator::calcDPhiBarrel(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0535   ap_uint<14> absRinv = Rinv >= 0 ? ap_uint<14>(Rinv) : ap_uint<14>(-Rinv);
0536   int preSum = ((absRinv >> dPhiBarrelRInvPreShift_) * dPhiBarrelC_) >> dPhiBarrelRInvPostShift_;
0537 
0538   if (debug_) {
0539     dbgPrintf("int dphi for z0 %+6d Rinv %+6d tanl %+6d:  ret  %8.2f\n",
0540               z0.to_int(),
0541               Rinv.to_int(),
0542               tanl.to_int(),
0543               (preSum + dPhiBarrelOffs_) >> dPhiBarrelBits_);
0544   }
0545 
0546   return (preSum + dPhiBarrelOffs_) >> dPhiBarrelBits_;
0547 }
0548 
0549 //using DSPs
0550 void l1ct::TrackInputEmulator::configDPhiBarrel(int dPhiBarrelBits,
0551                                                 int dPhiBarrelRInvPreShift,
0552                                                 int dPhiBarrelRInvPostShift,
0553                                                 float offs) {
0554   dPhiBarrelBits_ = dPhiBarrelBits;
0555 
0556   dPhiBarrelRInvPreShift_ = dPhiBarrelRInvPreShift;
0557   dPhiBarrelRInvPostShift_ = dPhiBarrelRInvPostShift;
0558   dPhiBarrelC_ =
0559       std::round(dPhiBarrelParamC_ * (1 << (dPhiBarrelRInvPreShift + dPhiBarrelRInvPostShift + dPhiBarrelBits)));
0560 
0561   int finalShift = dPhiBarrelBits_;
0562   dPhiBarrelOffs_ = std::round((1 << finalShift) * (0.5 + offs));
0563 
0564   if (debug_)
0565     dbgPrintf("Configured dphi with %d bits: preshift %8d  postshift %8d, offset %8d\n",
0566               dPhiBarrelBits,
0567               dPhiBarrelRInvPreShift_,
0568               dPhiBarrelRInvPostShift_,
0569               offs);
0570 
0571   assert(finalShift >= 0);
0572 }
0573 
0574 float l1ct::TrackInputEmulator::floatDEtaHGCal(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0575   float RinvScaled = Rinv.to_float() / (16 * 1024.0), RinvScaled2 = RinvScaled * RinvScaled;
0576   float invtanlScaled = (32 * 1024.0) / std::abs(tanl.to_float()), invtanlScaled2 = invtanlScaled * invtanlScaled;
0577   float tanlTerm = (tanl > 0 ? 1 : -1) * (dEtaHGCalParamRInv2C_ + dEtaHGCalParamRInv2ITanl1_ * invtanlScaled +
0578                                           dEtaHGCalParamRInv2ITanl2_ * invtanlScaled2);
0579   float ret = dEtaHGCalParamZ0_ * z0.to_float() + tanlTerm * RinvScaled2;
0580   if (debug_) {
0581     dbgPrintf(
0582         "flt deta for z0 %+6d Rinv %+6d tanl %+6d:  z0term %+8.2f  rinv2u %.4f tanlterm  %+8.3f (pre: %+8.2f)  ret  "
0583         "%+8.2f\n",
0584         z0.to_int(),
0585         Rinv.to_int(),
0586         tanl.to_int(),
0587         dEtaHGCalParamZ0_ * z0.to_float(),
0588         RinvScaled2,
0589         tanlTerm * RinvScaled2,
0590         tanlTerm,
0591         ret);
0592   }
0593   return ret;
0594 }
0595 
0596 l1ct::tkdeta_t l1ct::TrackInputEmulator::calcDEtaHGCal(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0597   int z0Term = dEtaHGCalZ0_ * (z0 >> dEtaHGCalZ0PreShift_);
0598 
0599   int rinvShift = Rinv.to_int() >> dEtaHGCalRInvPreShift_, rinvShift2 = rinvShift * rinvShift;
0600 
0601   ap_uint<16> unsTanl = tanl(15, 0);
0602   unsigned int tanlIdx = (unsTanl.to_int()) >> dEtaHGCalTanlShift_;
0603   assert(tanlIdx < dEtaHGCalLUT_.size());
0604   int tanlTerm = (rinvShift2 * dEtaHGCalLUT_[tanlIdx] + dEtaHGCalTanlTermOffs_) >> dEtaHGCalTanlTermShift_;
0605 
0606   int ret0 = z0Term + tanlTerm + dEtaHGCalOffs_;
0607   if (debug_) {
0608     dbgPrintf(
0609         "int deta for z0 %+6d Rinv %+6d tanl %+6d:  z0term %+8.2f  rinv2u %.4f tanlterm  %+8.2f (pre: %+8.2f)  ret  "
0610         "%+8.2f\n",
0611         z0.to_int(),
0612         Rinv.to_int(),
0613         tanl.to_int(),
0614         float(z0Term) / (1 << dEtaHGCalBits_),
0615         float(rinvShift2) / (1 << (28 - 2 * dEtaHGCalRInvPreShift_)),
0616         float(tanlTerm) / (1 << dEtaHGCalBits_),
0617         float(dEtaHGCalLUT_[tanlIdx]) / (1 << (dEtaHGCalBits_ - dEtaHGCalLUTShift_)),
0618         float(ret0) / (1 << dEtaHGCalBits_));
0619   }
0620   return (ret0 + (1 << (dEtaHGCalBits_ - 1))) >> dEtaHGCalBits_;
0621 }
0622 
0623 void l1ct::TrackInputEmulator::configDEtaHGCal(int dEtaHGCalBits,
0624                                                int dEtaHGCalZ0PreShift,
0625                                                int dEtaHGCalRInvPreShift,
0626                                                int dEtaHGCalLUTBits,
0627                                                int dEtaHGCalLUTShift,
0628                                                float offs) {
0629   dEtaHGCalBits_ = dEtaHGCalBits;
0630   float scale = (1 << dEtaHGCalBits);
0631 
0632   dEtaHGCalZ0PreShift_ = dEtaHGCalZ0PreShift;
0633   dEtaHGCalZ0_ = std::round(dEtaHGCalParamZ0_ * scale * (1 << dEtaHGCalZ0PreShift));
0634 
0635   dEtaHGCalRInvPreShift_ = dEtaHGCalRInvPreShift;
0636 
0637   dEtaHGCalTanlShift_ = 16 - dEtaHGCalLUTBits;
0638   dEtaHGCalLUT_.resize((1 << dEtaHGCalLUTBits));
0639   dEtaHGCalLUTShift_ = dEtaHGCalLUTShift;
0640 
0641   dEtaHGCalTanlTermShift_ = 28 - 2 * dEtaHGCalRInvPreShift_ - dEtaHGCalLUTShift_;
0642   dEtaHGCalTanlTermOffs_ = std::round(0.5 * (1 << dEtaHGCalTanlTermShift_));
0643   int lutmin = 1, lutmax = -1;
0644   float lutScale = scale / (1 << dEtaHGCalLUTShift);
0645   for (unsigned int u = 0, n = dEtaHGCalLUT_.size(), h = n / 2; u < n; ++u) {
0646     int i = (u < h) ? int(u) : int(u) - int(n);
0647     float tanl = (i + 0.5) * (1 << dEtaHGCalTanlShift_);
0648     float sign = tanl >= 0 ? 1 : -1;
0649     float invtanlScaled = 32 * 1024.0 / std::abs(tanl), invtanlScaled2 = invtanlScaled * invtanlScaled;
0650     float term = sign * (dEtaHGCalParamRInv2C_ + dEtaHGCalParamRInv2ITanl1_ * invtanlScaled +
0651                          dEtaHGCalParamRInv2ITanl2_ * invtanlScaled2);
0652     int iterm = std::round(lutScale * term);
0653     bool valid = mayReachHGCal(tanl);
0654     if (valid) {
0655       dEtaHGCalLUT_[u] = iterm;
0656       if (lutmin > lutmax) {
0657         lutmin = iterm;
0658         lutmax = iterm;
0659       } else {
0660         lutmin = std::min(lutmin, iterm);
0661         lutmax = std::max(lutmax, iterm);
0662       }
0663     } else {
0664       dEtaHGCalLUT_[u] = 0;
0665     }
0666   }
0667 
0668   dEtaHGCalOffs_ = std::round(scale * offs);
0669 
0670   if (debug_)
0671     dbgPrintf(
0672         "Configured deta with %d bits: z0 %8d [%8.2f], lutmin = %d, lutmax = %d, lutshift %d, rinvShift %d, "
0673         "tanlTermShift %d\n",
0674         dEtaHGCalBits,
0675         dEtaHGCalZ0_,
0676         dEtaHGCalZ0_ / float(scale),
0677         lutmin,
0678         lutmax,
0679         dEtaHGCalLUTShift,
0680         dEtaHGCalRInvPreShift_,
0681         dEtaHGCalTanlTermShift_);
0682 }
0683 
0684 float l1ct::TrackInputEmulator::floatDPhiHGCal(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0685   int dzsign = tanl >= 0 ? +1 : -1;
0686   float ret =
0687       (dPhiHGCalParamC_ - dPhiHGCalParamZ0_ * z0 * dzsign) * std::abs(Rinv.to_int()) / std::abs(tanl.to_float());
0688   if (debug_) {
0689     dbgPrintf(
0690         "flt dphi for z0 %+6d Rinv %+6d tanl %+6d:  preSum %+9.4f  Rinv/1k  %8.2f   1k/tanl  %8.5f   ret  %8.2f\n",
0691         z0.to_int(),
0692         Rinv.to_int(),
0693         tanl.to_int(),
0694         dPhiHGCalParamC_ - dPhiHGCalParamZ0_ * z0 * dzsign,
0695         std::abs(Rinv.to_int()) / 1024.0,
0696         1024.0 / std::abs(tanl.to_float()),
0697         ret);
0698   }
0699   return ret;
0700 }
0701 
0702 l1ct::tkdphi_t l1ct::TrackInputEmulator::calcDPhiHGCal(ap_int<12> z0, ap_int<15> Rinv, ap_int<16> tanl) const {
0703   int dzsign = tanl >= 0 ? +1 : -1;
0704   int preSum = (((z0 >> dPhiHGCalZ0PreShift_) * dPhiHGCalZ0_) >> dPhiHGCalZ0PostShift_) * dzsign + dPhiHGCalPreOffs_;
0705 
0706   ap_uint<14> absRinv = Rinv >= 0 ? ap_uint<14>(Rinv) : ap_uint<14>(-Rinv);
0707   int rinvShifted = absRinv.to_int() >> dPhiHGCalRInvShift_;
0708 
0709   ap_uint<15> absTanl = tanl >= 0 ? ap_uint<15>(tanl) : ap_uint<15>(-tanl);
0710   unsigned int tanlIdx = absTanl.to_int() >> dPhiHGCalTanlShift_;
0711   assert(tanlIdx < dPhiHGCalTanlLUT_.size());
0712   int tanlTerm = dPhiHGCalTanlLUT_[tanlIdx];
0713 
0714   int finalShift = dPhiHGCalBits_ + dPhiHGCalTanlInvShift_ - dPhiHGCalRInvShift_;
0715   if (debug_) {
0716     dbgPrintf(
0717         "int dphi for z0 %+6d Rinv %+6d tanl %+6d:  preSum %+9.4f  Rinv/1k  %8.2f   1k/tanl  %8.5f   ret  %8.2f: int "
0718         "preSum %8d  rivShift %8d  tanlTerm %8d\n",
0719         z0.to_int(),
0720         Rinv.to_int(),
0721         tanl.to_int(),
0722         float(preSum) / (1 << dPhiHGCalBits_),
0723         (rinvShifted << dPhiHGCalRInvShift_) / 1024.0,
0724         tanlTerm * 1024.0 / (1 << dPhiHGCalTanlInvShift_),
0725         float(preSum * rinvShifted * tanlTerm) / (1 << finalShift),
0726         preSum,
0727         rinvShifted,
0728         tanlTerm);
0729   }
0730 
0731   return (preSum * rinvShifted * tanlTerm + dPhiHGCalOffs_) >> finalShift;
0732 }
0733 
0734 void l1ct::TrackInputEmulator::configDPhiHGCal(int dPhiHGCalBits,
0735                                                int dPhiHGCalZ0PreShift,
0736                                                int dPhiHGCalZ0PostShift,
0737                                                int dPhiHGCalRInvShift,
0738                                                int dPhiHGCalTanlInvShift,
0739                                                int dPhiHGCalTanlLUTBits,
0740                                                float offs) {
0741   dPhiHGCalBits_ = dPhiHGCalBits;
0742 
0743   dPhiHGCalZ0PreShift_ = dPhiHGCalZ0PreShift;
0744   dPhiHGCalZ0PostShift_ = dPhiHGCalZ0PostShift;
0745   dPhiHGCalZ0_ = -std::round(dPhiHGCalParamZ0_ * (1 << (dPhiHGCalZ0PreShift + dPhiHGCalZ0PostShift + dPhiHGCalBits)));
0746 
0747   dPhiHGCalPreOffs_ = std::round(dPhiHGCalParamC_ * (1 << dPhiHGCalBits));
0748 
0749   dPhiHGCalRInvShift_ = dPhiHGCalRInvShift;
0750 
0751   dPhiHGCalTanlInvShift_ = dPhiHGCalTanlInvShift;
0752   dPhiHGCalTanlShift_ = 15 - dPhiHGCalTanlLUTBits;
0753   dPhiHGCalTanlLUT_.resize((1 << dPhiHGCalTanlLUTBits));
0754   int lutmin = 1, lutmax = -1;
0755   for (unsigned int u = 0, n = dPhiHGCalTanlLUT_.size(); u < n; ++u) {
0756     float tanl = (u + 0.5) * (1 << dPhiHGCalTanlShift_);
0757     int iterm = std::round((1 << dPhiHGCalTanlInvShift_) / tanl);
0758     bool valid = mayReachHGCal(tanl);
0759     if (valid) {
0760       dPhiHGCalTanlLUT_[u] = iterm;
0761       if (lutmin > lutmax) {
0762         lutmin = iterm;
0763         lutmax = iterm;
0764       } else {
0765         lutmin = std::min(lutmin, iterm);
0766         lutmax = std::max(lutmax, iterm);
0767       }
0768     } else {
0769       dPhiHGCalTanlLUT_[u] = 0;
0770     }
0771   }
0772 
0773   int finalShift = dPhiHGCalBits_ + dPhiHGCalTanlInvShift_ - dPhiHGCalRInvShift_;
0774   dPhiHGCalOffs_ = std::round((1 << finalShift) * (0.5 + offs));
0775 
0776   if (debug_)
0777     dbgPrintf(
0778         "Configured dphi with %d bits: z0 %8d [%8.2f], preoffs %8d [%8.2f], final shift %d, lutmin = %d, lutmax = %d\n",
0779         dPhiHGCalBits,
0780         dPhiHGCalZ0_,
0781         dPhiHGCalZ0_ / float(1 << (dPhiHGCalZ0PostShift + dPhiHGCalBits)),
0782         dPhiHGCalPreOffs_,
0783         dPhiHGCalPreOffs_ / float(1 << dPhiHGCalBits),
0784         finalShift,
0785         lutmin,
0786         lutmax);
0787 
0788   assert(finalShift >= 0);
0789 }