ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_RodDecoder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 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));
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));
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));
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));
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));
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
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));
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));
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));
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));
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));
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, &(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,
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 std::unordered_set<IdentifierHash>* foundHashes) const
433{
434 std::vector<IdentifierHash> hashIDs;
435 m_cabling->getHashesForRod(hashIDs, rodID);
436 for (const IdentifierHash& hash: hashIDs) {
437 // MissingLinkHeaderError is filled in only FE-links of the ROD whose headers are not found.
438 // We cannot know which FE-link does not have header. However, we should not add the error to found ones.
439 if ((error==SCT_ByteStreamErrors::MissingLinkHeaderError) and
440 foundHashes and foundHashes->count(hash)) {
441 continue;
442 }
443
444 // Skip disabled modules
445 if(!m_configTool->isGood(hash)) {
446 continue;
447 }
448
449 // Skip bad links
450 const auto & [link0Good, link1Good] = m_configTool->badLinks(hash);
451 int side{m_sctID->side(m_sctID->wafer_id(hash))};
452 const bool result{side==0 ? not link0Good : not link1Good};
453 if (result) continue;
454
455 ATH_CHECK(addSingleError(hash, error, errs));
456 }
457 return StatusCode::SUCCESS;
458}
459
460// addSingleError method
461
464 SCT_RodDecoderErrorsHelper& errs) const
465{
466 if (not hashID.is_valid()) {
467 ATH_MSG_INFO("addSingleError hashID " << hashID << " is invalid.");
468 return StatusCode::SUCCESS;
469 }
470
471 errs.add(hashID, error);
472
473 if ((error<SCT_ByteStreamErrors::ABCDError_Chip0 || error>SCT_ByteStreamErrors::ABCDError_Chip5) and
474 (error<SCT_ByteStreamErrors::TempMaskedChip0 || error>SCT_ByteStreamErrors::TempMaskedChip5)) {
475 std::pair<bool, bool> badLinks{m_configTool->badLinks(hashID)};
476 int side{m_sctID->side(m_sctID->wafer_id(hashID))};
477 bool result{(side==0 ? badLinks.first : badLinks.second) and (badLinks.first xor badLinks.second)};
478 if (result) {
481 IdentifierHash otherSide;
482 m_sctID->get_other_side(hashID, otherSide);
483 errs.add(otherSide, error);
484 ATH_MSG_DEBUG("Adding error to side " << 1-side << " for module with RX redundancy " << otherSide);
485 }
486 }
487
488 return StatusCode::SUCCESS;
489}
490
491// setFirstTempMaskedChip method
492
494 unsigned int firstTempMaskedChip,
495 SCT_RodDecoderErrorsHelper& errs) const
496{
497 if (not hashID.is_valid()) {
498 ATH_MSG_INFO("setFirstTempMaskedChip hashID " << hashID << " is invalid.");
499 return StatusCode::RECOVERABLE;
500 }
501 if (firstTempMaskedChip==0) {
502 ATH_MSG_WARNING("setFirstTempMaskedChip: firstTempMaskedChip should be greater than 0. firstTempMaskedChip is "
503 << firstTempMaskedChip);
504 return StatusCode::RECOVERABLE;
505 }
506
507 // wafer hash -> wafer id -> module id -> wafer hash on side-0, wafer hash on side-1
508 const Identifier waferID{m_sctID->wafer_id(hashID)};
509 const Identifier moduleID{m_sctID->module_id(waferID)};
510
511 // Side 0
512 IdentifierHash hashSide0;
513 m_sctID->get_hash(moduleID, hashSide0, &m_contextSCT);
514 unsigned int firstTempMaskedChipSide0{0};
515 if (hashID==hashSide0) firstTempMaskedChipSide0 = firstTempMaskedChip;
516
517 // Side 1
518 IdentifierHash hashSide1;
519 m_sctID->get_other_side(hashSide0, hashSide1);
520 unsigned int firstTempMaskedChipSide1{0};
521 if (hashID==hashSide1) firstTempMaskedChipSide1 = firstTempMaskedChip;
522
523 int type{0};
524 // Check if Rx redundancy is used or not in this module
525 const std::pair<bool, bool> badLinks{m_configTool->badLinks(hashID)};
526 if (badLinks.first xor badLinks.second) {
527 // Rx redundancy is used in this module.
528 if (badLinks.first and not badLinks.second) {
529 // link-1 is broken
530 type = 1;
531 }
532 else if (badLinks.second and not badLinks.first) {
533 // link-0 is broken
534 type = 2;
535 }
536 else if (badLinks.first and badLinks.second) {
537 // Both link-0 and link-1 are working
538 ATH_MSG_WARNING("setFirstTempMaskedChip: Both link-0 and link-1 are working. But Rx redundancy is used... Why?");
539 return StatusCode::RECOVERABLE;
540 }
541 else {
542 // Both link-0 and link-1 are broken
543 ATH_MSG_WARNING("setFirstTempMaskedChip: Both link-0 and link-1 are broken. But data are coming... Why?");
544 return StatusCode::RECOVERABLE;
545 }
546 }
547
548 // "Modified" module (using Rx redundancy) case
549 // Information of modified modules are found in
550 // modified0 and modified1 functions of SCT_ReadoutTool.cxx and
551 // Table 3.8 of CERN-THESIS-2008-001 https://cds.cern.ch/record/1078223
552 // However, there are two exceptions of the exceptions.
553 const unsigned long long fullSerialNumber{m_cabling->getSerialNumberFromHash(hashID).to_ulonglong()};
554 if (// Readout through link-0
555 fullSerialNumber==20220170200183 or // hash=4662 bec=0 layer=2 eta= 6 phi=39
556 fullSerialNumber==20220330200606 or // hash=5032 bec=0 layer=3 eta=-2 phi= 7
557 fullSerialNumber==20220330200693 // hash=5554 bec=0 layer=3 eta=-5 phi=29
558 ) {
559 if (type!=1) ATH_MSG_WARNING("Link-0 is broken but modified module readingout link-0, inconsistent");
560 type = 3;
561
562 // An exception:
563 // fullSerialNumber=20220170200941, hash=3560 bec=0 layer=1 eta=-6 phi=34
564 // This module is a modified one. However, it is not using modified configuration.
565 // Readout sequence is 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11.
566 }
567 if (// Readout through link-1
568 fullSerialNumber==20220170200653 or // hash=2786 bec=0 layer=1 eta= 4 phi= 1
569 fullSerialNumber==20220330200117 or // hash=5516 bec=0 layer=3 eta= 1 phi=27
570 fullSerialNumber==20220330200209 or // hash=5062 bec=0 layer=3 eta= 2 phi= 8
571 fullSerialNumber==20220330200505 or // hash=5260 bec=0 layer=3 eta= 5 phi=16
572 fullSerialNumber==20220330200637 or // hash=4184 bec=0 layer=2 eta=-6 phi=20
573 fullSerialNumber==20220330200701 // hash=4136 bec=0 layer=2 eta=-6 phi=18
574 ) {
575 if (type!=2) ATH_MSG_WARNING("Link-1 is broken but modified module readingout link-1, inconsistent");
576 type = 4;
577
578 // Another exception:
579 // fullSerialNumber=20220170200113, hash=3428 bec=0 layer=1 eta= 1 phi=28
580 // This module is a modified one. However, it is not using modified configuration.
581 // Readout sequence is 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5.
582 }
583
584 static const int chipOrder[5][N_SIDES*N_CHIPS_PER_SIDE]{
585 // type=0 not prepared for both link-0 and link-1 are working
586 {},
587 // type=1 link-1 is broken: chip 0 1 2 3 4 5 6 7 8 9 10 11
588 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
589 // type=2 link-0 is broken: chip 6 7 8 9 10 11 0 1 2 3 4 5
590 {6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5},
591 // type=3 "modified" modules and link-1 is broken: chip 0 1 2 3 4 5 7 8 9 10 11 6
592 {0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 6},
593 // type=4 "modified" modules and link-0 is broken: chip 6 7 8 9 10 11 1 2 3 4 5 0
594 {6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 0}
595 };
596
597 if (type==0) {
598 // Both link-0 and link-1 are working
599
600 // Chips 0-5 are on side 0 and chips 6-11 are on side 1.
601 // Normally, modules send hits on side 0 via link-0 and side 1 via link-1.
602 // The first temporally masked chip value is the id of the chip that is
603 // first masked in the readout chain "plus one".
604 // If the value is in between 1 to 6, it indicates side 0.
605 // If the value is in between 7 to 12, it indicates side 1.
606 // However, some special modules send hits on side 0 via link-1 and hits on
607 // side 1 via link-0. If the first masked chip value on side 1 (0) is
608 // between 1 to 6 (7 to 12), it indicates the module is a special one.
609 // In that case, information is swapped.
610 if ((N_CHIPS_PER_SIDE<firstTempMaskedChipSide0 and firstTempMaskedChipSide0<=N_SIDES*N_CHIPS_PER_SIDE) or
611 ( 0<firstTempMaskedChipSide1 and firstTempMaskedChipSide1<= N_CHIPS_PER_SIDE)) {
612 const unsigned int swapFirstTempMaskedChipSide0{firstTempMaskedChipSide0};
613 firstTempMaskedChipSide0 = firstTempMaskedChipSide1;
614 firstTempMaskedChipSide1 = swapFirstTempMaskedChipSide0;
615 }
616
617 if (firstTempMaskedChipSide0>0) {
618 for (unsigned int iChip{firstTempMaskedChipSide0-1}; iChip<N_CHIPS_PER_SIDE; iChip++) {
620 }
621 }
622 if (firstTempMaskedChipSide1>N_CHIPS_PER_SIDE) {
623 for (unsigned int iChip{firstTempMaskedChipSide1-1}; iChip<N_SIDES*N_CHIPS_PER_SIDE; iChip++) {
625 }
626 }
627 }
628 else {
629 // type=1, 2, 3, 4: cases using Rx redundancy
630 bool toBeMasked{false};
631 for (int iChip{0}; iChip<N_SIDES*N_CHIPS_PER_SIDE; iChip++) {
632 int jChip{chipOrder[type][iChip]};
633 if (jChip==static_cast<int>(firstTempMaskedChip-1)) toBeMasked = true;
634 if (toBeMasked) {
635 if (jChip<N_CHIPS_PER_SIDE) {
637 }
638 else {
640 }
641 }
642 }
643 }
644
645 ATH_MSG_VERBOSE("setFirstTempMaskedChip Hash " << hashID
646 << " SerialNumber " << m_cabling->getSerialNumberFromHash(hashID).str()
647 << " moduleID " << moduleID
648 << " barrel_ec " << m_sctID->barrel_ec(waferID)
649 << " layer_disk " << m_sctID->layer_disk(waferID)
650 << " eta_module " << m_sctID->eta_module(waferID)
651 << " phi_module " << m_sctID->phi_module(waferID)
652 << " side " << m_sctID->side(waferID)
653 << " firstTempMaskedChip " << firstTempMaskedChip);
654 return StatusCode::SUCCESS;
655}
656
657StatusCode SCT_RodDecoder::processHeader(const uint16_t inData,
658 const uint32_t robID,
660 SCT_RDO_Container& rdoIDCont,
661 DataPool<SCT3_RawData>* dataItemsPool,
662 CacheHelper& cache,
664 bool& hasError,
665 bool& breakNow,
666 const EventContext& ctx) const
667{
668 StatusCode sc{StatusCode::SUCCESS};
669
670 data.foundHeader = true;
671 m_headNumber++;
672
673 // Create the last RDO of the previous link if any
674 if (data.isStripValid()) {
675 if (not data.isSaved(false) and data.isOldStripValid()) {
676
677 const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
678 if (rdoMade == -1) {
679 hasError = true;
680 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
681 }
682 else {
683 data.setSaved(false, rdoMade);
684 }
685 }
686 }
687
688 // Everything is set to default for a new hunt of RDO
689 data.reset();
690
691 // Link Number (or stream) in the ROD fragment
692 const int rodlinkNumber{static_cast<int>(inData & 0x7F)};
693
694 // This is the real calculation for the offline
695 data.linkNumber = (((rodlinkNumber >>4)&0x7)*12+(rodlinkNumber &0xF));
696 const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
697 IdentifierHash hash;
698 if ((onlineID ==0) or (data.linkNumber > 95)) {
699 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
700 hasError = true;
701 ATH_MSG_DEBUG("Header: xxx Link number out of range (skipping following data)"
702 << std::dec << data.linkNumber);
703 breakNow = true;
704 return sc;
705 }
706 else {
707 hash = m_cabling->getHashFromOnlineId(onlineID, ctx);
708 if (hash.is_valid()) {
709 data.setCollection(m_sctID, hash, rdoIDCont, dataItemsPool, errs);
710 }
711 else {
712 std::stringstream msg;
713 msg <<std::hex << onlineID;
714 ATH_MSG_WARNING("Rob fragment (rob=" << robID << ") with invalid onlineID " << msg.str() << " -> " << hash << ".");
715 }
716 }
717 // Look for masked off links - bit 7
718 if ((inData >> 7) & 0x1) {
719 ATH_MSG_DEBUG("Masked link " << onlineID << " " << data.linkIDHash);
720 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::MaskedLink, errs));
721 hasError = true;
722 }
723 if (inData & 0x800) {
724 ATH_MSG_DEBUG(" Header: xxx TimeOut Error " << data.linkIDHash);
726 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::TimeOutError, errs));
727 hasError = true;
728 }
729
730 if (inData & 0x1000) {
731 ATH_MSG_DEBUG(" Header: xxx Preamble Error " << data.linkIDHash);
733 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::PreambleError, errs));
734 hasError = true;
735 }
736
737 if (inData & 0x400) {
738 ATH_MSG_DEBUG(" Header: xxx LVL1 ID Error " << data.linkIDHash);
740 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::LVL1IDError, errs));
741 hasError = true;
742 }
743
744 if (inData & 0x200) {
745 ATH_MSG_DEBUG(" Header: xxx BCID Error " << data.linkIDHash);
747 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::BCIDError, errs));
748 hasError = true;
749 }
750
751 if ((inData & 0xF) > 11) {
752 ATH_MSG_DEBUG(" Header: xxx Error in formatter " << data.linkIDHash);
754 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::FormatterError, errs));
755 hasError = true;
756 }
757 if (!hasError and not hash.is_valid()) {
758 std::stringstream msg;
759 msg <<std::hex << onlineID;
760 ATH_MSG_WARNING("Rob fragment (rob=" << robID << ") with invalid onlineID " << msg.str() << " -> " << hash << ".");
761 hasError = true;
762 }
763
764 data.condensedMode = static_cast<bool>(inData & 0x100);
765
766 return sc;
767}
768
769StatusCode SCT_RodDecoder::processSuperCondensedHit(const uint16_t inData,
770 const uint32_t robID,
772 SCT_RDO_Container& rdoIDCont,
773 DataPool<SCT3_RawData>* dataItemsPool,
774 CacheHelper& cache,
776 bool& hasError,
777 const EventContext& ctx) const
778{
779 StatusCode sc{StatusCode::SUCCESS};
780
781 // Super-condensed mode:
782 // Chip info: 4 bits data16[n]>>11) & 0xF
783 // Chip number == (data16[n]>>11) & 0x7
784 // Chip side == (data16[n]>>14) & 0x1
785 // For example if (data16[n]>>11) & 0xF = 0b0101 => chip 5 or chip5 on side0, (data16[n]>>11) & 0xF = 0b1101 => chip13 or chip5 on side1
786 const int chip{(inData>>11) & 0x7};
787 data.side = ((inData>>14) & 0x1);
788 data.strip = chip*N_STRIPS_PER_CHIP + ((inData>>4) & 0x7F);
789 data.timeBin = 0x2; // Assuming timeBin is 010 in super-condensed mode
790 const int nStripsInWord{(inData & 0xF)+1};
791 if (chip>=N_CHIPS_PER_SIDE) {
792 ATH_MSG_DEBUG(" Hit super-condensed : xxx Chip number = " << chip << " >= "<< N_CHIPS_PER_SIDE << " for hit "
793 << std::hex << inData);
795 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
796 hasError = true;
797 return sc;
798 }
799
800 // Search for redundancy only for the master chip
801 bool secondSide{false};
802 if ((data.side==1) and ((data.linkNumber%2)==0)) {
803 if (((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) and (data.groupSize>0)) {
804 // If it is a new cluster, make RDO with the previous cluster
805 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
806 if (rdoMade == -1) {
807 hasError = true;
808 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
809 }
810 else {
811 data.setSaved(true, rdoMade);
812 }
813 data.setOld();
814 }
815 data.linkNumber++;
816 secondSide = true;
817 }
818 else if ((data.side==0) and ((data.linkNumber%2)!=0)) {
819 if (((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) and (data.groupSize>0)) {
820 // If it is a new cluster, make RDO with the previous cluster
821 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
822 if (rdoMade == -1) {
823 hasError = true;
824 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
825 }
826 else {
827 data.setSaved(true, rdoMade);
828 }
829 data.setOld();
830 }
831 data.linkNumber--;
832 secondSide = true;
833 }
834 if (secondSide) {
835 const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
836 IdentifierHash id_hash(m_cabling->getHashFromOnlineId(onlineID,ctx));
837 if (!id_hash.is_valid()) {
838 hasError = true;
839 return sc;
840 }
841 data.setCollection(m_sctID, id_hash, rdoIDCont, dataItemsPool, errs);
842 }
843
844 if (data.groupSize == 0) {
845 data.setOld(); // If it's the first super-condensed word
846 }
847
848 if ((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) {
849 // If it is a new cluster, make RDO with the previous cluster
850 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
851 if (rdoMade == -1) {
852 hasError = true;
853 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
854 }
855 else {
856 data.setSaved(true, rdoMade);
857 }
858 data.setOld();
859 }
860 data.groupSize += nStripsInWord; // Split clusters have the same strip number.
861
862 return sc;
863}
864
865StatusCode SCT_RodDecoder::processCondensedHit(const uint16_t inData,
866 const uint32_t robID,
868 SCT_RDO_Container& rdoIDCont,
869 DataPool<SCT3_RawData>* dataItemsPool,
870 CacheHelper& cache,
872 bool& hasError,
873 const EventContext& ctx) const
874{
875 StatusCode sc{StatusCode::SUCCESS};
876
877 const int chip{(inData>>11) & 0x7};
878 data.side = ((inData>>14) & 0x1);
879 data.strip = chip*N_STRIPS_PER_CHIP + ((inData>>4) & 0x7F);
880 data.timeBin = 0x2; // Assuming timeBin is 010 in condensed mode
881 if (chip>=N_CHIPS_PER_SIDE) {
882 ATH_MSG_DEBUG(" Hit condensed : xxx Chip number = " << chip << " >= " << N_CHIPS_PER_SIDE << " for hit "
883 << std::hex << inData);
885 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
886 hasError = true;
887 return sc;
888 }
889
890 // Search for redundancy only for the master chip
891 bool secondSide{false};
892 if ((data.side==1) and ((data.linkNumber%2)==0)) {
893 if (((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) and (data.groupSize>0)) {
894 // If it is a new cluster, make RDO with the previous cluster
895 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
896 if (rdoMade == -1) {
897 hasError = true;
898 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
899 }
900 else {
901 data.setSaved(true, rdoMade);
902 }
903 data.setOld();
904 }
905 data.linkNumber++;
906 secondSide = true;
907 }
908 else if ((data.side==0) and ((data.linkNumber%2)!=0)) {
909 if (((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) and (data.groupSize>0)) {
910 // If it is a new cluster, make RDO with the previous cluster
911 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
912 if (rdoMade == -1) {
913 hasError = true;
914 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
915 }
916 else {
917 data.setSaved(true, rdoMade);
918 }
919 data.setOld();
920 }
921 data.linkNumber--;
922 secondSide = true;
923 }
924 if (secondSide) {
925 const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
926 data.setCollection(m_sctID, m_cabling->getHashFromOnlineId(onlineID, ctx), rdoIDCont, dataItemsPool, errs);
927 }
928
929 if (data.groupSize == 0) {
930 data.setOld(); // If it's the first condensed word
931 }
932
933 if (not (inData & 0x1)) { // 1-hit
935 if ((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) {
936 // If it is a new cluster, make RDO with the previous cluster
937 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
938 if (rdoMade == -1) {
939 hasError = true;
940 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
941 }
942 else {
943 data.setSaved(true, rdoMade);
944 }
945 data.setOld();
946 }
947
948 if (inData & 0x4) { // Error in the hit
949 ATH_MSG_DEBUG(" Hit condensed : xxx ERROR in 1-hit " << std::hex << inData);
950 data.errorHit.push_back(data.groupSize);
951 data.errors = (data.errors | 0x10);
953 hasError = true;
954 }
955 data.groupSize = (data.groupSize>=2 ? data.groupSize : 1);
956 }
957 else { // 2-hits
958 if (data.strip >= N_STRIPS_PER_SIDE) {
959 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
960 hasError = true;
961
962 ATH_MSG_DEBUG("Condensed mode - strip number out of range");
963
964 return sc;
965 }
967 if ((data.strip!=data.oldStrip) or (data.side!=data.oldSide)) {
968 // If it is a new cluster, make RDO with the previous cluster
969 const int rdoMade{makeRDO(true, data, cache, dataItemsPool)};
970 if (rdoMade == -1) {
971 hasError = true;
972 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
973 }
974 else {
975 data.setSaved(true, rdoMade);
976 }
977 data.setOld();
978 }
979 if (inData & 0x4) { // Error in the first hit
980 ATH_MSG_DEBUG(" Hit condensed : xxx ERROR in 1st hit" << std::hex << inData);
981 data.errorHit.push_back(data.groupSize);
983 data.errors = (data.errors | 0x10);
984 hasError = true;
985 }
986 if (inData & 0x8) { // Error in the second hit
987 ATH_MSG_DEBUG(" Hit condensed : xxx ERROR in 2nd hit" << std::hex << inData);
988 data.errorHit.push_back(data.groupSize);
990 data.errors = (data.errors | 0x20);
991 hasError = true;
992 }
993 data.groupSize = 2;
994 }
995
996 return sc;
997}
998
999StatusCode SCT_RodDecoder::processExpandedHit(const uint16_t inData,
1000 const uint32_t robID,
1002 SCT_RDO_Container& rdoIDCont,
1003 DataPool<SCT3_RawData>* dataItemsPool,
1004 CacheHelper& cache,
1006 bool& hasError,
1007 const EventContext& ctx) const
1008{
1009 StatusCode sc{StatusCode::SUCCESS};
1010
1011 int chip{0};
1012 if (not (inData & 0x8)) { // 1st hit cluster expanded
1014 chip = ((inData>>11) & 0x7);
1015 data.side = ((inData>>14) & 0x1);
1016 data.strip = chip*N_STRIPS_PER_CHIP + ((inData>>4) & 0x7F);
1017 data.timeBin = (inData & 0x7); // Real way for obtaining timeBin info
1018
1019 if (chip>=N_CHIPS_PER_SIDE) {
1020 ATH_MSG_DEBUG("Expanded hit: First hit xxx ERROR chip Nb = " << chip << " >= " << N_CHIPS_PER_SIDE);
1022 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
1023 return sc;
1024 }
1025
1026 // Search for redundancy only for the master chip
1027 bool secondSide{false};
1028 if ((data.side==1) and ((data.linkNumber%2)==0)) {
1029 data.linkNumber++;
1030 secondSide = true;
1031 }
1032 else if ((data.side==0) and ((data.linkNumber%2)!=0)) {
1033 data.linkNumber--;
1034 secondSide = true;
1035 }
1036 if (secondSide) {
1037 const uint32_t onlineID{(robID & 0xFFFFFF) | (data.linkNumber << 24)};
1038 data.setCollection(m_sctID, m_cabling->getHashFromOnlineId(onlineID, ctx), rdoIDCont, dataItemsPool, errs);
1039 }
1040 data.groupSize = 1;
1041 const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
1042 if (rdoMade == -1) {
1043 hasError = true;
1044 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
1045 }
1046 else {
1047 data.setSaved(false, rdoMade);
1048 }
1049 data.groupSize = 0;
1050 }
1051 else { // Next hits cluster expanded
1052 if (inData & 0x80) { // Paired hits
1053 if (data.strip >= N_STRIPS_PER_SIDE-2) {
1054 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
1055 hasError = true;
1056 ATH_MSG_DEBUG("Expanded mode - strip number out of range");
1057 return sc;
1058 }
1060 // First hit from the pair
1061 data.strip++;
1062 data.timeBin = (inData & 0x7);
1063 data.groupSize = 1;
1064 const int rdoMade1{makeRDO(false, data, cache, dataItemsPool)};
1065 if (rdoMade1 == -1) {
1066 hasError = true;
1067 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
1068 }
1069 else {
1070 data.setSaved(false, rdoMade1);
1071 }
1072 // Second hit from the pair
1073 data.strip++;
1074 data.timeBin = ((inData >> 4) & 0x7);
1075 const int rdoMade2{makeRDO(false, data, cache, dataItemsPool)};
1076 if (rdoMade2 == -1) {
1077 hasError = true;
1078 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
1079 }
1080 else {
1081 data.setSaved(false, rdoMade2);
1082 }
1083 data.groupSize = 0;
1084 }
1085 else { // Last hit of the cluster
1087 if (data.strip >= N_STRIPS_PER_SIDE-1) {
1088 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
1089 hasError = true;
1090 ATH_MSG_DEBUG("Expanded mode - strip number out of range");
1091 return sc;
1092 }
1093 data.strip++;
1094 data.timeBin = (inData & 0x7);
1095 data.groupSize = 1;
1096 const int rdoMade{makeRDO(false, data, cache, dataItemsPool)};
1097 if (rdoMade == -1) {
1098 hasError = true;
1099 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ByteStreamParseError, errs));
1100 }
1101 else {
1102 data.setSaved(false, rdoMade);
1103 }
1104 data.groupSize = 0;
1105 }
1106 }
1107
1108 return sc;
1109}
1110
1111StatusCode SCT_RodDecoder::processABCDError(const uint16_t inData,
1112 const uint32_t robID,
1115 bool& hasError) const
1116{
1117 StatusCode sc{StatusCode::SUCCESS};
1118
1119 if (not data.foundHeader) {
1120 ATH_MSG_INFO(" Missing link header in ROD " << std::hex << robID << std::dec);
1121 data.foundMissingLinkHeaderError = true;
1123 hasError = true;
1124 return sc;
1125 }
1126
1127 const int chip{(inData>>3) & 0xF};
1128 const int abcError{inData & 0x7};
1129 ATH_MSG_DEBUG(" xxx Flagged ABCD ERROR in chip " << chip
1130 << " Error code abcError " << abcError << " Link Number (or Stream) " << data.linkNumber);
1132 // Error code of ABCD error should be 1, 2, 4 or 7.
1133 if (abcError!=0x1 and abcError!=0x2 and abcError!=0x4 and abcError!=0x7) {
1134 ATH_MSG_DEBUG("ABCD error has an invalid error code " << abcError
1135 << " the 16-bit word is 0x" << std::hex << inData << std::dec
1136 << " for hash " << data.linkIDHash);
1137 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Invalid, errs));
1138 }
1139 else {
1140 // Chip is 4 bits. The highest bit 3 represents side. Chip 0-5 on side 0 and chip 8-13 on side 1.
1141 const unsigned int sideABCDError{static_cast<unsigned int>(chip/8)};
1142 if (data.linkIDHash.value()%2!=sideABCDError) {
1143 // If the sides from the ABCD error and online ID are different,
1144 // the module is expected to read side 0 via link 1 and side 1 and via link 0.
1145 // Hash Id is flipped.
1146 ATH_MSG_DEBUG("ABCD error and online ID have different side information for hash " << data.linkIDHash << ". "
1147 << sideABCDError << " from ABCD error and " << data.linkIDHash.value()%2 << " from online ID");
1148 data.linkIDHash = (data.linkIDHash.value()/2)*2+sideABCDError;
1149 errs.noerror(data.linkIDHash);
1150 }
1151 // Chip should be 0-5 or 8-13.
1152 if (chip%8>=N_CHIPS_PER_SIDE) {
1153 ATH_MSG_DEBUG("ABCD error has an invalid chip 0x" << std::hex << chip << std::dec
1154 << " the 16-bit word is 0x" << std::hex << inData << std::dec
1155 << " for hash " << data.linkIDHash.value());
1156 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Invalid, errs));
1157 }
1158 else {
1159 if ( abcError==0x1) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Error1, errs));
1160 else if (abcError==0x2) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Error2, errs));
1161 else if (abcError==0x4) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Error4, errs));
1162 else if (abcError==0x7) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Error7, errs));
1163 if ( chip%8==0) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip0, errs));
1164 else if (chip%8==1) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip1, errs));
1165 else if (chip%8==2) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip2, errs));
1166 else if (chip%8==3) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip3, errs));
1167 else if (chip%8==4) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip4, errs));
1168 else if (chip%8==5) ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError_Chip5, errs));
1169 }
1170 }
1171 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::ABCDError, errs));
1172 hasError = true;
1173
1174 return sc;
1175}
1176
1177StatusCode SCT_RodDecoder::processRawData(const uint16_t inData,
1178 const uint32_t robID,
1181 bool& hasError) const
1182{
1183 StatusCode sc{StatusCode::SUCCESS};
1184
1185 if (not data.foundHeader) {
1186 ATH_MSG_INFO(" Missing link header in ROD " << std::hex << robID << std::dec);
1187 data.foundMissingLinkHeaderError = true;
1189 hasError = true;
1190 return sc;
1191 }
1192
1193 ATH_MSG_DEBUG(" xxx Raw Data Mode " << std::hex << inData << std::dec << ": Config Data Mode ");
1194 // Too many errors in the BS for the ROD to decode the data
1196 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::RawError, errs));
1197 hasError = true;
1198
1199 return sc;
1200}
1201
1202StatusCode SCT_RodDecoder::processTrailer(const uint16_t inData,
1203 const uint32_t /*robID*/,
1206 bool& hasError) const
1207{
1208 StatusCode sc{StatusCode::SUCCESS};
1209 /* Temporarily disabled
1210 if (not data.foundHeader) {
1211 ATH_MSG_INFO(" Missing link header in ROD " << std::hex << robID << std::dec);
1212 data.foundMissingLinkHeaderError = true;
1213 m_numMissingLinkHeader++;
1214 hasError = true;
1215 }
1216 */
1217
1218 data.foundHeader = false;
1219
1221
1222 if (inData & 0x1000) {
1223 ATH_MSG_DEBUG(" Trailer: xxx Trailer ERROR " << std::hex << inData);
1225 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::TrailerError, errs));
1226 hasError = true;
1227 }
1228
1229 if (inData & 0x800) {
1230 // No data should appear between header and trailer
1231 // See 1.2.2 Formatter FPGA - Serial Data Decoding and Formatting of
1232 // http://www-eng.lbl.gov/~jmjoseph/Atlas-SiROD/Manuals/usersManual-v164.pdf
1233 ATH_MSG_DEBUG(" Trailer: xxx Header-Trailer limit ERROR " << std::hex << inData);
1235 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::HeaderTrailerLimitError, errs));
1236 hasError = true;
1237 }
1238
1239 if (inData & 0x400) {
1240 // Not sure if there are hit elements before (probably yes but in principle they are fine)
1241 ATH_MSG_DEBUG(" Trailer: xxx Data Overflow ERROR " << std::hex << inData);
1243 ATH_CHECK(addSingleError(data.linkIDHash, SCT_ByteStreamErrors::TrailerOverflowError, errs));
1244 hasError = true;
1245 }
1246 if (inData & 0xF) {
1247 // First temporarily masked chip information
1248 // 0 means no masked chip (always has been 0 until April 2017)
1249 //
1250 // If Rx redundacy is not used,
1251 // 1 means chips 0-5 are temporarily masked.
1252 // 6 means chip 5 is temporarily masked.
1253 // 7 means chips 6-11 are temporarily masked.
1254 // 12 means chip 11 is temporarily masked.
1255 //
1256 // If Rx redundacy is used and link-1 is not used,
1257 // 1 means chips 0-11 are temporarily masked.
1258 // 6 means chips 5-11 are 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-0 is not used,
1263 // 1 means chips 0-5 are temporarily masked.
1264 // 6 means chip 5 is temporarily masked.
1265 // 7 means chips 6-11, 0-5 are temporarily masked.
1266 // 12 means chips 11, 0-5 are temporarily masked.
1267 setFirstTempMaskedChip(data.linkIDHash, (inData & 0xF), errs).ignore();
1268 }
1269
1270 return sc;
1271}
#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)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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.
bool is_valid() const
Check if id is in a valid state.
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.
StatusCode addSingleError(const IdentifierHash &hashID, SCT_ByteStreamErrors::ErrorType error, SCT_RodDecoderErrorsHelper &errs) const
Add single eror.
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.
StatusCode processRawData(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RodDecoderErrorsHelper &errs, bool &hasError) const
Process raw data word.
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.
StatusCode setFirstTempMaskedChip(const IdentifierHash &hashID, unsigned int firstTempMaskedChip, SCT_RodDecoderErrorsHelper &errs) const
Set first temporarily masked chip information from byte stream trailer.
IdContext m_contextSCT
"Context" of an expanded identifier (ExpandedIdentifier) for compact or hash versions (Identifier32 o...
StatusCode addRODError(uint32_t rodID, SCT_ByteStreamErrors::ErrorType error, SCT_RodDecoderErrorsHelper &errs, const std::unordered_set< IdentifierHash > *foundHashes=nullptr) const
Add an error for each wafer in the problematic ROD.
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.
StatusCode processABCDError(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RodDecoderErrorsHelper &errs, bool &hasError) const
Process ABCD error.
SCT_RodDecoder(const std::string &type, const std::string &name, const IInterface *parent)
Constructor.
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.
StatusCode processTrailer(const uint16_t inData, const uint32_t robID, SharedData &data, SCT_RodDecoderErrorsHelper &errs, bool &hasError) const
Process trailer word.
std::atomic_uint m_maskedLinkNumber
Total number of masked links in the header data.
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.
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.
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.
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:138
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.
const std::vector< IdentifierHash > * vecHash
Struct to hold data shared in methods used in fillCollection method.
MsgStream & msg
Definition testRead.cxx:32