Skip to content

Commit f201da9

Browse files
mfasDadavidrohr
authored andcommitted
[EMCAL-1048] Consistent check fo RCU trailer and channel header integrity
- RCU trailer must have a valid trailer marker, valid trailer version and the corresponding expected size of the trailer - Channel header must have a valid branch ID (0-1), FEC ID (0-9) and ALTRO ID (0,2,3,4) - Channel headers only accept if bit 30 is set and bit 31 is not set Treating corruptions in case of bitflip of bit 31 leading to an artificial interpretation of a RCU trailer word in case the word is the last word on the page, even though the payload continues on the next page.
1 parent f1e1de0 commit f201da9

File tree

6 files changed

+86
-12
lines changed

6 files changed

+86
-12
lines changed

Detectors/EMCAL/base/include/EMCALBase/RCUTrailer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,11 @@ class RCUTrailer
388388
/// are assigned based on the trailer word marker.
389389
static RCUTrailer constructFromPayloadWords(const gsl::span<const uint32_t> payloadwords);
390390

391+
/// \brief Check whether the word is a valid last trailer word
392+
/// \param trailerword Word to be checked
393+
/// \return True if the word is a valid last trailer word, false if there are inconsistencies
394+
static bool checkLastTrailerWord(uint32_t trailerword);
395+
391396
private:
392397
/// \struct AltroConfig
393398
/// \brief Bit field configuration of the ALTRO config registers

Detectors/EMCAL/base/src/RCUTrailer.cxx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,29 @@ void RCUTrailer::reset()
3535
mIsInitialized = false;
3636
}
3737

38+
bool RCUTrailer::checkLastTrailerWord(uint32_t trailerword)
39+
{
40+
const int MIN_FWVERSION = 2;
41+
const int MAX_FWVERSION = 2;
42+
if ((trailerword >> 30) != 3) {
43+
return false;
44+
}
45+
auto firmwarevesion = (trailerword >> 16) & 0xFF;
46+
auto trailerSize = (trailerword & 0x7F);
47+
if (firmwarevesion < MIN_FWVERSION || firmwarevesion > MAX_FWVERSION) {
48+
return false;
49+
}
50+
if (trailerSize < 2) {
51+
return false;
52+
}
53+
if (firmwarevesion == 2) {
54+
if (trailerSize < 9) {
55+
return false;
56+
}
57+
}
58+
return true;
59+
}
60+
3861
void RCUTrailer::constructFromRawPayload(const gsl::span<const uint32_t> payloadwords)
3962
{
4063
reset();

Detectors/EMCAL/reconstruction/include/EMCALReconstruction/AltroDecoder.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class MinorAltroDecodingError
156156
/// \brief Error codes connected with the ALTRO decoding
157157
enum class ErrorType_t {
158158
BUNCH_HEADER_NULL, ///< Bunch header is 0
159+
CHANNEL_HEADER, ///< Channel header corruption
159160
CHANNEL_END_PAYLOAD_UNEXPECT, ///< Unexpected end of payload (channel or trailer word in bunch words)
160161
CHANNEL_PAYLOAD_EXCEED, ///< Exceeding channel payload block
161162
CHANNEL_ORDER, ///< Channels not in increasing order
@@ -210,7 +211,7 @@ class MinorAltroDecodingError
210211

211212
/// \brief Get the number of error types handled by the AltroDecoderError
212213
/// \return Number of error types
213-
static constexpr int getNumberOfErrorTypes() noexcept { return 7; }
214+
static constexpr int getNumberOfErrorTypes() noexcept { return 8; }
214215

215216
/// \brief Get the name connected to the error type
216217
///
@@ -352,6 +353,11 @@ class AltroDecoder
352353
/// In case of failure an exception is thrown.
353354
void checkRCUTrailer();
354355

356+
/// \brief Check hardware address in channel header for consistency
357+
/// \param hwaddress Hardware address to check
358+
/// \return True if the channel is consistent (branch, FEC and Altro in expected range) - false otherwise
359+
bool checkChannelHWAddress(int hwaddress);
360+
355361
RawReaderMemory& mRawReader; ///< underlying raw reader
356362
RCUTrailer mRCUTrailer; ///< RCU trailer
357363
std::vector<Channel> mChannels; ///< vector of channels in the raw stream

Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ void AltroDecoder::readChannels()
7575
uint16_t payloadsize = (channelheader >> 16) & 0x3FF;
7676
bool badchannel = (channelheader >> 29) & 0x1;
7777

78+
// check hardware address for consistency
79+
if (!checkChannelHWAddress(hwaddress)) {
80+
// Inconsistent HW address information, channel header corrupted, payload must be skipped
81+
mMinorDecodingErrors.emplace_back(MinorAltroDecodingError::ErrorType_t::CHANNEL_ORDER, channelheader, currentword);
82+
continue;
83+
}
84+
7885
int currentfec = 10 * Channel::getBranchIndexFromHwAddress(hwaddress) + Channel::getFecIndexFromHwAddress(hwaddress);
7986
// std::cout << "Branch: " << Channel::getBranchIndexFromHwAddress(hwaddress) << ", FEC " << Channel::getFecIndexFromHwAddress(hwaddress) << " -> " << currentfec << " (channel " << Channel::getChannelIndexFromHwAddress(hwaddress) << " )" << std::endl;
8087
if (currentfec < lastFEC) {
@@ -160,6 +167,23 @@ void AltroDecoder::readChannels()
160167
mChannelsInitialized = true;
161168
}
162169

170+
bool AltroDecoder::checkChannelHWAddress(int hwaddress)
171+
{
172+
unsigned int branch = Channel::getBranchIndexFromHwAddress(hwaddress),
173+
fec = Channel::getFecIndexFromHwAddress(hwaddress),
174+
altro = Channel::getAltroIndexFromHwAddress(hwaddress);
175+
if (branch > 1) {
176+
return false;
177+
}
178+
if (fec > 9) {
179+
return false;
180+
}
181+
if (!(altro == 0 || altro == 2 || altro == 3 || altro == 4)) {
182+
return false;
183+
}
184+
return true;
185+
}
186+
163187
const RCUTrailer& AltroDecoder::getRCUTrailer() const
164188
{
165189
if (!mRCUTrailer.isInitialized()) {
@@ -354,18 +378,21 @@ int MinorAltroDecodingError::errorTypeToInt(MinorAltroErrType errortype)
354378
case MinorAltroErrType::CHANNEL_ORDER:
355379
errorNumber = 2;
356380
break;
357-
case MinorAltroErrType::BUNCH_HEADER_NULL:
381+
case MinorAltroErrType::CHANNEL_HEADER:
358382
errorNumber = 3;
359383
break;
360-
case MinorAltroErrType::BUNCH_LENGTH_EXCEED:
384+
case MinorAltroErrType::BUNCH_HEADER_NULL:
361385
errorNumber = 4;
362386
break;
363-
case MinorAltroErrType::BUNCH_LENGTH_ALLOW_EXCEED:
387+
case MinorAltroErrType::BUNCH_LENGTH_EXCEED:
364388
errorNumber = 5;
365389
break;
366-
case MinorAltroErrType::BUNCH_STARTTIME:
390+
case MinorAltroErrType::BUNCH_LENGTH_ALLOW_EXCEED:
367391
errorNumber = 6;
368392
break;
393+
case MinorAltroErrType::BUNCH_STARTTIME:
394+
errorNumber = 7;
395+
break;
369396
};
370397

371398
return errorNumber;
@@ -387,15 +414,18 @@ MinorAltroErrType MinorAltroDecodingError::intToErrorType(int errornumber)
387414
errorType = MinorAltroErrType::CHANNEL_ORDER;
388415
break;
389416
case 3:
390-
errorType = MinorAltroErrType::BUNCH_HEADER_NULL;
417+
errorType = MinorAltroErrType::CHANNEL_HEADER;
391418
break;
392419
case 4:
393-
errorType = MinorAltroErrType::BUNCH_LENGTH_EXCEED;
420+
errorType = MinorAltroErrType::BUNCH_HEADER_NULL;
394421
break;
395422
case 5:
396-
errorType = MinorAltroErrType::BUNCH_LENGTH_ALLOW_EXCEED;
423+
errorType = MinorAltroErrType::BUNCH_LENGTH_EXCEED;
397424
break;
398425
case 6:
426+
errorType = MinorAltroErrType::BUNCH_LENGTH_ALLOW_EXCEED;
427+
break;
428+
case 7:
399429
errorType = MinorAltroErrType::BUNCH_STARTTIME;
400430
break;
401431
default:
@@ -414,6 +444,8 @@ const char* MinorAltroDecodingError::getErrorTypeName(ErrorType_t errortype)
414444
return "ChannelPayloadExceed";
415445
case MinorAltroErrType::CHANNEL_ORDER:
416446
return "ChannelOrderError";
447+
case MinorAltroErrType::CHANNEL_HEADER:
448+
return "ChannelHeader";
417449
case MinorAltroErrType::BUNCH_HEADER_NULL:
418450
return "BunchHeaderNull";
419451
case MinorAltroErrType::BUNCH_LENGTH_EXCEED:
@@ -435,6 +467,8 @@ const char* MinorAltroDecodingError::getErrorTypeTitle(ErrorType_t errortype)
435467
return "Channel exceed";
436468
case MinorAltroErrType::CHANNEL_ORDER:
437469
return "FEC order";
470+
case MinorAltroErrType::CHANNEL_HEADER:
471+
return "Channel header invalid";
438472
case MinorAltroErrType::BUNCH_HEADER_NULL:
439473
return "Bunch header null";
440474
case MinorAltroErrType::BUNCH_LENGTH_EXCEED:
@@ -456,6 +490,8 @@ const char* MinorAltroDecodingError::getErrorTypeDescription(ErrorType_t errorty
456490
return "Trying to access out-of-bound payload!";
457491
case MinorAltroErrType::CHANNEL_ORDER:
458492
return "Invalid FEC order";
493+
case MinorAltroErrType::CHANNEL_HEADER:
494+
return "Invalid channel header";
459495
case MinorAltroErrType::BUNCH_HEADER_NULL:
460496
return "Bunch header 0 or not configured!";
461497
case MinorAltroErrType::BUNCH_LENGTH_EXCEED:

Detectors/EMCAL/reconstruction/src/RawReaderMemory.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ void RawReaderMemory::nextPage(bool doResetPayload)
173173
// The trailer is only decoded if the DDL is in the range of SRU DDLs. STU pages are propagated
174174
// 1-1 without trailer parsing
175175
auto lastword = *(mRawBuffer.getDataWords().rbegin());
176-
if (lastword >> 30 == 3) {
176+
if (RCUTrailer::checkLastTrailerWord(lastword)) {
177177
// lastword is a trailer word
178178
// decode trailer and chop
179179
try {

Detectors/EMCAL/reconstruction/test/testMinorAltroDecodingError.cxx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,35 @@ namespace emcal
2323

2424
BOOST_AUTO_TEST_CASE(MinorAltroDecodingError_test)
2525
{
26-
BOOST_CHECK_EQUAL(MinorAltroDecodingError::getNumberOfErrorTypes(), 7);
27-
std::array<std::string, 7> errornames = {{"ChannelEndPayloadUnexpected",
26+
BOOST_CHECK_EQUAL(MinorAltroDecodingError::getNumberOfErrorTypes(), 8);
27+
std::array<std::string, 8> errornames = {{"ChannelEndPayloadUnexpected",
2828
"ChannelPayloadExceed",
2929
"ChannelOrderError",
30+
"ChannelHeader",
3031
"BunchHeaderNull",
3132
"BunchLengthExceed",
3233
"BunchLengthAllowExceed",
3334
"BunchStarttimeExceed"}},
3435
errortitles = {{"Channel end unexpected",
3536
"Channel exceed",
3637
"FEC order",
38+
"Channel header invalid",
3739
"Bunch header null",
3840
"Bunch length exceed",
3941
"Bunch length impossible",
4042
"Bunch starttime exceed"}},
4143
errordescriptions = {{"Unexpected end of payload in altro channel payload!",
4244
"Trying to access out-of-bound payload!",
4345
"Invalid FEC order",
46+
"Invalid channel header",
4447
"Bunch header 0 or not configured!",
4548
"Bunch length exceeding channel payload size!",
4649
"Bunch length exceeding max. possible bunch size!",
4750
"Bunch start time outside range!"}};
48-
std::array<MinorAltroDecodingError::ErrorType_t, 7> errortypes = {{MinorAltroDecodingError::ErrorType_t::CHANNEL_END_PAYLOAD_UNEXPECT,
51+
std::array<MinorAltroDecodingError::ErrorType_t, 8> errortypes = {{MinorAltroDecodingError::ErrorType_t::CHANNEL_END_PAYLOAD_UNEXPECT,
4952
MinorAltroDecodingError::ErrorType_t::CHANNEL_PAYLOAD_EXCEED,
5053
MinorAltroDecodingError::ErrorType_t::CHANNEL_ORDER,
54+
MinorAltroDecodingError::ErrorType_t::CHANNEL_HEADER,
5155
MinorAltroDecodingError::ErrorType_t::BUNCH_HEADER_NULL,
5256
MinorAltroDecodingError::ErrorType_t::BUNCH_LENGTH_EXCEED,
5357
MinorAltroDecodingError::ErrorType_t::BUNCH_LENGTH_ALLOW_EXCEED,

0 commit comments

Comments
 (0)