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