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 }
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
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
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 §or,
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
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);
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
0211 float fDEta = 0, fDPhi = 0;
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));
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
0423
0424
0425
0426
0427
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
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
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
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 }