ATLAS Offline Software
Loading...
Searching...
No Matches
TopoSteeringStructure.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
5
9
12
16
22
24#include "TrigConfData/L1Menu.h"
25
26#include <set>
27#include <iostream>
28#include <iomanip>
29#include <memory>
30#include <charconv>
31#include <string_view>
32
33using namespace std;
34using namespace TCS;
35
36namespace {
37 uint32_t interpretGenericParam(const std::string& parvalue) {
38 uint32_t val = 0;
39 std::string_view parvalue_sv = parvalue;
40 auto [ptr, ec] = std::from_chars(parvalue_sv.data(), parvalue_sv.data() + parvalue_sv.size(), val);
41 if (ec != std::errc()) {
42 if( parvalue.size()>=3 && parvalue[0]==':' and parvalue[parvalue.size()-1]==':' ) {
43
44 auto x = L1TopoHWParameters::get().find(parvalue.substr(1,parvalue.size()-2));
45
46 string parname = parvalue.substr(1,parvalue.size()-2);
47
48 if( x != L1TopoHWParameters::get().end()) {
49 val = x->second.value;
50 } else {
51 cout << "Hardware constrained parameters are" << endl;
52 for(auto & x : L1TopoHWParameters::get())
53 cout << " " << x.first << endl;
54
55 TCS_EXCEPTION("Generic parameter value " << parvalue << " has the hardware contrained parameter format, but '" << parname << "' is not listed in L1TopoHardware.cxx");
56 }
57 } else {
58 TCS_EXCEPTION("Generic parameter value " << parvalue << " is not a uint32_t and does not match the hardware contrained parameter specification ':<parname>:' ");
59 }
60 }
61 return val;
62 }
63}
64
65
69
70
72 for( Connector* c: m_connectors )
73 delete c;
74 for( ParameterSpace * ps : m_parameters )
75 delete ps;
76}
77
80 for(Connector* conn: m_connectors)
81 conn->reset();
83}
84
85
86void
87TCS::TopoSteeringStructure::print(std::ostream & o) const {
88 o << "Topo Steering Structure" << endl
89 << "-----------------------" << endl;
90
91 o << "Output summary:" << endl;
92 for(const auto & conn: outputConnectors() ) {
93 o << " " << *conn.second << endl;
94 }
95
96 o << endl
97 << "Algorithm detail:" << endl;
98 for(const auto & nc: outputConnectors() ) {
99 DecisionConnector * conn = nc.second;
100 unsigned int firstBit = conn->decision().firstBit();
101 unsigned int lastBit = conn->numberOutputBits() + firstBit - 1;
102 const ConfigurableAlg* alg = conn->algorithm();
103 const Connector* inputconn = conn->inputConnectors().back();
104 const ConfigurableAlg* sortalg = inputconn->algorithm();
105 o << std::setw(2) << "bits " << firstBit << "-" << lastBit << ": " << conn->name() << " [input " << inputconn->name() <<"]" << endl;
106 o << *alg << endl << endl;
107 o << *sortalg << endl;
108 }
109}
110
111
112void
114 unsigned int idx(0);
115 for(const ParameterSpace* ps: m_parameters) {
116 if(ps && ps->isInitialized())
117 o << "pos " << std::setw(2) << idx << ": " << ps << endl;
118 idx++;
119 }
120}
121
122
124TCS::TopoSteeringStructure::setupFromMenu ATLAS_NOT_THREAD_SAFE (const TrigConf::L1Menu& l1menu, bool legacy, bool debug) {
125
126 if(debug)
127 cout << "/***************************************************************************/" << endl
128 << " L1Topo steering structure: configuring from L1 Topo Menu " << endl
129 << "/***************************************************************************/" << endl;
130
131 // set<TCS::inputTOBType_t> neededInputs; // Stores inputs for DecisionConnectors
132 vector<string> storedConn; // Stores decision connectors in order to avoid double counting
133 vector<vector<string>> confAlgorithms; // Stores algorithm name/category that have been configured in L1Menu to be used for setting the parameters
134 vector<string> confMultAlgorithms; // Stores algorithm names that have been configured in L1Menu to be used for setting the multiplicity thresholds
135 // Loop over boards in L1Menu and skip the ones that are not TOPO. Use Run-2 boards if legacy flag is on
136
137 string AvailableMultAlgs[] = { "eEmMultiplicity",
138 "jEmMultiplicity",
139 "eTauMultiplicity",
140 "jTauMultiplicity",
141 "cTauMultiplicity",
142 "jJetMultiplicity",
143 "jLJetMultiplicity",
144 "gJetMultiplicity",
145 "gLJetMultiplicity",
146 "EnergyThreshold",
147 "LArSaturation" };
148
149 for (const string & boardName : l1menu.boardNames() ){
150
151 auto & l1board = l1menu.board(boardName);
152
153 if (l1board.type() != "TOPO") continue;
154 if (l1board.legacy() != legacy) continue;
155
156 // Access the connectors in the boards
157
158 for (const string & connName : l1board.connectorNames() ){
159
160 auto & l1conn = l1menu.connector(connName);
161
162 // First configure decision algorithms
163 // Look at all Topo algorithms in each connector, and get inputs from each algorithm to configure SortingConnectors
164 if ( l1conn.connectorType() == TrigConf::L1Connector::ConnectorType::ELECTRICAL ) {
165
166 for( size_t fpga : { 0, 1} ) {
167 for( size_t clock : { 0, 1} ) {
168 for( auto & tl : l1conn.triggerLines(fpga, clock) ) {
169
170 const string & tlName = tl.name();
171 auto & algo = l1menu.algorithmFromTriggerline(tlName);
172 const string algoName = (legacy?"R2_"+algo.name():algo.name());
173
174 // One algorithm can have multiple trigger lines. Check the connector/algorithm has not been stored already
175 auto it = find(storedConn.begin(), storedConn.end(), algoName);
176 if (it == storedConn.end()) { // Algorithm/Connector does not exist: create and store it
177
178 storedConn.push_back(algoName);
179 vector<string> inputNames;
180 for( auto & input : algo.inputs() ) {
181 if( sortingConnector(input) == 0 ) { // if connector does not exist, create it
182 if(debug)
183 cout << "L1TopoSteering: Decision algo( " << algo.name() << " ) input is not defined: " << input << ". Creating sortingConnector" << endl;
184
185 auto & sortAlgo = l1menu.algorithm(input, algo.category());
186 if(!(sortAlgo.type() == TrigConf::L1TopoAlgorithm::AlgorithmType::SORTING ) )
187 TCS_EXCEPTION("L1TopoSteering: Decision algo " << algo.name() << ") has as input " << input << " which is not associated to a sorting algorithm");
188
189 // Create connector
190 SortingConnector * sortConn = new SortingConnector(sortAlgo.inputs().at(0), sortAlgo.klass()+"/"+input, sortAlgo.outputs().at(0));
191 if(debug)
192 cout << "Adding sorting connector " << "[" << *sortConn << "]" << endl;
193 addSortingConnector( sortConn );
194 confAlgorithms.push_back({sortAlgo.name(), sortAlgo.category()});
195
196 } // if connector does not exist
197
198 inputNames.push_back(input);
199
200 } // loop over inputs
201
202 DecisionConnector * conn = new DecisionConnector(algoName, inputNames, algo.klass()+"/"+algoName, algo.outputs());
203 conn->m_decision.setNBits( algo.outputs().size() );
204
205 if(tl.name() != "UNDEF")
206 conn->m_triggers.push_back(tl);
207
208 if(debug)
209 cout << "Adding decision connector " << "[" << *conn << "]" << endl;
210 addDecisionConnector( conn );
211 confAlgorithms.push_back({algo.name(), algo.category()});
212
213 } else { // Connector already exists: look for it and add the trigger line
214 for(const auto & out : algo.outputs()){
215 auto c = m_outputLookup.find(out);
216 if (c != m_outputLookup.end()){
217 auto conn = c->second;
218 if(tl.name() != "UNDEF")
219 conn->m_triggers.push_back(tl);
220 break;
221 }
222 }
223 }
224
225 } // Trigger Line
226
227 } // Clock
228
229 } // FPGA
230
231 } else { // Configure optical connectors - multiplicity algorithms
232
233 // In multiplicity boards all trigger lines are copied into the L1Menu::Connector 4 times (fpga 0,1 and clock 0,1)
234 // Take (fpga, clock) = (0, 0)
235
236 for( auto & tl : l1conn.triggerLines(0, 0) ) {
237
238 const string & tlName = tl.name();
239 auto & algo = l1menu.algorithmFromTriggerline(tlName);
240
241 string algo_klass = algo.klass();
242 if(algo_klass=="eEmVarMultiplicity") algo_klass="eEmMultiplicity"; // in sim, use the same multiplicity algo for fixed and variable thresholds
243
244 //Zero Bias events can't be simulated.
245 //The following line is set to simply ignore it in the simulation
246 //ZeroBias Multiplicity algorithms are not added to confMultAlgorithms
247 if ( algo_klass == "ZeroBias" ) continue;
248
249 auto it = find(storedConn.begin(), storedConn.end(), algo.name());
250 if (it == storedConn.end()) { // Algorithm/Connector does not exist: create and store it
251
252 storedConn.push_back(algo.name());
253 if(debug)
254 cout << "L1TopoSteering: Multiplicity algo( " << algo.name() << " ) has as input " << algo.inputs().at(0) << endl;
255
256 CountingConnector * conn = new CountingConnector(algo.name(), algo.inputs().at(0), algo_klass+"/"+algo.name(), algo.outputs().at(0));
257 conn->m_count.setNBits( tl.nbits() );
258 conn->m_count.setFirstBit( tl.startbit() );
259
260 if(tl.name() != "UNDEF")
261 conn->m_triggers.push_back(tl);
262
263 if(debug)
264 cout << "Adding count connector " << "[" << *conn << "]" << endl;
265 addCountingConnector( conn );
266 confMultAlgorithms.push_back( algo.name() );
267 }
268
269 } // Trigger Line
270
271 } // Optical connectors - multiplicities
272
273 } // Connector in l1board
274
275 } // Board in l1menu
276
277
278 if(debug)
279 cout << "... building input connectors" << endl;
280 for(const auto & sortConn : m_sortedLookup) {
281 const string & in = sortConn.second->inputNames()[0]; // name of input
282
283 if( m_inputLookup.count(in) > 0 ) continue; // InputConnector already exists
284
285 InputConnector * conn = new InputConnector(in);
286 m_connectors.push_back(conn);
287 m_inputLookup[in] = conn;
288 if(debug)
289 cout << "Adding input connector " << "[" << *conn << "]" << endl;
290 }
291 for(const auto & countConn : m_countLookup) {
292 const string & in = countConn.second->inputNames()[0]; // name of input
293
294 if( m_inputLookup.count(in) > 0 ) continue; // InputConnector already exists
295
296 InputConnector * conn = new InputConnector(in);
297 m_connectors.push_back(conn);
298 m_inputLookup[in] = conn;
299 if(debug)
300 cout << "Adding input connector " << "[" << *conn << "]" << endl;
301 }
302
303 // link the connector objects together
304 TCS::StatusCode sc = linkConnectors();
305
306 // instantiate the algorithms from the algorithm names in the connectors
307 if(debug)
308 cout << "... instantiating algorithms" << endl;
309 sc &= instantiateAlgorithms(debug);
310
311
312 // set algorithm parameters
313 if(debug)
314 cout << "... setting algorithm parameters" << endl;
315
316 for ( auto & confAlgo : confAlgorithms ) {
317
318 auto & l1algo = l1menu.algorithm(confAlgo.at(0), confAlgo.at(1));
319 auto l1algoName = confAlgo.at(0);
320 if (l1algo.type() == TrigConf::L1TopoAlgorithm::AlgorithmType::DECISION && legacy)
321 l1algoName ="R2_"+confAlgo.at(0);
322
323 if(debug)
324 cout << "TopoSteeringStructure: Parameters for algorithm with name " << l1algoName << " going to be configured." << endl;
325 ConfigurableAlg * alg = AlgFactory::mutable_instance().algorithm(l1algoName);
326
327 if(alg->isDecisionAlg()){
328 ( static_cast<DecisionAlg *>(alg) )->setNumberOutputBits(l1algo.outputs().size());
329 }
330 // create ParameterSpace for this algorithm
331 auto ps = std::make_unique<ParameterSpace>(alg->name());
332
333 for(auto & pe : l1algo.parameters()) {
334
335 auto & pname = pe.name();
336 uint32_t val = pe.value();
337 uint32_t sel = pe.selection();
338
339 if(debug)
340 cout << "Algo Name: " << l1algoName << " parameter " << ": " << setw(20) << left << pname << " value = " << setw(3) << left << val << " (selection " << sel << ")" << endl;
341 ps->addParameter( pname, val, sel);
342
343 }
344
345 for(auto & gen : l1algo.generics().getKeys()) {
346
347 auto pe = l1algo.generics().getObject(gen);
348 string pname = gen;
349 uint32_t val = interpretGenericParam(pe.getAttribute("value"));
350 if (pname == "NumResultBits"){
351 if(val != l1algo.outputs().size()) {
352 TCS_EXCEPTION("Algorithm " << pname << " parameter OutputBits (" << val << ") is different from output size (" << l1algo.outputs().size() << ")");
353 }
354 continue; // ignore this, because it is defined through the output list
355 }
356 if(debug)
357 cout << " fixed parameter : " << setw(20) << left << pname << " value = " << setw(3) << left << val << endl;
358 ps->addParameter( pname, val );
359
360 }
361
362
363 if(debug)
364 cout << " (setting parameters)";
365 alg->setParameters( *ps );
366
367 if(debug)
368 cout << " --> (parameters set)";
369
370 if(debug)
371 cout << " --> (parameters stored)" << endl;
372 } // Set parameters for Sorting/Decision algorithms
373
374 // // set thresholds for multiplicity algorithms
375 for ( auto & multAlgo : confMultAlgorithms ) {
376
377 auto & l1algo = l1menu.algorithm(multAlgo, "MULTTOPO");
378
379 //Zero Bias events can't be simulated.
380 //The following line is set to simply ignore it in the simulation
381 if ( l1algo.klass() == "ZeroBias" ) continue;
382
383 ConfigurableAlg * alg = AlgFactory::mutable_instance().algorithm(l1algo.name());
384
385 // Get L1Threshold object and pass it to CountingAlg, from where it will be propagated to and decoded in each algorithm
386 // The output of each algorithm and the threshold name is the same - use output name to retrieve L1Threshold object
387 auto & l1thr = l1menu.threshold( l1algo.outputs().at(0) );
388 auto pCountAlg = dynamic_cast<CountingAlg *>(alg);
389 if (not pCountAlg) continue;
390 pCountAlg->setThreshold(l1thr);
391
392 } // Set thresholds for multiplicity algorithms
393
394
395 m_isConfigured = true;
396
397 if(debug)
398 cout << "... L1TopoSteering successfully configured" << endl;
399
400 return sc;
401}
402
403
404TCS::StatusCode
406 m_connectors.push_back(conn);
407 for( const string & output : conn->outputNames() )
408 m_sortedLookup[output] = conn;
410}
411
414 m_connectors.push_back(conn);
415 for( const string & output : conn->outputNames() )
416 m_outputLookup[output] = conn;
418}
419
420
423 m_connectors.push_back(conn);
424 for( const string & output : conn->outputNames() )
425 m_countLookup[output] = conn;
427}
428
429
432
433 for(TCS::Connector * conn: m_connectors)
434 for(const std::string & inconn: conn->inputNames())
435 conn->inputConnectors().push_back( connector(inconn) );
436
438}
439
440
442TCS::TopoSteeringStructure::instantiateAlgorithms ATLAS_NOT_THREAD_SAFE (bool debug) {
443
444 for(TCS::Connector* conn: m_connectors) {
445
446 if(conn->isInputConnector()) continue;
447
448 // for each connector instantiate the algorithm and add to connector
449 const std::string & alg = conn->algorithmName();
450
451 // split into name and type
452 std::string algType(alg, 0, alg.find('/'));
453 std::string algName(alg, alg.find('/')+1);
454
455 ConfigurableAlg * algInstance = TCS::AlgFactory::mutable_instance().algorithm(algName);
456 if(algInstance==0) {
457 if(debug)
458 cout << "Instantiating " << alg << endl;
459 algInstance = TCS::AlgFactory::mutable_instance().create(algType, algName);
460 } else {
461 if(algInstance->className() != algType) {
462 TCS_EXCEPTION("L1 TopoSteering: duplicate algorithm names: algorithm " << algName << " has already been instantiated but with different type");
463 }
464 }
465 conn->setAlgorithm(algInstance);
466 }
468}
469
470
471TCS::Connector *
472TCS::TopoSteeringStructure::connector(const std::string & connectorName) const {
473 for( TCS::Connector* conn: m_connectors ) {
474 if( conn->name() == connectorName )
475 return conn;
476 }
477 TCS_EXCEPTION("L1Topo Steering: can not find connector of name " << connectorName << ". Need to abort!");
478 return 0;
479}
480
481
483TopoSteeringStructure::sortingConnector(const std::string & connectorName) const {
484 SortingConnector * sc = nullptr;
485 for( TCS::Connector* conn: m_connectors ) {
486 if( conn->name() == connectorName ) {
487 sc = dynamic_cast<SortingConnector*>(conn);
488 if(sc==nullptr) {
489 TCS_EXCEPTION("TopoSteeringStructure: connector of name " << connectorName << " exists, but is not a SortingConnector. Need to abort!");
490 }
491 }
492 }
493
494 return sc;
495}
496
497
498
501 auto c = m_outputLookup.find(output);
502 if( c != m_outputLookup.end() )
503 return c->second;
504 TCS_EXCEPTION("L1Topo Steering: can not find output connector of that produces " << output << ". Need to abort!");
505 return 0;
506}
507
508
511 auto c = m_countLookup.find(output);
512 if( c != m_countLookup.end() )
513 return c->second;
514 TCS_EXCEPTION("L1Topo Steering: can not find counting connector of that produces " << output << ". Need to abort!");
515 return 0;
516}
517
static Double_t sc
const bool debug
#define x
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
const std::string & className() const
const std::string & name() const
Definition Connector.h:44
const TCS::ConfigurableAlg * algorithm() const
Definition Connector.h:50
void setThreshold(const TrigConf::L1Threshold &thr)
Definition CountingAlg.h:44
void printParameters(std::ostream &o) const
StatusCode addDecisionConnector(DecisionConnector *conn)
std::vector< TCS::Connector * > m_connectors
const std::map< std::string, TCS::DecisionConnector * > & outputConnectors() const
DecisionConnector * outputConnector(const std::string &output)
CountingConnector * countingConnector(const std::string &output)
void print(std::ostream &o) const
std::vector< TCS::ParameterSpace * > m_parameters
std::map< std::string, TCS::SortingConnector * > m_sortedLookup
std::map< std::string, TCS::CountingConnector * > m_countLookup
std::map< std::string, TCS::DecisionConnector * > m_outputLookup
StatusCode addCountingConnector(CountingConnector *conn)
StatusCode addSortingConnector(SortingConnector *conn)
Connector * connector(const std::string &connectorName) const
SortingConnector * sortingConnector(const std::string &output) const
L1 menu configuration.
Definition L1Menu.h:28
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:138
void * ptr(T *p)
Definition SGImplSvc.cxx:74
STL namespace.
setEventNumber uint32_t
static const std::map< std::string, HardwareParam > & get()