Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:31

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