ATLAS Offline Software
Loading...
Searching...
No Matches
PixelRodDecoder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5#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 std::array<uint64_t, PixelRodDecoder::ERROR_CONTAINER_MAX> bsErrWord{};
159 std::fill(bsErrWord.begin(),bsErrWord.end(),0);
160 // Check ROD status
161 if (robFrag->nstatus()!=0) {
162 const uint32_t* rob_status;
163 robFrag->status(rob_status);
164 // check the ROD status for truncation
165 if (ATH_UNLIKELY((*rob_status)!=0)) {
166 ATH_MSG_DEBUG( "ROB status word for robid 0x"<< std::hex << robId << " is non-zero 0x" << (*rob_status) << std::dec);
167 /*
168 Definition of the status words in a ROB fragment header is found in
169 https://twiki.cern.ch/twiki/bin/view/Atlas/ROBINFragmentErrors#Definition_of_the_first_status_e
170 */
171 if ((*rob_status) & (0x1u << 27)) {
172 propagateROBErrorsToModules(pixCabling.cptr(),robId,bsErrWord,decodingErrors,PixelByteStreamErrors::TruncatedROB, "data truncation");
173 return StatusCode::RECOVERABLE;
174 }
175 if ((*rob_status) & (0x1u << 31)) {
176 propagateROBErrorsToModules(pixCabling.cptr(),robId,bsErrWord,decodingErrors,PixelByteStreamErrors::MaskedROB, "resource was masked off");
177 return StatusCode::RECOVERABLE;
178 }
179 // in case the ROB fragment has a seemingly invalid size check the fragment and reject it if the check is not passed.
180 // Note: there are usable ROB fragments (i.e. ROB fragments which contribute pixel hits to tracks) which do not pass the check, so
181 // rejecting all fragments which do not pass the test would reject also seemingly "good" data.
182 if (robFrag->rod_ndata() > robFrag->payload_size_word() && !robFrag->check_rod_noex(robFrag->rod_version() >> 16)) {
183 propagateROBErrorsToModules(pixCabling.cptr(),robId,bsErrWord,decodingErrors,PixelByteStreamErrors::TruncatedROB,
184 " invalid ROD fragment, invalid payload size");
185 return StatusCode::RECOVERABLE;
186 }
187 }
188 }
189 StatusCode sc = StatusCode::SUCCESS;
190
191 // Fill the Collections for this ROB.
192 unsigned int mBCID = 0x3FFF; // create module BCID variable
193 unsigned int mLVL1ID = 0x3FFF; // create module LVL1ID variable
194 unsigned int mLink = 0x3FFF; // create module Link variable
195 int mLVL1A = 0x3FFF; // create LVL1A variable
196 int offsetBCID_ROB_FE = 0x3FFF; // offset between BCID in ROD header and FE header
197 // take the Header "nnnnn" bits as a reference for the other words (hit, feFlag, trailer words)
198 uint32_t linkNum_IBLheader = 0; // create variable containing 5 bits, corresponding to the "nnnnn" bits in the header IBL/DBM word
199 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)
200 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)
201 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
202 uint32_t sLinkHeader = 0; // create sLink variable, retrieved from the header words
203 // Various bookkeeping variables
204 bool link_start = false; // link (module) header found flag - reset by link (module) trailer
205 IdentifierHash offlineIdHash; // offlineIdHash
206 IdentifierHash previous_offlineIdHash; // previous module offline identifier
207 int mBCID_offset = -1; // BCID offset to calculate L1A
208 unsigned int mBCID_max_pix = 0x100; // cycle of BCID values
209 unsigned int mBCID_max_IBL = 0x400;
210 bool receivedCondensedWords = false; // to cross-check the condensed mode bit ('c')
211 int countHitCondensedWords = 0; // counter to the "condensed hits" of the IBL
212 uint32_t condensedWords[nCondensedWords] = {}; // this vector saves the 4 condensed hit words that are found
213 bool are_4condensed_words = false;
214 unsigned int prevBCID = 0x3FFF; // initialize to out-of-range value
215 unsigned int prevLVL1ID = 0x3FFF;
216 uint32_t prevLinkNum = 99;
217 int prevOffsetBCID_ROB_FE = 0x3FFF;
218 unsigned int prevStartingBCID = 0x3FFF;
219 unsigned int nFragmentsPerFE[8] = {0}; // number of header-trailer pairs per IBL FE
220 IdentifierHash skipHash = 0xffffffff, lastHash = 0xffffffff; // used for decoding to not have to search the vector all the time
221 PixelRawCollection* coll = nullptr;
222 // get the data from the word
224 robFrag->rod_data(vint);
225 int hitDiscCnfg = 3; // FE-I4 hit discrimination setting
226 // Do a check on IBL Slink ID
227 eformat::helper::SourceIdentifier sid_rob(robId);
228 sLinkSourceId = (sid_rob.module_id()) & 0x000F; // retrieve S-Link number from the source Identifier (0xRRRL, L = Slink number)
229 if ( isIBL( robId ) && sLinkSourceId>0x3) { // Check if SLink number for the IBL is correct!
230 generalwarning("In ROB 0x" << std::hex << robId << ": IBL/DBM SLink number not in correct range (0-3): SLink = " << std::dec << sLinkSourceId);
231 }
232 // Store length of module fragments, for monitoring
233 bool corruptionError = false;
234 // To check duplicated pixels
235 std::unordered_set<Identifier> foundPixels;
236 // ============== ============== ============== ============== ============== ============== ============== ============== //
237 // loop over the data in the fragment
238 const int nwords = robFrag->rod_ndata();
239 for (int dataword_it = 0; dataword_it < nwords; ++dataword_it) {
240 const uint32_t rawDataWord = vint[dataword_it];
241 corruptionError = corruptionError || checkDataWordsCorruption( rawDataWord );
242 uint32_t word_type = getDataType(rawDataWord, link_start); // get type of data word
243
244 serviceCodeCounter = 0;
245 serviceCode = 0;
246
247 int indexModule = -1;
248 int indexFE = -1;
249// if (word_type!=PRB_LINKHEADER) {
250 if (offlineIdHash!=0xffffffff) { // now write the error word to the service
251 isIBLModule = false;
252 isDBMModule = false;
253 if (m_is_ibl_present) {
254 isIBLModule = isIBL(robId);
255 isDBMModule = isDBM(robId);
256 }
257
258 int chFE = 0;
259 if (isIBLModule || isDBMModule) { // get FE channel id for IBL
260 linkNum_IBLheader = decodeModule_IBL(rawDataWord);
261 chFE = (extractFefromLinkNum(linkNum_IBLheader) & 0x1);
262 if (m_pixelReadout->getModuleType(m_pixel_id->wafer_id(offlineIdHash))==InDetDD::PixelModuleType::IBL_3D) { chFE=0; }
263 }
264 else { // for PIXEL
265 chFE = decodeFE(rawDataWord);
266 }
267 indexModule = static_cast<int>(offlineIdHash); // [0,2047]
268 indexFE = (1+chFE)*m_pixel_id->wafer_hash_max()+static_cast<int>(offlineIdHash); // index for IDCInDetBSErrContainer
269 }
270// }
271
272 bool headerErr_decoding = false;
273 bool headerErr_flagged = false;
274 bool headerErr_preamble = false;
275 bool headerErr_timeout = false;
276 bool headerErr_lvl1id = false;
277 bool headerErr_bcid = false;
278 switch (word_type) { // depending on type of word call the right decoding method
279 //-------------------------------------------------------------------------------------------- HEADER WORD FOUND
280 case PRB_LINKHEADER: // link (module) header found
281
282 ATH_MSG_DEBUG("Header word found");
283 errorRecoverable = 0; // reset errorcode
284
285 if (link_start) { // if header found before last header was closed by a trailer -> error
286 generalwarning("In ROB 0x" << std::hex << robId << ": Unexpected link header found: 0x" << std::hex << rawDataWord << ", data corruption" << std::dec);
288 headerErr_decoding = true;
289 }
290 else {
291 ATH_MSG_DEBUG( "Header decoding starts" );
292 }
293 link_start = true; // setting link (module) header found flag
294 are_4condensed_words = false;
295 receivedCondensedWords = false;
296 isIBLModule = false;
297 isDBMModule = false;
298 countHitCondensedWords = 0;
299 if (m_is_ibl_present) {
300 isIBLModule = isIBL(robId);
301 isDBMModule = isDBM(robId);
302 }
303 // Keep track of IDs for previous fragment before decoding the new values
304 prevLVL1ID = mLVL1ID;
305 prevBCID = mBCID;
306 prevLinkNum = mLink;
307 prevOffsetBCID_ROB_FE = offsetBCID_ROB_FE;
308
309 if (isIBLModule || isDBMModule) { // decode IBL/DBM header word.
310#ifdef PIXEL_DEBUG
311 ATH_MSG_VERBOSE( "Decoding the IBL/DBM header word: 0x" << std::hex << rawDataWord << std::dec );
312#endif
313
314 // IBL header data format: 001nnnnnFLLLLLLLLLLLLLBBBBBBBBBB
315 mBCID = decodeBCID_IBL(rawDataWord); // decode IBL BCID: B
316 mLVL1ID = decodeL1ID_IBL(rawDataWord); // decode IBL LVL1ID: L
317 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
318 if (decodeFeI4Bflag_IBL(rawDataWord)) {
320 headerErr_flagged = true;
321 }
322 fe_IBLheader = extractFefromLinkNum(linkNum_IBLheader);
323 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
324 sLinkHeader = extractSLinkfromLinkNum(linkNum_IBLheader); // this is used to check that the (redundant) info is correctly transmitted
325 if (sLinkHeader != sLinkSourceId) {
326 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);
327 }
328 // If decoding fragment from same FE as previous one, do LVL1ID and BCID checks
329 if (mLink == prevLinkNum) {
330 // Check that L1ID is the same for all fragments
331 if (mLVL1ID != prevLVL1ID && prevLVL1ID != 0x3FFF) {
332 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);
333 }
334 // Check that BCIDs are consecutive
335 if ((mBCID != prevBCID + 1) && prevBCID != 0x3FFF && prevBCID != mBCID_max_IBL) {
336 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);
337 }
338 }
339 else { // If decoding new FE, check BCID offset
340 offsetBCID_ROB_FE = static_cast<int>(mBCID) - robBCID;
341 if (offsetBCID_ROB_FE != prevOffsetBCID_ROB_FE && (offsetBCID_ROB_FE != 0x3FFF && prevOffsetBCID_ROB_FE != 0x3FFF)) {
342 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)");
343 }
344 // Check that first fragment from each FE starts at the same BCID
345 if (mBCID != prevStartingBCID && prevStartingBCID != 0x3FFF) {
346 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);
347 }
348 prevStartingBCID = mBCID;
349 }
350 // Count number of headers received
351 if (mLink < 0x8) { ++nFragmentsPerFE[mLink]; }
352 }
353 else { // this is Pixels detector decode header word. Data format: 001PtlbxdnnnnnnnMMMMLLLLBBBBBBBB (NOT IBL OR PIXEL)
354 ATH_MSG_VERBOSE( "Decoding Pixel header word: 0x" << std::hex << rawDataWord << std::dec );
355 mBCID = decodeBCID(rawDataWord); // decode Pixel BCID: B
356 mLVL1ID = decodeL1ID(rawDataWord); // decode Pixel LVL1ID: L
357 mLink = decodeModule(rawDataWord); // decode Pixel link (module): n
358 const uint32_t headerError = decodeHeaderErrors(rawDataWord); // get link (module) header errors
359 if ( headerError != 0 ) {
360 sc = StatusCode::RECOVERABLE;
361 errorRecoverable = errorRecoverable | (headerError << 20); //encode error as HHHHMMMMMMMMFFFFFFFFTTTT for header, flagword, trailer errors
362
363 { // only treatment for header errors now, FIXME
364 if (headerError & (1 << 3)) {
366 headerErr_preamble = true;
367 }
368 if (headerError & (1 << 2)) {
370 headerErr_timeout = true;
371 }
372 if (headerError & (1 << 1)) {
374 headerErr_lvl1id = true;
375 }
376 if (headerError & (1 << 0)) {
378 headerErr_bcid = true;
379 }
380 }
381
382 }
383 } // end of detector type decoding
384 // Get onlineId
385 onlineId = pixCabling->getOnlineIdFromRobId(robId, mLink);
386 if (onlineId == 0) {
387 generalwarning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": Got invalid onlineId (= 0) in FE header - dataword = 0x" << rawDataWord);
388 }
389
390#ifdef PIXEL_DEBUG
391 ATH_MSG_VERBOSE("In decoder: got onlineId 0x" << std::hex << onlineId );
392#endif
393
394 offlineIdHash = m_pixel_id->wafer_hash(pixCabling->find_entry_onoff(onlineId));
395 if (offlineIdHash != previous_offlineIdHash) {
396 mBCID_offset = mBCID; // set BCID offset if this is first LVL1A
397 // The index array is defined in PixelRawDataProviderTool::SizeOfIDCInDetBSErrContainer()
398 // Here, 52736 is a separator beween error flags and isActive flags.
399 bsErrWord[static_cast<int>(offlineIdHash)+52736] = 1;
400 }
401 mLVL1A = mBCID - mBCID_offset; // calculate the LVL1A
402 if (mLVL1A < 0) {
403 if (isIBLModule || isDBMModule) { mLVL1A=mLVL1A+mBCID_max_IBL; }
404 else { mLVL1A=mLVL1A+mBCID_max_pix; }
405 }
406
407 // Fill header error word per IBL FE
408 if (isIBLModule || isDBMModule) {
409 if (indexFE>-1) {
410 if (headerErr_decoding) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
411 if (headerErr_flagged) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Flagged); }
412 if (headerErr_preamble) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Preamble); }
413 if (headerErr_timeout) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::TimeOut); }
414 if (headerErr_lvl1id) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::LVL1ID); }
415 if (headerErr_bcid) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::BCID); }
416 }
417 }
418 else {
419 // Fill header error word per module
420 if (headerErr_decoding) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::Decoding); }
421 if (headerErr_flagged) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::Flagged); }
422 if (headerErr_preamble) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::Preamble); }
423 if (headerErr_timeout) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::TimeOut); }
424 if (headerErr_lvl1id) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::LVL1ID); }
425 if (headerErr_bcid) { PixelByteStreamErrors::addError(bsErrWord[static_cast<int>(offlineIdHash)],PixelByteStreamErrors::BCID); }
426 }
427
428
429#ifdef PIXEL_DEBUG
430 ATH_MSG_VERBOSE( "link header with BCID: " << mBCID << " LVL1ID: " << mLVL1ID << " LVL1A: " << mLVL1A << " link: " << mLink << " found");
431 ATH_MSG_VERBOSE( "got OfflineIDHash: 0x" << std::hex << offlineIdHash << " from OnlineID: 0x" << onlineId << std::dec << " link: " << mLink);
432#endif
433
434 if (offlineIdHash == 0xffffffff) { // if link (module) online identifier (ROBID and link number) not found by mapping
435 generalwarning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": Unknown OnlineId identifier in FE header - not found by mapping" << std::dec);
437 link_start = false; // resetting link (module) header found flag
438 continue; // skip this word and process next one
439 }
440 break;
441 //-------------------------------------------------------------------------------------------- HIT DATA WORD FOUND
442 case PRB_DATAWORD: // hit data found
443 if (link_start) { // if header found before hit -> expected
444 ATH_MSG_DEBUG("Hit word found");
445 unsigned int mFE = 0;
446 unsigned int mRow = 0;
447 unsigned int mColumn = 0;
448 int mToT = 0;
449 uint32_t row[nHits], col[nHits];
450 int tot[nHits];
451 if (isIBLModule || isDBMModule) { // check all the different types of IBL/DBM hit words (condensed and not condensed)
452
453#ifdef PIXEL_DEBUG
454 ATH_MSG_DEBUG ("Decoding IBL/DBM hit word: 0x" << std::hex << rawDataWord << std::dec);
455#endif
456
457 if (((rawDataWord & PRB_DATAMASK) == PRB_FIRSTHITCONDENSEDWORD) && (countHitCondensedWords == 0)) { // it is the first of the 4 hit condensed words (IBL/DBM)
458 countHitCondensedWords = 1;
459 are_4condensed_words = false; // All 4 words have to be found before turning it on
460 condensedWords[0] = rawDataWord;
461 continue;
462 }
463 else if (countHitCondensedWords == 1) { // it is the second of the 4 hit condensed words (IBL)
464 ++countHitCondensedWords;
465 condensedWords[1] = rawDataWord;
466 continue;
467 }
468 else if (countHitCondensedWords == 2) { // it is the third of the 4 hit condensed words (IBL)
469 ++countHitCondensedWords;
470 condensedWords[2] = rawDataWord;
471 continue;
472 }
473 else if (((rawDataWord & PRB_DATAMASK) == PRB_LASTHITCONDENSEDWORD) && (countHitCondensedWords == 3)) { // it is the fourth of the 4 hit condensed words (IBL)
474 are_4condensed_words = true;
475 receivedCondensedWords = true;
476 condensedWords[3] = rawDataWord;
477 uint32_t hitwords[nHits];
478 //Condensed words
479 // 101RRRRRTTTTTTTTCCCCCCCRRRRRRRRR
480 // 1CCCRRRRRRRRRTTTTTTTTCCCCCCCRRRR
481 // 1TTTCCCCCCCRRRRRRRRRTTTTTTTTCCCC
482 // 111TTTTTTTTCCCCCCCRRRRRRRRRTTTTT
483 // They become 5 hitwords with format : TTTTTTTTCCCCCCCRRRRRRRRR
484 // first hitword: simple mask of the first condensed word
485 hitwords[0] = (condensedWords[0] & mask24);
486 // 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)
487 hitwords[1] = ((condensedWords[0] >> (skipRow + skipCol+ skipTOT) ) & mask5) + ((condensedWords[1] & mask19) << skip5);
488 // 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
489 hitwords[2] = ((condensedWords[1] >> (skip4 + skipCol + skipTOT)) & mask12) + ((condensedWords[2] & mask12) << (skipRow + skip3));
490 // 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
491 hitwords[3] = ((condensedWords[2] >> (skipTOT + skip4)) & mask19) + ((condensedWords[3] & mask5) << (skip3 + skipRow + skipCol));
492 // fifth hitword: simply shift 5 right to eliminate the "TTTTT" and mask24
493 hitwords[4] = (condensedWords[3] >> skip5) & mask24;
494
495#ifdef PIXEL_DEBUG
496 ATH_MSG_VERBOSE( "4 consecutive IBL hit words found. Condensed hits are being decoded");
497#endif
498
499 for (unsigned int i(0); i < nHits; ++i) {
500 row[i] = divideHits (hitwords[i], 0, 8);
501 col[i] = divideHits (hitwords[i], 9, 15);
502 tot[i] = divideHits (hitwords[i], 16, 23);
503 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);
504 }
505 countHitCondensedWords = 0;
506 linkNum_IBLword = linkNum_IBLheader;
507 } // end of the condensed hit words (IBL)
508 else if ((rawDataWord & PRB_DATAMASK) == PRB_DATAWORD) { // it's a IBL not-condensed hit word
509 if (countHitCondensedWords != 0) { // I received some IBL words, but less than 4, there was an error in the rod transmission
510 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 << ")");
512 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
513 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
514 countHitCondensedWords = 0;
515 }
516 // IBL non-condensed Hit Words decoding:
517 are_4condensed_words = false;
518 mRow = decodeRow(rawDataWord, isIBLModule || isDBMModule );
519 mColumn = decodeColumn(rawDataWord, isIBLModule || isDBMModule);
520 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
521 linkNum_IBLword = decodeLinkNumHit_IBL(rawDataWord); // this corresponds to the "nnnnn" bits of the bytestream convention.
522 //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])
523 if (linkNum_IBLword != linkNum_IBLheader) {
524 generalwarning("In ROB 0x" << std::hex << robId << ": Link number mismatch - nnnnn (hit word) = 0x" << linkNum_IBLword << ", nnnnn (header) = 0x" << linkNum_IBLheader << std::dec);
525 }
526
527#ifdef PIXEL_DEBUG
528 ATH_MSG_DEBUG("hit dataword found for module offlineIDHash: " << offlineIdHash << " Row: 0x" << std::hex << mRow << " Col: 0x" << mColumn << " Tot: 0x" << mToT << std::dec);
529#endif
530
531 }
532 else { // it is an IBL/DBM hit word, but it hasn't been recognised
533 generalwarning("In ROB 0x" << std::hex << robId << ", FE: 0x" << mLink << ": IBL/DBM hit word 0x" << rawDataWord << " not recognised" << std::dec);
535 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
536 continue;
537 }
538 // 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,
539 // while is = 1 for the higher-eta FE on the planar sensor)
540 mFE = getLocalFEI4(fe_IBLheader, onlineId);
541 if (m_pixelReadout->getModuleType(pixCabling->find_entry_onoff(onlineId))==InDetDD::PixelModuleType::IBL_3D) {
542 mFE = 0;
543 }
544
545 } // end of the if (isIBLModule || isDBMModule)
546 else { // Pixel Hit Case
547
548#ifdef PIXEL_DEBUG
549 ATH_MSG_VERBOSE("Decoding Pixel hit word: 0x" << std::hex << rawDataWord << std::dec);
550#endif
551
552 if (countHitCondensedWords != 0){ // I received some IBL words, but less than 4, there was an error in the rod transmission
553 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink
554 << ": Interruption of IBL condensed words - hit(s) ignored (current dataword: 0x"
555 << std::hex << rawDataWord << std::dec << ")");
557 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
558 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
559 countHitCondensedWords = 0;
560 }
561 //Pixel Hit Words decoding:
562 are_4condensed_words = false;
563 mFE = decodeFE(rawDataWord);
564 mRow = decodeRow(rawDataWord, isIBLModule || isDBMModule );
565 mColumn = decodeColumn(rawDataWord, isIBLModule || isDBMModule);
566 mToT = decodeToT(rawDataWord, isIBLModule || isDBMModule);
567
568#ifdef PIXEL_DEBUG
569 ATH_MSG_DEBUG( "hit dataword found for module offlineIDHash: " << offlineIdHash << " FE: " << mFE << " Row: " << mRow << " Col: " << mColumn ); // hit found debug message
570#endif
571
572 } // end of the condition "!isIBLModule"
573 // ------------------------
574 // Create pixel collections
575
576 // Decode only modules in provided list of hashes (i.e. not doing full scan)
577 // Disabled for now.
578 if (offlineIdHash == skipHash) continue;
579 if (offlineIdHash != lastHash) {
580 lastHash = offlineIdHash;
581 if (vecHash!=nullptr) {
582 std::vector<IdentifierHash>::iterator p = std::find(vecHash->begin(),vecHash->end(),offlineIdHash);
583 if (p == vecHash->end()) { // is the Hash to be skipped (not in the request list)?
584 skipHash = offlineIdHash;
585 continue;
586 }
587 }
588 ATH_CHECK( rdoIdc->naughtyRetrieve(offlineIdHash, coll) );//Returns null if not present
589 if( coll == nullptr ) {
590 coll = new PixelRawCollection (offlineIdHash);
591 // get identifier from the hash, this is not nice
592 Identifier ident = m_pixel_id->wafer_id(offlineIdHash);
593 // set the Identifier to be nice to downstream clients
594 coll->setIdentifier(ident);
595
596 StatusCode sc = rdoIdc->addCollection(coll, offlineIdHash);
597 ATH_MSG_DEBUG("Adding " << offlineIdHash);
598 if (sc.isFailure()){
599 ATH_MSG_ERROR("failed to add Pixel RDO collection to container" );
600 }
601 }
602 }
603 // ------------------------
604 // Fill collections
605 if (isIBLModule || isDBMModule) {
606 unsigned int num_cycles_toFillCollection(0);
607 if (are_4condensed_words) {
608 num_cycles_toFillCollection = nHits;
609 }
610 else {
611 num_cycles_toFillCollection = 1;
612 row[0] = mRow;
613 col[0] = mColumn;
614 tot[0] = mToT;
615 }
616 int IBLtot[2];
617 for (unsigned int i(0); i < num_cycles_toFillCollection; ++i) {
618
619#ifdef PIXEL_DEBUG
620 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 );
621#endif
622
623 // ToT1 equal 0 means no hit, regardless of HitDiscCnfg
624 if ((tot[i] & 0xF0) == 0x00) {
625 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);
626 continue;
627 }
628 else {
629 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!
630 pixelId = m_pixelReadout ->getPixelIdfromHash (offlineIdHash, mFE, row[i], col[i]);
631
632#ifdef PIXEL_DEBUG
633 ATH_MSG_VERBOSE( "PixelId: " << pixelId );
634 int eta_i = m_pixel_id->eta_index(pixelId);
635 int phi_i = m_pixel_id->phi_index(pixelId);
636 int eta_m = m_pixel_id->eta_module(pixelId);
637 int phi_m = m_pixel_id->phi_module(pixelId);
638 ATH_MSG_VERBOSE( " eta_i: " << eta_i << ", phi_i: " << phi_i << ", eta_m: " << eta_m << ", phi_m: " << phi_m );
639#endif
640 if (pixelId == invalidPixelId) {
641 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);
643 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
644 continue;
645 }
646 IBLtot[0] = divideHits(tot[i], 4, 7); // corresponds to (col, row)
647 IBLtot[1] = divideHits(tot[i], 0, 3); // corresponds to (col, row+1)
648#ifdef PIXEL_DEBUG
649 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 );
650#endif
651
652 if (!pixHitDiscCnfg) {
653 pixHitDiscCnfg = std::make_unique<SG::ReadCondHandle<PixelHitDiscCnfgData> > (m_condHitDiscCnfgKey,ctx);
654 }
655 // Get the hit discrimination configuration setting for this FE
656 if (m_pixelReadout->getModuleType(pixelId) == InDetDD::PixelModuleType::IBL_PLANAR || m_pixelReadout->getModuleType(pixelId) == InDetDD::PixelModuleType::DBM) {
657 hitDiscCnfg = (*pixHitDiscCnfg)->getHitDiscCnfgPL();
658 }
659 else if (m_pixelReadout->getModuleType(pixelId) == InDetDD::PixelModuleType::IBL_3D) {
660 hitDiscCnfg = (*pixHitDiscCnfg)->getHitDiscCnfg3D();
661 }
662 // Now do some interpreting of the ToT values
663 if (hitDiscCnfg == 2 && IBLtot[0] == 2) IBLtot[0] = 16;
664 if (hitDiscCnfg == 2 && IBLtot[1] == 2) IBLtot[1] = 16;
665 if (not m_checkDuplicatedPixel or thisRdoIsUnique(pixelId, foundPixels)) {
666 // Insert the first part of the ToT info in the collection
667 coll->push_back(new RDO(pixelId, IBLtot[0], mBCID, mLVL1ID, mLVL1A));
668 }
669 else {
671 }
672
673#ifdef PIXEL_DEBUG
674 ATH_MSG_VERBOSE( "Collection filled with pixelId: " << pixelId << " TOT = 0x" << std::hex << IBLtot[0] << std::dec << " mBCID = " << mBCID << " mLVL1ID = " << mLVL1ID << " mLVL1A = " << mLVL1A );
675#endif
676
677 // Second ToT field:
678 // For HitDiscCnfg 0-2, consider 0 to indicate no hit
679 // For HitDiscCng = 3, consider also F to indicate no hit
680 if (IBLtot[1] != 0x0 && (IBLtot[1] != 0xF || hitDiscCnfg != 3)) {
681 if ((row[i] + 1) > 336) { // FIXME: hardcoded number - but it should still be ok, because it's a feature of the FE-I4!
682 // 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)
683 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] << ")");
684 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
686 continue;
687 }
688 else {
689 pixelId = m_pixelReadout->getPixelIdfromHash (offlineIdHash, mFE, row[i] + 1, col[i]);
690
691#ifdef PIXEL_DEBUG
692 int eta_i = m_pixel_id->eta_index(pixelId);
693 int phi_i = m_pixel_id->phi_index(pixelId);
694 int eta_m = m_pixel_id->eta_module(pixelId);
695 int phi_m = m_pixel_id->phi_module(pixelId);
696 int phi_i_max = m_pixel_id->phi_index_max(pixelId);
697 int eta_i_max = m_pixel_id->eta_index_max(pixelId);
698 ATH_MSG_VERBOSE( "PixelId = " << pixelId);
699 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 );
700#endif
701
702 if (pixelId == invalidPixelId) {
703 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);
705 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
706 continue;
707 }
708 if (not m_checkDuplicatedPixel or thisRdoIsUnique(pixelId, foundPixels)) {
709 coll->push_back(new RDO(pixelId, IBLtot[1], mBCID, mLVL1ID, mLVL1A));
710 }
711 else {
713 }
714
715#ifdef PIXEL_DEBUG
716 ATH_MSG_VERBOSE( "Collection filled with pixelId: " << pixelId << " TOT = 0x" << std::hex << IBLtot[1] << std::dec << " mBCID = " << mBCID << " mLVL1ID = " << mLVL1ID << " mLVL1A = " << mLVL1A );
717#endif
718
719 }
720 }
721 } // 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.
722 else {
723 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) << ")");
725 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
726 continue;
727 }
728 } // end of the else from the condition "(tot[i] & 0xF0) == 0xF", corresponding to an invalid tot sent by the ROD
729 } // end of the loop over the hit information coming from the IBL words (condensed or not)
730 } // end IBL/DBM words pushed into Collection
731
732 else { // it is a Pixel hit word to be saved into the Collection
733 pixelId = m_pixelReadout->getPixelIdfromHash(offlineIdHash, mFE, mRow, mColumn);
734 if (pixelId == invalidPixelId) {
735 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);
737 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Invalid); }
738 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
739 continue;
740 }
741 // Now the Collection is there for sure. Create RDO and push it into Collection.
742 if (not m_checkDuplicatedPixel or thisRdoIsUnique(pixelId, foundPixels)) {
743 coll->push_back(new RDO(pixelId, mToT, mBCID, mLVL1ID, mLVL1A));
744 }
745 else {
747 }
748
749#ifdef PIXEL_DEBUG
750 ATH_MSG_VERBOSE( "Collection filled with pixelId: " << pixelId << " TOT = 0x" << std::hex << mToT << std::dec << " mBCID = " << mBCID << " mLVL1ID = " << mLVL1ID << " mLVL1A = " << mLVL1A );
751#endif
752
753 } // end Pixel words pushed into Collection
754 } // end of the if (link_start)
755 else { // no header found before hit -> error
756 generalwarning("In ROB = 0x" << std::hex << robId << ", link 0x" << mLink << ": Unexpected hit dataword: " << rawDataWord << " - hit ignored");
758 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
759 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
760 continue;
761 }
762 break;
763 //-------------------------------------------------------------------------------------------- TRAILER WORD FOUND
764 case PRB_LINKTRAILER: // link (module) trailer found
765 if (link_start) { // if header found before trailer -> expected
766 ATH_MSG_DEBUG( "link trailer found" ); // trailer found debug message
767 }
768 else { // no header found before trailer -> error
769 generalwarning("In ROB = 0x" << std::hex << robId << ", link 0x" << mLink << ": Unexpected trailer found: 0x" << std::hex << rawDataWord << ", data corruption");
771 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
772 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
773 continue;
774 }
775 previous_offlineIdHash = offlineIdHash; // save offlineId for next header;
776 link_start = false; // resetting link (module) header found flag
777 are_4condensed_words = false;
778 // Trailer decoding and error handling
779 if (isIBLModule || isDBMModule) { // decode IBL/DBM Trailer word: 010nnnnnECPplbzhvMMMMMMMMMMxxxxx
780 ATH_MSG_VERBOSE( "Decoding IBL/DBM trailer word: 0x" << std::hex << rawDataWord << std::dec );
781 const uint32_t trailerError = decodeTrailerErrors_IBL(rawDataWord); // => E cPpl bzhv // taking all errors together.
782
783 if (trailerError & (1 << 8)) { // time out error bit => E
785 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::TimeOut); }
786 }
787
788 if (trailerError & (1 << 6)) {// link masked by PPC => P
790 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::LinkMaskedByPPC); }
791 }
792 if (trailerError & (1 << 5)) { // preamble error bit => p
794 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Preamble); }
795 }
796 if (trailerError & (1 << 4)) { // LVL1 error bit => l
798 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::LVL1ID); }
799 }
800 if (trailerError & (1 << 3)) {// BCID error bit => b
802 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::BCID); }
803 }
804 if (trailerError & (1 << 2)) { // trailer error bit => z
806 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Trailer); }
807 }
808 if (trailerError & (1 << 1)) { // header/trailer limit error=> h
810 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Limit); }
811 }
812 if (trailerError & (1 << 0)) { // data overflow error=> v
814 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Invalid); }
815 }
816
817 if (trailerError & (1 << 7)) { // condensed mode bit => W
818 if (!receivedCondensedWords) { generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": condensed mode bit is set, but no condensed words received" << std::dec); }
819 }
820 //At least temporarily removed because the data format is not clear (Franconi, 17.06.2014)
821 linkNum_IBLword = decodeLinkNumTrailer_IBL(rawDataWord); // => n
822 // Do checks on info in trailer vs header
823 if (linkNum_IBLword != linkNum_IBLheader) {
824 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);
825 }
826 if (decodeBcidTrailer_IBL(rawDataWord) != (mBCID & PRB_BCIDSKIPTRAILERmask_IBL)) {
827 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);
828 }
829 }
830 else { // decode Pixel trailer word
831 ATH_MSG_VERBOSE( "Decoding Pixel trailer word: 0x" << std::hex << rawDataWord << std::dec );
832 const uint32_t trailerError = decodeTrailerErrors(rawDataWord); // creating link (module) trailer error variable
833 if (trailerError != 0) {
834 sc = StatusCode ::RECOVERABLE;
835 errorRecoverable = errorRecoverable | trailerError; //encode error as HHHHMMMMMMMMFFFFFFFFTTTT for header, flagword, trailer errors
836
837 const std::array<unsigned long long, 4> bitPosition{0_BIT, 1_BIT, 2_BIT, 3_BIT};
838 for (const auto bit:bitPosition){
839 if (trailerError & bit) ++m_numTrailerErrors;
840 }
841
842 if ( trailerError & 0xF ) {
843 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Trailer); }
844 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Trailer); }
845 }
846
847 // Extra for pixel monitoring
848 if (trailerError != 0) {
849 if (indexModule>-1) {
850 if (trailerError & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::RODTrailerBitError); }
851 if (trailerError & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::RODHeaderLimit); }
852 if (trailerError & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::RODDataOVerflow); }
853 }
854 if (indexFE>-1) {
855 if (trailerError & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::RODTrailerBitError); }
856 if (trailerError & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::RODHeaderLimit); }
857 if (trailerError & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::RODDataOVerflow); }
858 }
859 }
860
861 }
862 }
863 break;
864 //-------------------------------------------------------------------------------------------- FE ERROR TYPE 2 WORD FOUND
865 case PRB_FEERROR2 : // type 2 flag found
866
867 are_4condensed_words = false;
868 if (isIBLModule || isDBMModule) { // IBL flag found
869 ATH_MSG_VERBOSE( "Decoding IBL/DBM FEflag word: 0x" << std::hex << rawDataWord << std::dec);
870 linkNum_IBLword = decodeLinkNumFEFlag_IBL(rawDataWord);
871 if (linkNum_IBLword != linkNum_IBLheader) {
872 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);
873 }
874 serviceCodeCounter = decodeServiceCodeCounter_IBL(rawDataWord)+1; // frequency of the serviceCode (with the exceptions of serviceCode = 14,15 or 16)
875 serviceCode = decodeServiceCode_IBL(rawDataWord); // is a code. the corresponding meaning is listed in the table in the FE-I4 manual, pag. 105
876 // Treat the service code only if its meaning is valid (i.e. value < 31)
877 if (serviceCode>31) {
878 generalwarning("In ROB 0x" << std::hex << robId << ", link 0x" << mLink << ": Got out-of-bounds service code: " << std::dec << serviceCode << " (counter: " << serviceCodeCounter << "), ignored");
879 }
880
881 int chFE = (extractFefromLinkNum(linkNum_IBLheader) & 0x1);
882 if (m_pixelReadout->getModuleType(m_pixel_id->wafer_id(offlineIdHash))==InDetDD::PixelModuleType::IBL_3D) { chFE=0; }
883
884 if (serviceCodeCounter>0 && serviceCode<32) {
885 if (serviceCode!=14) {
886 // Monitor service record for IBL (not DBM)
887 if (static_cast<int>(offlineIdHash)>155 && static_cast<int>(offlineIdHash)<436) {
888 // The index array is defined in PixelRawDataProviderTool::SizeOfIDCInDetBSErrContainer()
889 int indexOffset = 17*m_pixel_id->wafer_hash_max();
890 int indexSvcCounter = indexOffset+serviceCode*280*2+2*(static_cast<int>(offlineIdHash)-156)+chFE;
891
892 bsErrWord[indexSvcCounter] = serviceCodeCounter;
893 }
894 }
895 }
896
897 }
898 else { // Pixel type2 flag found
899 ATH_MSG_VERBOSE( "Decoding Pixel FEflag word: 0x" << std::hex << rawDataWord << std::dec );
900 uint32_t FEFlags = decodeFEFlags2(rawDataWord); // get FE flags
901 uint32_t MCCFlags = decodeMCCFlags(rawDataWord); // get MCC flags
902 FEFlags = FEFlags & 0xff;
903 if ((MCCFlags | FEFlags) != 0) {
904 sc = StatusCode::RECOVERABLE;
905 errorRecoverable = errorRecoverable | (MCCFlags << 12) | (FEFlags << 4); //encode error as HHHHMMMMMMMMFFFFFFFFTTTT for header, flagword, trailer errors
906 //for now just sum all flagged errors_
907 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};
908 for (const auto thisBit:bitPosition){
909 if (MCCFlags & thisBit) ++m_numFlaggedErrors;
910 if (FEFlags & 0xf3 & thisBit) ++m_numFlaggedErrors;
911 }
912
913 if ( MCCFlags & 0xff or FEFlags & 0xf3 ) {
914 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Flagged); }
915 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Flagged); }
916 }
917
918 if (indexModule>-1) {
919 if (MCCFlags & (1 << 7)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCUndefined); }
920 if (MCCFlags & (1 << 6)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCUndefined); }
921 if (MCCFlags & (1 << 5)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCUndefined); }
922 if (MCCFlags & (1 << 4)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCLVL1IDEoECheck); }
923 if (MCCFlags & (1 << 3)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCBCIDEoECheck); }
924 if (MCCFlags & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCLVL1IDCheck); }
925 if (MCCFlags & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCEoEOverflow); }
926 if (MCCFlags & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::MCCHitOverflow); }
927
928 if (FEFlags & (1 << 4)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FEWarning); }
929 if (FEFlags & (1 << 3)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FEHitParity); }
930 if (FEFlags & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FERegisterParity); }
931 if (FEFlags & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FEHammingCode); }
932 if (FEFlags & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::FEEoCOverflow); }
933 }
934
935 if (indexFE>-1) {
936 if (MCCFlags & (1 << 7)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCUndefined); }
937 if (MCCFlags & (1 << 6)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCUndefined); }
938 if (MCCFlags & (1 << 5)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCUndefined); }
939 if (MCCFlags & (1 << 4)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCLVL1IDEoECheck); }
940 if (MCCFlags & (1 << 3)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCBCIDEoECheck); }
941 if (MCCFlags & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCLVL1IDCheck); }
942 if (MCCFlags & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCEoEOverflow); }
943 if (MCCFlags & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::MCCHitOverflow); }
944
945 if (FEFlags & (1 << 4)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FEWarning); }
946 if (FEFlags & (1 << 3)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FEHitParity); }
947 if (FEFlags & (1 << 2)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FERegisterParity); }
948 if (FEFlags & (1 << 1)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FEHammingCode); }
949 if (FEFlags & (1 << 0)) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::FEEoCOverflow); }
950 }
951 }
952 else {
954 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::BadFE); }
955 ATH_MSG_DEBUG( "Disabled Pixel chip " << ((rawDataWord & 0x0F000000) >> 24) );
956 }
957 }
958
959 break;
960
961 //-------------------------------------------------------------------------------------------- RAWDATA WORD FOUND
962 case PRB_RAWDATA : // add treatment for raw data word here!
963
964 are_4condensed_words = false;
965
966 break;
967
968 //-------------------------------------------------------------------------------------------- UNKNOWN WORD
969 default:
970 generalwarning("In ROB 0x" << std::hex << robId << ", FE 0x" << mLink << ": Unknown word type found, 0x" << std::hex << rawDataWord << std::dec << ", ignoring");
972 if (indexModule>-1) { PixelByteStreamErrors::addError(bsErrWord[indexModule],PixelByteStreamErrors::Decoding); }
973 if (indexFE>-1) { PixelByteStreamErrors::addError(bsErrWord[indexFE],PixelByteStreamErrors::Decoding); }
974
975 } // end of switch
976 } // end of loop over ROD
977
978 ATH_CHECK( updateEventInfoIfEventCorrupted( corruptionError ) );
979
980 // Verify that all active IBL FEs sent the same number of headers
981 if (isIBLModule || isDBMModule) {
982 checkUnequalNumberOfHeaders( nFragmentsPerFE, robId );
983 }
984
985 // Fill error information in IDC
986 for (size_t i=0; i<static_cast<size_t>(bsErrWord.size()); i++) {
987 if (bsErrWord[i]>0) {
988 decodingErrors.setOrDrop(i,bsErrWord[i]);
989 }
990 }
991
992 if (sc == StatusCode::RECOVERABLE) {
993
994 if (errorRecoverable == (3 << 20) ){ // Fix for M8, this error always occurs, masked out REMOVE FIXME !!
996 return StatusCode::SUCCESS;
997 }
998 ATH_MSG_DEBUG( "Recoverable errors found in PixelRodDecoder, errorcode: " << errorRecoverable );
999 }
1000 return sc;
1001}
1002
1003// ****************************************************************************************************** DECODING FUNCTIONS
1004
1006// 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
1008uint32_t PixelRodDecoder::extractFefromLinkNum(const uint32_t linkNum) const
1009{
1010 return linkNum & 0x7;
1011}
1012
1014// 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
1016uint32_t PixelRodDecoder::extractSLinkfromLinkNum(const uint32_t linkNum) const
1017{
1018 return (linkNum >> 3) & 0x3;
1019}
1020
1021
1022// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HEADER BITS
1023
1025// decode IBL BCID (bits 0-9 of IBL module header word)
1027uint32_t PixelRodDecoder::decodeBCID_IBL(const uint32_t word) const
1028{
1029 return ((word >> PRB_BCIDskip_IBL) & PRB_BCIDmask_IBL);
1030}
1031
1033// decode IBL LVL1ID (bits 10-22 of IBL module header word)
1035uint32_t PixelRodDecoder::decodeL1ID_IBL(const uint32_t word) const
1036{
1037 return ((word >> PRB_L1IDskip_IBL) & PRB_L1IDmask_IBL);
1038}
1039
1041// decode IBL FeI4B flag bit (bit 23 of IBL module header word)
1043uint32_t PixelRodDecoder::decodeFeI4Bflag_IBL(const uint32_t word) const
1044{
1045 return ((word >> PRB_FeI4BFLAGskip_IBL) & PRB_FeI4BFLAGmask_IBL);
1046}
1047
1049// decode IBL module link number (bits 24-28 of IBL module header word)
1051uint32_t PixelRodDecoder::decodeModule_IBL(const uint32_t word) const
1052{
1053 return ((word >> PRB_MODULEskip_IBL) & PRB_MODULEmask_IBL);
1054}
1055
1057// decode BCID (bits 0-7 of module Pixel header word)
1059uint32_t PixelRodDecoder::decodeBCID(const uint32_t word) const
1060{
1061 return ((word >> PRB_BCIDskip) & PRB_BCIDmask);
1062}
1063
1065// decode LVL1ID (bits 8-11 of module Pixel header word)
1067uint32_t PixelRodDecoder::decodeL1ID(const uint32_t word) const
1068{
1069 return ((word >> PRB_L1IDskip) & PRB_L1IDmask);
1070}
1071
1073// decode LVL1ID skipped (bits 12-15 of module Pixel header word)
1075uint32_t PixelRodDecoder::decodeL1IDskip(const uint32_t word) const
1076{
1077 return ((word >> PRB_L1IDSKIPskip) & PRB_L1IDSKIPmask);
1078}
1079
1081// decode module link number (bits 16-22 of module Pixel header word)
1083uint32_t PixelRodDecoder::decodeModule(const uint32_t word) const
1084{
1085 return ((word >> PRB_MODULEskip) & PRB_MODULEmask);
1086}
1087
1089// decode header errors (bits 25-28 of module Pixel header word)
1091uint32_t PixelRodDecoder::decodeHeaderErrors(const uint32_t word) const
1092{
1093 return ((word >> PRB_HEADERERRORSskip) & PRB_HEADERERRORSmask);
1094}
1095
1096
1097
1098
1099// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HIT WORD BITS
1100
1102// decode hit row number (bits 0-7 of Pixel hit word, bits 0-8 of IBL hit word)
1104uint32_t PixelRodDecoder::decodeRow(const uint32_t word, bool isIBLorDBM) const {
1105 if( isIBLorDBM ) {
1106 return ((word >> PRB_ROWskip_IBL) & PRB_ROWmask_IBL);
1107 }
1108 else {
1109 return ((word >> PRB_ROWskip) & PRB_ROWmask);
1110 }
1111}
1112
1114// decode hit column number (bits 8-12 of Pixel hit word, bits 9-15 of IBL hit word)
1116uint32_t PixelRodDecoder::decodeColumn(const uint32_t word, bool isIBLorDBM) const {
1117 if( isIBLorDBM ) {
1118 return ((word >> PRB_COLUMNskip_IBL) & PRB_COLUMNmask_IBL);
1119 }
1120 else {
1121 return ((word >> PRB_COLUMNskip) & PRB_COLUMNmask);
1122 }
1123}
1124
1126// decode hit TimeOverThreshold value (bits 16-23 of Pixel hit word, bits 16-23 of IBL hit word)
1128uint32_t PixelRodDecoder::decodeToT(const uint32_t word, bool isIBLorDBM) const {
1129 if ( isIBLorDBM ) { // IBL Tot => 8 bits to be divided into 2 Tot info, each of which is 4 bits
1130 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)
1131 return Tot8Bits;
1132 }
1133 else { // Pixel Tot
1134 return ((word >> PRB_TOTskip) & PRB_TOTmask);
1135 }
1136}
1137
1139// decode Link number in the IBL not-condensed hit word (bits 24-26 of IBL hit word)
1141uint32_t PixelRodDecoder::decodeLinkNumHit_IBL(const uint32_t word) const {
1143}
1144
1146// decode module FE number (bits 24-27 of Pixel hit word)
1148uint32_t PixelRodDecoder::decodeFE(const uint32_t word) const {
1149 return ((word >> PRB_FEskip) & PRB_FEmask);
1150}
1151
1152// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TRAILER BITS
1153
1155// decode IBL "M" in the trailer (bits 5-14 of IBL module trailer word)
1160
1162// decode IBL trailer errors (bits 15-23 of IBL module trailer word)
1164uint32_t PixelRodDecoder::decodeTrailerErrors_IBL(const uint32_t word) const {
1166}
1167
1169// decode Link Number in the IBL Trailer (bits 24-26 of IBL module trailer word)
1171uint32_t PixelRodDecoder::decodeLinkNumTrailer_IBL(const uint32_t word) const {
1173}
1174
1175
1177// decode BCID in trailer word
1179uint32_t PixelRodDecoder::decodeBcidTrailer_IBL(const uint32_t word) const {
1181}
1182
1183
1185// decode Condensed Mode Bit in the IBL trailer (bit 22 of IBL module trailer word)
1187uint32_t PixelRodDecoder::decodeCondensedModeBit_IBL(const uint32_t word) const {
1189}
1190
1192// decode trailer errors (bits 26-28 of Pixel module trailer word)
1194//template <class ROBData>
1195uint32_t PixelRodDecoder::decodeTrailerErrors(const uint32_t word) const {
1196 return ((word >> PRB_TRAILERERRORSskip) & PRB_TRAILERERRORSmask);
1197}
1198
1200// look for bitflips in trailer word (bits 0-25 of Pixel module trailer word)
1202uint32_t PixelRodDecoder::decodeTrailerBitflips(const uint32_t word) const {
1203 uint32_t flipword = ((word >> PRB_TRAILERBITFLIPskip) & PRB_TRAILERBITFLIPmask);
1204 uint32_t errorcount = 0;
1205 if (flipword != 0) {
1206 for (int i=0; i<=25; i++){ // this calculates the checksum of the flipword = the number of bitflips
1207 if (flipword & 1) errorcount++;
1208 flipword >>= 1;
1209 }
1210 }
1211 return errorcount; // returns the number of errors
1212}
1213
1214// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLAG WORDS BITS
1215
1217// decodeServiceCodeCounter (bits 0-9 of IBL flag word)
1222
1224// decodeServiceCode (bits 17-22 of IBL flag word)
1226uint32_t PixelRodDecoder::decodeServiceCode_IBL(const uint32_t word) const {
1228}
1229
1231// decodeLinkNumFEFlag (bits 25-27 of IBL flag word)
1233uint32_t PixelRodDecoder::decodeLinkNumFEFlag_IBL(const uint32_t word) const {
1235}
1236
1237
1239// decode FE flag errors (bits 0-7 of Pixel flag type 2 word)
1241uint32_t PixelRodDecoder::decodeFEFlags2(const uint32_t word) const {
1242 return ((word >> PRB_FEFlagskip2) & PRB_FEFlagmask2);
1243}
1244
1246// decode MCC flag errors (bits 8-12 of Pixel flag type 2 word)
1248uint32_t PixelRodDecoder::decodeMCCFlags(const uint32_t word) const {
1249 return ((word >> PRB_MCCFlagskip) & PRB_MCCFlagmask);
1250}
1251
1253// determine module word type
1255uint32_t PixelRodDecoder::getDataType(unsigned int rawDataWord, bool link_start) const {
1256 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
1257 if ((rawDataWord & PRB_DATAMASK) == PRB_RAWDATA ) return PRB_RAWDATA; // module flag word found
1258 if (rawDataWord == PRB_TIMEOUT) return PRB_TIMEOUT; // time out word found
1259 }
1260 if ((rawDataWord & PRB_DATAMASK) == PRB_LINKHEADER) return PRB_LINKHEADER; // module header word found
1261 if (((rawDataWord & PRB_FEERRORMASK) == PRB_FEERROR2) && ((rawDataWord & PRB_FEERROR2CHECK) == PRB_FEERROR2CHECK)) return PRB_FEERROR2; // type 2 word found Pixel
1262 if (((rawDataWord & PRB_DATAMASK) == PRB_FEERROR_IBL)) return PRB_FEERROR2; // type word found IBL
1263 if ((rawDataWord & PRB_HITMASK) == PRB_DATAWORD) return PRB_DATAWORD; // module hit word found
1264 if ((rawDataWord & PRB_DATAMASK) == PRB_LINKTRAILER) return PRB_LINKTRAILER; // module trailer word found
1265 return PRB_UNKNOWNWORD; // unknown word found
1266}
1267
1268
1269bool PixelRodDecoder::checkDataWordsCorruption( uint32_t rawDataWord) const {
1270 if ( ATH_UNLIKELY( rawDataWord==0xaa1234aa )) {
1271 generalwarning("Evt marker encountered during loop on ROD datawords");
1272 return true;
1273 }
1274 else if ( ATH_UNLIKELY( rawDataWord==0xdd1234dd ) ){
1275 generalwarning("ROB marker encountered during loop on ROD datawords");
1276 return true;
1277 }
1278 else if ( ATH_UNLIKELY( rawDataWord==0xee1234ee) ){
1279 generalwarning("ROD marker encountered during loop on ROD datawords");
1280 return true;
1281 }
1282 return false; // no corruption
1283}
1284
1285uint32_t PixelRodDecoder::treatmentFEFlagInfo(unsigned int serviceCode, unsigned int serviceCodeCounter) const {
1286 unsigned int etc = 0, l1req = 0;
1287 // Log the code count
1288 if (serviceCode == 16) { // I'm not like those other codes
1289 etc = (serviceCodeCounter >> 4) & 0x1F;
1290 l1req = serviceCodeCounter & 0x7;
1291 }
1292 // Return a 19-bit code to be used for monitoring
1293 // Service codes of type 'inf' are excluded, except for codes 15, 16 and 25,
1294 // see FE-I4B manual table 39
1295 // The bit position of each monitored service code is sequential starting from the
1296 // least significant bit, see below
1297 uint32_t code = 0;
1298 switch (serviceCode) {
1299 case 0: // BCID counter error, from EOCHL
1300 ATH_MSG_DEBUG("BCID counter error (retrieved in IBL FE Flag word)");
1301 code = code | (1 << 0);
1302 break;
1303
1304 case 1: // Hamming code error in word 0, from EOCHL
1305 ATH_MSG_DEBUG("Hamming code error in word 0 (retrieved in IBL FE Flag word)");
1306 code = code | (1 << 1);
1307 break;
1308
1309 case 2: // Hamming code error in word 1, from EOCHL
1310 ATH_MSG_DEBUG("Hamming code error in word 1 (retrieved in IBL FE Flag word)");
1311 code = code | (1 << 2);
1312 break;
1313
1314 case 3: // Hamming code error in word 2, from EOCHL
1315 ATH_MSG_DEBUG("Hamming code error in word 2 (retrieved in IBL FE Flag word)");
1316 code = code | (1 << 3);
1317 break;
1318
1319 case 4: // L1_in counter error, from EOCHL
1320 ATH_MSG_DEBUG("L1_in counter error (retrieved in IBL FE Flag word)");
1321 code = code | (1 << 4);
1322 break;
1323
1324 case 5: // L1 request counter error from EOCHL
1325 ATH_MSG_DEBUG("L1 request counter error (retrieved in IBL FE Flag word)");
1326 code = code | (1 << 5);
1327 break;
1328
1329 case 6: // L1 register error from EOCHL
1330 ATH_MSG_DEBUG("L1 register error (retrieved in IBL FE Flag word)");
1331 code = code | (1 << 6);
1332 break;
1333
1334 case 7: // L1 Trigger ID error from EOCHL
1335 ATH_MSG_DEBUG("L1 Trigger ID error (retrieved in IBL FE Flag word)");
1336 code = code | (1 << 7);
1337 break;
1338
1339 case 8: // readout processor error from EOCHL
1340 ATH_MSG_DEBUG("Readout processor error (retrieved in IBL FE Flag word)");
1341 code = code | (1 << 8);
1342 break;
1343
1344 case 9: // Fifo_Full flag pulsed from EOCHL
1345 ATH_MSG_DEBUG("Fifo_Full flag pulsed (retrieved in IBL FE Flag word)");
1346 break;
1347
1348 case 10: // HitOr bus pulsed from PixelArray
1349 ATH_MSG_DEBUG("HitOr bus pulsed (retrieved in IBL FE Flag word)");
1350 break;
1351
1352 // case 11 to 13 not used
1353 case 11:
1354 case 12:
1355 case 13:
1356 ATH_MSG_DEBUG("Received invalid service code: " << serviceCode << " (payload = " << serviceCodeCounter << ")");
1357 break;
1358
1359 case 14: // 3 MSBs of bunch counter and 7 MSBs of L1A counter from EOCHL
1360 ATH_MSG_DEBUG("Received service code 14 - ignored");
1361 break;
1362
1363 case 15: // Skipped trigger counter
1364 ATH_MSG_DEBUG("Skipped trigger counter (retrieved in IBL FE Flag word). There are " << serviceCodeCounter << " skipped triggers.");
1365 code = code | (1 << 9);
1366 break;
1367
1368 case 16: // Truncated event flag and counter from EOCHL
1369 ATH_MSG_DEBUG("Truncated event flag: ETC = " << etc << ", L1Req = " << l1req);
1370 code = code | (1 << 10);
1371 break;
1372
1373 // case 17 to 20 not used
1374 case 17:
1375 case 18:
1376 case 19:
1377 case 20:
1378 ATH_MSG_DEBUG("Received invalid service code: " << serviceCode << " (payload = " << serviceCodeCounter << ")");
1379 break;
1380
1381 case 21: // Reset bar RA2b pulsedd from Pad, PRD
1382 ATH_MSG_DEBUG("Reset bar RA2b pulsed (retrieved in IBL FE Flag word)");
1383 break;
1384
1385 case 22: // PLL generated clock phase faster than reference from CLKGEN
1386 ATH_MSG_DEBUG("PLL generated clock phase faster than reference (retrieved in IBL FE Flag word)");
1387 break;
1388
1389 case 23: // Reference clock phase faster than PLL, from CLKGEN
1390 ATH_MSG_DEBUG("Reference clock phase faster than PLL (retrieved in IBL FE Flag word)");
1391 break;
1392
1393 case 24: // Triple redundant mismatchfrom CNFGMEM
1394 ATH_MSG_DEBUG("Triple redundant mismatch (retrieved in IBL FE Flag word)");
1395 code = code | (1 << 11);
1396 break;
1397
1398 case 25: // Write register data error from CMD
1399 ATH_MSG_DEBUG("Write register data error (retrieved in IBL FE Flag word)");
1400 code = code | (1 << 12);
1401 break;
1402
1403 case 26: // Address error from CMD
1404 ATH_MSG_DEBUG("Address error (retrieved in IBL FE Flag word)");
1405 code = code | (1 << 13);
1406 break;
1407
1408 case 27: // Other command decoder error- see CMD section from CMD
1409 ATH_MSG_DEBUG("Other command decoder error- see CMD section (retrieved in IBL FE Flag word)");
1410 code = code | (1 << 14);
1411 break;
1412
1413 case 28: // Bit flip detected in command decoder input stream from CMD
1414 ATH_MSG_DEBUG("Bit flip detected in command decoder input stream (retrieved in IBL FE Flag word)");
1415 code = code | (1 << 15);
1416 break;
1417
1418 case 29: // SEU upset detected in command decoder (triple redundant mismatch) from CMD
1419 ATH_MSG_DEBUG("SEU upset detected in command decoder (triple redundant mismatch) (retrieved in IBL FE Flag word)");
1420 code = code | (1 << 16);
1421 break;
1422
1423 case 30: // Data bus address error from CMD
1424 ATH_MSG_DEBUG("Data bus address error (retrieved in IBL FE Flag word)");
1425 code = code | (1 << 17);
1426 break;
1427
1428 case 31: // Triple redundant mismatch from CMD
1429 ATH_MSG_DEBUG("Triple redundant mismatch (retrieved in IBL FE Flag word)");
1430 code = code | (1 << 18);
1431 break;
1432
1433 default:
1434 ATH_MSG_DEBUG("ServiceCode not used at the moment");
1435
1436 }
1437 return code;
1438}
1439
1440StatusCode PixelRodDecoder::updateEventInfoIfEventCorrupted( bool isCorrupted ) const {
1441 if ( not isCorrupted )
1442 return StatusCode::SUCCESS;
1443 //Set EventInfo error
1444 const xAOD::EventInfo* eventInfo=nullptr;
1445 ATH_CHECK(evtStore()->retrieve(eventInfo));
1447 ATH_MSG_WARNING(" cannot set EventInfo error state for Pixel " );
1448 }
1449 if (!eventInfo->updateEventFlagBit(xAOD::EventInfo::Pixel,0x1)) { //FIXME an enum at some appropriate place to indicating 0x1 as
1450 ATH_MSG_WARNING(" cannot set flag bit for Pixel " );
1451 }
1452 return StatusCode::SUCCESS;
1453}
1454
1455
1456void PixelRodDecoder::checkUnequalNumberOfHeaders( const unsigned int nFragmentsPerFE[8], uint32_t robId ) const {
1457 unsigned int nFrags = 0;
1458 bool foundIssue = false;
1459 for (unsigned int i = 0; i < 8; ++i) {
1460 if (nFrags == 0) {
1461 if (nFragmentsPerFE[i] != 0) nFrags = nFragmentsPerFE[i]; // set nFrags on first non-zero occurence
1462 }
1463 else {
1464 if (nFragmentsPerFE[i] != 0 && nFragmentsPerFE[i] != nFrags) {
1465 foundIssue = true;
1466 }
1467 }
1468 }
1469 if ( not foundIssue ) return;
1470
1471 // Got unequal number of headers per FE for same ROD, this means trouble.
1472 // Print value for each FE
1473 std::string errmsg;
1474 for (unsigned int j = 0; j < 8; ++j) {
1475 if (nFragmentsPerFE[j] != 0) {
1476 errmsg += "FE "+ std::to_string(j) + " " +std::to_string(nFragmentsPerFE[j]) + " ";
1477 }
1478 }
1479 generalwarning("In ROB 0x" << std::hex << robId << ": got unequal number of headers per FE" << std::dec);
1480 generalwarning("[FE number] : [# headers] - " << errmsg);
1481}
1482
1483
1484unsigned int PixelRodDecoder::getLocalFEI4(const uint32_t fe, const uint64_t onlineId) const
1485{
1486 unsigned int linknum40 = (onlineId>>24) & 0xFF;
1487 unsigned int linknum80 = (onlineId>>32) & 0xFF;
1488
1489 if (fe == linknum40) {
1490 return 0;
1491 } else if (fe == linknum80) {
1492 return 1;
1493 } else {
1494 ATH_MSG_ERROR("Error in retrieving local FE-I4 number: linknumber " << fe << " not found in onlineID " << std::hex << onlineId);
1495 }
1496 return 0xF;
1497}
#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 thread_local 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.