diff --git a/L1Trigger/L1TTrackMatch/interface/Cordic.h b/L1Trigger/L1TTrackMatch/interface/Cordic.h index 653641e33d249..5c73c39f583ad 100644 --- a/L1Trigger/L1TTrackMatch/interface/Cordic.h +++ b/L1Trigger/L1TTrackMatch/interface/Cordic.h @@ -17,6 +17,8 @@ class Cordic { Cordic(); Cordic(const int aSteps, bool debug); + template + void cordic_subfunc(T &x, T &y, T &z) const; l1tmetemu::EtMiss toPolar(l1tmetemu::Et_t x, l1tmetemu::Et_t y) const; private: @@ -25,9 +27,9 @@ class Cordic { const bool debug; // To calculate atan - std::vector atanLUT; + std::vector atanLUT; // To normalise final magnitude - std::vector magNormalisationLUT; + std::vector magNormalisationLUT; }; #endif diff --git a/L1Trigger/L1TTrackMatch/interface/L1TkEtMissEmuAlgo.h b/L1Trigger/L1TTrackMatch/interface/L1TkEtMissEmuAlgo.h index 157b48ed71223..e427d7942a6fc 100644 --- a/L1Trigger/L1TTrackMatch/interface/L1TkEtMissEmuAlgo.h +++ b/L1Trigger/L1TTrackMatch/interface/L1TkEtMissEmuAlgo.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "DataFormats/L1TrackTrigger/interface/TTTrack_TrackWord.h" @@ -17,32 +18,35 @@ // Namespace that defines constants and types used by the EtMiss Emulation // Includes functions for writing LUTs and converting to integer representations namespace l1tmetemu { - + const unsigned int kInternalPtWidth{14}; const unsigned int kPtMagSize{9}; + const unsigned int kMETSize{16}; // For output Magnitude default 16 + const unsigned int kMETMagSize{11}; + const unsigned int kMETPhiSize{13}; // For Output Phi default 13 const unsigned int kEtExtra{4}; - const unsigned int kGlobalPhiExtra{3}; + const unsigned int kGlobalPhiExtra{4}; const unsigned int kCosLUTSize{10}; const unsigned int kCosLUTMagSize{1}; + const unsigned int kAtanLUTSize{64}; + const unsigned int kAtanLUTMagSize{2}; - typedef ap_uint global_phi_t; + typedef ap_ufixed METWord_t; + typedef ap_int METWordphi_t; + typedef ap_int global_phi_t; typedef ap_ufixed cos_lut_fixed_t; - typedef ap_fixed Et_t; - typedef ap_fixed E2t_t; + typedef ap_ufixed atan_lut_fixed_t; + typedef ap_fixed Et_t; + typedef ap_fixed metphi_fixed_t; + typedef ap_ufixed pi_bins_fixed_t; // Output definition as per interface document, only used when creating output format - const double kMaxMET{2048}; // 2 TeV + const double kMaxMET = 1 << kMETMagSize; // 2 TeV const double kMaxMETPhi{2 * M_PI}; - const unsigned int kMETSize{16}; // For output Magnitude default 16 - const unsigned int kMETMagSize{11}; - const unsigned int kMETPhiSize{13}; // For Output Phi default 13 - - typedef ap_ufixed METWord_t; - typedef ap_int METWordphi_t; - - const double kStepMETwordEt = kMaxMET / ( 1 << kMETSize); - const double kStepMETwordPhi = kMaxMETPhi / ( 1 << kMETPhiSize); + const double kStepMETwordEt = kMaxMET / (1 << kMETSize); + const double kStepMETwordPhi = kMaxMETPhi / (1 << kMETPhiSize); + const double kBinsInPi = 1.0 / kStepMETwordPhi; // Enough symmetry in cos and sin between 0 and pi/2 to get all possible values // of cos and sin phi @@ -59,14 +63,14 @@ namespace l1tmetemu { std::vector generateCosLUT(unsigned int size); - global_phi_t localToGlobalPhi(TTTrack_TrackWord::phi_t local_phi, global_phi_t sector_shift ); - + global_phi_t localToGlobalPhi(TTTrack_TrackWord::phi_t local_phi, global_phi_t sector_shift); + std::vector generatePhiSliceLUT(unsigned int N); template void printLUT(std::vector lut, std::string module = "", std::string name = "") { edm::LogVerbatim log(module); - log << "The " << name << "[" << lut.size() << "] values are ... \n"; + log << "The " << name << "[" << lut.size() << "] values are ... \n" << std::setprecision(30); for (unsigned int i = 0; i < lut.size(); i++) { log << "\t" << i << "\t" << lut[i] << "\n"; } diff --git a/L1Trigger/L1TTrackMatch/interface/L1TkHTMissEmulatorProducer.h b/L1Trigger/L1TTrackMatch/interface/L1TkHTMissEmulatorProducer.h index 7e630848a1a64..2504c4ad0fc4e 100644 --- a/L1Trigger/L1TTrackMatch/interface/L1TkHTMissEmulatorProducer.h +++ b/L1Trigger/L1TTrackMatch/interface/L1TkHTMissEmulatorProducer.h @@ -27,7 +27,7 @@ namespace l1tmhtemu { // extra room for sumPx, sumPy const unsigned int kEtExtra{10}; const unsigned int kValidSize{1}; - const unsigned int kMHTSize{16}; // For output Magnitude default 15 + const unsigned int kMHTSize{16}; // For output Magnitude default 15 const unsigned int kMHTIntSize{11}; const unsigned int kMHTPhiSize{13}; // For output Phi default 14 const unsigned int kHTSize{kInternalPtWidth + kEtExtra}; @@ -56,7 +56,7 @@ namespace l1tmhtemu { typedef ap_int phi_t; typedef ap_int Et_t; - typedef ap_ufixed MHT_t; + typedef ap_ufixed MHT_t; typedef ap_uint MHTphi_t; const unsigned int kMHTBins = 1 << kMHTSize; diff --git a/L1Trigger/L1TTrackMatch/plugins/L1TkHTMissEmulatorProducer.cc b/L1Trigger/L1TTrackMatch/plugins/L1TkHTMissEmulatorProducer.cc index 7c76e3828b2f8..c667ce0c9e949 100644 --- a/L1Trigger/L1TTrackMatch/plugins/L1TkHTMissEmulatorProducer.cc +++ b/L1Trigger/L1TTrackMatch/plugins/L1TkHTMissEmulatorProducer.cc @@ -249,13 +249,12 @@ void L1TkHTMissEmulatorProducer::produce(edm::Event& iEvent, const edm::EventSet << "\n" << "====MHT AP_INTS TO FLOATS====\n" << "sumPx: " << (float)sumPx * l1tmhtemu::kStepPt * l1tmhtemu::kStepPhi - << "| sumPy: " << (float)sumPy * l1tmhtemu::kStepPt * l1tmhtemu::kStepPhi - << "| ET: " << EtMiss.Et.to_double() << "| HT: " << (float)HT * l1tmhtemu::kStepPt - << "| PHI: " << (float)phi * l1tmhtemu::kStepMHTPhi - M_PI << "\n" + << "| sumPy: " << (float)sumPy * l1tmhtemu::kStepPt * l1tmhtemu::kStepPhi << "| ET: " << EtMiss.Et.to_double() + << "| HT: " << (float)HT * l1tmhtemu::kStepPt << "| PHI: " << (float)phi * l1tmhtemu::kStepMHTPhi - M_PI << "\n" << "-------------------------------------------------------------------------\n"; } //rescale HT to correct output range - HT = HT / (int)(1/l1tmhtemu::kStepPt); + HT = HT / (int)(1 / l1tmhtemu::kStepPt); EtSum L1HTSum(missingEt, EtSum::EtSumType::kMissingHt, (int)HT.range(), 0, (int)phi, (int)jetn); diff --git a/L1Trigger/L1TTrackMatch/plugins/L1TrackerEtMissEmulatorProducer.cc b/L1Trigger/L1TTrackMatch/plugins/L1TrackerEtMissEmulatorProducer.cc index e7c0ba6ca6a4a..f9652eeefd365 100644 --- a/L1Trigger/L1TTrackMatch/plugins/L1TrackerEtMissEmulatorProducer.cc +++ b/L1Trigger/L1TTrackMatch/plugins/L1TrackerEtMissEmulatorProducer.cc @@ -17,6 +17,7 @@ // // system include files +#include #include #include #include @@ -75,7 +76,6 @@ L1TrackerEtMissEmulatorProducer::L1TrackerEtMissEmulatorProducer(const edm::Para : trackToken_(consumes(iConfig.getParameter("L1TrackInputTag"))), vtxAssocTrackToken_( consumes(iConfig.getParameter("L1TrackAssociatedInputTag"))) { - phiQuadrants_ = l1tmetemu::generatePhiSliceLUT(l1tmetemu::kNQuadrants); phiShifts_ = l1tmetemu::generatePhiSliceLUT(l1tmetemu::kNSector); @@ -136,8 +136,8 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve // Initialize sector sums, need 0 initialization in case a sector has no // tracks - l1tmetemu::E2t_t sumPx[l1tmetemu::kNSector * 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - l1tmetemu::E2t_t sumPy[l1tmetemu::kNSector * 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + l1tmetemu::Et_t sumPx[l1tmetemu::kNSector * 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + l1tmetemu::Et_t sumPy[l1tmetemu::kNSector * 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int link_totals[l1tmetemu::kNSector * 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int sector_totals[l1tmetemu::kNSector] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -147,7 +147,6 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve for (const auto& track : *L1TTTrackHandle) { if (std::find(L1TTTrackAssociatedHandle->begin(), L1TTTrackAssociatedHandle->end(), track) != L1TTTrackAssociatedHandle->end()) { - bool EtaSector = (track->getTanlWord() & (1 << (TTTrack_TrackWord::TrackBitWidths::kTanlSize - 1))); ap_uint ptEmulationBits = track->getTrackWord()( @@ -155,16 +154,17 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve ap_ufixed ptEmulation; ptEmulation.V = ptEmulationBits.range(); - l1tmetemu::global_phi_t globalPhi = l1tmetemu::localToGlobalPhi(track->getPhiWord(),phiShifts_[track->phiSector()]); + l1tmetemu::global_phi_t globalPhi = + l1tmetemu::localToGlobalPhi(track->getPhiWord(), phiShifts_[track->phiSector()]); num_assoc_tracks++; if (debug_ == 7) { edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") << "Track to Vertex ID: " << num_assoc_tracks << "\n" - << "Phi Sector: " << track->phiSector() << " pT: " << track->getRinvWord() << " Phi: " << track->getPhiWord() - << " TanL: " << track->getTanlWord() << " Z0: " << track->getZ0Word() + << "Phi Sector: " << track->phiSector() << " pT: " << track->getRinvWord() + << " Phi: " << track->getPhiWord() << " TanL: " << track->getTanlWord() << " Z0: " << track->getZ0Word() << " Chi2rphi: " << track->getChi2RPhiWord() << " Chi2rz: " << track->getChi2RZWord() - << " bendChi2: " << track->getBendChi2Word() << " Emu pT " << ptEmulation.to_double() << "\n" + << " bendChi2: " << track->getBendChi2Word() << " Emu pT " << ptEmulation.to_double() << "\n" << "--------------------------------------------------------------\n"; } @@ -172,13 +172,14 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") << "========================Phi debug=================================\n" << "Emu pT: " << ptEmulation.to_double() << " float pT: " << track->momentum().perp() << "\n" - << "Int Phi: " << globalPhi << " Float Phi: " << track->phi() - << " Float Cos(Phi): " << cos(track->phi()) << " Float Sin(Phi): " << sin(track->phi()) - << " Float Px: " << track->momentum().perp()*cos(track->phi()) << " Float Py: " << track->momentum().perp()*sin(track->phi()) << "\n"; + << "Int Phi: " << globalPhi << " Float Phi: " << track->phi() << " Float Cos(Phi): " << cos(track->phi()) + << " Float Sin(Phi): " << sin(track->phi()) + << " Float Px: " << track->momentum().perp() * cos(track->phi()) + << " Float Py: " << track->momentum().perp() * sin(track->phi()) << "\n"; } - - l1tmetemu::E2t_t temppx = 0; - l1tmetemu::E2t_t temppy = 0; + + l1tmetemu::Et_t temppx = 0; + l1tmetemu::Et_t temppy = 0; // Split tracks in phi quadrants and access cosLUT_, backwards iteration // through cosLUT_ gives sin Sum sector Et -ve when cos or sin phi are -ve @@ -192,7 +193,6 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve << "Sector: " << track->phiSector() << " Quadrant: " << 1 << "\n" << "Emu Phi: " << globalPhi << " Emu Cos(Phi): " << cosLUT_[globalPhi] << " Emu Sin(Phi): " << cosLUT_[phiQuadrants_[1] - 1 - globalPhi] << "\n"; - } } else if (globalPhi >= phiQuadrants_[1] && globalPhi < phiQuadrants_[2]) { temppx = -((l1tmetemu::Et_t)ptEmulation * cosLUT_[phiQuadrants_[2] - 1 - globalPhi]); @@ -201,8 +201,7 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve if (debug_ == 2) { edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") << "Sector: " << track->phiSector() << " Quadrant: " << 2 << "\n" - << "Emu Phi: " << globalPhi << " Emu Cos(Phi): -" - << cosLUT_[phiQuadrants_[2] - 1 - globalPhi] + << "Emu Phi: " << globalPhi << " Emu Cos(Phi): -" << cosLUT_[phiQuadrants_[2] - 1 - globalPhi] << " Emu Sin(Phi): " << cosLUT_[globalPhi - phiQuadrants_[1]] << "\n"; } } else if (globalPhi >= phiQuadrants_[2] && globalPhi < phiQuadrants_[3]) { @@ -223,9 +222,8 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve if (debug_ == 2) { edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") << "Sector: " << track->phiSector() << " Quadrant: " << 4 << "\n" - << " Emu Phi: " << globalPhi - << " Emu Cos(Phi): " << cosLUT_[phiQuadrants_[4] - 1 - globalPhi] << " Emu Sin(Phi): -" - << cosLUT_[globalPhi - phiQuadrants_[3]] << "\n"; + << " Emu Phi: " << globalPhi << " Emu Cos(Phi): " << cosLUT_[phiQuadrants_[4] - 1 - globalPhi] + << " Emu Sin(Phi): -" << cosLUT_[globalPhi - phiQuadrants_[3]] << "\n"; } } else { temppx = 0; @@ -239,17 +237,18 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve if (debug_ == 4) { edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") - << "Sector: " << track->phiSector() << " Eta sector: " << EtaSector << "\n" - << "Track Ref Pt: " << track->momentum().perp() - << " Track Ref Px: " << track->momentum().x() << " Track Ref Py: " << track->momentum().y() << "\n" - << "Track Pt: " << ptEmulation << " Track Px: " << temppx << " Track Py: " << temppy << "\n" + << std::setprecision(8) << "Sector: " << track->phiSector() << " Eta sector: " << EtaSector << "\n" + << "Track Ref Pt: " << track->momentum().perp() << " Track Ref Px: " << track->momentum().x() + << " Track Ref Py: " << track->momentum().y() << "\n" + << "Track Pt: " << ptEmulation << " Track phi: " << globalPhi << " Track Px: " << temppx + << " Track Py: " << temppy << "\n" << "Sector Sum Px: " << sumPx[link_number] << " Sector Sum Py: " << sumPy[link_number] << "\n"; } } } // end loop over tracks - l1tmetemu::E2t_t GlobalPx = 0; - l1tmetemu::E2t_t GlobalPy = 0; + l1tmetemu::Et_t GlobalPx = 0; + l1tmetemu::Et_t GlobalPy = 0; // Global Et sum as floats to emulate rounding in HW for (unsigned int i = 0; i < l1tmetemu::kNSector * 2; i++) { @@ -259,24 +258,16 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve // Perform cordic sqrt, take x,y and converts to polar coordinate r,phi where // r=sqrt(x**2+y**2) and phi = atan(y/x) - l1tmetemu::EtMiss EtMiss = cordicSqrt.toPolar(GlobalPx, GlobalPy); - - if ((GlobalPx < 0) && (GlobalPy < 0)) - EtMiss.Phi -= l1tmetemu::METWordphi_t(M_PI/l1tmetemu::kStepMETwordPhi); - else if ((GlobalPx < 0) && (GlobalPy >= 0)) - EtMiss.Phi += l1tmetemu::METWordphi_t(M_PI/l1tmetemu::kStepMETwordPhi); + l1tmetemu::EtMiss EtMiss = cordicSqrt.toPolar(-GlobalPx, -GlobalPy); if (debug_ == 4 || debug_ == 6) { - - edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") - << "====Sector Pt====\n"; + edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") << "====Sector Pt====\n"; for (unsigned int i = 0; i < l1tmetemu::kNSector * 2; i++) { edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") - << "Sector " << i << "\n" - << "Px: " << sumPx[i] << " | Py: " << sumPy[i] - << " | Link Totals: " << link_totals[i] - << " | Sector Totals: " << sector_totals[(int)(i/2)] << "\n"; + << "Sector " << i << "\n" + << "Px: " << sumPx[i] << " | Py: " << sumPy[i] << " | Link Totals: " << link_totals[i] + << " | Sector Totals: " << sector_totals[(int)(i / 2)] << "\n"; } edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") @@ -285,9 +276,9 @@ void L1TrackerEtMissEmulatorProducer::produce(edm::Event& iEvent, const edm::Eve edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") << "====MET===\n" - << "MET word Et: " << EtMiss.Et.range()*l1tmetemu::kStepMETwordEt << "| MET word phi: " << EtMiss.Phi << "\n" - << "MET: " << EtMiss.Et.to_double() - << "| MET phi: " << (float)EtMiss.Phi * l1tmetemu::kStepMETwordPhi << "\n" + << "MET word Et: " << EtMiss.Et.range() * l1tmetemu::kStepMETwordEt << "| MET word phi: " << EtMiss.Phi << "\n" + << "MET: " << EtMiss.Et.to_double() << "| MET phi: " << EtMiss.Phi.to_double() * l1tmetemu::kStepMETwordPhi + << "\n" << "Word MET: " << EtMiss.Et.to_string(2) << " | Word MET phi: " << EtMiss.Phi.to_string(2) << "\n" << "# Tracks Associated to Vertex: " << num_assoc_tracks << "\n" << "========================================================\n"; diff --git a/L1Trigger/L1TTrackMatch/src/Cordic.cc b/L1Trigger/L1TTrackMatch/src/Cordic.cc index 535cd7903d93d..1d5a823213315 100644 --- a/L1Trigger/L1TTrackMatch/src/Cordic.cc +++ b/L1Trigger/L1TTrackMatch/src/Cordic.cc @@ -1,13 +1,12 @@ #include "L1Trigger/L1TTrackMatch/interface/Cordic.h" #include +#include #include using namespace l1tmetemu; -Cordic::Cordic(const int aSteps, bool debug) - : cordicSteps(aSteps), - debug(debug) { +Cordic::Cordic(const int aSteps, bool debug) : cordicSteps(aSteps), debug(debug) { atanLUT.reserve(aSteps); magNormalisationLUT.reserve(aSteps); @@ -16,7 +15,7 @@ Cordic::Cordic(const int aSteps, bool debug) } for (int i = 0; i < aSteps; i++) { - atanLUT.push_back(E2t_t(atan(pow(2, -i)))); + atanLUT.push_back(l1tmetemu::atan_lut_fixed_t(atan(pow(2, -i)))); if (debug) { edm::LogVerbatim("L1TkEtMissEmulator") << atanLUT[i] << " | "; } @@ -25,79 +24,168 @@ Cordic::Cordic(const int aSteps, bool debug) edm::LogVerbatim("L1TkEtMissEmulator") << "\n=====Normalisation LUT====="; } - float val = 1.0; + double val = 1.0; for (int j = 0; j < aSteps; j++) { val = val / (pow(1 + pow(4, -j), 0.5)); - magNormalisationLUT.push_back(E2t_t(val)); + magNormalisationLUT.push_back(l1tmetemu::atan_lut_fixed_t(val)); if (debug) { edm::LogVerbatim("L1TkEtMissEmulator") << magNormalisationLUT[j] << " | "; } } } -EtMiss Cordic::toPolar(Et_t x, Et_t y) const { - E2t_t in_x = x; - E2t_t in_y = y; - E2t_t new_x = 0; - E2t_t new_y = 0; +template +void Cordic::cordic_subfunc(T &x, T &y, T &z) const { + if (debug) { + edm::LogVerbatim("L1TkEtMissEmulator") << "\n=====Cordic Initial Conditions=====\n" + << "Cordic x: " << x << " Cordic y: " << y << " Cordic z: " << z << "\n" + << "\n=====Cordic Steps====="; + } - E2t_t phi = 0; - E2t_t new_phi = 0; - bool sign = false; + T tx, ty, tz; + + for (int step = 0; step < cordicSteps; step++) { + if (y < 0) { + tx = x - (y >> step); + ty = y + (x >> step); + tz = z - atanLUT[step]; + } else { + tx = x + (y >> step); + ty = y - (x >> step); + tz = z + atanLUT[step]; + } + + x = tx; + y = ty; + z = tz; + + if (debug) { + edm::LogVerbatim("L1TkEtMissEmulator") + << "Cordic x: " << x << " Cordic y: " << y << " Cordic phi: " << z << "\n" + << " Cordic gain: " << magNormalisationLUT[step] << " kStepMETwordPhi: " << kStepMETwordPhi << "\n"; + } + } +} +EtMiss Cordic::toPolar(Et_t x, Et_t y) const { EtMiss ret_etmiss; if (debug) { - edm::LogVerbatim("L1TkEtMissEmulator") << "\n=====Cordic Steps====="; + edm::LogVerbatim("L1TkEtMissEmulator") << "\n=====toPolar input=====\n" + << "x: " << x << " y: " << y; } - if (in_x >= 0 && in_y >= 0) { - sign = true; + // Some needed constants + const ap_fixed pi = M_PI; // pi + const ap_fixed pi2 = M_PI / 2.; // pi/2 + const l1tmetemu::METWordphi_t pistep = M_PI / l1tmetemu::kStepMETwordPhi; // (pi) / l1tmetemu::kStepMETwordPhi + const l1tmetemu::METWordphi_t pi2step = pistep / 2.; // (pi/2) / l1tmetemu::kStepMETwordPhi + + // Find the sign of the inputs + ap_uint<2> signx = (x > 0) ? 2 : (x == 0) ? 1 : 0; + ap_uint<2> signy = (y > 0) ? 2 : (y == 0) ? 1 : 0; + + // Corner cases + if (signy == 1 && signx == 2) { // y == 0 and x > 0 + ret_etmiss.Et = x; + ret_etmiss.Phi = 0; + return ret_etmiss; + } else if (signy == 1 && signx == 0) { // y == 0 and x < 0 + ret_etmiss.Et = -x; + ret_etmiss.Phi = pistep; + return ret_etmiss; + } else if (signy == 2 && signx == 1) { // y > 0 and x == 0 + ret_etmiss.Et = y; + ret_etmiss.Phi = pi2step; + return ret_etmiss; + } else if (signy == 0 && signx == 1) { // y < 0 and x == 0 + ret_etmiss.Et = -y; + ret_etmiss.Phi = -pi2step; + return ret_etmiss; + } - } else if (in_x < 0 && in_y >= 0) { - sign = false; - in_x = -in_x; + // Take absolute values to operate on the range (0, pi/2) + ap_fixed absx, absy; + if (signy == 0) { + absy = -y; + } else { + absy = y; + } - } else if (in_x < 0 && in_y < 0) { - sign = true; - in_x = -in_x; - in_y = -in_y; + if (signx == 0) { + absx = -x; + } else { + absx = x; + } + if (debug) { + edm::LogVerbatim("L1TkEtMissEmulator") << "\n=====Abs input=====\n" + << "abs(x): " << absx.to_double() << " abs(y): " << absy.to_double(); + } + + // Normalization (operate on a unit circle) + ap_fixed absx_sft, absy_sft; + for (int i = 0; i < Et_t::width + 1; i++) { + absx_sft[i] = absx[i]; + absy_sft[i] = absy[i]; + } + + if (debug) { + edm::LogVerbatim("L1TkEtMissEmulator") + << "\n=====Normalized input=====\n" + << "norm(abs(x)): " << absx_sft.to_double() << " norm(abs(y)): " << absy_sft.to_double(); + } + + // Setup the CORDIC inputs/outputs + ap_fixed cx, cy, cphi; + if (absy > absx) { + cx = absy_sft; + cy = absx_sft; + cphi = 0; } else { - sign = false; - in_y = -in_y; + cx = absx_sft; + cy = absy_sft; + cphi = 0; } - for (int step = 0; step < cordicSteps; step++) { - if (in_y < 0) { - new_x = in_x - (in_y >> step); - new_y = in_y + (in_x >> step); - } else { - new_x = in_x + (in_y >> step); - new_y = in_y - (in_x >> step); - } + if (debug) { + edm::LogVerbatim("L1TkEtMissEmulator") + << "\n=====CORDIC function arguments=====\n" + << "x: " << cx.to_double() << " y: " << cy.to_double() << " phi: " << cphi.to_double(); + } - if ((in_y < 0) == sign) { - new_phi = phi - atanLUT[step]; - } else { - new_phi = phi + atanLUT[step]; - } + // Perform the CORDIC (vectoring) function + cordic_subfunc(cx, cy, cphi); - in_x = new_x; - in_y = new_y; - phi = new_phi; + // Reorient the outputs to their appropriate quadrant + if (absy > absx) { + cphi = pi2 - cphi; + } - if (debug) { - edm::LogVerbatim("L1TkEtMissEmulator") - << " Cordic x: " << in_x << " Cordic y: " << in_y << " Cordic phi: " << phi << "\n"; - } + ap_fixed ophi; + if (signx == 0 && signy == 2) { // x < 0 and y > 0 + ophi = pi - cphi; + } else if (signx == 0 && signy == 0) { // x < 0 and y < 0 + ophi = cphi - pi; + } else if (signx == 2 && signy == 0) { // x > 0 and y < 0 + ophi = -cphi; + } else { + ophi = cphi; } - // Cordic performs calculation in internal Et granularity, convert to final - // granularity for Et word + // Re-scale the outputs + Et_t magnitude = ((ap_fixed)cx) + << (Et_t::iwidth + 1 - 2); + ret_etmiss.Et = l1tmetemu::Et_t(magnitude * magNormalisationLUT[cordicSteps - 1]); + ret_etmiss.Phi = ophi * pi_bins_fixed_t(kBinsInPi); + + if (debug) { + edm::LogVerbatim("L1TkEtMissEmulator") + << "\n=====toPolar output=====\n" + << std::setprecision(8) << "magnitude: " << magnitude.to_double() << " phi: " << ophi.to_double() + << " kBinsInPi: " << pi_bins_fixed_t(kBinsInPi).to_double() << "\n" + << "Et: " << ret_etmiss.Et.to_double() << " phi (int): " << ret_etmiss.Phi.to_int() << "\n"; + } - E2t_t tempMET = in_x * magNormalisationLUT[cordicSteps - 1]; - ret_etmiss.Et = tempMET; - ret_etmiss.Phi = phi.to_double() / kStepMETwordPhi; return ret_etmiss; } diff --git a/L1Trigger/L1TTrackMatch/src/L1TkEtMissEmuAlgo.cc b/L1Trigger/L1TTrackMatch/src/L1TkEtMissEmuAlgo.cc index c01c09ffa0b03..6f82bfd0bef2e 100644 --- a/L1Trigger/L1TTrackMatch/src/L1TkEtMissEmuAlgo.cc +++ b/L1Trigger/L1TTrackMatch/src/L1TkEtMissEmuAlgo.cc @@ -15,11 +15,14 @@ namespace l1tmetemu { return cosLUT; } - global_phi_t localToGlobalPhi(TTTrack_TrackWord::phi_t local_phi, global_phi_t sector_shift ) { + global_phi_t localToGlobalPhi(TTTrack_TrackWord::phi_t local_phi, global_phi_t sector_shift) { global_phi_t PhiMin = 0; - global_phi_t PhiMax = 2*M_PI / TTTrack_TrackWord::stepPhi0; + global_phi_t PhiMax = 2 * M_PI / TTTrack_TrackWord::stepPhi0; - int globalPhi = local_phi; + // The initial word comes in as a uint; the correct bits, but not automatically using 2s compliment format. + global_phi_t globalPhi = local_phi; + + // Once the word is in a larger, signed container, shift it down so that the negative numbers are automatically represented in 2s compliment. if (local_phi >= (1 << (TTTrack_TrackWord::TrackBitWidths::kPhiSize - 1))) globalPhi -= (1 << TTTrack_TrackWord::TrackBitWidths::kPhiSize); @@ -29,9 +32,9 @@ namespace l1tmetemu { globalPhi = globalPhi + PhiMax; } else if (globalPhi > PhiMax) { globalPhi = globalPhi - PhiMax; - } + } - return (global_phi_t)globalPhi; + return globalPhi; } std::vector generatePhiSliceLUT(unsigned int N) {