ATLAS Offline Software
Loading...
Searching...
No Matches
PpmByteStreamV1Tool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6#include <numeric>
7#include <set>
8#include <utility>
9
10#include "GaudiKernel/IInterface.h"
11#include "GaudiKernel/MsgStream.h"
12#include "GaudiKernel/StatusCode.h"
13#include "StoreGate/SegMemSvc.h"
14
16
21
22#include "CmmSubBlock.h"
24#include "L1CaloSrcIdMap.h"
25#include "L1CaloSubBlock.h"
26#include "L1CaloUserHeader.h"
27#include "ModifySlices.h"
28
29#include "PpmByteStreamV1Tool.h"
30
32
33namespace LVL1BS
34{
35
40
41// Interface ID
42
43static const InterfaceID IID_IPpmByteStreamV1Tool("PpmByteStreamV1Tool", 1, 1);
44
46{
48}
49
50// Constructor
51
53 const std::string &name,
54 const IInterface *parent)
55 : AthAlgTool(type, name, parent),
56 m_ppmMaps("LVL1::PpmMappingTool/PpmMappingTool"),
57 m_errorTool("LVL1BS::L1CaloErrorByteStreamTool/L1CaloErrorByteStreamTool"),
58 m_sms("SegMemSvc/SegMemSvc", name),
59 m_version(1), m_compVers(4),
60 m_subDetector(eformat::TDAQ_CALO_PREPROC)
61{
62 declareInterface<PpmByteStreamV1Tool>(this);
63
64 declareProperty("PpmMappingTool", m_ppmMaps,
65 "Crate/Module/Channel to Eta/Phi/Layer mapping tool");
66 declareProperty("ErrorTool", m_errorTool,
67 "Tool to collect errors for monitoring");
68
69 declareProperty("PrintCompStats", m_printCompStats = 0,
70 "Print compressed format statistics");
71 declareProperty("SlinksPerCrate", m_slinks = 4,
72 "The number of S-Links per crate");
73
74 // Properties for reading bytestream only
75 declareProperty("ZeroSuppress", m_zeroSuppress = 0,
76 "Only make trigger towers with non-zero EM or Had energy");
77 declareProperty("ROBSourceIDs", m_sourceIDsProp,
78 "ROB fragment source identifiers");
79 declareProperty("PedestalValue", m_pedestal = 10,
80 "Pedestal value - needed for compressed formats 0,1 only");
81
82 // Properties for writing bytestream only
83 declareProperty("DataFormat", m_dataFormat = 1,
84 "Format identifier (0-3) in sub-block header");
85 declareProperty("FADCBaseline", m_fadcBaseline = 0,
86 "FADC baseline lower bound for compressed formats");
87 declareProperty("FADCThreshold", m_fadcThreshold = 1,
88 "FADC threshold for super-compressed format");
89 declareProperty("SimulSlicesLUT", m_dfltSlicesLut = 1,
90 "The number of LUT slices in the simulation");
91 declareProperty("SimulSlicesFADC", m_dfltSlicesFadc = 7,
92 "The number of FADC slices in the simulation");
93 declareProperty("ForceSlicesLUT", m_forceSlicesLut = 0,
94 "If >0, the number of LUT slices in bytestream");
95 declareProperty("ForceSlicesFADC", m_forceSlicesFadc = 0,
96 "If >0, the number of FADC slices in bytestream");
97 declareProperty("CrateMin", m_crateMin = 0,
98 "Minimum crate number, allows partial output");
99 declareProperty("CrateMax", m_crateMax = s_crates - 1,
100 "Maximum crate number, allows partial output");
101
102}
103
104// Destructor
105
109
110// Initialize
111
112
114{
115 ATH_MSG_INFO ( "Initializing " << name() );
116
117 ATH_CHECK( m_ppmMaps.retrieve() );
118 ATH_CHECK( m_errorTool.retrieve() );
119 ATH_CHECK( m_sms.retrieve() );
120
121 return StatusCode::SUCCESS;
122}
123
124// Finalize
125
127{
128 if (m_printCompStats && msgLvl(MSG::INFO))
129 {
130 msg(MSG::INFO);
132 }
133 return StatusCode::SUCCESS;
134}
135
136
137// Conversion bytestream to trigger towers
138
140 const std::string& sgKey,
141 const IROBDataProviderSvc::VROBFRAG &robFrags,
142 DataVector<LVL1::TriggerTower> *const ttCollection) const
143{
144 const bool debug = msgLvl(MSG::DEBUG);
145 const bool verbose = msgLvl(MSG::VERBOSE);
146 if (debug) msg(MSG::DEBUG);
147
148 const std::string flag("Spare");
149 const std::string::size_type pos = sgKey.find(flag);
150 bool spareChannels =
151 (pos != std::string::npos && pos == (sgKey.length() - flag.length()));
152 const std::string flag2("Muon");
153 const std::string::size_type pos2 = sgKey.find(flag2);
154 bool muonChannels =
155 (pos2 != std::string::npos && pos2 == (sgKey.length() - flag2.length()));
156 bool dataChannels = (!spareChannels && !muonChannels);
157
158 // Set up TriggerTower pool and mappings
159 // (NB. This assumes mappings won't change during the course of a job)
160 const int maxChannels = s_crates * s_modules * s_channels;
161 const int chanBitVecSize = maxChannels / 32;
162
163 SlotData& sd = *m_slotData;
164 std::lock_guard guard (sd.m_mutex);
165
166 if (sd.m_ttData.empty())
167 {
168 const int spareSize = maxChannels - 2 * s_dataSize;
169 const int muonSize = 2 * s_channels;
170 const int modBitVecSize = (s_crates * s_modules) / 32;
171 sd.m_ttData.reserve(s_dataSize);
172 sd.m_ttSpare.reserve(spareSize);
173 sd.m_ttMuon.reserve(muonSize);
174 sd.m_ttPos.resize(maxChannels);
175 sd.m_chanLayer.resize(chanBitVecSize);
176 sd.m_dataChan.resize(chanBitVecSize);
177 sd.m_spareChan.resize(chanBitVecSize);
178 sd.m_muonChan.resize(chanBitVecSize);
179 sd.m_dataMod.resize(modBitVecSize);
180 sd.m_spareMod.resize(modBitVecSize);
181 sd.m_muonMod.resize(modBitVecSize);
182 TriggerTowerMap ttMap;
183 TriggerTowerMap::iterator itt;
184 std::vector<int> dummyS;
185 std::vector<int> dummyL(1);
186 std::vector<int> dummyF(5);
187 int dataCount = 0;
188 int spareCount = 0;
189 for (int crate = 0; crate < s_crates; ++crate)
190 {
191 for (int module = 0; module < s_modules; ++module)
192 {
193 const int index2 = (crate << 4) + module;
194 const int word2 = index2 / 32;
195 const int bit2 = index2 % 32;
196 for (int channel = 0; channel < s_channels; ++channel)
197 {
198 const int index = (crate << 10) + (module << 6) + channel;
199 const int word = index / 32;
200 const int bit = index % 32;
201 double eta = 0.;
202 double phi = 0.;
203 int layer = 0;
204 unsigned int key = 0;
205 if (m_ppmMaps->mapping(crate, module, channel, eta, phi, layer))
206 {
207 // Data channels
208 key = sd.m_towerKey.ttKey(phi, eta);
209 itt = ttMap.find(key);
210 if (itt == ttMap.end())
211 {
213 new (m_sms->allocate<LVL1::TriggerTower>(SegMemSvc::JOB))
215 dummyF, dummyL, dummyF, dummyL, 0, 0, 0,
216 dummyF, dummyL, dummyF, dummyL, 0, 0, 0);
217 sd.m_ttData.push_back(tt);
218 const int count = dataCount++;
219 sd.m_ttPos[index] = count;
220 ttMap.insert(std::make_pair(key, count));
221 }
222 else
223 {
224 sd.m_ttPos[index] = itt->second;
225 }
226 sd.m_chanLayer[word] |= (layer << bit);
227 sd.m_dataChan[word] |= (1 << bit);
228 sd.m_dataMod[word2] |= (1 << bit2);
229 }
230 else
231 {
232 // Spare channels
233 const int pin = channel % 16;
234 const int asic = channel / 16;
235 eta = 16 * crate + module;
236 phi = 4 * pin + asic;
237 layer = 0;
238 const int type = 1;
239 key = (crate << 24) | (type << 20) | (module << 16) | (pin << 8) | asic; // CoolID
241 new (m_sms->allocate<LVL1::TriggerTower>(SegMemSvc::JOB))
243 dummyF, dummyL, dummyF, dummyL, 0, 0, 0,
244 dummyS, dummyS, dummyS, dummyS, 0, 0, 0);
245 sd.m_ttSpare.push_back(tt);
246 sd.m_ttPos[index] = spareCount++;
247 sd.m_chanLayer[word] |= (layer << bit);
248 sd.m_spareChan[word] |= (1 << bit);
249 sd.m_spareMod[word2] |= (1 << bit2);
250 if ((crate == 2 || crate == 3) && (module == 0))
251 {
252 sd.m_ttMuon.push_back(tt);
253 sd.m_muonChan[word] |= (1 << bit);
254 sd.m_muonMod[word2] |= (1 << bit2);
255 }
256 }
257 }
258 }
259 }
260 }
261
262 // Set up according to the collection we want
263
264 TriggerTowerVector &ttCol(dataChannels ? sd.m_ttData
265 : spareChannels
266 ? sd.m_ttSpare
267 : sd.m_ttMuon);
268 TriggerTowerVector &ttColRef(dataChannels ? sd.m_ttData
269 : sd.m_ttSpare);
270 const ChannelBitVector &colChan(dataChannels ? sd.m_dataChan
271 : spareChannels
272 ? sd.m_spareChan
273 : sd.m_muonChan);
274 const ChannelBitVector &colMod(dataChannels ? sd.m_dataMod
275 : spareChannels
276 ? sd.m_spareMod
277 : sd.m_muonMod);
278 const int colSize = dataChannels ? 2 * ttCol.size()
279 : ttCol.size();
280 sd.m_foundChan.assign(chanBitVecSize, 0);
281 int ttCount = 0;
282
283 // Vectors to unpack into
284 std::vector<int> lut;
285 std::vector<int> fadc;
286 std::vector<int> bcidLut;
287 std::vector<int> bcidFadc;
288
289 // Loop over ROB fragments
290
291 int fadcBaseline = m_fadcBaseline;
292
293 int robCount = 0;
294 std::set<uint32_t> dupCheck;
295 ROBIterator rob = robFrags.begin();
296 ROBIterator robEnd = robFrags.end();
297 for (; rob != robEnd; ++rob)
298 {
299
300 if (debug)
301 {
302 ++robCount;
303 msg() << "Treating ROB fragment " << robCount << endmsg;
304 }
305
306 // Skip fragments with ROB status errors
307
308 uint32_t robid = (*rob)->source_id();
309 if ((*rob)->nstatus() > 0)
310 {
311 ROBPointer robData;
312 (*rob)->status(robData);
313 if (*robData != 0)
314 {
315 m_errorTool->robError(robid, *robData);
316 if (debug) msg() << "ROB status error - skipping fragment" << endmsg;
317 continue;
318 }
319 }
320
321 // Skip duplicate fragments
322
323 if (!dupCheck.insert(robid).second)
324 {
326 if (debug) msg() << "Skipping duplicate ROB fragment" << endmsg;
327 continue;
328 }
329
330 // Unpack ROD data (slinks)
331
332 RODPointer payloadBeg;
333 RODPointer payload;
334 RODPointer payloadEnd;
335 (*rob)->rod_data(payloadBeg);
336 payloadEnd = payloadBeg + (*rob)->rod_ndata();
337 payload = payloadBeg;
338 if (payload == payloadEnd)
339 {
340 if (debug) msg() << "ROB fragment empty" << endmsg;
341 continue;
342 }
343
344 // Check identifier
345 const uint32_t sourceID = (*rob)->rod_source_id();
346 if (m_srcIdMap.getRobID(sourceID) != robid ||
347 m_srcIdMap.subDet(sourceID) != m_subDetector ||
348 m_srcIdMap.daqOrRoi(sourceID) != 0 ||
349 m_srcIdMap.slink(sourceID) >= m_slinks ||
350 m_srcIdMap.crate(sourceID) >= s_crates)
351 {
353 if (debug)
354 {
355 msg() << "Wrong source identifier in data: ROD "
356 << MSG::hex << sourceID << " ROB " << robid
357 << MSG::dec << endmsg;
358 }
359 continue;
360 }
361
362 // Check minor version
363 const int minorVersion = (*rob)->rod_version() & 0xffff;
364 if (minorVersion > m_srcIdMap.minorVersionPreLS1())
365 {
366 if (debug) msg() << "Skipping post-LS1 data" << endmsg;
367 continue;
368 }
369 const int rodCrate = m_srcIdMap.crate(sourceID);
370 if (debug)
371 {
372 msg() << "Treating crate " << rodCrate
373 << " slink " << m_srcIdMap.slink(sourceID) << endmsg;
374 }
375
376 // First word should be User Header
377 if ( !L1CaloUserHeader::isValid(*payload) )
378 {
380 if (debug) msg() << "Invalid or missing user header" << endmsg;
381 continue;
382 }
383 L1CaloUserHeader userHeader(*payload);
384 userHeader.setVersion(minorVersion);
385 const int headerWords = userHeader.words();
386 if (headerWords != 1)
387 {
389 if (debug)
390 {
391 msg() << "Unexpected number of user header words: "
392 << headerWords << endmsg;
393 }
394 continue;
395 }
396 for (int i = 0; i < headerWords; ++i) ++payload;
397 // triggered slice offsets
398 const int trigLut = userHeader.ppmLut();
399 const int trigFadc = userHeader.ppmFadc();
400 // FADC baseline lower bound
401 fadcBaseline = userHeader.lowerBound();
402 if (debug)
403 {
404 msg() << "Minor format version number: "
405 << MSG::hex << minorVersion << MSG::dec << endmsg
406 << "LUT triggered slice offset: " << trigLut << endmsg
407 << "FADC triggered slice offset: " << trigFadc << endmsg
408 << "FADC baseline lower bound: " << fadcBaseline << endmsg;
409 }
410 const int runNumber = (*rob)->rod_run_no() & 0xffffff;
411
412 // Find the number of channels per sub-block
413
414 int chanPerSubBlock = 0;
415 bool firstBlock = false;
416 uint32_t firstWord = 0;
417 RODPointer payloadFirst;
418 if (payload != payloadEnd)
419 {
421 || CmmSubBlock::cmmBlock(*payload))
422 {
424 if (debug) msg() << "Missing Sub-block header" << endmsg;
425 continue;
426 }
427 firstBlock = true;
428 firstWord = *payload;
429 if (sd.m_ppmBlocks.empty())
430 {
431 sd.m_ppmBlocks.push_back(new PpmSubBlockV1());
432 }
433 PpmSubBlockV1 *const subBlock = sd.m_ppmBlocks[0];
434 subBlock->clear();
435 payloadFirst = subBlock->read(payload, payloadEnd);
436 chanPerSubBlock = subBlock->channelsPerSubBlock();
437 if (chanPerSubBlock == 0)
438 {
439 m_errorTool->rodError(robid, subBlock->unpackErrorCode());
440 if (debug) msg() << "Unsupported version/data format: "
441 << subBlock->version() << "/"
442 << subBlock->format() << endmsg;
443 continue;
444 }
445 if (debug) msg() << "Channels per sub-block: "
446 << chanPerSubBlock << endmsg;
447 }
448 else
449 {
450 if (debug) msg() << "ROB fragment contains user header only" << endmsg;
451 continue;
452 }
453 const int numSubBlocks = s_channels / chanPerSubBlock;
454 const int size = sd.m_ppmBlocks.size();
455 if (numSubBlocks > size)
456 {
457 for (int i = size; i < numSubBlocks; ++i)
458 {
459 sd.m_ppmBlocks.push_back(new PpmSubBlockV1());
460 }
461 }
462
463 // Loop over PPMs
464
465 payload = payloadBeg;
466 for (int i = 0; i < headerWords; ++i) ++payload;
467 unsigned int rodErr = L1CaloSubBlock::ERROR_NONE;
468 while (payload != payloadEnd)
469 {
470
471 // Get all sub-blocks for one PPM (first already read in above)
472
473 int crate = 0;
474 int module = 0;
475 int nPpmBlocks = 0;
476 for (int block = 0; block < numSubBlocks; ++block)
477 {
478 const uint32_t word = (firstBlock) ? firstWord : *payload;
480 || CmmSubBlock::cmmBlock(word)
482 {
483 if (debug) msg() << "Unexpected data sequence" << endmsg;
485 break;
486 }
487 if (chanPerSubBlock != s_channels &&
488 L1CaloSubBlock::seqno(word) != block * chanPerSubBlock)
489 {
490 if (debug)
491 {
492 msg() << "Unexpected channel sequence number: "
493 << L1CaloSubBlock::seqno(word) << " expected "
494 << block *chanPerSubBlock << endmsg;
495 }
497 break;
498 }
499 PpmSubBlockV1 *const subBlock = sd.m_ppmBlocks[block];
500 nPpmBlocks++;
501 if (firstBlock)
502 {
503 payload = payloadFirst;
504 firstBlock = false;
505 }
506 else
507 {
508 subBlock->clear();
509 payload = subBlock->read(payload, payloadEnd);
510 }
511 if (block == 0)
512 {
513 crate = subBlock->crate();
514 module = subBlock->module();
515 if (debug)
516 {
517 msg() << "Crate " << crate << " Module " << module << endmsg;
518 }
519 if (crate != rodCrate)
520 {
521 if (debug)
522 {
523 msg() << "Inconsistent crate number in ROD source ID" << endmsg;
524 }
526 break;
527 }
528 }
529 else
530 {
531 if (subBlock->crate() != crate)
532 {
533 if (debug) msg() << "Inconsistent crate number in sub-blocks"
534 << endmsg;
536 break;
537 }
538 if (subBlock->module() != module)
539 {
540 if (debug) msg() << "Inconsistent module number in sub-blocks"
541 << endmsg;
543 break;
544 }
545 }
546 if (payload == payloadEnd && block != numSubBlocks - 1)
547 {
548 if (debug) msg() << "Premature end of data" << endmsg;
550 break;
551 }
552 }
553 if (rodErr != L1CaloSubBlock::ERROR_NONE) break;
554
555 // Is there an error block?
556
557 bool isErrBlock = false;
558 if (payload != payloadEnd)
559 {
561 && !CmmSubBlock::cmmBlock(*payload)
562 && PpmSubBlockV1::errorBlock(*payload))
563 {
564 if (debug) msg() << "Error block found" << endmsg;
565 sd.m_errorBlock.clear();
566 isErrBlock = true;
567 payload = sd.m_errorBlock.read(payload, payloadEnd);
568 if (sd.m_errorBlock.crate() != crate)
569 {
570 if (debug) msg() << "Inconsistent crate number in error block"
571 << endmsg;
573 break;
574 }
575 if (sd.m_errorBlock.module() != module)
576 {
577 if (debug) msg() << "Inconsistent module number in error block"
578 << endmsg;
580 break;
581 }
582 if (sd.m_errorBlock.dataWords() && !sd.m_errorBlock.unpack())
583 {
584 if (debug)
585 {
586 std::string errMsg(sd.m_errorBlock.unpackErrorMsg());
587 msg() << "Unpacking error block failed: " << errMsg << endmsg;
588 }
589 rodErr = sd.m_errorBlock.unpackErrorCode();
590 break;
591 }
592 }
593 }
594
595 // Don't bother unpacking modules that aren't used for required collection
596
597 const int index2 = (crate << 4) + module;
598 const int word2 = index2 / 32;
599 const int bit2 = index2 % 32;
600 if (!((colMod[word2] >> bit2) & 1)) continue;
601
602 // Loop over sub-blocks and fill trigger towers
603
604 for (int block = 0; block < nPpmBlocks; ++block)
605 {
606 PpmSubBlockV1 *const subBlock = sd.m_ppmBlocks[block];
607 subBlock->setLutOffset(trigLut);
608 subBlock->setFadcOffset(trigFadc);
609 subBlock->setPedestal(m_pedestal);
610 subBlock->setFadcBaseline(fadcBaseline);
611 subBlock->setRunNumber(runNumber);
612 if (debug)
613 {
614 msg() << "Unpacking sub-block version/format/seqno: "
615 << subBlock->version() << "/" << subBlock->format() << "/"
616 << subBlock->seqno() << endmsg;
617 }
618 if (subBlock->dataWords() && !subBlock->unpack())
619 {
620 if (debug)
621 {
622 std::string errMsg(subBlock->unpackErrorMsg());
623 msg() << "Unpacking PPM sub-block failed: " << errMsg << endmsg;
624 }
625 rodErr = subBlock->unpackErrorCode();
626 break;
627 }
628 if (m_printCompStats) addCompStats(subBlock->compStats());
629 for (int chan = 0; chan < chanPerSubBlock; ++chan)
630 {
631 const int channel = block * chanPerSubBlock + chan;
632 const int index = (crate << 10) + (module << 6) + channel;
633 const int word = index / 32;
634 const int bit = index % 32;
635 if (!((colChan[word] >> bit) & 1)) continue; // skip unwanted channels
636 if (((sd.m_foundChan[word] >> bit) & 1))
637 {
638 if (debug) msg() << "Duplicate data for crate/module/channel: "
639 << crate << "/" << module << "/" << channel
640 << endmsg;
642 break;
643 }
644 lut.clear();
645 fadc.clear();
646 bcidLut.clear();
647 bcidFadc.clear();
648 subBlock->ppmData(channel, lut, fadc, bcidLut, bcidFadc);
649 if (lut.size() < size_t(trigLut + 1))
650 {
651 if (debug)
652 {
653 msg() << "Triggered LUT slice from header "
654 << "inconsistent with number of slices: "
655 << trigLut << ", " << lut.size() << endmsg;
656 }
658 break;
659 }
660 if (fadc.size() < size_t(trigFadc + 1))
661 {
662 if (debug)
663 {
664 msg() << "Triggered FADC slice from header "
665 << "inconsistent with number of slices: "
666 << trigFadc << ", " << fadc.size() << endmsg;
667 }
669 break;
670 }
671 LVL1::DataError errorBits(0);
672 if (isErrBlock)
673 {
675 sd.m_errorBlock.ppmError(channel));
677 sd.m_errorBlock.subStatus());
678 }
679 else
680 {
682 subBlock->ppmError(channel));
683 const PpmSubBlockV1 *const lastBlock =
684 sd.m_ppmBlocks[nPpmBlocks - 1];
686 lastBlock->subStatus());
687 }
688 // Wrong bit set for compressed formats 1.01 to 1.03
689 if (subBlock->format() > 1 && subBlock->seqno() < 4)
690 {
692 (errorBits.error() >> (LVL1::DataError::ModuleError + 1)) & 0x1);
693 }
694 const int error = errorBits.error();
695
696 // Save to TriggerTower
697
698 if (verbose)
699 {
700 msg(MSG::VERBOSE) << "channel/LUT/FADC/bcidLUT/bcidFADC/error: "
701 << channel << "/";
702 printVec(lut);
703 printVec(fadc);
704 printVec(bcidLut);
705 printVec(bcidFadc);
706 msg() << MSG::hex << error << MSG::dec << "/";
707 }
708 sd.m_foundChan[word] |= (1 << bit);
709 ++ttCount;
710 LVL1::TriggerTower *tt = ttColRef[sd.m_ttPos[index]];
711 const int layer = ((sd.m_chanLayer[word] >> bit) & 1);
712 if (layer == 0) // EM
713 {
714 tt->addEM(fadc, lut, bcidFadc, bcidLut, error, trigLut, trigFadc);
715 }
716 else // Had
717 {
718 tt->addHad(fadc, lut, bcidFadc, bcidLut, error, trigLut, trigFadc);
719 }
720 }
721 if (rodErr != L1CaloSubBlock::ERROR_NONE) break;
722 }
723 if (rodErr != L1CaloSubBlock::ERROR_NONE) break;
724 }
725 if (rodErr != L1CaloSubBlock::ERROR_NONE)
726 m_errorTool->rodError(robid, rodErr);
727 }
728
729 // Reset any missing channels (should be rare)
730
731 if (ttCount != colSize)
732 {
733 if (debug)
734 {
735 msg() << "Found " << ttCount << " channels, expected " << colSize << endmsg;
736 }
737 std::vector<int> dummy(1);
738 for (int word = 0; word < chanBitVecSize; ++word)
739 {
740 if (sd.m_foundChan[word] != colChan[word])
741 {
742 for (int bit = 0; bit < 32; ++bit)
743 {
744 if (((sd.m_foundChan[word] >> bit) & 1) != ((colChan[word] >> bit) & 1))
745 {
746 const int index = word * 32 + bit;
747 LVL1::TriggerTower *tt = ttColRef[sd.m_ttPos[index]];
748 const int layer = ((sd.m_chanLayer[word] >> bit) & 1);
749 if (layer == 0) // EM
750 {
751 tt->addEM(dummy, dummy, dummy, dummy, 0, 0, 0);
752 }
753 else if (dataChannels) // Had
754 {
755 tt->addHad(dummy, dummy, dummy, dummy, 0, 0, 0);
756 }
757 }
758 }
759 }
760 }
761 }
762
763 // And copy into output collection
764
765 if (m_zeroSuppress)
766 {
767 TriggerTowerVector::iterator itr = ttCol.begin();
768 TriggerTowerVector::iterator itrE = ttCol.end();
769 for (; itr != itrE; ++itr)
770 {
771 if ((*itr)->emEnergy() || (dataChannels && (*itr)->hadEnergy()))
772 {
773 ttCollection->push_back(*itr);
774 }
775 }
776 }
777 else
778 {
779 ttCollection->assign(ttCol.begin(), ttCol.end());
780 }
781
782 return StatusCode::SUCCESS;
783}
784
785// Conversion of trigger towers to bytestream
786
788 const DataVector<LVL1::TriggerTower> *const ttCollection,
789 RawEventWrite *const re) const
790{
791 const bool debug = msgLvl(MSG::DEBUG);
792 if (debug) msg(MSG::DEBUG);
793
794 // Clear the event assembler
796 fea.clear();
797 const uint16_t minorVersion = m_srcIdMap.minorVersionPreLS1();
798 fea.setRodMinorVersion(minorVersion);
799
800 // Pointer to ROD data vector
801
803
804 LVL1::TriggerTowerKey towerKey;
805
806 // Set up trigger tower maps
807
808 // Trigger tower map for conversion EM to bytestream
809 TriggerTowerMapConst ttEmMap;
810 // Trigger tower map for conversion Had to bytestream
811 TriggerTowerMapConst ttHadMap;
812 setupTTMaps(ttCollection, ttEmMap, ttHadMap, towerKey);
813
814 // Create the sub-blocks to do the packing
815
816 PpmSubBlockV1 subBlock;
817 const int chanPerSubBlock = subBlock.channelsPerSubBlock(m_version,
819 if (chanPerSubBlock == 0)
820 {
821 msg(MSG::ERROR) << "Unsupported version/data format: "
822 << m_version << "/" << m_dataFormat << endmsg;
823 return StatusCode::FAILURE;
824 }
825 PpmSubBlockV1 errorBlock;
826
827 int slicesLut = 1;
828 int slicesFadc = 1;
829 int trigLut = 0;
830 int trigFadc = 0;
831 int slicesLutNew = 1;
832 int slicesFadcNew = 1;
833 int trigLutNew = 0;
834 int trigFadcNew = 0;
835 const int modulesPerSlink = s_modules / m_slinks;
836 for (int crate = m_crateMin; crate <= m_crateMax; ++crate)
837 {
838 for (int module = 0; module < s_modules; ++module)
839 {
840
841 // Pack required number of modules per slink
842
843 if (module % modulesPerSlink == 0)
844 {
845 const int daqOrRoi = 0;
846 const int slink = module / modulesPerSlink;
847 if (debug)
848 {
849 msg() << "Treating crate " << crate << " slink " << slink << endmsg;
850 }
851 // Get number of slices and triggered slice offsets
852 // for this slink
853 if ( ! slinkSlices(crate, module, modulesPerSlink,
854 slicesLut, slicesFadc, trigLut, trigFadc,
855 ttEmMap, ttHadMap,
856 towerKey))
857 {
858 msg(MSG::ERROR) << "Inconsistent number of slices or "
859 << "triggered slice offsets in data for crate "
860 << crate << " slink " << slink << endmsg;
861 return StatusCode::FAILURE;
862 }
863 slicesLutNew = (m_forceSlicesLut) ? m_forceSlicesLut : slicesLut;
864 slicesFadcNew = (m_forceSlicesFadc) ? m_forceSlicesFadc : slicesFadc;
865 trigLutNew = ModifySlices::peak(trigLut, slicesLut, slicesLutNew);
866 trigFadcNew = ModifySlices::peak(trigFadc, slicesFadc, slicesFadcNew);
867 if (debug)
868 {
869 msg() << "Data Version/Format: " << m_version
870 << " " << m_dataFormat << endmsg
871 << "LUT slices/offset: " << slicesLut << " " << trigLut;
872 if (slicesLut != slicesLutNew)
873 {
874 msg() << " modified to " << slicesLutNew << " " << trigLutNew;
875 }
876 msg() << endmsg
877 << "FADC slices/offset: " << slicesFadc << " " << trigFadc;
878 if (slicesFadc != slicesFadcNew)
879 {
880 msg() << " modified to " << slicesFadcNew << " " << trigFadcNew;
881 }
882 msg() << endmsg;
883 }
884 L1CaloUserHeader userHeader;
885 userHeader.setPpmLut(trigLutNew);
886 userHeader.setPpmFadc(trigFadcNew);
887 userHeader.setLowerBound(m_fadcBaseline);
888 const uint32_t rodIdPpm = m_srcIdMap.getRodID(crate, slink, daqOrRoi,
890 theROD = fea.getRodData(rodIdPpm);
891 theROD->push_back(userHeader.header());
892 }
893 if (debug) msg() << "Module " << module << endmsg;
894
895 // Find trigger towers corresponding to each eta/phi pair and fill
896 // sub-blocks
897
898 bool upstreamError = false;
899 for (int channel = 0; channel < s_channels; ++channel)
900 {
901 const int chan = channel % chanPerSubBlock;
902 if (channel == 0 && m_dataFormat == L1CaloSubBlock::UNCOMPRESSED)
903 {
904 errorBlock.clear();
905 errorBlock.setPpmErrorHeader(m_version, m_dataFormat, crate,
906 module, slicesFadcNew, slicesLutNew);
907 }
908 if (chan == 0)
909 {
910 subBlock.clear();
912 {
914 module, slicesFadcNew, slicesLutNew);
915 }
916 else
917 {
918 subBlock.setPpmHeader(m_version, m_dataFormat, channel, crate,
919 module, slicesFadcNew, slicesLutNew);
920 }
921 subBlock.setLutOffset(trigLutNew);
922 subBlock.setFadcOffset(trigFadcNew);
925 }
926 const LVL1::TriggerTower *tt = 0;
927 double eta = 0.;
928 double phi = 0.;
929 int layer = 0;
930 if (m_ppmMaps->mapping(crate, module, channel, eta, phi, layer))
931 {
932 tt = findLayerTriggerTower(eta, phi, layer, ttEmMap, ttHadMap, towerKey);
933 }
934 if (tt )
935 {
936 int err = 0;
937 std::vector<int> lut;
938 std::vector<int> fadc;
939 std::vector<int> bcidLut;
940 std::vector<int> bcidFadc;
941 if (layer == 0) // em
942 {
943 ModifySlices::data(tt->emLUT(), lut, slicesLutNew);
944 ModifySlices::data(tt->emADC(), fadc, slicesFadcNew);
945 ModifySlices::data(tt->emBCIDvec(), bcidLut, slicesLutNew);
946 ModifySlices::data(tt->emBCIDext(), bcidFadc, slicesFadcNew);
947 err = tt->emError();
948 }
949 else // had
950 {
951 ModifySlices::data(tt->hadLUT(), lut, slicesLutNew);
952 ModifySlices::data(tt->hadADC(), fadc, slicesFadcNew);
953 ModifySlices::data(tt->hadBCIDvec(), bcidLut, slicesLutNew);
954 ModifySlices::data(tt->hadBCIDext(), bcidFadc, slicesFadcNew);
955 err = tt->hadError();
956 }
957 subBlock.fillPpmData(channel, lut, fadc, bcidLut, bcidFadc);
958 if (err)
959 {
960 const LVL1::DataError errorBits(err);
961 const int errpp = errorBits.get(LVL1::DataError::PPMErrorWord);
963 {
964 errorBlock.fillPpmError(channel, errpp);
965 }
966 else subBlock.fillPpmError(channel, errpp);
967 if (errpp >> 2) upstreamError = true;
968 }
969 }
970 if (chan == chanPerSubBlock - 1)
971 {
972 // output the packed sub-block
973 if ( !subBlock.pack())
974 {
975 msg(MSG::ERROR) << "PPM sub-block packing failed" << endmsg;
976 return StatusCode::FAILURE;
977 }
978 if (m_printCompStats) addCompStats(subBlock.compStats());
979 if (channel != s_channels - 1)
980 {
981 // Only put errors in last sub-block
982 subBlock.setStatus(0, false, false, false, false,
983 false, false, false);
984 if (debug)
985 {
986 msg() << "PPM sub-block data words: "
987 << subBlock.dataWords() << endmsg;
988 }
989 subBlock.write(theROD);
990 }
991 else
992 {
993 // Last sub-block - write error block
994 bool glinkTimeout = false;
995 bool daqOverflow = false;
996 bool bcnMismatch = false;
997 bool glinkParity = false;
999 {
1000 glinkTimeout = errorBlock.mcmAbsent() ||
1001 errorBlock.timeout();
1002 daqOverflow = errorBlock.asicFull() ||
1003 errorBlock.fpgaCorrupt();
1004 bcnMismatch = errorBlock.eventMismatch() ||
1005 errorBlock.bunchMismatch();
1006 glinkParity = errorBlock.glinkPinParity();
1007 }
1008 else
1009 {
1010 glinkTimeout = subBlock.mcmAbsent() ||
1011 subBlock.timeout();
1012 daqOverflow = subBlock.asicFull() ||
1013 subBlock.fpgaCorrupt();
1014 bcnMismatch = subBlock.eventMismatch() ||
1015 subBlock.bunchMismatch();
1016 glinkParity = subBlock.glinkPinParity();
1017 }
1018 subBlock.setStatus(0, glinkTimeout, false, upstreamError,
1019 daqOverflow, bcnMismatch, false, glinkParity);
1020 if (debug)
1021 {
1022 msg() << "PPM sub-block data words: "
1023 << subBlock.dataWords() << endmsg;
1024 }
1025 subBlock.write(theROD);
1026 // Only uncompressed format has a separate error block
1028 {
1029 if ( ! errorBlock.pack())
1030 {
1031 msg(MSG::ERROR) << "PPM error block packing failed" << endmsg;
1032 return StatusCode::FAILURE;
1033 }
1034 errorBlock.setStatus(0, glinkTimeout, false, upstreamError,
1035 daqOverflow, bcnMismatch, false, glinkParity);
1036 errorBlock.write(theROD);
1037 if (debug)
1038 {
1039 msg() << "PPM error block data words: "
1040 << errorBlock.dataWords() << endmsg;
1041 }
1042 }
1043 }
1044 }
1045 }
1046 }
1047 }
1048
1049 // Fill the raw event
1050
1051 fea.fill(re, msg());
1052
1053 return StatusCode::SUCCESS;
1054}
1055
1056// Add compression stats to totals
1057
1058void PpmByteStreamV1Tool::addCompStats(const std::vector<uint32_t> &stats) const
1059{
1060 if (stats.empty()) return;
1061 const int n = std::min (stats.size(), static_cast<size_t>(MAXFORMATS));
1062 for (int i = 0; i < n; ++i) {
1063 std::atomic<uint32_t>& stat ATLAS_THREAD_SAFE =
1064 const_cast<std::atomic<uint32_t>&> (m_compStats[i]);
1065 stat += stats[i];
1066 }
1067}
1068
1069// Print compression stats
1070
1072{
1073 msg() << "Compression stats format/count: ";
1074 for (unsigned int i = 0; i < MAXFORMATS; ++i)
1075 {
1076 msg() << " " << i << "/" << m_compStats[i];
1077 }
1078 msg() << endmsg;
1079}
1080
1081// Find a trigger tower using separate layer maps
1082
1084 const double eta, const double phi, const int layer,
1085 const TriggerTowerMapConst& ttEmMap,
1086 const TriggerTowerMapConst& ttHadMap,
1087 LVL1::TriggerTowerKey& towerKey) const
1088{
1089 const LVL1::TriggerTower *tt = 0;
1090 const unsigned int key = towerKey.ttKey(phi, eta);
1091 TriggerTowerMapConst::const_iterator mapIter;
1092 if (layer == 0)
1093 {
1094 mapIter = ttEmMap.find(key);
1095 if (mapIter != ttEmMap.end()) tt = mapIter->second;
1096 }
1097 else
1098 {
1099 mapIter = ttHadMap.find(key);
1100 if (mapIter != ttHadMap.end()) tt = mapIter->second;
1101 }
1102 return tt;
1103}
1104
1105// Set up trigger tower maps
1106
1108 const ttCollection,
1109 TriggerTowerMapConst& ttEmMap,
1110 TriggerTowerMapConst& ttHadMap,
1111 LVL1::TriggerTowerKey& towerKey) const
1112{
1113 using std::accumulate;
1114
1115 ttEmMap.clear();
1116 ttHadMap.clear();
1117 TriggerTowerCollection::const_iterator pos = ttCollection->begin();
1118 TriggerTowerCollection::const_iterator pose = ttCollection->end();
1119 for (; pos != pose; ++pos)
1120 {
1121 const LVL1::TriggerTower *tt = *pos;
1122 const unsigned int key = towerKey.ttKey(tt->phi(), tt->eta());
1123 // Ignore any with zero data
1124 // EM
1125 if (accumulate((tt->emLUT()).begin(), (tt->emLUT()).end(), 0) ||
1126 accumulate((tt->emADC()).begin(), (tt->emADC()).end(), 0) ||
1127 accumulate((tt->emBCIDvec()).begin(), (tt->emBCIDvec()).end(), 0) ||
1128 accumulate((tt->emBCIDext()).begin(), (tt->emBCIDext()).end(), 0) ||
1129 tt->emError())
1130 {
1131 ttEmMap.insert(std::make_pair(key, tt));
1132 }
1133 // Had
1134 if (accumulate((tt->hadLUT()).begin(), (tt->hadLUT()).end(), 0) ||
1135 accumulate((tt->hadADC()).begin(), (tt->hadADC()).end(), 0) ||
1136 accumulate((tt->hadBCIDvec()).begin(), (tt->hadBCIDvec()).end(), 0) ||
1137 accumulate((tt->hadBCIDext()).begin(), (tt->hadBCIDext()).end(), 0) ||
1138 tt->hadError())
1139 {
1140 ttHadMap.insert(std::make_pair(key, tt));
1141 }
1142 }
1143}
1144
1145// Get number of slices and triggered slice offsets for next slink
1146
1147bool PpmByteStreamV1Tool::slinkSlices(const int crate, const int module,
1148 const int modulesPerSlink, int &slicesLut, int &slicesFadc,
1149 int &trigLut, int &trigFadc,
1150 const TriggerTowerMapConst& ttEmMap,
1151 const TriggerTowerMapConst& ttHadMap,
1152 LVL1::TriggerTowerKey& towerKey) const
1153{
1154 int sliceL = -1;
1155 int sliceF = m_dfltSlicesFadc;
1156 int trigL = m_dfltSlicesLut / 2;
1157 int trigF = m_dfltSlicesFadc / 2;
1158 for (int mod = module; mod < module + modulesPerSlink; ++mod)
1159 {
1160 for (int chan = 0; chan < s_channels; ++chan)
1161 {
1162 double eta = 0.;
1163 double phi = 0.;
1164 int layer = 0;
1165 if (!m_ppmMaps->mapping(crate, mod, chan,
1166 eta, phi, layer)) continue;
1167 const LVL1::TriggerTower *const tt = findLayerTriggerTower(
1168 eta, phi, layer, ttEmMap, ttHadMap,
1169 towerKey);
1170 if ( !tt ) continue;
1171 if (layer == 0)
1172 {
1173 if (sliceL < 0) // initialise
1174 {
1175 sliceL = (tt->emLUT()).size();
1176 sliceF = (tt->emADC()).size();
1177 trigL = tt->emPeak();
1178 trigF = tt->emADCPeak();
1179 }
1180 else // check consistent
1181 {
1182 if ((tt->emLUT()).size() != size_t(sliceL) ||
1183 (tt->emADC()).size() != size_t(sliceF) ||
1184 tt->emPeak() != trigL || tt->emADCPeak() != trigF)
1185 {
1186 return false;
1187 }
1188 }
1189 }
1190 else
1191 {
1192 if (sliceL < 0)
1193 {
1194 sliceL = (tt->hadLUT()).size();
1195 sliceF = (tt->hadADC()).size();
1196 trigL = tt->hadPeak();
1197 trigF = tt->hadADCPeak();
1198 }
1199 else
1200 {
1201 if ((tt->hadLUT()).size() != size_t(sliceL) ||
1202 (tt->hadADC()).size() != size_t(sliceF) ||
1203 tt->hadPeak() != trigL || tt->hadADCPeak() != trigF)
1204 {
1205 return false;
1206 }
1207 }
1208 }
1209 }
1210 }
1211 if (sliceL < 0) sliceL = m_dfltSlicesLut;
1212 slicesLut = sliceL;
1213 slicesFadc = sliceF;
1214 trigLut = trigL;
1215 trigFadc = trigF;
1216 return true;
1217}
1218
1219// Return reference to vector with all possible Source Identifiers
1220
1221std::vector<uint32_t>
1222PpmByteStreamV1Tool::makeSourceIDs (bool spareChannels, bool muonChannels) const
1223{
1224 std::vector<uint32_t> robIds;
1225
1226 if (!spareChannels && !muonChannels) {
1227 robIds = m_sourceIDsProp;
1228 }
1229
1230 if (robIds.empty()) {
1231 const int maxlinks = m_srcIdMap.maxSlinks();
1232 for (int crate = 0; crate < s_crates; ++crate)
1233 {
1234 for (int slink = 0; slink < maxlinks; ++slink)
1235 {
1236 const int daqOrRoi = 0;
1237 const uint32_t rodId = m_srcIdMap.getRodID(crate, slink, daqOrRoi,
1239 const uint32_t robId = m_srcIdMap.getRobID(rodId);
1240
1241 if (spareChannels && !(crate > 1 && crate < 6)) {
1242 continue;
1243 }
1244
1245 if (muonChannels && !(crate > 1 && crate < 4 && slink == 0)) {
1246 continue;
1247 }
1248
1249 robIds.push_back (robId);
1250 }
1251 }
1252 }
1253 return robIds;
1254}
1255
1256const std::vector<uint32_t> &PpmByteStreamV1Tool::sourceIDs(
1257 const std::string &sgKey) const
1258{
1259 // Check if spare channels wanted
1260 const std::string flag("Spare");
1261 const std::string::size_type pos = sgKey.find(flag);
1262 bool spareChannels =
1263 (pos != std::string::npos && pos == (sgKey.length() - flag.length()));
1264 // Check if Tile Muon channels wanted
1265 const std::string flag2("Muon");
1266 const std::string::size_type pos2 = sgKey.find(flag2);
1267 bool muonChannels =
1268 (pos2 != std::string::npos && pos2 == (sgKey.length() - flag2.length()));
1269
1270 if (spareChannels) {
1271 static const std::vector<uint32_t> sourceIDsSpare =
1272 makeSourceIDs (true, false);
1273 return sourceIDsSpare;
1274 }
1275
1276 if (muonChannels) {
1277 static const std::vector<uint32_t> sourceIDsMuon =
1278 makeSourceIDs (false, true);
1279 return sourceIDsMuon;
1280 }
1281
1282 static const std::vector<uint32_t> sourceIDs =
1283 makeSourceIDs (false, false);
1284 return sourceIDs;
1285}
1286
1287// Print a vector
1288
1289void PpmByteStreamV1Tool::printVec(const std::vector<int> &vec) const
1290{
1291 std::vector<int>::const_iterator pos;
1292 for (pos = vec.begin(); pos != vec.end(); ++pos)
1293 {
1294 if (pos != vec.begin()) msg() << ",";
1295 msg() << *pos;
1296 }
1297 msg() << "/";
1298}
1299
1300
1301} // end namespace
const boost::regex re(r_e)
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
std::vector< size_t > vec
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
const bool debug
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::FullEventFragment RawEventWrite
data type for writing raw event
Definition RawEvent.h:39
Define macros for attributes used to control the static checker.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
value_type push_back(value_type pElem)
Add an element to the end of the collection.
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
void assign(InputIterator first, InputIterator last)
Assign from iterators.
Template class for assembling a full atlas raw event from subfragments.
void setRodMinorVersion(uint16_t m)
change the ROD minor version
void clear()
Clear internal stack.
void fill(RawEventWrite *re, MsgStream &log)
Fill the FullEventFragment with all the ROD data stored in this.
std::vector< uint32_t > RODDATA
ROD data as a vector of unsigned int.
RODDATA * getRodData(uint32_t id)
get a block of ROD data
std::vector< const ROBF * > VROBFRAG
static bool cmmBlock(uint32_t word)
Determine if header word corresponds to CMM.
void setStatus(uint32_t failingBCN, bool glinkTimeout, bool glinkDown, bool upstreamError, bool daqOverflow, bool bcnMismatch, bool glinkProtocol, bool glinkParity)
Store error status trailer.
int unpackErrorCode() const
Return the unpacking error code.
uint32_t subStatus() const
Return Sub-status word.
int dataWords() const
Return number of data words.
static SubBlockWordType wordType(uint32_t word)
Word identification.
void write(FullEventAssembler< L1CaloSrcIdMap >::RODDATA *theROD) const
Output complete packed sub-block to ROD vector.
std::string unpackErrorMsg() const
Return the unpacking error message for printing.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType read(const OFFLINE_FRAGMENTS_NAMESPACE::PointerType beg, const OFFLINE_FRAGMENTS_NAMESPACE::PointerType end)
Input complete packed sub-block from ROD array.
L1Calo User Header class.
static bool isValid(uint32_t word)
Test for valid header word.
void setVersion(int minorVersion)
Set version flag.
int lowerBound() const
Return FADC lower bound.
int words() const
Return number of header words (should be one)
uint32_t header() const
Return packed header.
void setLowerBound(int bound)
Set FADC lower bound.
static void data(const std::vector< int > &oldVec, std::vector< int > &newVec, int newSlices)
Return modified data vector<int>
static int peak(int oldPeak, int oldSlices, int newSlices)
Return new triggered slice offset.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType RODPointer
int m_crateMax
Property: Maximum crate number when writing out bytestream.
const eformat::SubDetector m_subDetector
Sub-detector type.
static constexpr unsigned int MAXFORMATS
Vector for compression statistics.
std::vector< uint32_t > ChannelBitVector
int m_dataFormat
Property: Data compression format.
int m_crateMin
Property: Minimum crate number when writing out bytestream.
virtual StatusCode initialize() override
const std::vector< uint32_t > & sourceIDs(const std::string &sgKey) const
Return reference to vector with all possible Source Identifiers.
int m_pedestal
Property: Pedestal value.
int m_fadcBaseline
Property: FADC baseline lower bound.
int m_dfltSlicesFadc
Property: Default number of FADC slices in simulation.
std::vector< LVL1::TriggerTower * > TriggerTowerVector
void setupTTMaps(const TriggerTowerCollection *ttCollection, TriggerTowerMapConst &ttEmMap, TriggerTowerMapConst &ttHadMap, LVL1::TriggerTowerKey &towerKey) const
Set up separate Em and Had trigger tower maps.
void printCompStats() const
Print compression stats.
const LVL1::TriggerTower * findLayerTriggerTower(double eta, double phi, int layer, const TriggerTowerMapConst &ttEmMap, const TriggerTowerMapConst &ttHadMap, LVL1::TriggerTowerKey &towerKey) const
Find a trigger tower using separate layer maps.
static const InterfaceID & interfaceID()
AlgTool InterfaceID.
int m_fadcThreshold
Property: FADC threshold for super-compressed format.
std::map< unsigned int, int > TriggerTowerMap
int m_slinks
Property: Number of slinks per crate when writing out bytestream.
const int m_version
Sub_block header version.
std::vector< uint32_t > makeSourceIDs(bool spareChannels, bool muonChannels) const
ToolHandle< LVL1BS::L1CaloErrorByteStreamTool > m_errorTool
Property: Error collection tool.
int m_forceSlicesLut
Property: Force number of LUT slices in bytestream.
int m_dfltSlicesLut
Property: Default number of LUT slices in simulation.
void printVec(const std::vector< int > &vec) const
Print a vector.
int m_forceSlicesFadc
Property: Force number of FADC slices in bytestream.
ServiceHandle< SegMemSvc > m_sms
Memory pool service.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType ROBPointer
int m_zeroSuppress
Property: Zero suppression on input.
SG::SlotSpecificObj< SlotData > m_slotData ATLAS_THREAD_SAFE
std::vector< uint32_t > m_sourceIDsProp
Property: ROB source IDs.
const L1CaloSrcIdMap m_srcIdMap
Source ID converter.
int m_printCompStats
Property: Compression statistics print flag.
bool slinkSlices(int crate, int module, int modulesPerSlink, int &slicesLut, int &slicesFadc, int &trigLut, int &trigFadc, const TriggerTowerMapConst &ttEmMap, const TriggerTowerMapConst &ttHadMap, LVL1::TriggerTowerKey &towerKey) const
Get number of slices and triggered slice offsets for next slink.
PpmByteStreamV1Tool(const std::string &type, const std::string &name, const IInterface *parent)
std::map< unsigned int, const LVL1::TriggerTower * > TriggerTowerMapConst
StatusCode convert(const std::string &sgKey, const IROBDataProviderSvc::VROBFRAG &robFrags, DataVector< LVL1::TriggerTower > *ttCollection) const
Convert ROB fragments to trigger towers.
void addCompStats(const std::vector< uint32_t > &stats) const
Add compression stats to totals.
ToolHandle< LVL1::IL1CaloMappingTool > m_ppmMaps
Property: Channel mapping tool.
const int m_compVers
Compression version.
DataVector< LVL1::TriggerTower > TriggerTowerCollection
std::atomic< uint32_t > m_compStats[MAXFORMATS]
virtual StatusCode finalize() override
IROBDataProviderSvc::VROBFRAG::const_iterator ROBIterator
Sub-Block class for PPM data.
void clear()
Clear all data.
void setFadcOffset(int offset)
void setPpmErrorHeader(int version, int format, int crate, int module, int slicesFadc, int slicesLut)
Store PPM error block header.
const std::vector< uint32_t > & compStats() const
Return reference to compression stats.
static bool errorBlock(uint32_t word)
Check if a header word is for an error block.
void setPedestal(int pedval)
bool timeout(int chan) const
bool bunchMismatch(int chan) const
int ppmError(int chan) const
Return the error word for a data channel.
int channelsPerSubBlock(int version, int format)
Return the number of channels per sub-block.
bool glinkPinParity(int chan) const
void setRunNumber(int run)
bool pack()
Pack data.
bool eventMismatch(int chan) const
void setPpmHeader(int version, int format, int seqno, int crate, int module, int slicesFadc, int slicesLut)
Store PPM header.
void fillPpmData(int chan, const std::vector< int > &lut, const std::vector< int > &fadc, const std::vector< int > &bcidLut, const std::vector< int > &bcidFadc)
Store PPM data for later packing.
void setFadcThreshold(int threshold)
void ppmData(int chan, std::vector< int > &lut, std::vector< int > &fadc, std::vector< int > &bcidLut, std::vector< int > &bcidFadc)
Return unpacked data for given channel.
void fillPpmError(int chan, int errorWord)
Store an error word corresponding to a data channel.
void setFadcBaseline(int baseline)
bool asicFull(int chan) const
void setLutOffset(int offset)
bool mcmAbsent(int chan) const
bool unpack()
Unpack data.
bool fpgaCorrupt(int chan) const
Error data.
Definition DataError.h:27
int error() const
Return the full error word.
Definition DataError.h:78
void set(ErrorBit bit, int value=1)
Set an error bit or data.
Definition DataError.cxx:28
int get(ErrorBit bit) const
Return an error bit or data.
Definition DataError.cxx:48
The TriggerTowerKey object provides the key for each trigger tower depending on its eta-phi coords.
virtual unsigned int ttKey(const TriggerTower &tower)
returns the key of the passed tower
Trigger towers are the inputs to all other parts of the calorimeter trigger.
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
bool verbose
Definition hcg.cxx:73
static const InterfaceID IID_IPpmByteStreamV1Tool("PpmByteStreamV1Tool", 1, 1)
Definition index.py:1