ATLAS Offline Software
Loading...
Searching...
No Matches
ResultBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Local includes:
6#include "./ResultBuilder.h"
8#include "./CTPUtil.h"
9#include "./CTPTriggerItem.h"
10#include "./SpecialTrigger.h"
11
12// eformat for data fragments:
13#include "eformat/eformat.h"
14#include "eformat/SourceIdentifier.h"
15
16// Output to the DAQ:
17#include "TrigT1Result/Header.h"
19
20// random number generator
21#include "CLHEP/Random/RandomEngine.h"
22#include "CLHEP/Random/RandFlat.h"
23
24// L1 configuration data
26
27// STL includes:
28#include <vector>
29#include <map>
30
31using namespace std;
32
34 const std::string& name,
35 const IInterface* parent )
36 : AthAlgTool(type, name, parent)
37{
38 m_ctpDataFormat = new CTPdataformatVersion(m_ctpVersionNumber);
39}
40
41
43 delete m_ctpDataFormat;
44 for(auto & x : m_internalTrigger) {
45 delete x.second;
46 }
47}
48
49
50StatusCode
52{
53 ATH_MSG_DEBUG( "Set configuration with CTP version " << m_ctpVersionNumber );
54
55 return createTriggerConfigMaps(l1menu);
56}
57
58
59StatusCode
61{
62 ATH_MSG_DEBUG("Creating trigger configuration maps from run-3-style menu");
63
64 std::vector<unsigned int> bg{1};
65 std::vector<unsigned int> bgEmpty{1};
66
67 // declare internal bunch group triggers
68 for (size_t i = 0; i < 16; ++i) {
69 auto bgrp = new BunchGroupTrigger(i, bg, m_ctpDataFormat);
70 m_internalTrigger[ bgrp->name() ] = bgrp;
71 }
72
73 // declare internal random triggers
74 for(int rndmIdx = 0; rndmIdx<4; rndmIdx++) {
75 auto rndm = new RandomTrigger(rndmIdx, m_ctpDataFormat);
76 m_internalTrigger[ rndm->name() ] = rndm;
77 }
78
79 // build map of name to ctp thresholds
80 m_thrConfigMap = std::make_unique<ThresholdMap>( &l1menu );
81
82 // build map of name to ctp items
83 m_itemConfigMap = std::make_unique<ItemMap>( &l1menu );
84
85 return StatusCode::SUCCESS;
86}
87
88StatusCode
89LVL1CTP::ResultBuilder::constructTIPVector( const std::map<std::string, unsigned int> & thrMultiMap,
90 std::vector<uint32_t> & tip ) const
91{
92 tip.resize( m_ctpDataFormat->getTIPwords(), 0 );
93
94 for( auto & entry : thrMultiMap ) {
95 const std::string & thrName = entry.first;
96 size_t multiplicity = entry.second;
97
98 // if multiplicity is 0 then there is nothing to set
99 if(multiplicity==0) {
100 continue;
101 }
102
103 auto x = m_internalTrigger.find(thrName);
104 if(x != m_internalTrigger.end()) {
105 // internal triggers (BGRP or RNDM)
106
107 size_t wordNr = m_ctpDataFormat->getTIPwords() - 1; // internal triggers are stored in the last word
108 size_t posWithinWord = x->second->pitPos() % 32;
109
110 tip[wordNr] |= ( 1L << posWithinWord );
111
112 } else {
113 // all other trigger threshold multiplicities
114
115 const CTPTriggerThreshold & ctpTT = m_thrConfigMap->getCTPThreshold( thrName );
116 size_t startBit = ctpTT.startBit();
117 size_t nBits = ctpTT.endBit() - startBit + 1;
118
119 // restrict to the maximum possible multiplicity
120 if(multiplicity >= (1U<<nBits)) {
121 multiplicity = (1U<<nBits)-1;
122 }
123
124 size_t wordNr = startBit / 32;
125 size_t posWithinWord = startBit % 32;
126
127 uint64_t result = multiplicity; // need 64 bit in case the word boundary is crossed by the threshold start..end
128 result <<= posWithinWord;
129
130 tip[wordNr] |= result & 0xFFFFFFFF;
131 if(wordNr+1 < m_ctpDataFormat->getTIPwords()-1) {
132 tip[wordNr+1] |= uint32_t((result & 0xFFFFFFFF00000000) >> 32);
133 }
134 }
135 }
136
137 size_t wrdNr(0);
138 for( uint32_t word : tip ) {
139 ATH_MSG_DEBUG( "REGTEST - " << "TIP word #" << std::dec << wrdNr++
140 << " is: 0x" << std::hex << std::setw( 8 ) << std::setfill( '0' ) << word );
141 }
142
143 return StatusCode::SUCCESS;
144}
145
146
147
148StatusCode
149LVL1CTP::ResultBuilder::buildItemDecision( const std::map<std::string, unsigned int> & thrMultiMap,
150 std::map<std::string, unsigned int> & itemDecisionMap,
151 CLHEP::HepRandomEngine* rndmEngine ) const
152{
153 // build trigger result for all items
154 itemDecisionMap.clear();
155
156 try {
157 for( const auto & itemName : m_itemConfigMap->itemNames() ) {
158 auto ctpItem = m_itemConfigMap->getItem(itemName);
159
160 bool pass_beforePrescale = ctpItem->evaluate(thrMultiMap);
161 bool pass_afterPrescale = false;
162 bool pass_afterVeto = false;
163
164 if ( pass_beforePrescale ) {
165 long random = CLHEP::RandFlat::shootInt( rndmEngine, pow(2,24) );
166 int32_t cut = TrigConf::PrescaleSet::getCutFromPrescale( m_itemConfigMap->getItem( itemName )->prescale() );
167 pass_afterPrescale = (random >= cut) && (cut > 0); // no pass if PS set to "-1"
168 pass_afterVeto = pass_afterPrescale; // dead time is not simulated
169 }
170
171 unsigned int result = (pass_beforePrescale ? TBP : 0) + (pass_afterPrescale ? TAP : 0) + (pass_afterVeto ? TAV : 0);
172
173 itemDecisionMap[itemName] = result;
174 }
175 } catch (TrigConf::LogicParsingException & ex) {
176 ATH_MSG_FATAL("Error in evaluating logic. " << ex.msg());
177 return StatusCode::FAILURE;
178 }
179 return StatusCode::SUCCESS;
180}
181
182StatusCode
183LVL1CTP::ResultBuilder::constructResultVectors( const std::map<std::string, unsigned int> & itemDecisionMap,
184 std::vector<uint32_t> & tbp, std::vector<uint32_t> & tap, std::vector<uint32_t> & tav,
185 unsigned char & triggerType ) const
186{
187 tbp.resize( m_ctpDataFormat->getTBPwords(), 0 );
188 tap.resize( m_ctpDataFormat->getTAPwords(), 0 );
189 tav.resize( m_ctpDataFormat->getTAVwords(), 0 );
190 triggerType = 0;
191
192 for( auto & entry : itemDecisionMap ) {
193 const std::string & itemName = entry.first;
194 unsigned int result = entry.second;
195 bool passBP = (result & TBP) != 0;
196 bool passAP = (result & TAP) != 0;
197 bool passAV = (result & TAV) != 0;
198
199
200
201
202 auto l1Item = m_itemConfigMap->getItem( itemName );
203
204 if( passAV ) {
205 triggerType |= l1Item->triggerType();
206 }
207
208 auto ctpId = l1Item->ctpId();
209 unsigned int wordNr = ctpId / 32;
210 unsigned int posWithinWord = ctpId % 32;
211
212 if( passBP ) { tbp[wordNr] |= 1L << posWithinWord; }
213 if( passAP ) { tap[wordNr] |= 1L << posWithinWord; }
214 if( passAV ) { tav[wordNr] |= 1L << posWithinWord; }
215
216 ATH_MSG_DEBUG( " --> Trigger item " << itemName <<
217 " is " << ( !passBP ? "INACTIVE" : ( passAV ? "ACTIVE" : "ACTIVE (but PRESCALED)" ) ) );
218 }
219 ATH_MSG_DEBUG( "REGTEST - " << "TriggerType byte is: 0x" << std::setw( 2 ) << std::setfill( '0' ) << std::hex << int(triggerType) );
220
221 return StatusCode::SUCCESS;
222}
223
224
225
226
227std::unique_ptr<LVL1CTP::CTPSLink>
229 const std::vector<uint32_t> & tbp,
230 const std::vector<uint32_t> & tap,
231 const std::vector<uint32_t> & tav,
232 const std::vector<uint32_t> & tip,
233 const std::vector<uint32_t> & extra,
234 const unsigned char triggerType ) const
235{
236 //
237 // Build the data words:
238 //
239 std::vector<uint32_t> roi_vector;
240 roi_vector.push_back( eventID.time_stamp_ns_offset() ); // Time stamp: 28-bit nanoseconds
241 roi_vector.push_back( eventID.time_stamp() ); // Time stamp: 32-bit UTC seconds
242
243 roi_vector.insert(roi_vector.end(), tip.begin(), tip.end()); // TIP + 1 extra word
244 roi_vector.insert(roi_vector.end(), tbp.begin(), tbp.end()); // TBP
245 roi_vector.insert(roi_vector.end(), tap.begin(), tap.end()); // TAP
246 roi_vector.insert(roi_vector.end(), tav.begin(), tav.end()); // TAV
247 roi_vector.insert(roi_vector.end(), extra.begin(), extra.end()); // Extra words
248
249 ATH_MSG_VERBOSE( "Stored data elements of RoI result" );
250
251 //
252 // Build the trailer:
253 //
254
255 std::vector<unsigned int> trailer(ROIB::Trailer(roi_vector.size()).trailer());
256 roi_vector.insert(roi_vector.end(), trailer.begin(), trailer.end());
257 ATH_MSG_VERBOSE( "Created trailer of RoI result" );
258
259 //
260 // Build the header:
261 //
262
263 // convention for source id in LVL1: 0 for DAQ, 1 for RoIB
264 const uint32_t source_id{eformat::helper::SourceIdentifier(eformat::TDAQ_CTP, 1).code()};
265
266 // version word
267 uint32_t version_word = eformat::DEFAULT_ROD_VERSION;
268 const uint32_t l1a_pos{0}; // there's only one BC in RoIB fragment, which is the L1A one
269 version_word |= ((extra.size() & m_ctpDataFormat->getProgrammableExtraWordsMask()) << m_ctpDataFormat->getProgrammableExtraWordsShift());
270 version_word |= ((l1a_pos & m_ctpDataFormat->getL1APositionMask()) << m_ctpDataFormat->getL1APositionShift());
271 version_word |= ((m_ctpVersionNumber & m_ctpDataFormat->getCTPFormatVersionMask()) << m_ctpDataFormat->getCTPFormatVersionShift());
272
273 ROIB::Header helperHeader(source_id, 0, version_word);
274
275 helperHeader.setRunNumber( eventID.run_number());
276 //helperHeader.setL1ID( eventID.extendedL1ID());
277 helperHeader.setBCID( eventID.bunch_crossing_id());
278 helperHeader.setTriggerType(triggerType);
279 //helperHeader.setEventType(EventInfo::instance().eventType());
280
281 std::vector<unsigned int> header(helperHeader.header());
282 roi_vector.insert(roi_vector.begin(), header.begin(), header.end());
283 ATH_MSG_VERBOSE( "Created header of RoI result" );
284
285 //
286 // Build the SLink:
287 //
288
289 std::unique_ptr<CTPSLink> result ( new CTPSLink( roi_vector, m_ctpVersionNumber ));
290 ATH_MSG_DEBUG( "Created CTPSlink object" );
291 ATH_MSG_VERBOSE( "Dump CTPSlink object:\n" + result->dump() );
292
293 //
294 // Debug output for ART
295 //
296 if( msgLvl(MSG::VERBOSE) ) {
297 for( auto & itemName : firedItems(tbp) ) {
298 ATH_MSG_VERBOSE( "REGTEST - Items fired before prescale: " << itemName );
299 }
300 for( auto & itemName : firedItems(tap) ) {
301 ATH_MSG_VERBOSE( "REGTEST - Items fired after prescale: " << itemName );
302 }
303 for( auto & itemName : firedItems(tav) ) {
304 ATH_MSG_VERBOSE( "REGTEST - Items fired after veto: " << itemName );
305 }
306 }
307 return result;
308}
309
310
311// TODO to be obsolete in favour of the CTPResult - see below
312
313std::unique_ptr<CTP_RDO>
315 const std::vector<uint32_t> & tbp,
316 const std::vector<uint32_t> & tap,
317 const std::vector<uint32_t> & tav,
318 const std::vector<uint32_t> & tip,
319 const std::vector<uint32_t> & extra ) const
320{
321 auto wrongSize = [this](const std::vector<uint32_t> & vec, uint32_t exp, std::string_view name) {
322 if (vec.size() == exp) {return false;}
323 ATH_MSG_ERROR("Wrong " << name << " vector size passed to constructRDOResult, " << vec.size() << " instead of " << exp);
324 return true;
325 };
326 if (wrongSize(tip, m_ctpDataFormat->getTIPwords(), "TIP")
327 || wrongSize(tbp, m_ctpDataFormat->getTBPwords(), "TBP")
328 || wrongSize(tap, m_ctpDataFormat->getTAPwords(), "TAP")
329 || wrongSize(tav, m_ctpDataFormat->getTAVwords(), "TAV")) {
330 return nullptr;
331 }
332
333 std::vector<uint32_t> data(static_cast<size_t>(m_ctpDataFormat->getNumberTimeWords()), uint32_t{0});
334 data.reserve(m_ctpDataFormat->getNumberTimeWords() + m_ctpDataFormat->getDAQwordsPerBunch() + extra.size());
335 data.insert(data.end(),tip.begin(),tip.end());
336 data.insert(data.end(),tbp.begin(),tbp.end());
337 data.insert(data.end(),tap.begin(),tap.end());
338 data.insert(data.end(),tav.begin(),tav.end());
339 data.insert(data.end(),extra.begin(),extra.end());
340
341 std::unique_ptr<CTP_RDO> result( new CTP_RDO(m_ctpVersionNumber, std::move(data), extra.size()) );
342 result->setTimeSec(eventID.time_stamp()); // Time stamp: 32-bit UTC seconds
343 result->setTimeNanoSec(eventID.time_stamp_ns_offset()); // Time stamp: 28-bit nanoseconds
344 ATH_MSG_DEBUG( "Created CTP_RDO object" );
345 return result;
346}
347
348
349
350
351std::pair< std::unique_ptr<xAOD::CTPResult>, std::unique_ptr<xAOD::CTPResultAuxInfo> >
353 const std::vector<uint32_t> & tbp,
354 const std::vector<uint32_t> & tap,
355 const std::vector<uint32_t> & tav,
356 const std::vector<uint32_t> & tip,
357 const std::vector<uint32_t> & extra,
358 const unsigned char triggerType ) const
359{
360 auto wrongSize = [this](const std::vector<uint32_t> & vec, uint32_t exp, std::string_view name) {
361 if (vec.size() == exp) {return false;}
362 ATH_MSG_ERROR("Wrong " << name << " vector size passed to constructCTPResult, " << vec.size() << " instead of " << exp);
363 return true;
364 };
365 if (wrongSize(tip, m_ctpDataFormat->getTIPwords(), "TIP")
366 || wrongSize(tbp, m_ctpDataFormat->getTBPwords(), "TBP")
367 || wrongSize(tap, m_ctpDataFormat->getTAPwords(), "TAP")
368 || wrongSize(tav, m_ctpDataFormat->getTAVwords(), "TAV")) {
369 return {nullptr, nullptr};
370 }
371
372 std::vector<uint32_t> data(static_cast<size_t>(m_ctpDataFormat->getNumberTimeWords()), uint32_t{0});
373 data.reserve(m_ctpDataFormat->getNumberTimeWords() + m_ctpDataFormat->getDAQwordsPerBunch() + extra.size());
374 data[m_ctpDataFormat->getTimeSecondsPos()] = eventID.time_stamp(); // Time stamp in seconds
375 data[m_ctpDataFormat->getTimeNanosecondsPos()] = eventID.time_stamp_ns_offset(); // Time stamp in nanoseconds
376 data.insert(data.end(),tip.begin(),tip.end());
377 data.insert(data.end(),tbp.begin(),tbp.end());
378 data.insert(data.end(),tap.begin(),tap.end());
379 data.insert(data.end(),tav.begin(),tav.end());
380 data.insert(data.end(),extra.begin(),extra.end());
381
382 // Source id for header words. Convention for source id in LVL1: 0 for DAQ
383 const uint32_t source_id{eformat::helper::SourceIdentifier(eformat::TDAQ_CTP, 1).code()};
384
385 // Version word for header words
386 uint32_t version_word = eformat::DEFAULT_ROD_VERSION;
387 const uint32_t l1a_pos{0};
388 version_word |= ((extra.size() & m_ctpDataFormat->getProgrammableExtraWordsMask()) << m_ctpDataFormat->getProgrammableExtraWordsShift());
389 version_word |= ((l1a_pos & m_ctpDataFormat->getL1APositionMask()) << m_ctpDataFormat->getL1APositionShift());
390 version_word |= ((m_ctpVersionNumber & m_ctpDataFormat->getCTPFormatVersionMask()) << m_ctpDataFormat->getCTPFormatVersionShift());
391
392 // Create the CTPResult and CTPResultAuxInfo objects
393 auto result = std::make_unique<xAOD::CTPResult>();
394 auto resultAux = std::make_unique<xAOD::CTPResultAuxInfo>();
395 result->setStore(resultAux.get());
396 CTPResultUtils::initialize(*result, m_ctpVersionNumber, data, extra.size()); // Payload words
397 result->setHeader(eformat::ROD, version_word, source_id, 0, eventID.run_number(), eventID.bunch_crossing_id(), triggerType, 0); // Header words
398 result->setTrailer(data.size()); // Trailer words
399 result->setL1AcceptBunchPosition(l1a_pos); // L1A bunch position
401 ATH_MSG_DEBUG( "Created CTPResult object" );
402 return std::make_pair(std::move(result), std::move(resultAux));
403}
404
405
406std::vector<std::string>
407LVL1CTP::ResultBuilder::firedItems(const std::vector<uint32_t>& triggerWords) const {
408 std::vector<std::string> passedItems;
409 for( const std::string & itemName : m_itemConfigMap->itemNames() ) {
410 auto item = m_itemConfigMap->getItem(itemName);
411 size_t idx = item->ctpId() / 32;
412 size_t bit = item->ctpId() % 32;
413 if ( triggerWords[idx] % (1L << bit) ) {
414 passedItems.push_back(item->name());
415 }
416 }
417 std::sort(passedItems.begin(), passedItems.end());
418 return passedItems;
419}
420
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
std::vector< size_t > vec
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
#define x
constexpr int pow(int base, int exp) noexcept
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
bool msgLvl(const MSG::Level lvl) const
Class for simulating the internal bunch group trigger.
Helper class holding trigger threshold multiplicity.
unsigned int endBit() const
Get the end position of the threshold.
unsigned int startBit() const
Get the start position of the threshold.
StatusCode createTriggerConfigMaps(const TrigConf::L1Menu &l1menu)
ResultBuilder(const std::string &type, const std::string &name, const IInterface *parent)
StatusCode setConfiguration(const TrigConf::L1Menu &l1menu)
StatusCode constructResultVectors(const std::map< std::string, unsigned int > &itemDecisionMap, std::vector< uint32_t > &tbp, std::vector< uint32_t > &tap, std::vector< uint32_t > &tav, unsigned char &triggerType) const
std::pair< std::unique_ptr< xAOD::CTPResult >, std::unique_ptr< xAOD::CTPResultAuxInfo > > constructCTPResult(const EventIDBase &eventID, const std::vector< uint32_t > &tbp, const std::vector< uint32_t > &tap, const std::vector< uint32_t > &tav, const std::vector< uint32_t > &tip, const std::vector< uint32_t > &extra, const unsigned char triggerType) const
build RDO result (CTPResult)
StatusCode constructTIPVector(const std::map< std::string, unsigned int > &thrMultiMap, std::vector< uint32_t > &tip) const
InternalTriggerMap m_internalTrigger
internal triggers BGRP and RNDM
std::unique_ptr< ItemMap > m_itemConfigMap
Map between item objects and their CTP-internal description.
CTPdataformatVersion * m_ctpDataFormat
CTP data format details.
StatusCode buildItemDecision(const std::map< std::string, unsigned int > &thrMultiMap, std::map< std::string, unsigned int > &itemDecisionMap, CLHEP::HepRandomEngine *rndmEngine) const
std::vector< std::string > firedItems(const std::vector< uint32_t > &triggerWords) const
build list of fired items and dump to string
unsigned int m_ctpVersionNumber
CTP data format version (4 in most of Run 2 and in Run 3)
std::unique_ptr< CTP_RDO > constructRDOResult(const EventIDBase &eventID, const std::vector< uint32_t > &tbp, const std::vector< uint32_t > &tap, const std::vector< uint32_t > &tav, const std::vector< uint32_t > &tip, const std::vector< uint32_t > &extra) const
build RDO result (CTP_RDO) - TODO obsolete it in favor of xAOD::CTPResult
std::unique_ptr< CTPSLink > constructRoIResult(const EventIDBase &eventID, const std::vector< uint32_t > &tbp, const std::vector< uint32_t > &tap, const std::vector< uint32_t > &tav, const std::vector< uint32_t > &tip, const std::vector< uint32_t > &extra, const unsigned char triggerType) const
build RoI result (LVL1CTP::CTPSLink)
std::unique_ptr< ThresholdMap > m_thrConfigMap
Map between threshold objects and their CTP-internal description.
Header models the LVL1 ROD Header.
void setBCID(const uint32_t i)
set bunch crossing ID
void setRunNumber(const uint32_t)
set run number
const std::vector< uint32_t > & header() const
get full header
void setTriggerType(const uint32_t i)
set LVL1 trigger type
ROIB::Trailer models the LVL1 ROD Trailer.
Definition Trailer.h:37
const std::vector< uint32_t > & trailer() const
get full trailer
L1 menu configuration.
Definition L1Menu.h:28
const std::string & msg() const
Definition Logic.h:21
static int32_t getCutFromPrescale(double prescale)
calculate cut value for hardware configuration cut = 2*24/prescale - 1
void initialize(xAOD::CTPResult &ctpRes, const uint32_t ctpVersionNumber, std::vector< uint32_t > &data, const uint32_t nExtraWords)
Initialize the object using xAOD::Header, xAOD::Trailer, and the payload data.
void dumpData(xAOD::CTPResult &ctpRes)
Print object content to default message stream.
STL namespace.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.