ATLAS Offline Software
Loading...
Searching...
No Matches
PixelRodDecoder.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 "PixelRodDecoder.h"
12#include "eformat/SourceIdentifier.h"
14
15#include <fstream>
16#include <iostream>
17#include <unordered_set>
18#include <string>
19
20//#define PIXEL_DEBUG ;
21namespace {
22 constexpr unsigned long long operator"" _BIT(unsigned long long bitPosition){
23 return 1ull << bitPosition;
24 }
25}
26
27#define generalwarning(x) \
28 if (this->m_numGenWarnings < this->m_maxNumGenWarnings) \
29 {ATH_MSG_DEBUG(x); ++this->m_numGenWarnings;} \
30 else if (this->m_numGenWarnings == this->m_maxNumGenWarnings) \
31 {ATH_MSG_DEBUG("PixelRodDecoder: suppressing further general warnings"); ++this->m_numGenWarnings;} \
32 else {++this->m_numGenWarnings; /* No warning */}
33
34#define lvl1id_bcid_warning(x) \
35 if (this->m_numBCIDWarnings < this->m_maxNumBCIDWarnings) \
36 {ATH_MSG_DEBUG(x); ++this->m_numBCIDWarnings;} \
37 else if (this->m_numBCIDWarnings == this->m_maxNumBCIDWarnings) \
38 {ATH_MSG_DEBUG("PixelRodDecoder: suppressing further BCID/LVL1ID warnings"); ++this->m_numBCIDWarnings;} \
39 else {++this->m_numBCIDWarnings; /* No warning */}
40
41
43
44inline bool isIBL( uint32_t robId ) { return ((robId>>16) & 0xFF)==0x14; }
45inline bool isDBM( uint32_t robId ) { return ((robId>>16) & 0xFF)==0x15; }
46
47//--------------------------------------------------------------------------- constructor
49( const std::string& type, const std::string& name,const IInterface* parent )
50 : AthAlgTool(type,name,parent),
51 m_is_ibl_present(false){
52 declareInterface< IPixelRodDecoder >( this );
53}
54
55//--------------------------------------------------------------------------- destructor
56//destructor
60
61//--------------------------------------------------------------------------- initialize
62
63
65 ATH_MSG_INFO("PixelRodDecoder::initialize()");
66 ATH_CHECK(m_pixelReadout.retrieve());
67 ATH_CHECK(detStore()->retrieve(m_pixel_id, "PixelID"));
68 const InDetDD::PixelDetectorManager* pixelManager;
69 ATH_CHECK(detStore()->retrieve(pixelManager, "Pixel"));
70 // check if the ibl layer is present or not (this is necessary for backward compatibility with non-IBL geometries)
71 m_is_ibl_present = false;
72 const InDetDD::SiNumerology& pixSiNum = pixelManager->numerology();
73 m_is_ibl_present = (pixSiNum.numLayers() == 4);
74 ATH_MSG_DEBUG( "m_is_ibl_present = " << m_is_ibl_present );
75 // Retrieve Pixel Errors Service
76 ATH_CHECK(m_condCablingKey.initialize());
78 return StatusCode::SUCCESS;
79}
80
81
82//--------------------------------------------------------------------------- finalize
84
85#ifdef PIXEL_DEBUG
86 ATH_MSG_VERBOSE( "in PixelRodDecoder::finalize" );
87 ATH_MSG_DEBUG(m_masked_errors << " times BCID and LVL1ID error masked" );
88#endif
89
90 ATH_MSG_INFO("Total number of warnings (output limit)");
91 ATH_MSG_INFO("General (corruption / illegal value)\t" << m_numGenWarnings << " (" << m_maxNumGenWarnings << ")");
92 ATH_MSG_INFO("Unexpected BCID / LVL1ID \t" << m_numBCIDWarnings << " (" << m_maxNumBCIDWarnings << ")");
93 if (m_checkDuplicatedPixel) ATH_MSG_INFO("Duplicated pixels \t" << m_numDuplicatedPixels);
94 ATH_MSG_INFO(" --- Summary from PixelRodDecoder --- ");
95 ATH_MSG_INFO(" - Number of invalid Identifiers Errors: " << m_numInvalidIdentifiers);
96 ATH_MSG_INFO(" - Number of Preamble Errors: " << m_numPreambleErrors);
97 ATH_MSG_INFO(" - Number of TimeOut Errors: " << m_numTimeOutErrors);
98 ATH_MSG_INFO(" - Number of LVL1ID Errors: " << m_numLVL1IDErrors);
99 ATH_MSG_INFO(" - Number of BCID Errors: " << m_numBCIDErrors);
100 ATH_MSG_INFO(" - Number of Flagged Errors: " << m_numFlaggedErrors);
101 ATH_MSG_INFO(" - Number of Trailer Errors: " << m_numTrailerErrors);
102 ATH_MSG_INFO(" - Number of Disabled FE Errors: " << m_numDisabledFEErrors);
103 ATH_MSG_INFO(" - Number of ROD Errors: " << m_numRODErrors);
104 ATH_MSG_INFO(" - Number of links masked by PPC: " << m_numLinkMaskedByPPC);
105 ATH_MSG_INFO(" - Number of header/trailer limit errors: " << m_numLimitError);
106 ATH_MSG_INFO(" - Number of Unknown word Errors: " << m_numDecodingErrors);
107 ATH_MSG_INFO(" --------------------------------------------- ");
108 return StatusCode::SUCCESS;
109}
110
112 uint32_t robId,
113 std::array<uint64_t, PixelRodDecoder::ERROR_CONTAINER_MAX> &bsErrWord,
114 IDCInDetBSErrContainer& decodingErrors,
116 const char *error_description) const {
117 assert( pixCabling);
118 const std::deque<Identifier> offlineIdList = pixCabling->find_entry_offlineList(robId);
119 for (const Identifier& id: offlineIdList) {
120 IdentifierHash idHash = m_pixel_id->wafer_hash(id);
121 PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(idHash)],error_code);
122 }
123 ATH_MSG_DEBUG("ROB status word for robid 0x"<< std::hex << robId << std::dec <<" indicates " << error_description << ".");
124 assert( bsErrWord.size() <= decodingErrors.maxSize() );
125 for (size_t i=0; i<static_cast<size_t>(bsErrWord.size()); i++) {
126 if (bsErrWord[i]>0) {
127 decodingErrors.setOrDrop(i,bsErrWord[i]);
128 }
129 }
130}
131
132//---------------------------------------------------------------------------------------------------- fillCixollection
133StatusCode PixelRodDecoder::fillCollection( const ROBFragment *robFrag, IPixelRDO_Container* rdoIdc, IDCInDetBSErrContainer& decodingErrors, std::vector<IdentifierHash>* vecHash, const EventContext& ctx) const {
134#ifdef PIXEL_DEBUG
135 ATH_MSG_VERBOSE( "-------------------------------------------------------------------------------------------------------------");
136 ATH_MSG_DEBUG("Entering PixelRodDecoder");
137#endif
138
139 const Identifier invalidPixelId = Identifier(); // used by Cabling for an invalid entry
140 Identifier pixelId;
141 uint64_t onlineId(0);
142 bool isIBLModule = false;
143 bool isDBMModule = false;
144 uint32_t rodId = robFrag->rod_source_id(); // get source ID => method of ROBFragment, Returns the source identifier of the ROD fragment
145 uint32_t robId = robFrag->rob_source_id(); // get source ID => returns the Identifier of the ROB fragment. More correct to use w.r.t. rodId.
146 uint32_t robBCID = robFrag->rod_bc_id();
147 if ( isIBL( robId ) && robId != rodId ) { // isIBL(robId)
148 generalwarning("Discrepancy in IBL SourceId: ROBID 0x" << std::hex << robId << " unequal to RODID 0x" << rodId);
149 }
151 std::unique_ptr<SG::ReadCondHandle<PixelHitDiscCnfgData> > pixHitDiscCnfg;
152 unsigned int errorRecoverable = 0;
153 uint32_t serviceCodeCounter = 0; // frequency of the serviceCode (with the exceptions of serviceCode = 14,15 or 16)
154 uint32_t serviceCode = 0; // is a code. the corresponding meaning is listed in the table in the FE-I4 manual, pag. 105
155
156 // @TODO find better solution for the error counter to avoid complex index computations and hard coded maximum size.
157 // The index array is defined in PixelRawDataProviderTool::SizeOfIDCInDetBSErrContainer()
158 // Local variable bsErrWord uses 452048 bytes of stack space
159 //coverity[STACK_USE]
160 std::array<uint64_t, PixelRodDecoder::ERROR_CONTAINER_MAX> bsErrWord{};
161 // Check ROD status
162 if (robFrag->nstatus()!=0) {
163 const uint32_t* rob_status;
164 robFrag->status(rob_status);
165 // check the ROD status for truncation
166 if (ATH_UNLIKELY((*rob_status)!=0)) {
167 ATH_MSG_DEBUG( "ROB status word for robid 0x"<< std::hex << robId << " is non-zero 0x" << (*rob_status) << std::dec);
168 /*
169 Definition of the status words in a ROB fragment header is found in
170 https://twiki.cern.ch/twiki/bin/view/Atlas/ROBINFragmentErrors#Definition_of_the_first_status_e
171 */
172 if ((*rob_status) & (0x1u << 27)) {
173 propagateROBErrorsToModules(pixCabling.cptr(),robId,bsErrWord,decodingErrors,PixelByteStreamErrors::TruncatedROB, "data truncation");
174 return StatusCode::RECOVERABLE;
175 }
176 if ((*rob_status) & (0x1u << 31)) {
177 propagateROBErrorsToModules(pixCabling.cptr(),robId,bsErrWord,decodingErrors,PixelByteStreamErrors::MaskedROB, "resource was masked off");
178 return StatusCode::RECOVERABLE;
179 }
180 // in case the ROB fragment has a seemingly invalid size check the fragment and reject it if the check is not passed.
181 // Note: there are usable ROB fragments (i.e. ROB fragments which contribute pixel hits to tracks) which do not pass the check, so
182 // rejecting all fragments which do not pass the test would reject also seemingly "good" data.
183 if (robFrag->rod_ndata() > robFrag->payload_size_word() && !robFrag->check_rod_noex(robFrag->rod_version() >> 16)) {
184 propagateROBErrorsToModules(pixCabling.cptr(),robId,bsErrWord,decodingErrors,PixelByteStreamErrors::TruncatedROB,
185 " invalid ROD fragment, invalid payload size");
186 return StatusCode::RECOVERABLE;
187 }
188 }
189 }
190 StatusCode sc = StatusCode::SUCCESS;
191
192 // Fill the Collections for this ROB.
193 unsigned int mBCID = 0x3FFF; // create module BCID variable
194 unsigned int mLVL1ID = 0x3FFF; // create module LVL1ID variable
195 unsigned int mLink = 0x3FFF; // create module Link variable
196 int mLVL1A = 0x3FFF; // create LVL1A variable
197 int offsetBCID_ROB_FE = 0x3FFF; // offset between BCID in ROD header and FE header
198 // take the Header "nnnnn" bits as a reference for the other words (hit, feFlag, trailer words)
199 uint32_t linkNum_IBLheader = 0; // create variable containing 5 bits, corresponding to the "nnnnn" bits in the header IBL/DBM word
200 uint32_t fe_IBLheader = 0; // create fe variable, corresponding to the IBL FE number w.r.t. the sLink (bits 24-26 "nnn" in Header)
201 uint32_t linkNum_IBLword = 0; // create variable containing 5 bits, corresponding to the "nnnnn" bits in the hit/feFlag/trailer IBL/DBM word // At least temporarily not used, because IBL data format is not clear (Franconi, 17.06.2014)
202 uint32_t sLinkSourceId = 0; // create sLink variable, corresponding to the number of the sLink of IBL/DBM, runs from 1 to 4. Retrieved from the robId
203 uint32_t sLinkHeader = 0; // create sLink variable, retrieved from the header words
204 // Various bookkeeping variables
205 bool link_start = false; // link (module) header found flag - reset by link (module) trailer
206 IdentifierHash offlineIdHash; // offlineIdHash
207 IdentifierHash previous_offlineIdHash; // previous module offline identifier
208 int mBCID_offset = -1; // BCID offset to calculate L1A
209 unsigned int mBCID_max_pix = 0x100; // cycle of BCID values
210 unsigned int mBCID_max_IBL = 0x400;
211 bool receivedCondensedWords = false; // to cross-check the condensed mode bit ('c')
212 int countHitCondensedWords = 0; // counter to the "condensed hits" of the IBL
213 uint32_t condensedWords[nCondensedWords] = {}; // this vector saves the 4 condensed hit words that are found
214 bool are_4condensed_words = false;
215 unsigned int prevBCID = 0x3FFF; // initialize to out-of-range value
216 unsigned int prevLVL1ID = 0x3FFF;
217 uint32_t prevLinkNum = 99;
218 int prevOffsetBCID_ROB_FE = 0x3FFF;
219 unsigned int prevStartingBCID = 0x3FFF;
220 unsigned int nFragmentsPerFE[8] = {0}; // number of header-trailer pairs per IBL FE
221 IdentifierHash skipHash = 0xffffffff, lastHash = 0xffffffff; // used for decoding to not have to search the vector all the time
222 PixelRawCollection* coll = nullptr;
223 // get the data from the word
225 robFrag->rod_data(vint);
226 int hitDiscCnfg = 3; // FE-I4 hit discrimination setting
227 // Do a check on IBL Slink ID
228 eformat::helper::SourceIdentifier sid_rob(robId);
229 sLinkSourceId = (sid_rob.module_id()) & 0x000F; // retrieve S-Link number from the source Identifier (0xRRRL, L = Slink number)
230 if ( isIBL( robId ) && sLinkSourceId>0x3) { // Check if SLink number for the IBL is correct!
231 generalwarning("In ROB 0x" << std::hex << robId << ": IBL/DBM SLink number not in correct range (0-3): SLink = " << std::dec << sLinkSourceId);
232 }
233 // Store length of module fragments, for monitoring
234 bool corruptionError = false;
235 // To check duplicated pixels
236 std::unordered_set<Identifier> foundPixels;
237 // ============== ============== ============== ============== ============== ============== ============== ============== //
238 // loop over the data in the fragment
239 const int nwords = robFrag->rod_ndata();
240 for (int dataword_it = 0; dataword_it < nwords; ++dataword_it) {
241 const uint32_t rawDataWord = vint[dataword_it];
242 corruptionError = corruptionError || checkDataWordsCorruption( rawDataWord );
243 uint32_t word_type = getDataType(rawDataWord, link_start); // get type of data word
244
245 serviceCodeCounter = 0;
246 serviceCode = 0;
247
248 int indexModule = -1;
249 int indexFE = -1;
250// if (word_type!=PRB_LINKHEADER) {
251 if (offlineIdHash!=0xffffffff) { // now write the error word to the service
252 isIBLModule = false;
253 isDBMModule = false;
254 if (m_is_ibl_present) {
255 isIBLModule = isIBL(robId);
256 isDBMModule = isDBM(robId);
257 }
258
259 int chFE = 0;
260 if (isIBLModule || isDBMModule) { // get FE channel id for IBL
261 linkNum_IBLheader = decodeModule_IBL(rawDataWord);
262 chFE = (extractFefromLinkNum(linkNum_IBLheader) & 0x1);
263 if (m_pixelReadout->getModuleType(m_pixel_id->wafer_id(offlineIdHash))==InDetDD::PixelModuleType::IBL_3D) { chFE=0; }
264 }
265 else { // for PIXEL
266 chFE = decodeFE(rawDataWord);
267 }
268 indexModule = static_cast<int>(offlineIdHash); // [0,2047]
269 indexFE = (1+chFE)*m_pixel_id->wafer_hash_max()+static_cast<int>(offlineIdHash); // index for IDCInDetBSErrContainer
270 }
271// }
272
273 bool headerErr_decoding = false;
274 bool headerErr_flagged = false;
275 bool headerErr_preamble = false;
276 bool headerErr_timeout = false;
277 bool headerErr_lvl1id = false;
278 bool headerErr_bcid = false;
279 switch (word_type) { // depending on type of word call the right decoding method
280 //-------------------------------------------------------------------------------------------- HEADER WORD FOUND
281 case PRB_LINKHEADER: // link (module) header found
282
283 ATH_MSG_DEBUG("Header word found");
284 errorRecoverable = 0; // reset errorcode
285
286 if (link_start) { // if header found before last header was closed by a trailer -> error
287 generalwarning("In ROB 0x" << std::hex << robId << ": Unexpected link header found: 0x" << std::hex << rawDataWord << ", data corruption" << std::dec);
289 headerErr_decoding = true;
290 }
291 else {
292 ATH_MSG_DEBUG( "Header decoding starts" );
293 }
294 link_start = true; // setting link (module) header found flag
295 are_4condensed_words = false;
296 receivedCondensedWords = false;
297 isIBLModule = false;
298 isDBMModule = false;
299 countHitCondensedWords = 0;
300 if (m_is_ibl_present) {
301 isIBLModule = isIBL(robId);
302 isDBMModule = isDBM(robId);
303 }
304 // Keep track of IDs for previous fragment before decoding the new values
305 prevLVL1ID = mLVL1ID;
306 prevBCID = mBCID;
307 prevLinkNum = mLink;
308 prevOffsetBCID_ROB_FE = offsetBCID_ROB_FE;
309
310 if (isIBLModule || isDBMModule) { // decode IBL/DBM header word.
311#ifdef PIXEL_DEBUG
312 ATH_MSG_VERBOSE( "Decoding the IBL/DBM header word: 0x" << std::hex << rawDataWord << std::dec );
313#endif
314
315 // IBL header data format: 001nnnnnFLLLLLLLLLLLLLBBBBBBBBBB
316 mBCID = decodeBCID_IBL(rawDataWord); // decode IBL BCID: B
317 mLVL1ID = decodeL1ID_IBL(rawDataWord); // decode IBL LVL1ID: L
318 linkNum_IBLheader = decodeModule_IBL(rawDataWord); // decode IBL FE number on the S-Link (range [0,7], as 8 FEs are connected to 1 S-Link in IBL) and the S-Link number itself: n
319 if (decodeFeI4Bflag_IBL(rawDataWord)) {
321 headerErr_flagged = true;
322 }
323 fe_IBLheader = extractFefromLinkNum(linkNum_IBLheader);
324 mLink = fe_IBLheader; // this is used to retrieve the onlineId. It contains only the 3 LSBs of the nnnnn, indicating the number of FE w.r.t. the SLink
325 sLinkHeader = extractSLinkfromLinkNum(linkNum_IBLheader); // this is used to check that the (redundant) info is correctly transmitted
326 if (sLinkHeader != sLinkSourceId) {
327 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": SLink discrepancy: Slink number from SourceId = 0x" << std::hex << sLinkSourceId << ", number from link header = 0x" << sLinkHeader << std::dec);
328 }
329 // If decoding fragment from same FE as previous one, do LVL1ID and BCID checks
330 if (mLink == prevLinkNum) {
331 // Check that L1ID is the same for all fragments
332 if (mLVL1ID != prevLVL1ID && prevLVL1ID != 0x3FFF) {
333 lvl1id_bcid_warning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": frame header LVL1ID differs from previous one (current frame LVL1ID = 0x" << mLVL1ID << ", previous frame LVL1ID = 0x" << prevLVL1ID << ")" << std::dec);
334 }
335 // Check that BCIDs are consecutive
336 if ((mBCID != prevBCID + 1) && prevBCID != 0x3FFF && prevBCID != mBCID_max_IBL) {
337 lvl1id_bcid_warning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": frame header with non-consecutive BCID (current BCID = 0x" << mBCID << ", previous BCID = 0x" << prevBCID << ")" << std::dec);
338 }
339 }
340 else { // If decoding new FE, check BCID offset
341 offsetBCID_ROB_FE = static_cast<int>(mBCID) - robBCID;
342 if (offsetBCID_ROB_FE != prevOffsetBCID_ROB_FE && (offsetBCID_ROB_FE != 0x3FFF && prevOffsetBCID_ROB_FE != 0x3FFF)) {
343 lvl1id_bcid_warning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << std::dec << ": FE header with unexpected BCID offset" << " wrt to ROB header (offset = " << offsetBCID_ROB_FE << ", expected " << prevOffsetBCID_ROB_FE << " from ROB)");
344 }
345 // Check that first fragment from each FE starts at the same BCID
346 if (mBCID != prevStartingBCID && prevStartingBCID != 0x3FFF) {
347 lvl1id_bcid_warning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": FE BCID starts at different value than in previous FE (current BCID = 0x" << mBCID << ", prev starting BCID = 0x" << prevStartingBCID << ")" << std::dec);
348 }
349 prevStartingBCID = mBCID;
350 }
351 // Count number of headers received
352 if (mLink < 0x8) { ++nFragmentsPerFE[mLink]; }
353 }
354 else { // this is Pixels detector decode header word. Data format: 001PtlbxdnnnnnnnMMMMLLLLBBBBBBBB (NOT IBL OR PIXEL)
355 ATH_MSG_VERBOSE( "Decoding Pixel header word: 0x" << std::hex << rawDataWord << std::dec );
356 mBCID = decodeBCID(rawDataWord); // decode Pixel BCID: B
357 mLVL1ID = decodeL1ID(rawDataWord); // decode Pixel LVL1ID: L
358 mLink = decodeModule(rawDataWord); // decode Pixel link (module): n
359 const uint32_t headerError = decodeHeaderErrors(rawDataWord); // get link (module) header errors
360 if ( headerError != 0 ) {
361 sc = StatusCode::RECOVERABLE;
362 errorRecoverable = errorRecoverable | (headerError << 20); //encode error as HHHHMMMMMMMMFFFFFFFFTTTT for header, flagword, trailer errors
363
364 { // only treatment for header errors now, FIXME
365 if (headerError & (1 << 3)) {
367 headerErr_preamble = true;
368 }
369 if (headerError & (1 << 2)) {
371 headerErr_timeout = true;
372 }
373 if (headerError & (1 << 1)) {
375 headerErr_lvl1id = true;
376 }
377 if (headerError & (1 << 0)) {
379 headerErr_bcid = true;
380 }
381 }
382
383 }
384 } // end of detector type decoding
385 // Get onlineId
386 onlineId = pixCabling->getOnlineIdFromRobId(robId, mLink);
387 if (onlineId == 0) {
388 generalwarning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": Got invalid onlineId (= 0) in FE header - dataword = 0x" << rawDataWord);
389 }
390
391#ifdef PIXEL_DEBUG
392 ATH_MSG_VERBOSE("In decoder: got onlineId 0x" << std::hex << onlineId );
393#endif
394
395 offlineIdHash = m_pixel_id->wafer_hash(pixCabling->find_entry_onoff(onlineId));
396 if (offlineIdHash != previous_offlineIdHash) {
397 mBCID_offset = mBCID; // set BCID offset if this is first LVL1A
398 // The index array is defined in PixelRawDataProviderTool::SizeOfIDCInDetBSErrContainer()
399 // Here, 52736 is a separator beween error flags and isActive flags.
400 bsErrWord[static_cast<int>(offlineIdHash)+52736] = 1;
401 }
402 mLVL1A = mBCID - mBCID_offset; // calculate the LVL1A
403 if (mLVL1A < 0) {
404 if (isIBLModule || isDBMModule) { mLVL1A=mLVL1A+mBCID_max_IBL; }
405 else { mLVL1A=mLVL1A+mBCID_max_pix; }
406 }
407
408 // Fill header error word per IBL FE
409 if (isIBLModule || isDBMModule) {
410 if (indexFE>-1) {
411 if (headerErr_decoding) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
412 if (headerErr_flagged) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Flagged); }
413 if (headerErr_preamble) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Preamble); }
414 if (headerErr_timeout) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::TimeOut); }
415 if (headerErr_lvl1id) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::LVL1ID); }
416 if (headerErr_bcid) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::BCID); }
417 }
418 }
419 else {
420 // Fill header error word per module
421 if (headerErr_decoding) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::Decoding); }
422 if (headerErr_flagged) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::Flagged); }
423 if (headerErr_preamble) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::Preamble); }
424 if (headerErr_timeout) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::TimeOut); }
425 if (headerErr_lvl1id) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::LVL1ID); }
426 if (headerErr_bcid) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::BCID); }
427 }
428
429
430#ifdef PIXEL_DEBUG
431 ATH_MSG_VERBOSE( "link header with BCID: " << mBCID << " LVL1ID: " << mLVL1ID << " LVL1A: " << mLVL1A << " link: " << mLink << " found");
432 ATH_MSG_VERBOSE( "got OfflineIDHash: 0x" << std::hex << offlineIdHash << " from OnlineID: 0x" << onlineId << std::dec << " link: " << mLink);
433#endif
434
435 if (offlineIdHash == 0xffffffff) { // if link (module) online identifier (ROBID and link number) not found by mapping
436 generalwarning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": Unknown OnlineId identifier in FE header - not found by mapping" << std::dec);
438 link_start = false; // resetting link (module) header found flag
439 continue; // skip this word and process next one
440 }
441 break;
442 //-------------------------------------------------------------------------------------------- HIT DATA WORD FOUND
443 case PRB_DATAWORD: // hit data found
444 if (link_start) { // if header found before hit -> expected
445 ATH_MSG_DEBUG("Hit word found");
446 unsigned int mFE = 0;
447 unsigned int mRow = 0;
448 unsigned int mColumn = 0;
449 int mToT = 0;
450 uint32_t row[nHits], col[nHits];
451 int tot[nHits];
452 if (isIBLModule || isDBMModule) { // check all the different types of IBL/DBM hit words (condensed and not condensed)
453
454#ifdef PIXEL_DEBUG
455 ATH_MSG_DEBUG ("Decoding IBL/DBM hit word: 0x" << std::hex << rawDataWord << std::dec);
456#endif
457
458 if (((rawDataWord & PRB_DATAMASK) == PRB_FIRSTHITCONDENSEDWORD) && (countHitCondensedWords == 0)) { // it is the first of the 4 hit condensed words (IBL/DBM)
459 countHitCondensedWords = 1;
460 are_4condensed_words = false; // All 4 words have to be found before turning it on
461 condensedWords[0] = rawDataWord;
462 continue;
463 }
464 else if (countHitCondensedWords == 1) { // it is the second of the 4 hit condensed words (IBL)
465 ++countHitCondensedWords;
466 condensedWords[1] = rawDataWord;
467 continue;
468 }
469 else if (countHitCondensedWords == 2) { // it is the third of the 4 hit condensed words (IBL)
470 ++countHitCondensedWords;
471 condensedWords[2] = rawDataWord;
472 continue;
473 }
474 else if (((rawDataWord & PRB_DATAMASK) == PRB_LASTHITCONDENSEDWORD) && (countHitCondensedWords == 3)) { // it is the fourth of the 4 hit condensed words (IBL)
475 are_4condensed_words = true;
476 receivedCondensedWords = true;
477 condensedWords[3] = rawDataWord;
478 uint32_t hitwords[nHits];
479 //Condensed words
480 // 101RRRRRTTTTTTTTCCCCCCCRRRRRRRRR
481 // 1CCCRRRRRRRRRTTTTTTTTCCCCCCCRRRR
482 // 1TTTCCCCCCCRRRRRRRRRTTTTTTTTCCCC
483 // 111TTTTTTTTCCCCCCCRRRRRRRRRTTTTT
484 // They become 5 hitwords with format : TTTTTTTTCCCCCCCRRRRRRRRR
485 // first hitword: simple mask of the first condensed word
486 hitwords[0] = (condensedWords[0] & mask24);
487 // second hitword: takes the "RRRRR" from the first condensed word + the "TTTTTTTTCCCCCCCRRRR" from the second (shifted left 5 bits to accomodate the "RRRRR" as LSB)
488 hitwords[1] = ((condensedWords[0] >> (skipRow + skipCol+ skipTOT) ) & mask5) + ((condensedWords[1] & mask19) << skip5);
489 // third hitword: takes remaining "CCCRRRRRRRRR" from the second condensed word + the "TTTTTTTTCCCC" from the third (shifted left 12 bits to accomodate the LSB coming from the second condensed word
490 hitwords[2] = ((condensedWords[1] >> (skip4 + skipCol + skipTOT)) & mask12) + ((condensedWords[2] & mask12) << (skipRow + skip3));
491 // fourth hitword: takes remaning "TTTCCCCCCCRRRRRRRRR" from the third condensed word + the "TTTTT" from the fourth (shifted left 19 bits to accomodate the LSB coming from the third condensed word
492 hitwords[3] = ((condensedWords[2] >> (skipTOT + skip4)) & mask19) + ((condensedWords[3] & mask5) << (skip3 + skipRow + skipCol));
493 // fifth hitword: simply shift 5 right to eliminate the "TTTTT" and mask24
494 hitwords[4] = (condensedWords[3] >> skip5) & mask24;
495
496#ifdef PIXEL_DEBUG
497 ATH_MSG_VERBOSE( "4 consecutive IBL hit words found. Condensed hits are being decoded");
498#endif
499
500 for (unsigned int i(0); i < nHits; ++i) {
501 row[i] = divideHits (hitwords[i], 0, 8);
502 col[i] = divideHits (hitwords[i], 9, 15);
503 tot[i] = divideHits (hitwords[i], 16, 23);
504 ATH_MSG_VERBOSE( "hitword[" << i << "] = 0x" << std::hex << hitwords[i] << ", row: 0x" << row[i] << ", col: 0x" << col[i] << ", 8-bit ToT: 0x" << tot[i] << std::dec);
505 }
506 countHitCondensedWords = 0;
507 linkNum_IBLword = linkNum_IBLheader;
508 } // end of the condensed hit words (IBL)
509 else if ((rawDataWord & PRB_DATAMASK) == PRB_DATAWORD) { // it's a IBL not-condensed hit word
510 if (countHitCondensedWords != 0) { // I received some IBL words, but less than 4, there was an error in the rod transmission
511 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": Interruption of IBL condensed words - hit(s) ignored (current dataword: 0x" << std::hex << rawDataWord << std::dec << ")");
513 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
514 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
515 countHitCondensedWords = 0;
516 }
517 // IBL non-condensed Hit Words decoding:
518 are_4condensed_words = false;
519 mRow = decodeRow(rawDataWord, isIBLModule || isDBMModule );
520 mColumn = decodeColumn(rawDataWord, isIBLModule || isDBMModule);
521 mToT = decodeToT(rawDataWord, isIBLModule || isDBMModule); // this needs, later in the code, to be divided into Tot(0) and Tot(1), because the IBL TOT information can give information of the ToTs from up to two adjacent pixels
522 linkNum_IBLword = decodeLinkNumHit_IBL(rawDataWord); // this corresponds to the "nnnnn" bits of the bytestream convention.
523 //They represent: 3 LSB = number of the FE linked by the S-Link sending the block (range [0,7]); 2 MSB = S-Link number (range [1,4])
524 if (linkNum_IBLword != linkNum_IBLheader) {
525 generalwarning("In ROB 0x" << std::hex << robId << ": Link number mismatch - nnnnn (hit word) = 0x" << linkNum_IBLword << ", nnnnn (header) = 0x" << linkNum_IBLheader << std::dec);
526 }
527
528#ifdef PIXEL_DEBUG
529 ATH_MSG_DEBUG("hit dataword found for module offlineIDHash: " << offlineIdHash << " Row: 0x" << std::hex << mRow << " Col: 0x" << mColumn << " Tot: 0x" << mToT << std::dec);
530#endif
531
532 }
533 else { // it is an IBL/DBM hit word, but it hasn't been recognised
534 generalwarning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": IBL/DBM hit word 0x" << rawDataWord << " not recognised" << std::dec);
536 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
537 continue;
538 }
539 // computing the FE number on the silicon wafer for IBL ( mFE is = 0 for IBL 3D and the lower-eta FE on the planar sensor,
540 // while is = 1 for the higher-eta FE on the planar sensor)
541 mFE = getLocalFEI4(fe_IBLheader, onlineId);
542 if (m_pixelReadout->getModuleType(pixCabling->find_entry_onoff(onlineId))==InDetDD::PixelModuleType::IBL_3D) {
543 mFE = 0;
544 }
545
546 } // end of the if (isIBLModule || isDBMModule)
547 else { // Pixel Hit Case
548
549#ifdef PIXEL_DEBUG
550 ATH_MSG_VERBOSE("Decoding Pixel hit word: 0x" << std::hex << rawDataWord << std::dec);
551#endif
552
553 if (countHitCondensedWords != 0){ // I received some IBL words, but less than 4, there was an error in the rod transmission
554 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink
555 << ": Interruption of IBL condensed words - hit(s) ignored (current dataword: 0x"
556 << std::hex << rawDataWord << std::dec << ")");
558 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
559 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
560 countHitCondensedWords = 0;
561 }
562 //Pixel Hit Words decoding:
563 are_4condensed_words = false;
564 mFE = decodeFE(rawDataWord);
565 mRow = decodeRow(rawDataWord, isIBLModule || isDBMModule );
566 mColumn = decodeColumn(rawDataWord, isIBLModule || isDBMModule);
567 mToT = decodeToT(rawDataWord, isIBLModule || isDBMModule);
568
569#ifdef PIXEL_DEBUG
570 ATH_MSG_DEBUG( "hit dataword found for module offlineIDHash: " << offlineIdHash << " FE: " << mFE << " Row: " << mRow << " Col: " << mColumn ); // hit found debug message
571#endif
572
573 } // end of the condition "!isIBLModule"
574 // ------------------------
575 // Create pixel collections
576
577 // Decode only modules in provided list of hashes (i.e. not doing full scan)
578 // Disabled for now.
579 if (offlineIdHash == skipHash) continue;
580 if (offlineIdHash != lastHash) {
581 lastHash = offlineIdHash;
582 if (vecHash!=nullptr) {
583 std::vector<IdentifierHash>::iterator p = std::find(vecHash->begin(),vecHash->end(),offlineIdHash);
584 if (p == vecHash->end()) { // is the Hash to be skipped (not in the request list)?
585 skipHash = offlineIdHash;
586 continue;
587 }
588 }
589 ATH_CHECK( rdoIdc->naughtyRetrieve(offlineIdHash, coll) );//Returns null if not present
590 if( coll == nullptr ) {
591 coll = new PixelRawCollection (offlineIdHash);
592 // get identifier from the hash, this is not nice
593 Identifier ident = m_pixel_id->wafer_id(offlineIdHash);
594 // set the Identifier to be nice to downstream clients
595 coll->setIdentifier(ident);
596
597 StatusCode sc = rdoIdc->addCollection(coll, offlineIdHash);
598 ATH_MSG_DEBUG("Adding " << offlineIdHash);
599 if (sc.isFailure()){
600 ATH_MSG_ERROR("failed to add Pixel RDO collection to container" );
601 }
602 }
603 }
604 // ------------------------
605 // Fill collections
606 if (isIBLModule || isDBMModule) {
607 unsigned int num_cycles_toFillCollection(0);
608 if (are_4condensed_words) {
609 num_cycles_toFillCollection = nHits;
610 }
611 else {
612 num_cycles_toFillCollection = 1;
613 row[0] = mRow;
614 col[0] = mColumn;
615 tot[0] = mToT;
616 }
617 int IBLtot[2];
618 for (unsigned int i(0); i < num_cycles_toFillCollection; ++i) {
619
620#ifdef PIXEL_DEBUG
621 ATH_MSG_VERBOSE( "ROW[" << i << "] = 0x" << std::hex << row[i] << std::dec << ", COL[" << i << "] = 0x" << std::hex << col[i] << std::dec << ", 8-bit TOT[" << i << "] = 0x" << std::hex << tot[i] << std::dec );
622#endif
623
624 // ToT1 equal 0 means no hit, regardless of HitDiscCnfg
625 if ((tot[i] & 0xF0) == 0x00) {
626 generalwarning("In ROB 0x" << std::hex << robId << ", FE 0x" << mLink << ": First IBL ToT field is 0 - hit word 0x" << rawDataWord << " decodes to ToT1 = 0" << (tot[i] >> 4) << ", ToT2 = 0x" << (tot[i] & 0xF) << ", row = " << std::dec << row[i] << " col = " << col[i] << std::dec);
627 continue;
628 }
629 else {
630 if (((row[i] != 0) && (col[i] != 0) && (row[i] <= 336) && (col[i] <= 80)) || isDBMModule) { // FIXME : Hardcoded numbers. Should be ok as they are features of the FE-I4, but worth checking!
631 pixelId = m_pixelReadout ->getPixelIdfromHash (offlineIdHash, mFE, row[i], col[i]);
632
633#ifdef PIXEL_DEBUG
634 ATH_MSG_VERBOSE( "PixelId: " << pixelId );
635 int eta_i = m_pixel_id->eta_index(pixelId);
636 int phi_i = m_pixel_id->phi_index(pixelId);
637 int eta_m = m_pixel_id->eta_module(pixelId);
638 int phi_m = m_pixel_id->phi_module(pixelId);
639 ATH_MSG_VERBOSE( " eta_i: " << eta_i << ", phi_i: " << phi_i << ", eta_m: " << eta_m << ", phi_m: " << phi_m );
640#endif
641 if (pixelId == invalidPixelId) {
642 generalwarning("In ROB 0x" << std::hex << robId << ", FE 0x" << mLink << ": Illegal pixelId - hit word 0x" << rawDataWord << " decodes to ToT1 = 0" << (tot[i] >> 4) << ", ToT2 = 0x" << (tot[i] & 0xF) << ", row = " << std::dec << row[i] << " col = " << col[i] << std::dec);
644 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
645 continue;
646 }
647 IBLtot[0] = divideHits(tot[i], 4, 7); // corresponds to (col, row)
648 IBLtot[1] = divideHits(tot[i], 0, 3); // corresponds to (col, row+1)
649#ifdef PIXEL_DEBUG
650 ATH_MSG_VERBOSE("Starting from tot = 0x" << std::hex << tot[i] << " IBLtot[0] = 0x" << std::hex << IBLtot[0] << " IBLtot[1] = 0x" << IBLtot[1] << std::dec );
651#endif
652
653 if (!pixHitDiscCnfg) {
654 pixHitDiscCnfg = std::make_unique<SG::ReadCondHandle<PixelHitDiscCnfgData> > (m_condHitDiscCnfgKey,ctx);
655 }
656 // Get the hit discrimination configuration setting for this FE
657 if (m_pixelReadout->getModuleType(pixelId) == InDetDD::PixelModuleType::IBL_PLANAR || m_pixelReadout->getModuleType(pixelId) == InDetDD::PixelModuleType::DBM) {
658 hitDiscCnfg = (*pixHitDiscCnfg)->getHitDiscCnfgPL();
659 }
660 else if (m_pixelReadout->getModuleType(pixelId) == InDetDD::PixelModuleType::IBL_3D) {
661 hitDiscCnfg = (*pixHitDiscCnfg)->getHitDiscCnfg3D();
662 }
663 // Now do some interpreting of the ToT values
664 if (hitDiscCnfg == 2 && IBLtot[0] == 2) IBLtot[0] = 16;
665 if (hitDiscCnfg == 2 && IBLtot[1] == 2) IBLtot[1] = 16;
666 if (not m_checkDuplicatedPixel or thisRdoIsUnique(pixelId, foundPixels)) {
667 // Insert the first part of the ToT info in the collection
668 if (coll) coll->push_back(new RDO(pixelId, IBLtot[0], mBCID, mLVL1ID, mLVL1A));
669 }
670 else {
672 }
673
674#ifdef PIXEL_DEBUG
675 ATH_MSG_VERBOSE( "Collection filled with pixelId: " << pixelId << " TOT = 0x" << std::hex << IBLtot[0] << std::dec << " mBCID = " << mBCID << " mLVL1ID = " << mLVL1ID << " mLVL1A = " << mLVL1A );
676#endif
677
678 // Second ToT field:
679 // For HitDiscCnfg 0-2, consider 0 to indicate no hit
680 // For HitDiscCng = 3, consider also F to indicate no hit
681 if (IBLtot[1] != 0x0 && (IBLtot[1] != 0xF || hitDiscCnfg != 3)) {
682 if ((row[i] + 1) > 336) { // FIXME: hardcoded number - but it should still be ok, because it's a feature of the FE-I4!
683 // this should never happen. If row[i] == 336, (row[i]+1) == 337. This row does not exist, so the TOT(337) should always be 0 (== no hit)
684 generalwarning("In ROB = 0x" << std::hex << robId << ", link 0x" << mLink << ": Illegal IBL row number for second ToT field, hit word 0x" << rawDataWord << " decodes to row = " << std::dec << row[i]+1 << " col = " << col[i] << " (ToT1 = 0x" << std::hex << IBLtot[0] << " ToT2 = 0x" << IBLtot[1] << ")");
685 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
687 continue;
688 }
689 else {
690 pixelId = m_pixelReadout->getPixelIdfromHash (offlineIdHash, mFE, row[i] + 1, col[i]);
691
692#ifdef PIXEL_DEBUG
693 int eta_i = m_pixel_id->eta_index(pixelId);
694 int phi_i = m_pixel_id->phi_index(pixelId);
695 int eta_m = m_pixel_id->eta_module(pixelId);
696 int phi_m = m_pixel_id->phi_module(pixelId);
697 int phi_i_max = m_pixel_id->phi_index_max(pixelId);
698 int eta_i_max = m_pixel_id->eta_index_max(pixelId);
699 ATH_MSG_VERBOSE( "PixelId = " << pixelId);
700 ATH_MSG_VERBOSE( " eta_i: " << eta_i << ", phi_i: " << phi_i << ", eta_m: " << eta_m << ", phi_m: " << phi_m << ", eta_i_max: " << eta_i_max << ", phi_i_max: " << phi_i_max );
701#endif
702
703 if (pixelId == invalidPixelId) {
704 generalwarning("In ROB 0x" << std::hex << robId << ", FE 0x" << mLink << ": Illegal pixelId - hit word 0x" << rawDataWord << " decodes to ToT1 = 0" << (tot[i] >> 4) << ", ToT2 = 0x" << (tot[i] & 0xF) << ", row = " << std::dec << row[i] << " col = " << col[i] << std::dec);
706 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
707 continue;
708 }
709 if (not m_checkDuplicatedPixel or thisRdoIsUnique(pixelId, foundPixels)) {
710 coll->push_back(new RDO(pixelId, IBLtot[1], mBCID, mLVL1ID, mLVL1A));
711 }
712 else {
714 }
715
716#ifdef PIXEL_DEBUG
717 ATH_MSG_VERBOSE( "Collection filled with pixelId: " << pixelId << " TOT = 0x" << std::hex << IBLtot[1] << std::dec << " mBCID = " << mBCID << " mLVL1ID = " << mLVL1ID << " mLVL1A = " << mLVL1A );
718#endif
719
720 }
721 }
722 } // end of the if that checks that Row and Column of the IBL have a value > 0 and smaller than the maximum of the FE-I4.
723 else {
724 generalwarning("In ROB = 0x" << std::hex << robId << ", link 0x" << mLink << ": Illegal IBL row/col number, hit word 0x" << rawDataWord << " decodes to row = " << std::dec << row[i] << " col = " << col[i] << " (ToT1 = 0x" << std::hex << (tot[i] >> 4) << " ToT2 = 0x" << (tot[i] & 0xF) << ")");
726 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
727 continue;
728 }
729 } // end of the else from the condition "(tot[i] & 0xF0) == 0xF", corresponding to an invalid tot sent by the ROD
730 } // end of the loop over the hit information coming from the IBL words (condensed or not)
731 } // end IBL/DBM words pushed into Collection
732
733 else { // it is a Pixel hit word to be saved into the Collection
734 pixelId = m_pixelReadout->getPixelIdfromHash(offlineIdHash, mFE, mRow, mColumn);
735 if (pixelId == invalidPixelId) {
736 ATH_MSG_DEBUG("In ROB = 0x" << std::hex << robId << ", link 0x" << mLink << ": Illegal pixelId - row = " << std::dec << mRow << ", col = " << mColumn << ", dataword = 0x" << std::hex << rawDataWord << std::dec);
738 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Invalid); }
739 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
740 continue;
741 }
742 // Now the Collection is there for sure. Create RDO and push it into Collection.
743 if (not m_checkDuplicatedPixel or thisRdoIsUnique(pixelId, foundPixels)) {
744 coll->push_back(new RDO(pixelId, mToT, mBCID, mLVL1ID, mLVL1A));
745 }
746 else {
748 }
749
750#ifdef PIXEL_DEBUG
751 ATH_MSG_VERBOSE( "Collection filled with pixelId: " << pixelId << " TOT = 0x" << std::hex << mToT << std::dec << " mBCID = " << mBCID << " mLVL1ID = " << mLVL1ID << " mLVL1A = " << mLVL1A );
752#endif
753
754 } // end Pixel words pushed into Collection
755 } // end of the if (link_start)
756 else { // no header found before hit -> error
757 generalwarning("In ROB = 0x" << std::hex << robId << ", link 0x" << mLink << ": Unexpected hit dataword: " << rawDataWord << " - hit ignored");
759 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
760 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
761 continue;
762 }
763 break;
764 //-------------------------------------------------------------------------------------------- TRAILER WORD FOUND
765 case PRB_LINKTRAILER: // link (module) trailer found
766 if (link_start) { // if header found before trailer -> expected
767 ATH_MSG_DEBUG( "link trailer found" ); // trailer found debug message
768 }
769 else { // no header found before trailer -> error
770 generalwarning("In ROB = 0x" << std::hex << robId << ", link 0x" << mLink << ": Unexpected trailer found: 0x" << std::hex << rawDataWord << ", data corruption");
772 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
773 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
774 continue;
775 }
776 previous_offlineIdHash = offlineIdHash; // save offlineId for next header;
777 link_start = false; // resetting link (module) header found flag
778 are_4condensed_words = false;
779 // Trailer decoding and error handling
780 if (isIBLModule || isDBMModule) { // decode IBL/DBM Trailer word: 010nnnnnECPplbzhvMMMMMMMMMMxxxxx
781 ATH_MSG_VERBOSE( "Decoding IBL/DBM trailer word: 0x" << std::hex << rawDataWord << std::dec );
782 const uint32_t trailerError = decodeTrailerErrors_IBL(rawDataWord); // => E cPpl bzhv // taking all errors together.
783
784 if (trailerError & (1 << 8)) { // time out error bit => E
786 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::TimeOut); }
787 }
788
789 if (trailerError & (1 << 6)) {// link masked by PPC => P
791 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::LinkMaskedByPPC); }
792 }
793 if (trailerError & (1 << 5)) { // preamble error bit => p
795 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Preamble); }
796 }
797 if (trailerError & (1 << 4)) { // LVL1 error bit => l
799 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::LVL1ID); }
800 }
801 if (trailerError & (1 << 3)) {// BCID error bit => b
803 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::BCID); }
804 }
805 if (trailerError & (1 << 2)) { // trailer error bit => z
807 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Trailer); }
808 }
809 if (trailerError & (1 << 1)) { // header/trailer limit error=> h
811 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Limit); }
812 }
813 if (trailerError & (1 << 0)) { // data overflow error=> v
815 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
816 }
817
818 if (trailerError & (1 << 7)) { // condensed mode bit => W
819 if (!receivedCondensedWords) { generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": condensed mode bit is set, but no condensed words received" << std::dec); }
820 }
821 //At least temporarily removed because the data format is not clear (Franconi, 17.06.2014)
822 linkNum_IBLword = decodeLinkNumTrailer_IBL(rawDataWord); // => n
823 // Do checks on info in trailer vs header
824 if (linkNum_IBLword != linkNum_IBLheader) {
825 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": Link number mismatch - nnnnn (trailer) = 0x" << linkNum_IBLword << ", nnnnn (header) = 0x" << linkNum_IBLheader << std::dec);
826 }
827 if (decodeBcidTrailer_IBL(rawDataWord) != (mBCID & PRB_BCIDSKIPTRAILERmask_IBL)) {
828 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": Trailer BCID does not match header (trailer BCID = 0x" << decodeBcidTrailer_IBL(rawDataWord) << ", 5LSB of header BCID = 0x" << (mBCID & PRB_BCIDSKIPTRAILERmask_IBL) << ")" << std::dec);
829 }
830 }
831 else { // decode Pixel trailer word
832 ATH_MSG_VERBOSE( "Decoding Pixel trailer word: 0x" << std::hex << rawDataWord << std::dec );
833 const uint32_t trailerError = decodeTrailerErrors(rawDataWord); // creating link (module) trailer error variable
834 if (trailerError != 0) {
835 sc = StatusCode ::RECOVERABLE;
836 errorRecoverable = errorRecoverable | trailerError; //encode error as HHHHMMMMMMMMFFFFFFFFTTTT for header, flagword, trailer errors
837
838 const std::array<unsigned long long, 4> bitPosition{0_BIT, 1_BIT, 2_BIT, 3_BIT};
839 for (const auto bit:bitPosition){
840 if (trailerError & bit) ++m_numTrailerErrors;
841 }
842
843 if ( trailerError & 0xF ) {
844 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Trailer); }
845 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Trailer); }
846 }
847
848 // Extra for pixel monitoring
849 if (trailerError != 0) {
850 if (indexModule>-1) {
851 if (trailerError & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::RODTrailerBitError); }
852 if (trailerError & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::RODHeaderLimit); }
853 if (trailerError & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::RODDataOVerflow); }
854 }
855 if (indexFE>-1) {
856 if (trailerError & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::RODTrailerBitError); }
857 if (trailerError & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::RODHeaderLimit); }
858 if (trailerError & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::RODDataOVerflow); }
859 }
860 }
861
862 }
863 }
864 break;
865 //-------------------------------------------------------------------------------------------- FE ERROR TYPE 2 WORD FOUND
866 case PRB_FEERROR2 : // type 2 flag found
867
868 are_4condensed_words = false;
869 if (isIBLModule || isDBMModule) { // IBL flag found
870 ATH_MSG_VERBOSE( "Decoding IBL/DBM FEflag word: 0x" << std::hex << rawDataWord << std::dec);
871 linkNum_IBLword = decodeLinkNumFEFlag_IBL(rawDataWord);
872 if (linkNum_IBLword != linkNum_IBLheader) {
873 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": Link number mismatch - nnnnn (error word) = 0x" << linkNum_IBLword << ", nnnnn (header) = 0x" << linkNum_IBLheader << std::dec);
874 }
875 serviceCodeCounter = decodeServiceCodeCounter_IBL(rawDataWord)+1; // frequency of the serviceCode (with the exceptions of serviceCode = 14,15 or 16)
876 serviceCode = decodeServiceCode_IBL(rawDataWord); // is a code. the corresponding meaning is listed in the table in the FE-I4 manual, pag. 105
877 // Treat the service code only if its meaning is valid (i.e. value < 31)
878 if (serviceCode>31) {
879 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": Got out-of-bounds service code: " << std::dec << serviceCode << " (counter: " << serviceCodeCounter << "), ignored");
880 }
881
882 int chFE = (extractFefromLinkNum(linkNum_IBLheader) & 0x1);
883 if (m_pixelReadout->getModuleType(m_pixel_id->wafer_id(offlineIdHash))==InDetDD::PixelModuleType::IBL_3D) { chFE=0; }
884
885 if (serviceCodeCounter>0 && serviceCode<32) {
886 if (serviceCode!=14) {
887 // Monitor service record for IBL (not DBM)
888 if (static_cast<int>(offlineIdHash)>155 && static_cast<int>(offlineIdHash)<436) {
889 // The index array is defined in PixelRawDataProviderTool::SizeOfIDCInDetBSErrContainer()
890 int indexOffset = 17*m_pixel_id->wafer_hash_max();
891 int indexSvcCounter = indexOffset+serviceCode*280*2+2*(static_cast<int>(offlineIdHash)-156)+chFE;
892
893 bsErrWord[indexSvcCounter] = serviceCodeCounter;
894 }
895 }
896 }
897
898 }
899 else { // Pixel type2 flag found
900 ATH_MSG_VERBOSE( "Decoding Pixel FEflag word: 0x" << std::hex << rawDataWord << std::dec );
901 uint32_t FEFlags = decodeFEFlags2(rawDataWord); // get FE flags
902 uint32_t MCCFlags = decodeMCCFlags(rawDataWord); // get MCC flags
903 FEFlags = FEFlags & 0xff;
904 if ((MCCFlags | FEFlags) != 0) {
905 sc = StatusCode::RECOVERABLE;
906 errorRecoverable = errorRecoverable | (MCCFlags << 12) | (FEFlags << 4); //encode error as HHHHMMMMMMMMFFFFFFFFTTTT for header, flagword, trailer errors
907 //for now just sum all flagged errors_
908 static constexpr std::array<unsigned long long, 8> bitPosition {0_BIT, 1_BIT, 2_BIT, 3_BIT, 4_BIT, 5_BIT, 6_BIT, 7_BIT};
909 for (const auto thisBit:bitPosition){
910 if (MCCFlags & thisBit) ++m_numFlaggedErrors;
911 if (FEFlags & 0xf3 & thisBit) ++m_numFlaggedErrors;
912 }
913
914 if ( MCCFlags & 0xff or FEFlags & 0xf3 ) {
915 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Flagged); }
916 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Flagged); }
917 }
918
919 if (indexModule>-1) {
920 if (MCCFlags & (1 << 7)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCUndefined); }
921 if (MCCFlags & (1 << 6)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCUndefined); }
922 if (MCCFlags & (1 << 5)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCUndefined); }
923 if (MCCFlags & (1 << 4)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCLVL1IDEoECheck); }
924 if (MCCFlags & (1 << 3)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCBCIDEoECheck); }
925 if (MCCFlags & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCLVL1IDCheck); }
926 if (MCCFlags & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCEoEOverflow); }
927 if (MCCFlags & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCHitOverflow); }
928
929 if (FEFlags & (1 << 4)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FEWarning); }
930 if (FEFlags & (1 << 3)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FEHitParity); }
931 if (FEFlags & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FERegisterParity); }
932 if (FEFlags & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FEHammingCode); }
933 if (FEFlags & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FEEoCOverflow); }
934 }
935
936 if (indexFE>-1) {
937 if (MCCFlags & (1 << 7)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCUndefined); }
938 if (MCCFlags & (1 << 6)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCUndefined); }
939 if (MCCFlags & (1 << 5)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCUndefined); }
940 if (MCCFlags & (1 << 4)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCLVL1IDEoECheck); }
941 if (MCCFlags & (1 << 3)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCBCIDEoECheck); }
942 if (MCCFlags & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCLVL1IDCheck); }
943 if (MCCFlags & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCEoEOverflow); }
944 if (MCCFlags & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCHitOverflow); }
945
946 if (FEFlags & (1 << 4)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FEWarning); }
947 if (FEFlags & (1 << 3)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FEHitParity); }
948 if (FEFlags & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FERegisterParity); }
949 if (FEFlags & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FEHammingCode); }
950 if (FEFlags & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FEEoCOverflow); }
951 }
952 }
953 else {
955 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::BadFE); }
956 ATH_MSG_DEBUG( "Disabled Pixel chip " << ((rawDataWord & 0x0F000000) >> 24) );
957 }
958 }
959
960 break;
961
962 //-------------------------------------------------------------------------------------------- RAWDATA WORD FOUND
963 case PRB_RAWDATA : // add treatment for raw data word here!
964
965 are_4condensed_words = false;
966
967 break;
968
969 //-------------------------------------------------------------------------------------------- UNKNOWN WORD
970 default:
971 generalwarning("In ROB 0x" << std::hex << robId << ", FE 0x" << mLink << ": Unknown word type found, 0x" << std::hex << rawDataWord << std::dec << ", ignoring");
973 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
974 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
975
976 } // end of switch
977 } // end of loop over ROD
978
979 ATH_CHECK( updateEventInfoIfEventCorrupted( corruptionError ) );
980
981 // Verify that all active IBL FEs sent the same number of headers
982 if (isIBLModule || isDBMModule) {
983 checkUnequalNumberOfHeaders( nFragmentsPerFE, robId );
984 }
985
986 // Fill error information in IDC
987 for (size_t i=0; i<static_cast<size_t>(bsErrWord.size()); i++) {
988 if (bsErrWord[i]>0) {
989 decodingErrors.setOrDrop(i,bsErrWord[i]);
990 }
991 }
992
993 if (sc == StatusCode::RECOVERABLE) {
994
995 if (errorRecoverable == (3 << 20) ){ // Fix for M8, this error always occurs, masked out REMOVE FIXME !!
997 return StatusCode::SUCCESS;
998 }
999 ATH_MSG_DEBUG( "Recoverable errors found in PixelRodDecoder, errorcode: " << errorRecoverable );
1000 }
1001 return sc;
1002}
1003
1004// ****************************************************************************************************** DECODING FUNCTIONS
1005
1007// extract the FE (w.r.t. SLink) from the Link Number (nnnnn), present in the IBL header, long hit, fe flag error and trailer words
1009uint32_t PixelRodDecoder::extractFefromLinkNum(const uint32_t linkNum) const
1010{
1011 return linkNum & 0x7;
1012}
1013
1015// extract the FE (w.r.t. SLink) from the Link Number (nnnnn), present in the IBL header, long hit, fe flag error and trailer words
1017uint32_t PixelRodDecoder::extractSLinkfromLinkNum(const uint32_t linkNum) const
1018{
1019 return (linkNum >> 3) & 0x3;
1020}
1021
1022
1023// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HEADER BITS
1024
1026// decode IBL BCID (bits 0-9 of IBL module header word)
1028uint32_t PixelRodDecoder::decodeBCID_IBL(const uint32_t word) const
1029{
1030 return ((word >> PRB_BCIDskip_IBL) & PRB_BCIDmask_IBL);
1031}
1032
1034// decode IBL LVL1ID (bits 10-22 of IBL module header word)
1036uint32_t PixelRodDecoder::decodeL1ID_IBL(const uint32_t word) const
1037{
1038 return ((word >> PRB_L1IDskip_IBL) & PRB_L1IDmask_IBL);
1039}
1040
1042// decode IBL FeI4B flag bit (bit 23 of IBL module header word)
1044uint32_t PixelRodDecoder::decodeFeI4Bflag_IBL(const uint32_t word) const
1045{
1046 return ((word >> PRB_FeI4BFLAGskip_IBL) & PRB_FeI4BFLAGmask_IBL);
1047}
1048
1050// decode IBL module link number (bits 24-28 of IBL module header word)
1052uint32_t PixelRodDecoder::decodeModule_IBL(const uint32_t word) const
1053{
1054 return ((word >> PRB_MODULEskip_IBL) & PRB_MODULEmask_IBL);
1055}
1056
1058// decode BCID (bits 0-7 of module Pixel header word)
1060uint32_t PixelRodDecoder::decodeBCID(const uint32_t word) const
1061{
1062 return ((word >> PRB_BCIDskip) & PRB_BCIDmask);
1063}
1064
1066// decode LVL1ID (bits 8-11 of module Pixel header word)
1068uint32_t PixelRodDecoder::decodeL1ID(const uint32_t word) const
1069{
1070 return ((word >> PRB_L1IDskip) & PRB_L1IDmask);
1071}
1072
1074// decode LVL1ID skipped (bits 12-15 of module Pixel header word)
1076uint32_t PixelRodDecoder::decodeL1IDskip(const uint32_t word) const
1077{
1078 return ((word >> PRB_L1IDSKIPskip) & PRB_L1IDSKIPmask);
1079}
1080
1082// decode module link number (bits 16-22 of module Pixel header word)
1084uint32_t PixelRodDecoder::decodeModule(const uint32_t word) const
1085{
1086 return ((word >> PRB_MODULEskip) & PRB_MODULEmask);
1087}
1088
1090// decode header errors (bits 25-28 of module Pixel header word)
1092uint32_t PixelRodDecoder::decodeHeaderErrors(const uint32_t word) const
1093{
1094 return ((word >> PRB_HEADERERRORSskip) & PRB_HEADERERRORSmask);
1095}
1096
1097
1098
1099
1100// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HIT WORD BITS
1101
1103// decode hit row number (bits 0-7 of Pixel hit word, bits 0-8 of IBL hit word)
1105uint32_t PixelRodDecoder::decodeRow(const uint32_t word, bool isIBLorDBM) const {
1106 if( isIBLorDBM ) {
1107 return ((word >> PRB_ROWskip_IBL) & PRB_ROWmask_IBL);
1108 }
1109 else {
1110 return ((word >> PRB_ROWskip) & PRB_ROWmask);
1111 }
1112}
1113
1115// decode hit column number (bits 8-12 of Pixel hit word, bits 9-15 of IBL hit word)
1117uint32_t PixelRodDecoder::decodeColumn(const uint32_t word, bool isIBLorDBM) const {
1118 if( isIBLorDBM ) {
1119 return ((word >> PRB_COLUMNskip_IBL) & PRB_COLUMNmask_IBL);
1120 }
1121 else {
1122 return ((word >> PRB_COLUMNskip) & PRB_COLUMNmask);
1123 }
1124}
1125
1127// decode hit TimeOverThreshold value (bits 16-23 of Pixel hit word, bits 16-23 of IBL hit word)
1129uint32_t PixelRodDecoder::decodeToT(const uint32_t word, bool isIBLorDBM) const {
1130 if ( isIBLorDBM ) { // IBL Tot => 8 bits to be divided into 2 Tot info, each of which is 4 bits
1131 uint32_t Tot8Bits = ((word >> PRB_TOTskip_IBL) & PRB_TOTmask_IBL); // this Tot information returns a 8-bit word. In the case of the IBL, it will be splitted into Tot(1) and Tot(2), corresponding to pixels (col,row) and (col, row+1)
1132 return Tot8Bits;
1133 }
1134 else { // Pixel Tot
1135 return ((word >> PRB_TOTskip) & PRB_TOTmask);
1136 }
1137}
1138
1140// decode Link number in the IBL not-condensed hit word (bits 24-26 of IBL hit word)
1142uint32_t PixelRodDecoder::decodeLinkNumHit_IBL(const uint32_t word) const {
1144}
1145
1147// decode module FE number (bits 24-27 of Pixel hit word)
1149uint32_t PixelRodDecoder::decodeFE(const uint32_t word) const {
1150 return ((word >> PRB_FEskip) & PRB_FEmask);
1151}
1152
1153// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TRAILER BITS
1154
1156// decode IBL "M" in the trailer (bits 5-14 of IBL module trailer word)
1161
1163// decode IBL trailer errors (bits 15-23 of IBL module trailer word)
1165uint32_t PixelRodDecoder::decodeTrailerErrors_IBL(const uint32_t word) const {
1167}
1168
1170// decode Link Number in the IBL Trailer (bits 24-26 of IBL module trailer word)
1172uint32_t PixelRodDecoder::decodeLinkNumTrailer_IBL(const uint32_t word) const {
1174}
1175
1176
1178// decode BCID in trailer word
1180uint32_t PixelRodDecoder::decodeBcidTrailer_IBL(const uint32_t word) const {
1182}
1183
1184
1186// decode Condensed Mode Bit in the IBL trailer (bit 22 of IBL module trailer word)
1188uint32_t PixelRodDecoder::decodeCondensedModeBit_IBL(const uint32_t word) const {
1190}
1191
1193// decode trailer errors (bits 26-28 of Pixel module trailer word)
1195//template <class ROBData>
1196uint32_t PixelRodDecoder::decodeTrailerErrors(const uint32_t word) const {
1197 return ((word >> PRB_TRAILERERRORSskip) & PRB_TRAILERERRORSmask);
1198}
1199
1201// look for bitflips in trailer word (bits 0-25 of Pixel module trailer word)
1203uint32_t PixelRodDecoder::decodeTrailerBitflips(const uint32_t word) const {
1204 uint32_t flipword = ((word >> PRB_TRAILERBITFLIPskip) & PRB_TRAILERBITFLIPmask);
1205 uint32_t errorcount = 0;
1206 if (flipword != 0) {
1207 for (int i=0; i<=25; i++){ // this calculates the checksum of the flipword = the number of bitflips
1208 if (flipword & 1) errorcount++;
1209 flipword >>= 1;
1210 }
1211 }
1212 return errorcount; // returns the number of errors
1213}
1214
1215// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLAG WORDS BITS
1216
1218// decodeServiceCodeCounter (bits 0-9 of IBL flag word)
1223
1225// decodeServiceCode (bits 17-22 of IBL flag word)
1227uint32_t PixelRodDecoder::decodeServiceCode_IBL(const uint32_t word) const {
1229}
1230
1232// decodeLinkNumFEFlag (bits 25-27 of IBL flag word)
1234uint32_t PixelRodDecoder::decodeLinkNumFEFlag_IBL(const uint32_t word) const {
1236}
1237
1238
1240// decode FE flag errors (bits 0-7 of Pixel flag type 2 word)
1242uint32_t PixelRodDecoder::decodeFEFlags2(const uint32_t word) const {
1243 return ((word >> PRB_FEFlagskip2) & PRB_FEFlagmask2);
1244}
1245
1247// decode MCC flag errors (bits 8-12 of Pixel flag type 2 word)
1249uint32_t PixelRodDecoder::decodeMCCFlags(const uint32_t word) const {
1250 return ((word >> PRB_MCCFlagskip) & PRB_MCCFlagmask);
1251}
1252
1254// determine module word type
1256uint32_t PixelRodDecoder::getDataType(unsigned int rawDataWord, bool link_start) const {
1257 if (link_start) { // there was a header, so if a timeout is found it's really a timeout and not an empty header, same for raw data
1258 if ((rawDataWord & PRB_DATAMASK) == PRB_RAWDATA ) return PRB_RAWDATA; // module flag word found
1259 if (rawDataWord == PRB_TIMEOUT) return PRB_TIMEOUT; // time out word found
1260 }
1261 if ((rawDataWord & PRB_DATAMASK) == PRB_LINKHEADER) return PRB_LINKHEADER; // module header word found
1262 if (((rawDataWord & PRB_FEERRORMASK) == PRB_FEERROR2) && ((rawDataWord & PRB_FEERROR2CHECK) == PRB_FEERROR2CHECK)) return PRB_FEERROR2; // type 2 word found Pixel
1263 if (((rawDataWord & PRB_DATAMASK) == PRB_FEERROR_IBL)) return PRB_FEERROR2; // type word found IBL
1264 if ((rawDataWord & PRB_HITMASK) == PRB_DATAWORD) return PRB_DATAWORD; // module hit word found
1265 if ((rawDataWord & PRB_DATAMASK) == PRB_LINKTRAILER) return PRB_LINKTRAILER; // module trailer word found
1266 return PRB_UNKNOWNWORD; // unknown word found
1267}
1268
1269
1270bool PixelRodDecoder::checkDataWordsCorruption( uint32_t rawDataWord) const {
1271 if ( ATH_UNLIKELY( rawDataWord==0xaa1234aa )) {
1272 generalwarning("Evt marker encountered during loop on ROD datawords");
1273 return true;
1274 }
1275 else if ( ATH_UNLIKELY( rawDataWord==0xdd1234dd ) ){
1276 generalwarning("ROB marker encountered during loop on ROD datawords");
1277 return true;
1278 }
1279 else if ( ATH_UNLIKELY( rawDataWord==0xee1234ee) ){
1280 generalwarning("ROD marker encountered during loop on ROD datawords");
1281 return true;
1282 }
1283 return false; // no corruption
1284}
1285
1286uint32_t PixelRodDecoder::treatmentFEFlagInfo(unsigned int serviceCode, unsigned int serviceCodeCounter) const {
1287 unsigned int etc = 0, l1req = 0;
1288 // Log the code count
1289 if (serviceCode == 16) { // I'm not like those other codes
1290 etc = (serviceCodeCounter >> 4) & 0x1F;
1291 l1req = serviceCodeCounter & 0x7;
1292 }
1293 // Return a 19-bit code to be used for monitoring
1294 // Service codes of type 'inf' are excluded, except for codes 15, 16 and 25,
1295 // see FE-I4B manual table 39
1296 // The bit position of each monitored service code is sequential starting from the
1297 // least significant bit, see below
1298 uint32_t code = 0;
1299 switch (serviceCode) {
1300 case 0: // BCID counter error, from EOCHL
1301 ATH_MSG_DEBUG("BCID counter error (retrieved in IBL FE Flag word)");
1302 code = code | (1 << 0);
1303 break;
1304
1305 case 1: // Hamming code error in word 0, from EOCHL
1306 ATH_MSG_DEBUG("Hamming code error in word 0 (retrieved in IBL FE Flag word)");
1307 code = code | (1 << 1);
1308 break;
1309
1310 case 2: // Hamming code error in word 1, from EOCHL
1311 ATH_MSG_DEBUG("Hamming code error in word 1 (retrieved in IBL FE Flag word)");
1312 code = code | (1 << 2);
1313 break;
1314
1315 case 3: // Hamming code error in word 2, from EOCHL
1316 ATH_MSG_DEBUG("Hamming code error in word 2 (retrieved in IBL FE Flag word)");
1317 code = code | (1 << 3);
1318 break;
1319
1320 case 4: // L1_in counter error, from EOCHL
1321 ATH_MSG_DEBUG("L1_in counter error (retrieved in IBL FE Flag word)");
1322 code = code | (1 << 4);
1323 break;
1324
1325 case 5: // L1 request counter error from EOCHL
1326 ATH_MSG_DEBUG("L1 request counter error (retrieved in IBL FE Flag word)");
1327 code = code | (1 << 5);
1328 break;
1329
1330 case 6: // L1 register error from EOCHL
1331 ATH_MSG_DEBUG("L1 register error (retrieved in IBL FE Flag word)");
1332 code = code | (1 << 6);
1333 break;
1334
1335 case 7: // L1 Trigger ID error from EOCHL
1336 ATH_MSG_DEBUG("L1 Trigger ID error (retrieved in IBL FE Flag word)");
1337 code = code | (1 << 7);
1338 break;
1339
1340 case 8: // readout processor error from EOCHL
1341 ATH_MSG_DEBUG("Readout processor error (retrieved in IBL FE Flag word)");
1342 code = code | (1 << 8);
1343 break;
1344
1345 case 9: // Fifo_Full flag pulsed from EOCHL
1346 ATH_MSG_DEBUG("Fifo_Full flag pulsed (retrieved in IBL FE Flag word)");
1347 break;
1348
1349 case 10: // HitOr bus pulsed from PixelArray
1350 ATH_MSG_DEBUG("HitOr bus pulsed (retrieved in IBL FE Flag word)");
1351 break;
1352
1353 // case 11 to 13 not used
1354 case 11:
1355 case 12:
1356 case 13:
1357 ATH_MSG_DEBUG("Received invalid service code: " << serviceCode << " (payload = " << serviceCodeCounter << ")");
1358 break;
1359
1360 case 14: // 3 MSBs of bunch counter and 7 MSBs of L1A counter from EOCHL
1361 ATH_MSG_DEBUG("Received service code 14 - ignored");
1362 break;
1363
1364 case 15: // Skipped trigger counter
1365 ATH_MSG_DEBUG("Skipped trigger counter (retrieved in IBL FE Flag word). There are " << serviceCodeCounter << " skipped triggers.");
1366 code = code | (1 << 9);
1367 break;
1368
1369 case 16: // Truncated event flag and counter from EOCHL
1370 ATH_MSG_DEBUG("Truncated event flag: ETC = " << etc << ", L1Req = " << l1req);
1371 code = code | (1 << 10);
1372 break;
1373
1374 // case 17 to 20 not used
1375 case 17:
1376 case 18:
1377 case 19:
1378 case 20:
1379 ATH_MSG_DEBUG("Received invalid service code: " << serviceCode << " (payload = " << serviceCodeCounter << ")");
1380 break;
1381
1382 case 21: // Reset bar RA2b pulsedd from Pad, PRD
1383 ATH_MSG_DEBUG("Reset bar RA2b pulsed (retrieved in IBL FE Flag word)");
1384 break;
1385
1386 case 22: // PLL generated clock phase faster than reference from CLKGEN
1387 ATH_MSG_DEBUG("PLL generated clock phase faster than reference (retrieved in IBL FE Flag word)");
1388 break;
1389
1390 case 23: // Reference clock phase faster than PLL, from CLKGEN
1391 ATH_MSG_DEBUG("Reference clock phase faster than PLL (retrieved in IBL FE Flag word)");
1392 break;
1393
1394 case 24: // Triple redundant mismatchfrom CNFGMEM
1395 ATH_MSG_DEBUG("Triple redundant mismatch (retrieved in IBL FE Flag word)");
1396 code = code | (1 << 11);
1397 break;
1398
1399 case 25: // Write register data error from CMD
1400 ATH_MSG_DEBUG("Write register data error (retrieved in IBL FE Flag word)");
1401 code = code | (1 << 12);
1402 break;
1403
1404 case 26: // Address error from CMD
1405 ATH_MSG_DEBUG("Address error (retrieved in IBL FE Flag word)");
1406 code = code | (1 << 13);
1407 break;
1408
1409 case 27: // Other command decoder error- see CMD section from CMD
1410 ATH_MSG_DEBUG("Other command decoder error- see CMD section (retrieved in IBL FE Flag word)");
1411 code = code | (1 << 14);
1412 break;
1413
1414 case 28: // Bit flip detected in command decoder input stream from CMD
1415 ATH_MSG_DEBUG("Bit flip detected in command decoder input stream (retrieved in IBL FE Flag word)");
1416 code = code | (1 << 15);
1417 break;
1418
1419 case 29: // SEU upset detected in command decoder (triple redundant mismatch) from CMD
1420 ATH_MSG_DEBUG("SEU upset detected in command decoder (triple redundant mismatch) (retrieved in IBL FE Flag word)");
1421 code = code | (1 << 16);
1422 break;
1423
1424 case 30: // Data bus address error from CMD
1425 ATH_MSG_DEBUG("Data bus address error (retrieved in IBL FE Flag word)");
1426 code = code | (1 << 17);
1427 break;
1428
1429 case 31: // Triple redundant mismatch from CMD
1430 ATH_MSG_DEBUG("Triple redundant mismatch (retrieved in IBL FE Flag word)");
1431 code = code | (1 << 18);
1432 break;
1433
1434 default:
1435 ATH_MSG_DEBUG("ServiceCode not used at the moment");
1436
1437 }
1438 return code;
1439}
1440
1441StatusCode PixelRodDecoder::updateEventInfoIfEventCorrupted( bool isCorrupted ) const {
1442 if ( not isCorrupted )
1443 return StatusCode::SUCCESS;
1444 //Set EventInfo error
1445 const xAOD::EventInfo* eventInfo=nullptr;
1446 ATH_CHECK(evtStore()->retrieve(eventInfo));
1448 ATH_MSG_WARNING(" cannot set EventInfo error state for Pixel " );
1449 }
1450 if (!eventInfo->updateEventFlagBit(xAOD::EventInfo::Pixel,0x1)) { //FIXME an enum at some appropriate place to indicating 0x1 as
1451 ATH_MSG_WARNING(" cannot set flag bit for Pixel " );
1452 }
1453 return StatusCode::SUCCESS;
1454}
1455
1456
1457void PixelRodDecoder::checkUnequalNumberOfHeaders( const unsigned int nFragmentsPerFE[8], uint32_t robId ) const {
1458 unsigned int nFrags = 0;
1459 bool foundIssue = false;
1460 for (unsigned int i = 0; i < 8; ++i) {
1461 if (nFrags == 0) {
1462 if (nFragmentsPerFE[i] != 0) nFrags = nFragmentsPerFE[i]; // set nFrags on first non-zero occurence
1463 }
1464 else {
1465 if (nFragmentsPerFE[i] != 0 && nFragmentsPerFE[i] != nFrags) {
1466 foundIssue = true;
1467 }
1468 }
1469 }
1470 if ( not foundIssue ) return;
1471
1472 // Got unequal number of headers per FE for same ROD, this means trouble.
1473 // Print value for each FE
1474 std::string errmsg;
1475 for (unsigned int j = 0; j < 8; ++j) {
1476 if (nFragmentsPerFE[j] != 0) {
1477 errmsg += "FE "+ std::to_string(j) + " " +std::to_string(nFragmentsPerFE[j]) + " ";
1478 }
1479 }
1480 generalwarning("In ROB 0x" << std::hex << robId << ": got unequal number of headers per FE" << std::dec);
1481 generalwarning("[FE number] : [# headers] - " << errmsg);
1482}
1483
1484
1485unsigned int PixelRodDecoder::getLocalFEI4(const uint32_t fe, const uint64_t onlineId) const
1486{
1487 unsigned int linknum40 = (onlineId>>24) & 0xFF;
1488 unsigned int linknum80 = (onlineId>>32) & 0xFF;
1489
1490 if (fe == linknum40) {
1491 return 0;
1492 } else if (fe == linknum80) {
1493 return 1;
1494 } else {
1495 ATH_MSG_ERROR("Error in retrieving local FE-I4 number: linknumber " << fe << " not found in onlineID " << std::hex << onlineId);
1496 }
1497 return 0xF;
1498}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define ATH_UNLIKELY(x)
unsigned int divideHits(unsigned int &sourceWord, const unsigned int startBit, const unsigned int endBit)
Push bits from a sourceWord to a target word, returns true if successful.
Header file for utility functions shiftRight and DivideHITS.
static Double_t sc
static const uint32_t PRB_FEERROR2CHECK
static const uint32_t PRB_L1IDSKIPmask
static const uint32_t PRB_MCCFlagmask
static const uint32_t PRB_TOTskip
static const uint32_t PRB_L1IDmask
static const uint32_t PRB_TOTskip_IBL
static const uint32_t PRB_LINKHEADER
static const uint32_t skipRow
static const uint32_t PRB_FEskip
static const uint32_t skip5
static const uint32_t PRB_ROWskip_IBL
static const uint32_t PRB_SKIPPEDTRIGGERTRAILERskip_IBL
static const uint32_t PRB_SERVICECODEskip_IBL
static const uint32_t PRB_BCIDSKIPTRAILERmask_IBL
static const uint32_t PRB_ROWmask
static const uint32_t PRB_TRAILERERRORSskip_IBL
static const uint32_t PRB_LINKNUMTRAILERmask_IBL
static const uint32_t PRB_MODULEskip_IBL
static const uint32_t skip3
static const uint32_t PRB_SERVICECODECOUNTERskip_IBL
static const uint32_t PRB_FEERRORMASK
static const uint32_t PRB_LINKNUMBERFEFLAGmask_IBL
static const uint32_t PRB_BCIDmask
static const uint32_t PRB_FEERROR_IBL
static const uint32_t PRB_UNKNOWNWORD
static const uint32_t PRB_MODULEmask_IBL
static const uint32_t PRB_TRAILERBITFLIPmask
static const uint32_t PRB_LINKNUMBERFEFLAGskip_IBL
static const uint32_t PRB_SERVICECODEmask_IBL
static const uint32_t PRB_DATAWORD
static const int nCondensedWords
static const uint32_t PRB_COLUMNmask
static const uint32_t PRB_TRAILERERRORSmask_IBL
static const uint32_t PRB_TRAILERBITFLIPskip
static const uint32_t PRB_TOTmask
static const uint32_t PRB_BCIDskip_IBL
static const uint32_t PRB_CONDENSEDMODEskip_IBL
static const uint32_t mask19
static const uint32_t PRB_FEmask
static const uint32_t PRB_L1IDmask_IBL
static const uint32_t PRB_MCCFlagskip
static const uint32_t PRB_FEERROR2
static const uint32_t PRB_BCIDskip
static const uint32_t PRB_TRAILERERRORSskip
static const uint32_t mask12
static const uint32_t PRB_FeI4BFLAGskip_IBL
static const uint32_t PRB_L1IDskip
static const uint32_t PRB_HEADERERRORSmask
static const uint32_t PRB_ROWmask_IBL
static const uint32_t PRB_TIMEOUT
static const uint32_t PRB_FEFlagmask2
static const uint32_t PRB_COLUMNskip
static const uint32_t PRB_DATAMASK
static const uint32_t PRB_LASTHITCONDENSEDWORD
static const uint32_t PRB_COLUMNskip_IBL
static const uint32_t PRB_LINKNUMTRAILERskip_IBL
static const uint32_t PRB_L1IDSKIPskip
static const uint32_t PRB_LINKNUMHITskip_IBL
static const uint32_t skip4
static const uint32_t mask24
static const uint32_t PRB_HITMASK
static const uint32_t PRB_TOTmask_IBL
static const uint32_t skipTOT
static const uint32_t PRB_RAWDATA
static const uint32_t PRB_COLUMNmask_IBL
static const uint32_t PRB_SKIPPEDTRIGGERTRAILERmask_IBL
static const uint32_t PRB_LINKNUMHITmask_IBL
static const uint32_t PRB_HEADERERRORSskip
static const uint32_t PRB_FEFlagskip2
static const uint32_t PRB_MODULEskip
static const uint32_t PRB_CONDENSEDMODEmask_IBL
static const uint32_t PRB_FIRSTHITCONDENSEDWORD
static const uint32_t skipCol
static const uint32_t PRB_TRAILERERRORSmask
static const uint32_t PRB_ROWskip
static const uint32_t PRB_BCIDSKIPTRAILERskip_IBL
static const uint32_t PRB_FeI4BFLAGmask_IBL
static const uint32_t nHits
static const uint32_t PRB_MODULEmask
static const uint32_t PRB_LINKTRAILER
static const uint32_t PRB_BCIDmask_IBL
static const uint32_t PRB_L1IDskip_IBL
static const uint32_t PRB_SERVICECODECOUNTERmask_IBL
static const uint32_t mask5
This is an Identifier helper class for the Pixel subdetector.
EventContainers::IIdentifiableCont< InDetRawDataCollection< PixelRDORawData > > IPixelRDO_Container
bool isIBL(uint32_t robId)
#define generalwarning(x)
#define lvl1id_bcid_warning(x)
bool isDBM(uint32_t robId)
static std::ostringstream errmsg
Definition WaferTree.h:25
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
ServiceHandle< StoreGateSvc > & evtStore()
const ServiceHandle< StoreGateSvc > & detStore() const
value_type push_back(value_type pElem)
virtual StatusCode addCollection(const T *coll, IdentifierHash hashId)=0
virtual StatusCode naughtyRetrieve(IdentifierHash hashId, T *&collToRetrieve) const =0
IDC like storage for BS errors, TODO, customise implementation further so that we store int rather th...
size_t maxSize() const
Return the maxSize of the collection.
bool setOrDrop(size_t i, const T &value)
Set the value for the given hash.
This is a "hash" representation of an Identifier.
Dedicated detector manager extending the functionality of the SiDetectorManager with dedicated pixel ...
const SiNumerology & numerology() const
Access Numerology.
Class to extract numerology for Pixel and SCT.
int numLayers() const
Number of layers.
void setIdentifier(Identifier id)
std::deque< Identifier > find_entry_offlineList(uint32_t robid) const
std::atomic_uint m_numLVL1IDErrors
uint32_t extractFefromLinkNum(const uint32_t linkNum) const
std::atomic_uint m_numPreambleErrors
InDetRawDataCollection< PixelRDORawData > PixelRawCollection
std::atomic_uint m_numLinkMaskedByPPC
std::atomic_uint m_numTimeOutErrors
std::atomic_uint m_numDecodingErrors
const unsigned m_maxNumBCIDWarnings
uint32_t getDataType(unsigned int rawDataWord, bool link_start) const
uint32_t decodeTrailerBitflips(const uint32_t word) const
uint32_t decodeTrailerErrors_IBL(const uint32_t word) const
StatusCode fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment *robFrag, IPixelRDO_Container *rdoIdc, IDCInDetBSErrContainer &decodingErrors, std::vector< IdentifierHash > *vecHash, const EventContext &ctx) const override
void propagateROBErrorsToModules(const PixelCablingCondData *pixCabling, uint32_t robId, std::array< uint64_t, PixelRodDecoder::ERROR_CONTAINER_MAX > &bsErrWord, IDCInDetBSErrContainer &decodingErrors, PixelByteStreamErrors::PixelErrorsEnum error_code, const char *error_description) const
std::atomic_uint m_numBCIDWarnings
ServiceHandle< InDetDD::IPixelReadoutManager > m_pixelReadout
StatusCode finalize() override
StatusCode updateEventInfoIfEventCorrupted(bool isCorrupted) const
checks if all FEs have sent the same number of headers, if not, generate warning message
uint32_t decodeSkippedTrigTrailer_IBL(const uint32_t word) const
uint32_t decodeHeaderErrors(const uint32_t word) const
uint32_t decodeCondensedModeBit_IBL(const uint32_t word) const
std::atomic_uint m_numBCIDErrors
std::atomic_uint m_numDuplicatedPixels
Pixel1RawData RDO
uint32_t decodeFeI4Bflag_IBL(const uint32_t word) const
uint32_t treatmentFEFlagInfo(unsigned int serviceCode, unsigned int serviceCodeCounter) const
uint32_t decodeMCCFlags(const uint32_t word) const
bool thisRdoIsUnique(const Identifier &pixelRdo, std::unordered_set< Identifier > &pixelRdosSeenSoFar) const
get local FEI4
uint32_t decodeRow(const uint32_t word, bool isIBLorDBM) const
uint32_t decodeModule_IBL(const uint32_t word) const
void checkUnequalNumberOfHeaders(const unsigned int nFragmentsPerFE[8], uint32_t robId) const
if the check duplicated RDO flag is true, check that this RDO is unique (returns true if unique)
StatusCode initialize() override
uint32_t decodeFE(const uint32_t word) const
std::atomic_uint m_numLimitError
SG::ReadCondHandleKey< PixelHitDiscCnfgData > m_condHitDiscCnfgKey
uint32_t decodeTrailerErrors(const uint32_t word) const
std::atomic_uint m_numGenWarnings
SG::ReadCondHandleKey< PixelCablingCondData > m_condCablingKey
const unsigned m_maxNumGenWarnings
uint32_t decodeServiceCode_IBL(const uint32_t word) const
std::atomic_uint m_numFlaggedErrors
const PixelID * m_pixel_id
uint32_t decodeColumn(const uint32_t word, bool isIBLorDBM) const
uint32_t decodeToT(const uint32_t word, bool isIBLorDBM) const
uint32_t decodeModule(const uint32_t word) const
unsigned int getLocalFEI4(const uint32_t fe, const uint64_t onlineId) const
in case of invalid ROB fragments set corresponding error flags in all linked modules.
uint32_t decodeL1IDskip(const uint32_t word) const
uint32_t decodeFEFlags2(const uint32_t word) const
uint32_t decodeLinkNumHit_IBL(const uint32_t word) const
uint32_t decodeL1ID_IBL(const uint32_t word) const
uint32_t decodeBcidTrailer_IBL(const uint32_t word) const
std::atomic_uint m_numRODErrors
uint32_t decodeServiceCodeCounter_IBL(const uint32_t word) const
uint32_t decodeBCID_IBL(const uint32_t word) const
uint32_t extractSLinkfromLinkNum(const uint32_t linkNum) const
uint32_t decodeLinkNumFEFlag_IBL(const uint32_t word) const
std::atomic_uint m_numTrailerErrors
std::atomic_uint m_numDisabledFEErrors
std::atomic_uint m_numInvalidIdentifiers
PixelRodDecoder(const std::string &type, const std::string &name, const IInterface *parent)
std::atomic_uint m_masked_errors
BooleanProperty m_checkDuplicatedPixel
bool checkDataWordsCorruption(uint32_t word) const
checks if data words do not look like header & trailer markers, return true if so,...
uint32_t decodeL1ID(const uint32_t word) const
uint32_t decodeLinkNumTrailer_IBL(const uint32_t word) const
uint32_t decodeBCID(const uint32_t word) const
const_pointer_type cptr()
@ Pixel
The pixel tracker.
bool updateEventFlagBit(const EventFlagSubDet subDet, const size_t bit) const
Change detector flags with update semantics.
@ Error
The sub-detector issued an error.
bool updateErrorState(const EventFlagSubDet subDet, const EventFlagErrorState state) const
Update the error state for one particular sub-detector.
const DataType * PointerType
Definition RawEvent.h:25
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27
void addError(IDCInDetBSErrContainer::ErrorCode &errWord, PixelErrorsEnum errType)
PixelErrorsEnum
< Possible errors in pixel data decoding
EventInfo_v1 EventInfo
Definition of the latest event info version.