ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_RodDecoder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "SCT_RodDecoder.h"
6
11
13
14#include <algorithm>
15#include <array>
16#include <utility>
17
18// Constructor
19
20SCT_RodDecoder::SCT_RodDecoder(const std::string& type, const std::string& name,
21 const IInterface* parent) :
22 base_class(type, name, parent)
23{
24}
25
26// Initialize
27
29{
30 ATH_CHECK(AlgTool::initialize());
31
32 // Retrieve cabling tool
33 ATH_CHECK(m_cabling.retrieve());
34 ATH_MSG_DEBUG("Retrieved tool " << m_cabling);
35
36 ATH_CHECK(detStore()->retrieve(m_sctID,"SCT_ID"));
37 m_contextSCT = m_sctID->wafer_context();
38 m_swapPhiReadoutDirection.resize(m_sctID->wafer_hash_max(), false);
39
40 ATH_CHECK(m_configTool.retrieve());
41
42 // See if strip numbers go from 0 to N_STRIPS_PER_SIDE-1(=767) or vice versa for all the wafers.
43 // swapPhiReadoutDirection will not change during a run.
44 // Since this is access to SiDetectorElement during initialization,
45 // condition object of SiDetectorElementCollection is not accessible.
46 // SCT_DetectorManager has to be used.
47 const InDetDD::SCT_DetectorManager* sctDetManager{nullptr};
48 ATH_CHECK(detStore()->retrieve(sctDetManager, "SCT"));
49
50 const InDetDD::SiDetectorElementCollection* sctDetElementColl{sctDetManager->getDetectorElementCollection()};
51 for (const InDetDD::SiDetectorElement* element: *sctDetElementColl) {
52 if (element->swapPhiReadoutDirection()) {
53 m_swapPhiReadoutDirection[element->identifyHash()] = true;
54 }
55 }
56
57 return StatusCode::SUCCESS;
58}
59
60// Finalize
61
63{
64 // Print out summaries of data and errors decoded
65 ATH_MSG_INFO("SCT BytestreamCnv summary: " << m_headNumber <<" link headers found");
66 ATH_MSG_INFO("SCT BytestreamCnv summary: " << m_trailerNumber << " link trailers found");
67
68 ATH_MSG_INFO("SCT decoding bytestream summary: "
69 << m_singleCondHitNumber << " single strips with hit in condensed mode");
70 ATH_MSG_INFO("SCT decoding bytestream summary: "
71 << m_pairedCondHitNumber << " paired strips with hit in condensed mode");
72 ATH_MSG_INFO("SCT decoding bytestream summary: "
73 << m_firstExpHitNumber << " first strips with hit in expanded mode");
74 ATH_MSG_INFO("SCT decoding bytestream summary: "
75 << m_evenExpHitNumber << " consecutive paired strips with hit in expanded mode");
76 ATH_MSG_INFO("SCT decoding bytestream summary: "
77 << m_lastExpHitNumber << " last consecutive strips with hit in expanded mode");
78
79 if (m_headErrorBCID > 0) {
80 ATH_MSG_INFO("SCT BytestreamCnv summary: header-> "
81 << m_headErrorLvl1ID << " LVL1d errors found");
82 }
83 if (m_headErrorTimeout > 0) {
84 ATH_MSG_INFO("SCT BytestreamCnv summary: header-> "
85 << m_headErrorTimeout << " timeout errors found");
86 }
87 if (m_headErrorFormatter > 0) {
88 ATH_MSG_INFO("SCT BytestreamCnv summary: header-> "
89 << m_headErrorFormatter << " formatter errors found");
90 }
91 if (m_headErrorPreamble > 0) {
92 ATH_MSG_INFO("SCT BytestreamCnv summary: header-> "
93 << m_headErrorPreamble << " preamble errors found");
94 }
95 if (m_maskedLinkNumber > 0) {
96 ATH_MSG_INFO("SCT BytestreamCnv summary: header-> "
97 << m_maskedLinkNumber << " masked links found");
98 }
99
100 if (m_trailerErrorOverflow > 0) {
101 ATH_MSG_INFO("SCT BytestreamCnv summary: trailer-> "
102 << m_trailerErrorOverflow << " trailer data overflow errors found");
103 }
104 if (m_trailerErrorLimit > 0) {
105 ATH_MSG_INFO("SCT BytestreamCnv summary: trailer-> "
106 << m_trailerErrorLimit << " header trailer limit errors found");
107 }
108 if (m_trailerErrorBit > 0) {
109 ATH_MSG_INFO("SCT BytestreamCnv summary: trailer-> "
110 << m_trailerErrorBit << " trailer bit errors found");
111 }
112
113 if (m_configDataBit > 0) {
114 ATH_MSG_INFO("SCT BytestreamCnv summary: raw Data-> "
115 << m_configDataBit << " raw data found: Config data mode");
116 }
117
118 if (m_flagErrorBit > 0) {
119 ATH_MSG_INFO("SCT BytestreamCnv summary: flag-> "
120 << m_flagErrorBit << " module link flag bit errors found");
121 }
122
123 if (m_condHit1Error > 0) {
124 ATH_MSG_INFO("SCT BytestreamCnv summary: hit-> "
125 << m_condHit1Error << " 1st hit error found in condensed mode");
126 }
127 if (m_condHit2Error > 0) {
128 ATH_MSG_INFO("SCT BytestreamCnv summary: hit-> "
129 << m_condHit2Error << " 2nd hit error found in condensed mode");
130 }
131 if (m_chipNumberError > 0) {
132 ATH_MSG_INFO("SCT BytestreamCnv summary: hit-> "
133 << m_chipNumberError << " Chip number > 5 error found");
134 }
135
136 if (m_unknownDataFormat > 0) {
137 ATH_MSG_INFO("SCT BytestreamCnv summary: unknown data-> "
138 << m_unknownDataFormat << " Unknown data format found");
139 }
140
141 if (m_rodClockErrorNumber > 0) {
142 ATH_MSG_INFO("SCT BytestreamCnv summary: ROD status word-> "
143 << m_rodClockErrorNumber << " ROD clock errors found");
144 }
145 if (m_maskedRODNumber > 0) {
146 ATH_MSG_INFO("SCT BytestreamCnv summary: ROB status word-> "
147 << m_maskedRODNumber << " masked RODs found");
148 }
149 if (m_truncatedRODNumber > 0) {
150 ATH_MSG_INFO("SCT BytestreamCnv summary: ROB status word-> "
151 << m_truncatedRODNumber << " truncated ROBFragments");
152 }
153
154 ATH_MSG_INFO("Number of SCT hits in ByteStream-> " << m_nHits);
155 ATH_MSG_INFO("Number of SCT RDOs created-> " << m_nRDOs);
156
157 if (m_numMissingLinkHeader > 0) ATH_MSG_WARNING("SCT Missing Link Headers found " << m_numMissingLinkHeader);
158
159 ATH_CHECK(AlgTool::finalize());
160 ATH_MSG_DEBUG("SCT_RodDecoder::finalize()");
161
162 return StatusCode::SUCCESS;
163}
164
165
166// fillCollection method
168 SCT_RDO_Container& rdoIDCont,
169 IDCInDetBSErrContainer& errorsIDC,
170 DataPool<SCT3_RawData>* dataItemsPool,
171 const EventContext& ctx,
172 const std::vector<IdentifierHash>* vecHash) const
173{
174 SCT_RodDecoderErrorsHelper errs{errorsIDC}; // on destruction will fill the IDC
175
176 const uint32_t robID{robFrag.rod_source_id()};
177
178 // Determine whether this data was generated using the ROD simulator
179 const uint32_t rodDataType{robFrag.rod_detev_type()};
180 const bool rodSimulatedData{static_cast<bool>((rodDataType >> 20) & 0x1)};
181 if (rodSimulatedData) ATH_CHECK(addRODError(robID, SCT_ByteStreamErrors::RODSimulatedData, errs, ctx));
182
183 // Look for the bit that denotes "Super-condensed" mode
184 const bool superCondensedMode{static_cast<bool>((rodDataType >> 21) & 0x1)};
185
186 StatusCode sc{StatusCode::SUCCESS};
187
188 // Look at ROB status word
189 if (robFrag.nstatus()!=0) {
190 const uint32_t* robStatus;
191 robFrag.status(robStatus);
192 if ((*robStatus)!=0) {
193 ATH_MSG_DEBUG("ROB status word for robID " << std::hex << robID
194 << " is non-zero " << (*robStatus) << std::dec);
195 // First store generic "ROBFragmentError" error type.
196 ATH_CHECK(addRODError(robID, SCT_ByteStreamErrors::ROBFragmentError, errs, ctx));
197 sc = StatusCode::RECOVERABLE;
198 // Now look for specific problems, e.g. truncated or masked-off RODs
199 if (((*robStatus) >> 27) & 0x1) {
200 ATH_MSG_DEBUG("ROB status word for robID " << std::hex << robID
201 << std::dec << " indicates data truncation.");
202 ATH_CHECK(addRODError(robID, SCT_ByteStreamErrors::TruncatedROD, errs, ctx));
204 return sc;
205 }
206 if ((((*robStatus) >> 29) & 0x1) or (((*robStatus) >> 31) & 0x1)) {
207 ATH_MSG_DEBUG("ROB status word for robID " << std::hex << robID
208 << std::dec << " indicates resource was masked off.");
209 ATH_CHECK(addRODError(robID, SCT_ByteStreamErrors::MaskedROD, errs, ctx));
211 return sc;
212 }
213 }
214 }
215
216 // Look at ROD status words
218 const long unsigned int vecRODStatusSize{robFrag.rod_nstatus()};
219
220 robFrag.rod_status(vecRODStatus);
221 for (long unsigned int i{0}; i<vecRODStatusSize; i++) {
222 const uint32_t statusWord{vecRODStatus[i]};
223 // Check for clock errors in second ROD status word
224 if (i==1) {
225 const int timClockError{static_cast<int>((statusWord >> 16) & 0x1)};
226 const int bocClockError{static_cast<int>((statusWord >> 17) & 0x1)};
227 if (timClockError or bocClockError) {
228 ATH_MSG_DEBUG(" Clock error in ROD status word: " << timClockError << " " << bocClockError);
229 ATH_CHECK(addRODError(robID, SCT_ByteStreamErrors::RODClockError, errs, ctx));
231 sc=StatusCode::RECOVERABLE;
232 }
233 // Look at bits 20-23 for DCS HV
234 // const int hvBits{static_cast<int>((statusWord >> 20) & 0xF)};
235 // const bool hvOn{hvBits==0xF};
236 }
237 }
238
239 SharedData data;
240 data.reset();
241
242 CacheHelper cache; // For the trigger
243 cache.vecHash = vecHash;
244
246 const unsigned long int vecROBDataSize{robFrag.rod_ndata()};
247 if (vecROBDataSize > robFrag.payload_size_word()) {
248 ATH_MSG_WARNING("The ROB data does not seem to fit in the payload. Rejecting fragment (ndata size " << vecROBDataSize << " !< payload size " << robFrag.payload_size_word()
249 << " header size: " << robFrag.rod_header_size_word()
250 << " trailer size: " << robFrag.rod_trailer_size_word()
251 << " fragment size: " << robFrag.rod_fragment_size_word()
252 << ")");
253 return StatusCode::RECOVERABLE;
254 }
255 robFrag.rod_data(vecROBData);
256
257 // Loop over header, hit element, flagged ABCD error, raw data, trailer words
258 for (unsigned long int i{0}; i<vecROBDataSize; i++) {
259 // The data is 16-bits wide packed to a 32-bit word (rob_it1). So we unpack it here.
260 uint16_t data16[2];
261 data16[0] = ((vecROBData[i] >> 16) & 0xFFFF);
262 data16[1] = ( vecROBData[i] & 0xFFFF);
263
264 for (int n{0}; n<2; n++) {
265 bool hasError{false};
266 if (((data16[n]>>13) & 0x7) == 0x1) { // Header
267 bool breakNow{false};
268 ATH_CHECK(processHeader(data16[n], robID, data, rdoIDCont, dataItemsPool, cache, errs, hasError, breakNow, ctx));
269 if (hasError) sc = StatusCode::RECOVERABLE;
270 if (breakNow) break;
271 continue;
272 }
273 else if (data16[n] & 0x8000) { // Hit element
274 if (not data.foundHeader) {
275 ATH_MSG_INFO(" Missing link header in ROD " << std::hex << robID << std::dec);
276 data.foundMissingLinkHeaderError = true;
278 sc = StatusCode::RECOVERABLE;
279 continue;
280 }
281 m_nHits++;
282 if (superCondensedMode) { // Super-condensed mode:
283 ATH_CHECK(processSuperCondensedHit(data16[n], robID, data, rdoIDCont, dataItemsPool, cache, errs, hasError, ctx));
284 if (hasError) sc = StatusCode::RECOVERABLE;
285 continue;
286 }
287 else if (data.condensedMode) { // Condensed mode
288 ATH_CHECK(processCondensedHit(data16[n], robID, data, rdoIDCont, dataItemsPool, cache, errs, hasError, ctx));
289 if (hasError) sc = StatusCode::RECOVERABLE;
290 continue;
291 }
292 else { // Expanded mode
293 ATH_CHECK(processExpandedHit(data16[n], robID, data, rdoIDCont, dataItemsPool, cache, errs, hasError, ctx));
294 if (hasError) sc = StatusCode::RECOVERABLE;
295 continue;
296 }
297 }
298 else if (((data16[n]>>13) & 0x7) == 0x0) { // FlaggedABCD error
299 ATH_CHECK(processABCDError(data16[n], robID, data, errs, hasError, ctx));
300 if (hasError) sc = StatusCode::RECOVERABLE;
301 continue;
302 }
303 else if (((data16[n]>>13) & 0x7) == 0x3) { // Raw Data
304 ATH_CHECK(processRawData(data16[n], robID, data, errs, hasError, ctx));
305 if (hasError) sc = StatusCode::RECOVERABLE;
306 continue;
307 }
308 else if (((data16[n]>>13) & 0x7) == 0x2) { // Trailer
309 ATH_CHECK(processTrailer(data16[n], robID, data, errs, hasError, ctx));
310 if (hasError) sc = StatusCode::RECOVERABLE;
311 continue;
312 }
313 else {
314 ATH_MSG_DEBUG("Data word format unknown ");
316 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
317 sc = StatusCode::RECOVERABLE;
318 }
319 } // End of 16-bit word loop
320 } // End of 32-bit word loop
321
322 // Create the last RDO of the last link of the event
323 if (data.isStripValid()) {
324 if (not data.isSaved(false) and data.isOldStripValid()) {
325 const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
326 if (rdoMade == -1) {
327 sc = StatusCode::RECOVERABLE;
328 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
329 }
330 else {
331 data.setSaved(false, rdoMade);
332 }
333 }
334 }
335
336 // MissingLinkHeaderError is filled in only FE-lins of the ROD whose headers are not found.
337 // We cannot know which FE-link does not have header. However, we should not add the error to found ones.
338 if (data.foundMissingLinkHeaderError) {
339 ATH_CHECK(addRODError(robID, SCT_ByteStreamErrors::MissingLinkHeaderError, errs, ctx, &(data.foundHashes)));
340 }
341
342 for (auto& [hash, rdoColl] : data.rdoCollMap) {
343 if (rdoColl==nullptr) continue; // nullptr means the collection is already filled.
344
345 if (rdoColl->empty()) { // Empty collection is not filled.
346 rdoColl.reset();
347 errs.removeIfEmpty(hash); // To get the same result as before. Not sure whether we need this.
348 continue;
349 }
350
351 ATH_CHECK(data.writeHandleMap[hash].addOrDelete(std::move(rdoColl)));
352 }
353
354 if (sc.isFailure()) ATH_MSG_DEBUG("One or more ByteStream errors found ");
355 return sc;
356}
357
358// makeRDO method
359
360int SCT_RodDecoder::makeRDO(const bool isOld,
361 SharedData& data,
362 CacheHelper& cache,
363 DataPool<SCT3_RawData>* dataItemsPool) const
364{
365 // If the link is already decoded, RDO will not be created.
366 SCT_RDO_Collection* rdoColl{data.rdoCollMap[data.linkIDHash].get()};
367 if (rdoColl==nullptr) return 0;
368
369 int strip{isOld ? data.oldStrip : data.strip};
370 if (((strip & 0x7F) + (data.groupSize-1) >= N_STRIPS_PER_CHIP) or (strip<0) or (strip>=N_STRIPS_PER_SIDE)) {
371 ATH_MSG_DEBUG("Cluster with " << data.groupSize << " strips, starting at strip " << (strip & 0x7F) << " in Chip" << (strip / N_STRIPS_PER_SIDE) << " Side " << data.side <<", (old side, old strip) = (" << data.oldSide << ", " << data.oldStrip << ")"
372 << " in collection " << data.linkIDHash << " (= " << m_cabling->getSerialNumberFromHash(data.linkIDHash) << ") out of range. Will not make RDO");
373 return -1;
374 }
375
376 // This option is for the trigger, if there is a vecHash* given, test it!
377 if (cache.vecHash) {
378 if (data.linkIDHash == cache.skipHash) {
379 ATH_MSG_VERBOSE("Collection for Hash not to be decoded, skip");
380 return 0;
381 }
382 else if (data.linkIDHash != cache.lastHash) {
383 cache.lastHash = data.linkIDHash;
384 // Maybe the new hash is not in the list, so test it
385 std::vector<IdentifierHash>::const_iterator hashIDIterator{find(cache.vecHash->begin(),
386 cache.vecHash->end(),
387 data.linkIDHash)};
388 if (hashIDIterator == cache.vecHash->end()) {
389 ATH_MSG_VERBOSE("Collection for Hash not to be decoded, skip");
390 // Remember this one, so that we do not find(...) forever
391 cache.skipHash = data.linkIDHash;
392 return 0;
393 }
394 }
395 }
396
397 // See if strips go from 0 to N_STRIPS_PER_SIDE-1(=767) or vice versa
398 if (m_swapPhiReadoutDirection[data.linkIDHash]) {
400 strip = strip-(data.groupSize-1);
401 }
402
403 // Get identifier from the hash, this is not nice
404 const Identifier digitID{m_sctID->strip_id(data.collID, strip)};
405 if (not m_sctID->is_sct(digitID)) {
406 ATH_MSG_WARNING("Cluster with invalid Identifier. Will not make RDO");
407 return -1;
408 }
409
410 const unsigned int rawDataWord{static_cast<unsigned int>(data.groupSize | (strip << 11) | (data.timeBin <<22) | (data.errors << 25))};
411
412 ATH_MSG_DEBUG("Output Raw Data " << std::hex << " Coll " << data.collID.getString()
413 << ":-> " << m_sctID->print_to_string(digitID) << std::dec);
414
415 // Now the Collection is there for sure. Create RDO and push it into Collection.
416 m_nRDOs++;
417
418 if(dataItemsPool){
419 SCT3_RawData* sct_rdo = dataItemsPool->nextElementPtr();
420 (*sct_rdo) = SCT3_RawData(digitID, rawDataWord, &(data.errorHit));
421 rdoColl->push_back(sct_rdo);
422 }else{
423 rdoColl->push_back(std::make_unique<SCT3_RawData>(digitID, rawDataWord, &(data.errorHit)));
424 }
425 return 1;
426}
427
428// addRODError method
429
432 const EventContext& ctx,
433 const std::unordered_set<IdentifierHash>* foundHashes) const
434{
435 std::vector<IdentifierHash> hashIDs;
436 m_cabling->getHashesForRod(hashIDs, rodID);
437 for (const IdentifierHash& hash: hashIDs) {
438 // MissingLinkHeaderError is filled in only FE-links of the ROD whose headers are not found.
439 // We cannot know which FE-link does not have header. However, we should not add the error to found ones.
440 if ((error==SCT_ByteStreamErrors::MissingLinkHeaderError) and
441 foundHashes and foundHashes->count(hash)) {
442 continue;
443 }
444
445 // Skip disabled modules
446 if(!m_configTool->isGood(hash, ctx)) {
447 continue;
448 }
449
450 // Skip bad links
451 const auto & [link0Good, link1Good] = m_configTool->badLinks(hash, ctx);
452 int side{m_sctID->side(m_sctID->wafer_id(hash))};
453 const bool result{side==0 ? not link0Good : not link1Good};
454 if (result) continue;
455
456 ATH_CHECK(addSingleError(hash, error, errs, ctx));
457 }
458 return StatusCode::SUCCESS;
459}
460
461// addSingleError method
462
466 const EventContext& ctx) const
467{
468 if (not hashID.is_valid()) {
469 ATH_MSG_INFO("addSingleError hashID " << hashID << " is invalid.");
470 return StatusCode::SUCCESS;
471 }
472
473 errs.add(hashID, error);
474
475 if ((error<SCT_ByteStreamErrors::ABCDError_Chip0 || error>SCT_ByteStreamErrors::ABCDError_Chip5) and
476 (error<SCT_ByteStreamErrors::TempMaskedChip0 || error>SCT_ByteStreamErrors::TempMaskedChip5)) {
477 std::pair<bool, bool> badLinks{m_configTool->badLinks(hashID, ctx)};
478 int side{m_sctID->side(m_sctID->wafer_id(hashID))};
479 bool result{(side==0 ? badLinks.first : badLinks.second) and (badLinks.first xor badLinks.second)};
480 if (result) {
483 IdentifierHash otherSide;
484 m_sctID->get_other_side(hashID, otherSide);
485 errs.add(otherSide, error);
486 ATH_MSG_DEBUG("Adding error to side " << 1-side << " for module with RX redundancy " << otherSide);
487 }
488 }
489
490 return StatusCode::SUCCESS;
491}
492
493// setFirstTempMaskedChip method
494
496 unsigned int firstTempMaskedChip,
498 const EventContext& ctx) const
499{
500 if (not hashID.is_valid()) {
501 ATH_MSG_INFO("setFirstTempMaskedChip hashID " << hashID << " is invalid.");
502 return StatusCode::RECOVERABLE;
503 }
504 if (firstTempMaskedChip==0) {
505 ATH_MSG_WARNING("setFirstTempMaskedChip: firstTempMaskedChip should be greater than 0. firstTempMaskedChip is "
506 << firstTempMaskedChip);
507 return StatusCode::RECOVERABLE;
508 }
509
510 // wafer hash -> wafer id -> module id -> wafer hash on side-0, wafer hash on side-1
511 const Identifier waferID{m_sctID->wafer_id(hashID)};
512 const Identifier moduleID{m_sctID->module_id(waferID)};
513
514 // Side 0
515 IdentifierHash hashSide0;
516 m_sctID->get_hash(moduleID, hashSide0, &m_contextSCT);
517 unsigned int firstTempMaskedChipSide0{0};
518 if (hashID==hashSide0) firstTempMaskedChipSide0 = firstTempMaskedChip;
519
520 // Side 1
521 IdentifierHash hashSide1;
522 m_sctID->get_other_side(hashSide0, hashSide1);
523 unsigned int firstTempMaskedChipSide1{0};
524 if (hashID==hashSide1) firstTempMaskedChipSide1 = firstTempMaskedChip;
525
526 int type{0};
527 // Check if Rx redundancy is used or not in this module
528 const std::pair<bool, bool> badLinks{m_configTool->badLinks(hashID, ctx)};
529 if (badLinks.first xor badLinks.second) {
530 // Rx redundancy is used in this module.
531 if (badLinks.first and not badLinks.second) {
532 // link-1 is broken
533 type = 1;
534 }
535 else if (badLinks.second and not badLinks.first) {
536 // link-0 is broken
537 type = 2;
538 }
539 else if (badLinks.first and badLinks.second) {
540 // Both link-0 and link-1 are working
541 ATH_MSG_WARNING("setFirstTempMaskedChip: Both link-0 and link-1 are working. But Rx redundancy is used... Why?");
542 return StatusCode::RECOVERABLE;
543 }
544 else {
545 // Both link-0 and link-1 are broken
546 ATH_MSG_WARNING("setFirstTempMaskedChip: Both link-0 and link-1 are broken. But data are coming... Why?");
547 return StatusCode::RECOVERABLE;
548 }
549 }
550
551 // "Modified" module (using Rx redundancy) case
552 // Information of modified modules are found in
553 // modified0 and modified1 functions of SCT_ReadoutTool.cxx and
554 // Table 3.8 of CERN-THESIS-2008-001 https://cds.cern.ch/record/1078223
555 // However, there are two exceptions of the exceptions.
556 const unsigned long long fullSerialNumber{m_cabling->getSerialNumberFromHash(hashID).to_ulonglong()};
557 if (// Readout through link-0
558 fullSerialNumber==20220170200183 or // hash=4662 bec=0 layer=2 eta= 6 phi=39
559 fullSerialNumber==20220330200606 or // hash=5032 bec=0 layer=3 eta=-2 phi= 7
560 fullSerialNumber==20220330200693 // hash=5554 bec=0 layer=3 eta=-5 phi=29
561 ) {
562 if (type!=1) ATH_MSG_WARNING("Link-0 is broken but modified module readingout link-0, inconsistent");
563 type = 3;
564
565 // An exception:
566 // fullSerialNumber=20220170200941, hash=3560 bec=0 layer=1 eta=-6 phi=34
567 // This module is a modified one. However, it is not using modified configuration.
568 // Readout sequence is 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11.
569 }
570 if (// Readout through link-1
571 fullSerialNumber==20220170200653 or // hash=2786 bec=0 layer=1 eta= 4 phi= 1
572 fullSerialNumber==20220330200117 or // hash=5516 bec=0 layer=3 eta= 1 phi=27
573 fullSerialNumber==20220330200209 or // hash=5062 bec=0 layer=3 eta= 2 phi= 8
574 fullSerialNumber==20220330200505 or // hash=5260 bec=0 layer=3 eta= 5 phi=16
575 fullSerialNumber==20220330200637 or // hash=4184 bec=0 layer=2 eta=-6 phi=20
576 fullSerialNumber==20220330200701 // hash=4136 bec=0 layer=2 eta=-6 phi=18
577 ) {
578 if (type!=2) ATH_MSG_WARNING("Link-1 is broken but modified module readingout link-1, inconsistent");
579 type = 4;
580
581 // Another exception:
582 // fullSerialNumber=20220170200113, hash=3428 bec=0 layer=1 eta= 1 phi=28
583 // This module is a modified one. However, it is not using modified configuration.
584 // Readout sequence is 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5.
585 }
586
587 static const int chipOrder[5][N_SIDES*N_CHIPS_PER_SIDE]{
588 // type=0 not prepared for both link-0 and link-1 are working
589 {},
590 // type=1 link-1 is broken: chip 0 1 2 3 4 5 6 7 8 9 10 11
591 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
592 // type=2 link-0 is broken: chip 6 7 8 9 10 11 0 1 2 3 4 5
593 {6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5},
594 // type=3 "modified" modules and link-1 is broken: chip 0 1 2 3 4 5 7 8 9 10 11 6
595 {0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 6},
596 // type=4 "modified" modules and link-0 is broken: chip 6 7 8 9 10 11 1 2 3 4 5 0
597 {6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 0}
598 };
599
600 if (type==0) {
601 // Both link-0 and link-1 are working
602
603 // Chips 0-5 are on side 0 and chips 6-11 are on side 1.
604 // Normally, modules send hits on side 0 via link-0 and side 1 via link-1.
605 // The first temporally masked chip value is the id of the chip that is
606 // first masked in the readout chain "plus one".
607 // If the value is in between 1 to 6, it indicates side 0.
608 // If the value is in between 7 to 12, it indicates side 1.
609 // However, some special modules send hits on side 0 via link-1 and hits on
610 // side 1 via link-0. If the first masked chip value on side 1 (0) is
611 // between 1 to 6 (7 to 12), it indicates the module is a special one.
612 // In that case, information is swapped.
613 if ((N_CHIPS_PER_SIDE<firstTempMaskedChipSide0 and firstTempMaskedChipSide0<=N_SIDES*N_CHIPS_PER_SIDE) or
614 ( 0<firstTempMaskedChipSide1 and firstTempMaskedChipSide1<= N_CHIPS_PER_SIDE)) {
615 const unsigned int swapFirstTempMaskedChipSide0{firstTempMaskedChipSide0};
616 firstTempMaskedChipSide0 = firstTempMaskedChipSide1;
617 firstTempMaskedChipSide1 = swapFirstTempMaskedChipSide0;
618 }
619
620 if (firstTempMaskedChipSide0>0) {
621 for (unsigned int iChip{firstTempMaskedChipSide0-1}; iChip<N_CHIPS_PER_SIDE; iChip++) {
623 }
624 }
625 if (firstTempMaskedChipSide1>N_CHIPS_PER_SIDE) {
626 for (unsigned int iChip{firstTempMaskedChipSide1-1}; iChip<N_SIDES*N_CHIPS_PER_SIDE; iChip++) {
628 }
629 }
630 }
631 else {
632 // type=1, 2, 3, 4: cases using Rx redundancy
633 bool toBeMasked{false};
634 for (int iChip{0}; iChip<N_SIDES*N_CHIPS_PER_SIDE; iChip++) {
635 int jChip{chipOrder[type][iChip]};
636 if (jChip==static_cast<int>(firstTempMaskedChip-1)) toBeMasked = true;
637 if (toBeMasked) {
638 if (jChip<N_CHIPS_PER_SIDE) {
640 }
641 else {
643 }
644 }
645 }
646 }
647
648 ATH_MSG_VERBOSE("setFirstTempMaskedChip Hash " << hashID
649 << " SerialNumber " << m_cabling->getSerialNumberFromHash(hashID).str()
650 << " moduleID " << moduleID
651 << " barrel_ec " << m_sctID->barrel_ec(waferID)
652 << " layer_disk " << m_sctID->layer_disk(waferID)
653 << " eta_module " << m_sctID->eta_module(waferID)
654 << " phi_module " << m_sctID->phi_module(waferID)
655 << " side " << m_sctID->side(waferID)
656 << " firstTempMaskedChip " << firstTempMaskedChip);
657 return StatusCode::SUCCESS;
658}
659
660StatusCode SCT_RodDecoder::processHeader(const uint16_t inData,
661 const uint32_t robID,
662 SharedData& data,
663 SCT_RDO_Container& rdoIDCont,
664 DataPool<SCT3_RawData>* dataItemsPool,
665 CacheHelper& cache,
667 bool& hasError,
668 bool& breakNow,
669 const EventContext& ctx) const
670{
671 StatusCode sc{StatusCode::SUCCESS};
672
673 data.foundHeader = true;
674 m_headNumber++;
675
676 // Create the last RDO of the previous link if any
677 if (data.isStripValid()) {
678 if (not data.isSaved(false) and data.isOldStripValid()) {
679
680 const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
681 if (rdoMade == -1) {
682 hasError = true;
683 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
684 }
685 else {
686 data.setSaved(false, rdoMade);
687 }
688 }
689 }
690
691 // Everything is set to default for a new hunt of RDO
692 data.reset();
693
694 // Link Number (or stream) in the ROD fragment
695 const int rodlinkNumber{static_cast<int>(inData & 0x7F)};
696
697 // This is the real calculation for the offline
698 data.linkNumber = (((rodlinkNumber >>4)&0x7)*12+(rodlinkNumber &0xF));
699 const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
700 IdentifierHash hash;
701 if ((onlineID ==0) or (data.linkNumber > 95)) {
702 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
703 hasError = true;
704 ATH_MSG_DEBUG("Header: xxx Link number out of range (skipping following data)"
705 << std::dec << data.linkNumber);
706 breakNow = true;
707 return sc;
708 }
709 else {
710 hash = m_cabling->getHashFromOnlineId(onlineID, ctx);
711 if (hash.is_valid()) {
712 data.setCollection(m_sctID, hash, rdoIDCont, dataItemsPool, errs);
713 }
714 else {
715 std::stringstream msg;
716 msg <<std::hex << onlineID;
717 ATH_MSG_WARNING("Rob fragment (rob=" << robID << ") with invalid onlineID " << msg.str() << " -> " << hash << ".");
718 }
719 }
720 // Look for masked off links - bit 7
721 if ((inData >> 7) & 0x1) {
722 ATH_MSG_DEBUG("Masked link " << onlineID << " " << data.linkIDHash);
723 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::MaskedLink, errs, ctx));
724 hasError = true;
725 }
726 if (inData & 0x800) {
727 ATH_MSG_DEBUG(" Header: xxx TimeOut Error " << data.linkIDHash);
729 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::TimeOutError, errs, ctx));
730 hasError = true;
731 }
732
733 if (inData & 0x1000) {
734 ATH_MSG_DEBUG(" Header: xxx Preamble Error " << data.linkIDHash);
736 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::PreambleError, errs, ctx));
737 hasError = true;
738 }
739
740 if (inData & 0x400) {
741 ATH_MSG_DEBUG(" Header: xxx LVL1 ID Error " << data.linkIDHash);
743 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::LVL1IDError, errs, ctx));
744 hasError = true;
745 }
746
747 if (inData & 0x200) {
748 ATH_MSG_DEBUG(" Header: xxx BCID Error " << data.linkIDHash);
750 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::BCIDError, errs, ctx));
751 hasError = true;
752 }
753
754 if ((inData & 0xF) > 11) {
755 ATH_MSG_DEBUG(" Header: xxx Error in formatter " << data.linkIDHash);
757 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::FormatterError, errs, ctx));
758 hasError = true;
759 }
760 if (!hasError and not hash.is_valid()) {
761 std::stringstream msg;
762 msg <<std::hex << onlineID;
763 ATH_MSG_WARNING("Rob fragment (rob=" << robID << ") with invalid onlineID " << msg.str() << " -> " << hash << ".");
764 hasError = true;
765 }
766
767 data.condensedMode = static_cast<bool>(inData & 0x100);
768
769 return sc;
770}
771
772StatusCode SCT_RodDecoder::processSuperCondensedHit(const uint16_t inData,
773 const uint32_t robID,
774 SharedData& data,
775 SCT_RDO_Container& rdoIDCont,
776 DataPool<SCT3_RawData>* dataItemsPool,
777 CacheHelper& cache,
779 bool& hasError,
780 const EventContext& ctx) const
781{
782 StatusCode sc{StatusCode::SUCCESS};
783
784 // Super-condensed mode:
785 // Chip info: 4 bits data16[n]>>11) & 0xF
786 // Chip number == (data16[n]>>11) & 0x7
787 // Chip side == (data16[n]>>14) & 0x1
788 // For example if (data16[n]>>11) & 0xF = 0b0101 => chip 5 or chip5 on side0, (data16[n]>>11) & 0xF = 0b1101 => chip13 or chip5 on side1
789 const int chip{(inData>>11) & 0x7};
790 data.side = ((inData>>14) & 0x1);
791 data.strip = chip*N_STRIPS_PER_CHIP + ((inData>>4) & 0x7F);
792 data.timeBin = 0x2; // Assuming timeBin is 010 in super-condensed mode
793 const int nStripsInWord{(inData & 0xF)+1};
794 if (chip>=N_CHIPS_PER_SIDE) {
795 ATH_MSG_DEBUG(" Hit super-condensed : xxx Chip number = " << chip << " >= "<< N_CHIPS_PER_SIDE << " for hit "
796 << std::hex << inData);
798 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
799 hasError = true;
800 return sc;
801 }
802
803 // Search for redundancy only for the master chip
804 bool secondSide{false};
805 if ((data.side==1) and ((data.linkNumber%2)==0)) {
806 if (((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) and (data.groupSize>0)) {
807 // If it is a new cluster, make RDO with the previous cluster
808 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
809 if (rdoMade == -1) {
810 hasError = true;
811 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
812 }
813 else {
814 data.setSaved(true, rdoMade);
815 }
816 data.setOld();
817 }
818 data.linkNumber++;
819 secondSide = true;
820 }
821 else if ((data.side==0) and ((data.linkNumber%2)!=0)) {
822 if (((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) and (data.groupSize>0)) {
823 // If it is a new cluster, make RDO with the previous cluster
824 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
825 if (rdoMade == -1) {
826 hasError = true;
827 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
828 }
829 else {
830 data.setSaved(true, rdoMade);
831 }
832 data.setOld();
833 }
834 data.linkNumber--;
835 secondSide = true;
836 }
837 if (secondSide) {
838 const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
839 IdentifierHash id_hash(m_cabling->getHashFromOnlineId(onlineID,ctx));
840 if (!id_hash.is_valid()) {
841 hasError = true;
842 return sc;
843 }
844 data.setCollection(m_sctID, id_hash, rdoIDCont, dataItemsPool, errs);
845 }
846
847 if (data.groupSize == 0) {
848 data.setOld(); // If it's the first super-condensed word
849 }
850
851 if ((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) {
852 // If it is a new cluster, make RDO with the previous cluster
853 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
854 if (rdoMade == -1) {
855 hasError = true;
856 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
857 }
858 else {
859 data.setSaved(true, rdoMade);
860 }
861 data.setOld();
862 }
863 data.groupSize += nStripsInWord; // Split clusters have the same strip number.
864
865 return sc;
866}
867
868StatusCode SCT_RodDecoder::processCondensedHit(const uint16_t inData,
869 const uint32_t robID,
870 SharedData& data,
871 SCT_RDO_Container& rdoIDCont,
872 DataPool<SCT3_RawData>* dataItemsPool,
873 CacheHelper& cache,
875 bool& hasError,
876 const EventContext& ctx) const
877{
878 StatusCode sc{StatusCode::SUCCESS};
879
880 const int chip{(inData>>11) & 0x7};
881 data.side = ((inData>>14) & 0x1);
882 data.strip = chip*N_STRIPS_PER_CHIP + ((inData>>4) & 0x7F);
883 data.timeBin = 0x2; // Assuming timeBin is 010 in condensed mode
884 if (chip>=N_CHIPS_PER_SIDE) {
885 ATH_MSG_DEBUG(" Hit condensed : xxx Chip number = " << chip << " >= " << N_CHIPS_PER_SIDE << " for hit "
886 << std::hex << inData);
888 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
889 hasError = true;
890 return sc;
891 }
892
893 // Search for redundancy only for the master chip
894 bool secondSide{false};
895 if ((data.side==1) and ((data.linkNumber%2)==0)) {
896 if (((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) and (data.groupSize>0)) {
897 // If it is a new cluster, make RDO with the previous cluster
898 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
899 if (rdoMade == -1) {
900 hasError = true;
901 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
902 }
903 else {
904 data.setSaved(true, rdoMade);
905 }
906 data.setOld();
907 }
908 data.linkNumber++;
909 secondSide = true;
910 }
911 else if ((data.side==0) and ((data.linkNumber%2)!=0)) {
912 if (((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) and (data.groupSize>0)) {
913 // If it is a new cluster, make RDO with the previous cluster
914 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
915 if (rdoMade == -1) {
916 hasError = true;
917 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
918 }
919 else {
920 data.setSaved(true, rdoMade);
921 }
922 data.setOld();
923 }
924 data.linkNumber--;
925 secondSide = true;
926 }
927 if (secondSide) {
928 const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
929 data.setCollection(m_sctID, m_cabling->getHashFromOnlineId(onlineID, ctx), rdoIDCont, dataItemsPool, errs);
930 }
931
932 if (data.groupSize == 0) {
933 data.setOld(); // If it's the first condensed word
934 }
935
936 if (not (inData & 0x1)) { // 1-hit
938 if ((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) {
939 // If it is a new cluster, make RDO with the previous cluster
940 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
941 if (rdoMade == -1) {
942 hasError = true;
943 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
944 }
945 else {
946 data.setSaved(true, rdoMade);
947 }
948 data.setOld();
949 }
950
951 if (inData & 0x4) { // Error in the hit
952 ATH_MSG_DEBUG(" Hit condensed : xxx ERROR in 1-hit " << std::hex << inData);
953 data.errorHit.push_back(data.groupSize);
954 data.errors = (data.errors | 0x10);
956 hasError = true;
957 }
958 data.groupSize = (data.groupSize>=2 ? data.groupSize : 1);
959 }
960 else { // 2-hits
961 if (data.strip >= N_STRIPS_PER_SIDE) {
962 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
963 hasError = true;
964
965 ATH_MSG_DEBUG("Condensed mode - strip number out of range");
966
967 return sc;
968 }
970 if ((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) {
971 // If it is a new cluster, make RDO with the previous cluster
972 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
973 if (rdoMade == -1) {
974 hasError = true;
975 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
976 }
977 else {
978 data.setSaved(true, rdoMade);
979 }
980 data.setOld();
981 }
982 if (inData & 0x4) { // Error in the first hit
983 ATH_MSG_DEBUG(" Hit condensed : xxx ERROR in 1st hit" << std::hex << inData);
984 data.errorHit.push_back(data.groupSize);
986 data.errors = (data.errors | 0x10);
987 hasError = true;
988 }
989 if (inData & 0x8) { // Error in the second hit
990 ATH_MSG_DEBUG(" Hit condensed : xxx ERROR in 2nd hit" << std::hex << inData);
991 data.errorHit.push_back(data.groupSize);
993 data.errors = (data.errors | 0x20);
994 hasError = true;
995 }
996 data.groupSize = 2;
997 }
998
999 return sc;
1000}
1001
1002StatusCode SCT_RodDecoder::processExpandedHit(const uint16_t inData,
1003 const uint32_t robID,
1004 SharedData& data,
1005 SCT_RDO_Container& rdoIDCont,
1006 DataPool<SCT3_RawData>* dataItemsPool,
1007 CacheHelper& cache,
1009 bool& hasError,
1010 const EventContext& ctx) const
1011{
1012 StatusCode sc{StatusCode::SUCCESS};
1013
1014 int chip{0};
1015 if (not (inData & 0x8)) { // 1st hit cluster expanded
1017 chip = ((inData>>11) & 0x7);
1018 data.side = ((inData>>14) & 0x1);
1019 data.strip = chip*N_STRIPS_PER_CHIP + ((inData>>4) & 0x7F);
1020 data.timeBin = (inData & 0x7); // Real way for obtaining timeBin info
1021
1022 if (chip>=N_CHIPS_PER_SIDE) {
1023 ATH_MSG_DEBUG("Expanded hit: First hit xxx ERROR chip Nb = " << chip << " >= " << N_CHIPS_PER_SIDE);
1025 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
1026 return sc;
1027 }
1028
1029 // Search for redundancy only for the master chip
1030 bool secondSide{false};
1031 if ((data.side==1) and ((data.linkNumber%2)==0)) {
1032 data.linkNumber++;
1033 secondSide = true;
1034 }
1035 else if ((data.side==0) and ((data.linkNumber%2)!=0)) {
1036 data.linkNumber--;
1037 secondSide = true;
1038 }
1039 if (secondSide) {
1040 const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
1041 data.setCollection(m_sctID, m_cabling->getHashFromOnlineId(onlineID, ctx), rdoIDCont, dataItemsPool, errs);
1042 }
1043 data.groupSize = 1;
1044 const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
1045 if (rdoMade == -1) {
1046 hasError = true;
1047 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
1048 }
1049 else {
1050 data.setSaved(false, rdoMade);
1051 }
1052 data.groupSize = 0;
1053 }
1054 else { // Next hits cluster expanded
1055 if (inData & 0x80) { // Paired hits
1056 if (data.strip >= N_STRIPS_PER_SIDE-2) {
1057 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
1058 hasError = true;
1059 ATH_MSG_DEBUG("Expanded mode - strip number out of range");
1060 return sc;
1061 }
1063 // First hit from the pair
1064 data.strip++;
1065 data.timeBin = (inData & 0x7);
1066 data.groupSize = 1;
1067 const int rdoMade1{makeRDO(false, data, cache, dataItemsPool)};
1068 if (rdoMade1 == -1) {
1069 hasError = true;
1070 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
1071 }
1072 else {
1073 data.setSaved(false, rdoMade1);
1074 }
1075 // Second hit from the pair
1076 data.strip++;
1077 data.timeBin = ((inData >> 4) & 0x7);
1078 const int rdoMade2{makeRDO(false, data, cache, dataItemsPool)};
1079 if (rdoMade2 == -1) {
1080 hasError = true;
1081 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
1082 }
1083 else {
1084 data.setSaved(false, rdoMade2);
1085 }
1086 data.groupSize = 0;
1087 }
1088 else { // Last hit of the cluster
1090 if (data.strip >= N_STRIPS_PER_SIDE-1) {
1091 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
1092 hasError = true;
1093 ATH_MSG_DEBUG("Expanded mode - strip number out of range");
1094 return sc;
1095 }
1096 data.strip++;
1097 data.timeBin = (inData & 0x7);
1098 data.groupSize = 1;
1099 const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
1100 if (rdoMade == -1) {
1101 hasError = true;
1102 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs, ctx));
1103 }
1104 else {
1105 data.setSaved(false, rdoMade);
1106 }
1107 data.groupSize = 0;
1108 }
1109 }
1110
1111 return sc;
1112}
1113
1114StatusCode SCT_RodDecoder::processABCDError(const uint16_t inData,
1115 const uint32_t robID,
1116 SharedData& data,
1118 bool& hasError,
1119 const EventContext& ctx) const
1120{
1121 StatusCode sc{StatusCode::SUCCESS};
1122
1123 if (not data.foundHeader) {
1124 ATH_MSG_INFO(" Missing link header in ROD " << std::hex << robID << std::dec);
1125 data.foundMissingLinkHeaderError = true;
1127 hasError = true;
1128 return sc;
1129 }
1130
1131 const int chip{(inData>>3) & 0xF};
1132 const int abcError{inData & 0x7};
1133 ATH_MSG_DEBUG(" xxx Flagged ABCD ERROR in chip " << chip
1134 << " Error code abcError " << abcError << " Link Number (or Stream) " << data.linkNumber);
1136 // Error code of ABCD error should be 1, 2, 4 or 7.
1137 if (abcError!=0x1 and abcError!=0x2 and abcError!=0x4 and abcError!=0x7) {
1138 ATH_MSG_DEBUG("ABCD error has an invalid error code " << abcError
1139 << " the 16-bit word is 0x" << std::hex << inData << std::dec
1140 << " for hash " << data.linkIDHash);
1141 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Invalid, errs, ctx));
1142 }
1143 else {
1144 // Chip is 4 bits. The highest bit 3 represents side. Chip 0-5 on side 0 and chip 8-13 on side 1.
1145 const unsigned int sideABCDError{static_cast<unsigned int>(chip/8)};
1146 if (data.linkIDHash.value()%2!=sideABCDError) {
1147 // If the sides from the ABCD error and online ID are different,
1148 // the module is expected to read side 0 via link 1 and side 1 and via link 0.
1149 // Hash Id is flipped.
1150 ATH_MSG_DEBUG("ABCD error and online ID have different side information for hash " << data.linkIDHash << ". "
1151 << sideABCDError << " from ABCD error and " << data.linkIDHash.value()%2 << " from online ID");
1152 data.linkIDHash = (data.linkIDHash.value()/2)*2+sideABCDError;
1153 errs.noerror(data.linkIDHash);
1154 }
1155 // Chip should be 0-5 or 8-13.
1156 if (chip%8>=N_CHIPS_PER_SIDE) {
1157 ATH_MSG_DEBUG("ABCD error has an invalid chip 0x" << std::hex << chip << std::dec
1158 << " the 16-bit word is 0x" << std::hex << inData << std::dec
1159 << " for hash " << data.linkIDHash.value());
1160 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Invalid, errs, ctx));
1161 }
1162 else {
1163 if ( abcError==0x1) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Error1, errs, ctx));
1164 else if (abcError==0x2) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Error2, errs, ctx));
1165 else if (abcError==0x4) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Error4, errs, ctx));
1166 else if (abcError==0x7) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Error7, errs, ctx));
1167 if ( chip%8==0) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip0, errs, ctx));
1168 else if (chip%8==1) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip1, errs, ctx));
1169 else if (chip%8==2) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip2, errs, ctx));
1170 else if (chip%8==3) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip3, errs, ctx));
1171 else if (chip%8==4) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip4, errs, ctx));
1172 else if (chip%8==5) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip5, errs, ctx));
1173 }
1174 }
1175 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError, errs, ctx));
1176 hasError = true;
1177
1178 return sc;
1179}
1180
1181StatusCode SCT_RodDecoder::processRawData(const uint16_t inData,
1182 const uint32_t robID,
1183 SharedData& data,
1185 bool& hasError,
1186 const EventContext& ctx) const
1187{
1188 StatusCode sc{StatusCode::SUCCESS};
1189
1190 if (not data.foundHeader) {
1191 ATH_MSG_INFO(" Missing link header in ROD " << std::hex << robID << std::dec);
1192 data.foundMissingLinkHeaderError = true;
1194 hasError = true;
1195 return sc;
1196 }
1197
1198 ATH_MSG_DEBUG(" xxx Raw Data Mode " << std::hex << inData << std::dec << ": Config Data Mode ");
1199 // Too many errors in the BS for the ROD to decode the data
1201 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::RawError, errs, ctx));
1202 hasError = true;
1203
1204 return sc;
1205}
1206
1207StatusCode SCT_RodDecoder::processTrailer(const uint16_t inData,
1208 const uint32_t /*robID*/,
1209 SharedData& data,
1211 bool& hasError,
1212 const EventContext& ctx) const
1213{
1214 StatusCode sc{StatusCode::SUCCESS};
1215 /* Temporarily disabled
1216 if (not data.foundHeader) {
1217 ATH_MSG_INFO(" Missing link header in ROD " << std::hex << robID << std::dec);
1218 data.foundMissingLinkHeaderError = true;
1219 m_numMissingLinkHeader++;
1220 hasError = true;
1221 }
1222 */
1223
1224 data.foundHeader = false;
1225
1227
1228 if (inData & 0x1000) {
1229 ATH_MSG_DEBUG(" Trailer: xxx Trailer ERROR " << std::hex << inData);
1231 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::TrailerError, errs, ctx));
1232 hasError = true;
1233 }
1234
1235 if (inData & 0x800) {
1236 // No data should appear between header and trailer
1237 // See 1.2.2 Formatter FPGA - Serial Data Decoding and Formatting of
1238 // http://www-eng.lbl.gov/~jmjoseph/Atlas-SiROD/Manuals/usersManual-v164.pdf
1239 ATH_MSG_DEBUG(" Trailer: xxx Header-Trailer limit ERROR " << std::hex << inData);
1241 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::HeaderTrailerLimitError, errs, ctx));
1242 hasError = true;
1243 }
1244
1245 if (inData & 0x400) {
1246 // Not sure if there are hit elements before (probably yes but in principle they are fine)
1247 ATH_MSG_DEBUG(" Trailer: xxx Data Overflow ERROR " << std::hex << inData);
1249 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::TrailerOverflowError, errs, ctx));
1250 hasError = true;
1251 }
1252 if (inData & 0xF) {
1253 // First temporarily masked chip information
1254 // 0 means no masked chip (always has been 0 until April 2017)
1255 //
1256 // If Rx redundacy is not used,
1257 // 1 means chips 0-5 are temporarily masked.
1258 // 6 means chip 5 is temporarily masked.
1259 // 7 means chips 6-11 are temporarily masked.
1260 // 12 means chip 11 is temporarily masked.
1261 //
1262 // If Rx redundacy is used and link-1 is not used,
1263 // 1 means chips 0-11 are temporarily masked.
1264 // 6 means chips 5-11 are temporarily masked.
1265 // 7 means chips 6-11 are temporarily masked.
1266 // 12 means chip 11 is temporarily masked.
1267 //
1268 // If Rx redundacy is used and link-0 is not used,
1269 // 1 means chips 0-5 are temporarily masked.
1270 // 6 means chip 5 is temporarily masked.
1271 // 7 means chips 6-11, 0-5 are temporarily masked.
1272 // 12 means chips 11, 0-5 are temporarily masked.
1273 setFirstTempMaskedChip(data.linkIDHash, (inData & 0xF), errs, ctx).ignore();
1274 }
1275
1276 return sc;
1277}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sc
InDetRawDataCollection< SCT_RDORawData > SCT_RDO_Collection
InDetRawDataContainer< InDetRawDataCollection< SCT_RDORawData > > SCT_RDO_Container
a typed memory pool that saves time spent allocation small object.
Definition DataPool.h:63
pointer nextElementPtr()
obtain the next available element in pool by pointer pool is resized if its limit has been reached On...
value_type push_back(value_type pElem)
IDC like storage for BS errors, TODO, customise implementation further so that we store int rather th...
This is a "hash" representation of an Identifier.
constexpr bool is_valid() const
Dedicated detector manager extending the functionality of the SiDetectorManager with dedicated SCT in...
virtual const SiDetectorElementCollection * getDetectorElementCollection() const override
access to whole collectiom
Class to hold the SiDetectorElement objects to be put in the detector store.
Class to hold geometrical description of a silicon detector element.
allows to accumulate errors in one fillColection call
void add(const IdentifierHash id, SCT_ByteStreamErrors::ErrorType etype)
void removeIfEmpty(const IdentifierHash id)
void noerror(const IdentifierHash id)
std::atomic_uint m_firstExpHitNumber
Total number of first strips with hit decoded in expanded mode.
std::atomic_uint m_singleCondHitNumber
Total number of single strips with hit decoded in condensed mode.
std::atomic_uint m_nHits
Total number of SCT hits in ByteStream.
ToolHandle< ISCT_ConfigurationConditionsTool > m_configTool
Service that keeps track of configuration conditions.
std::atomic_uint m_pairedCondHitNumber
Total number of paired strips with hit decoded in condensed mode.
StatusCode processCondensedHit(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RDO_Container &rdoIDCont, DataPool< SCT3_RawData > *dataItemsPool, CacheHelper &cache, SCT_RodDecoderErrorsHelper &errs, bool &hasError, const EventContext &ctx) const
Process hit word in Condensed mode.
std::atomic_uint m_headNumber
Total number of decoded header data.
IdContext m_contextSCT
"Context" of an expanded identifier (ExpandedIdentifier) for compact or hash versions (Identifier32 o...
StatusCode processTrailer(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RodDecoderErrorsHelper &errs, bool &hasError, const EventContext &ctx) const
Process trailer word.
std::atomic_uint m_headErrorFormatter
Total number of formatter errors in the header data.
std::atomic_uint m_headErrorLvl1ID
Total number of Lvl1ID errors in the header data.
StatusCode processSuperCondensedHit(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RDO_Container &rdoIDCont, DataPool< SCT3_RawData > *dataItemsPool, CacheHelper &cache, SCT_RodDecoderErrorsHelper &errs, bool &hasError, const EventContext &ctx) const
Process hit word in Super-Condensed mode.
std::atomic_uint m_truncatedRODNumber
Total number of truncated ROBFragments.
std::atomic_uint m_flagErrorBit
Total number of flag error data.
std::atomic_uint m_maskedRODNumber
Total number of masked RDOs.
std::atomic_uint m_headErrorTimeout
Total number of timeout errors in the header data.
std::atomic_uint m_trailerErrorBit
Total number of trailer bit errors.
SCT_RodDecoder(const std::string &type, const std::string &name, const IInterface *parent)
Constructor.
StatusCode addRODError(uint32_t rodID, SCT_ByteStreamErrors::ErrorType error, SCT_RodDecoderErrorsHelper &errs, const EventContext &ctx, const std::unordered_set< IdentifierHash > *foundHashes=nullptr) const
Add an error for each wafer in the problematic ROD.
std::atomic_uint m_rodClockErrorNumber
Total number of ROD clock errors.
std::atomic_uint m_trailerErrorOverflow
Total number of overflow errors in the trailer data.
const SCT_ID * m_sctID
Identifier helper class for the SCT subdetector that creates compact Identifier objects and Identifie...
std::atomic_uint m_headErrorPreamble
Total number of preamble errors in the header data.
std::vector< bool > m_swapPhiReadoutDirection
Swap phi readout direction.
std::atomic_uint m_condHit1Error
Total number of first hit data errors.
virtual StatusCode finalize() override
Finalize.
std::atomic_uint m_chipNumberError
Total number of chip number errors.
virtual StatusCode initialize() override
Initialize.
std::atomic_uint m_maskedLinkNumber
Total number of masked links in the header data.
StatusCode setFirstTempMaskedChip(const IdentifierHash &hashID, unsigned int firstTempMaskedChip, SCT_RodDecoderErrorsHelper &errs, const EventContext &ctx) const
Set first temporarily masked chip information from byte stream trailer.
StatusCode processExpandedHit(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RDO_Container &rdoIDCont, DataPool< SCT3_RawData > *dataItemsPool, CacheHelper &cache, SCT_RodDecoderErrorsHelper &errs, bool &hasError, const EventContext &ctx) const
Process hit word in Expanded mode.
std::atomic_uint m_nRDOs
Total number of SCT RDOs created.
std::atomic_uint m_unknownDataFormat
Total number of unknown data formats.
StatusCode addSingleError(const IdentifierHash &hashID, SCT_ByteStreamErrors::ErrorType error, SCT_RodDecoderErrorsHelper &errs, const EventContext &ctx) const
Add single eror.
std::atomic_uint m_headErrorBCID
Total number of BCID errors in the header data.
std::atomic_uint m_lastExpHitNumber
Total number of last consecutive strips with hit decoded in expanded mode.
ToolHandle< ISCT_CablingTool > m_cabling
Providing mappings of online and offline identifiers and also serial numbers.
std::atomic_uint m_trailerNumber
Total number of decoded trailer data.
StatusCode processHeader(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RDO_Container &rdoIDCont, DataPool< SCT3_RawData > *dataItemsPool, CacheHelper &cache, SCT_RodDecoderErrorsHelper &errs, bool &hasError, bool &breakNow, const EventContext &ctx) const
Process header word.
std::atomic_uint m_configDataBit
Total number of configuration data for raw data.
int makeRDO(const bool isOld, SharedData &data, CacheHelper &cache, DataPool< SCT3_RawData > *dataItemsPool) const
Builds RawData RDO and adds to RDO container.
virtual StatusCode fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment &robFrag, SCT_RDO_Container &rdoIDCont, IDCInDetBSErrContainer &errs, DataPool< SCT3_RawData > *dataItemsPool, const EventContext &ctx, const std::vector< IdentifierHash > *vecHash=nullptr) const override
Fill SCT RDO Collection with decoded ROB data.
std::atomic_uint m_evenExpHitNumber
Total number of consecutive paired strips with hit decoded in expanded mode.
std::atomic_uint m_numMissingLinkHeader
Total number of missing link headers.
StatusCode processRawData(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RodDecoderErrorsHelper &errs, bool &hasError, const EventContext &ctx) const
Process raw data word.
std::atomic_uint m_trailerErrorLimit
Total number of header trailer limit errors in the trailer data.
std::atomic_uint m_condHit2Error
Total number second hit data errors.
StatusCode processABCDError(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RodDecoderErrorsHelper &errs, bool &hasError, const EventContext &ctx) const
Process ABCD error.
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:140
const DataType * PointerType
Definition RawEvent.h:25
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27
ErrorType
SCT byte stream error type enums used in SCT_RodDecoder, SCT_ByteStreamErrorsTool,...
ErrorType TempMaskedChipToBit(const int chip)
Temp object to help with trigger caching.
Struct to hold data shared in methods used in fillCollection method.
MsgStream & msg
Definition testRead.cxx:32