Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update GlobalBoard class FDL for fractional prescales, to match logic in firmware #39464

Merged
merged 1 commit into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions L1Trigger/L1TGlobal/interface/GlobalBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
#include <bitset>
#include <cassert>
#include <vector>
#include <cmath>

// user include files
#include "FWCore/Utilities/interface/typedefs.h"
#include "FWCore/Utilities/interface/Exception.h"

#include "DataFormats/L1TGlobal/interface/GlobalObjectMapRecord.h"

#include "L1Trigger/L1TGlobal/interface/AlgorithmEvaluation.h"
Expand Down Expand Up @@ -165,10 +168,6 @@ namespace l1t {
/// pointer to Tau data list
inline const BXVector<const GlobalExtBlk*>* getCandL1External() const { return m_candL1External; }

//initializer prescale counter using a semi-random value between [1, prescale value]
static const std::vector<double> semirandomNumber(const edm::Event& iEvent,
const std::vector<double>& prescaleFactorsAlgoTrig);

/* Drop individual EtSums for Now
/// pointer to ETM data list
inline const l1t::EtSum* getCandL1ETM() const
Expand Down Expand Up @@ -246,9 +245,6 @@ namespace l1t {
// cache of maps
std::vector<AlgorithmEvaluation::ConditionEvaluationMap> m_conditionResultMaps;

/// prescale counters: NumberPhysTriggers counters per bunch cross in event
std::vector<std::vector<double>> m_prescaleCounterAlgoTrig;

bool m_firstEv;
bool m_firstEvLumiSegment;
uint m_currentLumi;
Expand Down Expand Up @@ -277,7 +273,40 @@ namespace l1t {

// start the PS counter from a random value between [1,PS] instead of PS
bool m_semiRandomInitialPSCounters = false;

// step-size in prescale counter corresponding to 10^p,
// where p is the precision allowed for non-integer prescales;
// since the introduction of L1T fractional prescales, p == 2
static constexpr size_t m_singlestep = 100;

// struct to increment the prescale according to fractional prescale logic in firmware
struct PrescaleCounter {
const size_t prescale_count;
size_t trigger_counter = 0;

PrescaleCounter(double prescale) : prescale_count(std::lround(prescale * m_singlestep)) {
if (prescale_count != 0 and (prescale_count < m_singlestep or prescale < 0)) {
throw cms::Exception("PrescaleCounterConstructor")
<< "invalid initialisation of PrescaleCounter: prescale = " << prescale
<< ", prescale_count = " << prescale_count << " (< " << m_singlestep << " = m_singlestep)";
}
}

// function to increment the prescale counter and return the decision
bool accept();
};

// prescale counters: NumberPhysTriggers counters per bunch cross in event
std::vector<std::vector<PrescaleCounter>> m_prescaleCounterAlgoTrig;

// create prescale counters, initialising trigger_counter to a semirandom number between 0 and prescale_count - 1 inclusive
static const std::vector<PrescaleCounter> semirandomNumber(const edm::Event& iEvent,
const std::vector<double>& prescaleFactorsAlgoTrig);

// create prescale counters, initialising trigger_counter to zero
static const std::vector<PrescaleCounter> zeroPrescaleCounters(const std::vector<double>& prescaleFactorsAlgoTrig);
};

} // namespace l1t
#endif

#endif
98 changes: 58 additions & 40 deletions L1Trigger/L1TGlobal/src/GlobalBoard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
#include "L1Trigger/L1TGlobal/interface/CorrCondition.h"
#include "L1Trigger/L1TGlobal/interface/CorrThreeBodyCondition.h"
#include "L1Trigger/L1TGlobal/interface/CorrWithOverlapRemovalCondition.h"
#include "FWCore/Utilities/interface/Exception.h"

#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/MessageLogger/interface/MessageDrop.h"
Expand Down Expand Up @@ -971,28 +970,29 @@ void l1t::GlobalBoard::runFDL(edm::Event& iEvent,
// prescale counters are reset at the beginning of the luminosity segment
if (m_firstEv) {
// prescale counters: numberPhysTriggers counters per bunch cross
m_prescaleCounterAlgoTrig.reserve(totalBxInEvent);

auto const& prescaleCountersAlgoTrig =
m_semiRandomInitialPSCounters ? semirandomNumber(iEvent, prescaleFactorsAlgoTrig) : prescaleFactorsAlgoTrig;
auto const& prescaleCountersAlgoTrig = m_semiRandomInitialPSCounters
? semirandomNumber(iEvent, prescaleFactorsAlgoTrig)
: zeroPrescaleCounters(prescaleFactorsAlgoTrig);

for (int iBxInEvent = 0; iBxInEvent <= totalBxInEvent; ++iBxInEvent) {
rappoccio marked this conversation as resolved.
Show resolved Hide resolved
m_prescaleCounterAlgoTrig.push_back(prescaleCountersAlgoTrig);
}

m_firstEv = false;
m_currentLumi = iEvent.luminosityBlock();
}

// update and clear prescales at the beginning of the luminosity segment
if (m_firstEvLumiSegment || (m_currentLumi != iEvent.luminosityBlock() && m_resetPSCountersEachLumiSec)) {
m_prescaleCounterAlgoTrig.clear();
m_prescaleCounterAlgoTrig.reserve(totalBxInEvent + 1);
auto const& prescaleCountersAlgoTrig = m_semiRandomInitialPSCounters
? semirandomNumber(iEvent, prescaleFactorsAlgoTrig)
: zeroPrescaleCounters(prescaleFactorsAlgoTrig);
for (int iBxInEvent = 0; iBxInEvent <= totalBxInEvent; ++iBxInEvent) {
if (m_semiRandomInitialPSCounters) {
m_prescaleCounterAlgoTrig.push_back(semirandomNumber(iEvent, prescaleFactorsAlgoTrig));
} else {
m_prescaleCounterAlgoTrig.push_back(prescaleFactorsAlgoTrig);
}
m_prescaleCounterAlgoTrig.push_back(prescaleCountersAlgoTrig);
}

m_firstEvLumiSegment = false;
m_currentLumi = iEvent.luminosityBlock();
}
Expand All @@ -1011,15 +1011,14 @@ void l1t::GlobalBoard::runFDL(edm::Event& iEvent,
bool temp_algPrescaledOr = false;
bool alreadyReported = false;
for (unsigned int iBit = 0; iBit < numberPhysTriggers; ++iBit) {
bool bitValue = m_uGtAlgBlk.getAlgoDecisionInitial(iBit);
const bool bitValue = m_uGtAlgBlk.getAlgoDecisionInitial(iBit);
if (bitValue) {
// Make sure algo bit in range, warn otherwise
if (iBit < prescaleFactorsAlgoTrig.size()) {
if (prescaleFactorsAlgoTrig.at(iBit) != 1) {
mitaylor marked this conversation as resolved.
Show resolved Hide resolved
(m_prescaleCounterAlgoTrig.at(inBxInEvent).at(iBit))--;
if (m_prescaleCounterAlgoTrig.at(inBxInEvent).at(iBit) == 0) {
// bit already true in algoDecisionWord, just reset counter
m_prescaleCounterAlgoTrig.at(inBxInEvent).at(iBit) = prescaleFactorsAlgoTrig.at(iBit);
const bool triggered = m_prescaleCounterAlgoTrig.at(inBxInEvent).at(iBit).accept();

if (triggered) {
temp_algPrescaledOr = true;
} else {
// change bit to false in prescaled word and final decision word
Expand Down Expand Up @@ -1055,7 +1054,7 @@ void l1t::GlobalBoard::runFDL(edm::Event& iEvent,
bool temp_algFinalOr = false;
bool alreadyReported = false;
for (unsigned int iBit = 0; iBit < numberPhysTriggers; ++iBit) {
bool bitValue = m_uGtAlgBlk.getAlgoDecisionInterm(iBit);
const bool bitValue = m_uGtAlgBlk.getAlgoDecisionInterm(iBit);

if (bitValue) {
//bool isMasked = ( triggerMaskAlgoTrig.at(iBit) == 0 );
Expand All @@ -1068,7 +1067,7 @@ void l1t::GlobalBoard::runFDL(edm::Event& iEvent,
<< std::endl;
}

bool passMask = (bitValue && !isMasked);
const bool passMask = (bitValue && !isMasked);

if (passMask)
temp_algFinalOr = true;
Expand Down Expand Up @@ -1168,35 +1167,54 @@ void l1t::GlobalBoard::printGmtData(const int iBxInEvent) const {
LogTrace("L1TGlobal") << std::endl;
}

//initializer prescale counter using a semi-random value between [1, prescale value]
const std::vector<double> l1t::GlobalBoard::semirandomNumber(const edm::Event& iEvent,
const std::vector<double>& prescaleFactorsAlgoTrig) {
auto out = prescaleFactorsAlgoTrig;
// initializer prescale counters using a semi-random value between [0, prescale value * 10 ^ precision - 1]
const std::vector<l1t::GlobalBoard::PrescaleCounter> l1t::GlobalBoard::semirandomNumber(
const edm::Event& iEvent, const std::vector<double>& prescaleFactorsAlgoTrig) {
// pick a random number from a combination of run, lumi, event numbers
std::srand(iEvent.id().run());
std::srand(std::rand() + iEvent.id().luminosityBlock());
// this causes different (semi)random number number for different streams
// reminder: different streams have different initial event number
std::srand(iEvent.id().run());
std::srand(std::rand() + iEvent.id().luminosityBlock());
std::srand(std::rand() + iEvent.id().event());

mitaylor marked this conversation as resolved.
Show resolved Hide resolved
// very large (semi)random number
double const semirandom = std::rand();
for (auto& ps : out) {
// if the ps is smaller than 1 (e.g. ps=0, ps=1), it is not changed
// else, replace ps with a semirandom integer in the [1,ps] range
if (ps > 1) {
auto nps = semirandom - floor(semirandom / ps) * ps;
// if nps=0 or a wrong value (<0,>ps) use PS value (standard method)
if (nps > 0 and nps <= ps)
ps = nps;
else {
if (nps != 0) // complain only if nps <0 or nps >PS
edm::LogWarning("L1TGlobal::semirandomNumber")
<< "\n The inital prescale counter obtained by L1TGlobal::semirandomNumber is wrong."
<< "\n This is probably do to the floating-point precision. Using the PS value."
<< "\n semirandom = " << semirandom << "\n PS = " << ps << "\n nps = " << nps
<< " <-- it should be in the range [0 , " << ps << "]" << std::endl;
}
const int semirandom = std::rand();
std::vector<PrescaleCounter> out;
out.reserve(prescaleFactorsAlgoTrig.size());

for (size_t iAlgo = 0; iAlgo < prescaleFactorsAlgoTrig.size(); iAlgo++) {
// for prescaled triggers, initialise trigger_counter to
// a semirandom integer between 0 and prescale_count - 1 (inclusive)
out.emplace_back(PrescaleCounter(prescaleFactorsAlgoTrig[iAlgo]));

auto& prescaleCounter = out.back();
if (prescaleCounter.prescale_count > 0) {
prescaleCounter.trigger_counter = semirandom % prescaleCounter.prescale_count;
}
}

return out;
}

// initialize prescale counters to zero
const std::vector<l1t::GlobalBoard::PrescaleCounter> l1t::GlobalBoard::zeroPrescaleCounters(
const std::vector<double>& prescaleFactorsAlgoTrig) {
std::vector<PrescaleCounter> out;
out.reserve(prescaleFactorsAlgoTrig.size());
for (size_t iAlgo = 0; iAlgo < prescaleFactorsAlgoTrig.size(); iAlgo++) {
out.emplace_back(PrescaleCounter(prescaleFactorsAlgoTrig[iAlgo]));
}

return out;
}

bool l1t::GlobalBoard::PrescaleCounter::accept() {
trigger_counter += m_singlestep;

if (prescale_count == 0 or trigger_counter < prescale_count)
return false;

trigger_counter -= prescale_count;

return true;
}