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 }
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
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
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 §or,
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
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
0206 float fDEta = 0, fDPhi = 0;
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
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
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
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 }