Skip to content

Commit 6ee924d

Browse files
authored
MCH: improve raw decoder diagnostics (#9881)
* [MCH] improved detection of TimeFrame start * [MCH] improved error detection in raw decoder - badly formatted SYNC words - SAMPA packet headers consistency - chip address and e-link index compatibility - num of 10-bit words multiple of 4 in cluster sum mode * [MCH] removed check of digits time in DataDecoder This is because the corresponding "Bad digit time" error type has been removed, because it is redundant. The digit time can be checked offline with `digit.getTime() != DataDecoder::tfTimeInvalid` * [MCH] skip HB decoding when not needed * [MCH] added detection of mis-placed SYNC packet * [MCH] send HB packets regardless of mTimeRecoMode value
1 parent a40a5a6 commit 6ee924d

9 files changed

Lines changed: 111 additions & 46 deletions

File tree

Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/DataDecoder.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ class DataDecoder
177177
/// Compute the time of all the digits that have been decoded in the current TimeFrame
178178
void computeDigitsTimeBCRst();
179179
void computeDigitsTime();
180-
void checkDigitsTime();
181180

182181
/// Get the vector of digits that have been decoded in the current TimeFrame
183182
const RawDigitVector& getDigits() const { return mDigits; }

Detectors/MUON/MCH/Raw/Decoder/include/MCHRawDecoder/ErrorCodes.h

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,18 @@ enum ErrorCodes {
2525
ErrorParity = 1, // 1
2626
ErrorHammingCorrectable = 1 << 1, // 2
2727
ErrorHammingUncorrectable = 1 << 2, // 4
28-
ErrorBadClusterSize = 1 << 3, // 8
29-
ErrorBadPacketType = 1 << 4, // 16
30-
ErrorBadHeartBeatPacket = 1 << 5, // 32
31-
ErrorBadIncompleteWord = 1 << 6, // 64
32-
ErrorTruncatedData = 1 << 7, // 128
33-
ErrorBadELinkID = 1 << 8, // 256
34-
ErrorBadLinkID = 1 << 9, // 512
35-
ErrorUnknownLinkID = 1 << 10, // 1024
36-
ErrorInvalidDigitTime = 1 << 11, // 2048
37-
ErrorNonRecoverableDecodingError = 1 << 12 // 4096
28+
ErrorBadSyncPacket = 1 << 3, // 8
29+
ErrorBadHeartBeatPacket = 1 << 4, // 16
30+
ErrorBadDataPacket = 1 << 5, // 32
31+
ErrorBadClusterSize = 1 << 6, // 64
32+
ErrorBadIncompleteWord = 1 << 7, // 128
33+
ErrorTruncatedData = 1 << 8, // 256
34+
ErrorUnexpectedSyncPacket = 1 << 9, // 512
35+
ErrorBadELinkID = 1 << 10, // 1024
36+
ErrorBadLinkID = 1 << 11, // 2048
37+
ErrorUnknownLinkID = 1 << 12, // 4096
38+
ErrorBadHBTime = 1 << 13, // 8192
39+
ErrorNonRecoverableDecodingError = 1 << 14 // 16384
3840
};
3941

4042
uint32_t getErrorCodesSize();

Detectors/MUON/MCH/Raw/Decoder/src/DataDecoder.cxx

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,9 @@ void DataDecoder::decodePage(gsl::span<const std::byte> page)
564564

565565
mHBPackets.emplace_back(solar, ds, chip, bunchCrossing);
566566

567-
if (!mTimeFrameStartRecords[chipId].update(mFirstOrbitInTF, bunchCrossing)) {
568-
if (mErrorCount < MCH_DECODER_MAX_ERROR_COUNT) {
567+
if (mTimeRecoMode == TimeRecoMode::HBPackets) {
568+
bool isOk = mTimeFrameStartRecords[chipId].update(mFirstOrbitInTF, bunchCrossing);
569+
if (!isOk && mErrorCount < MCH_DECODER_MAX_ERROR_COUNT) {
569570
auto s = asString(dsElecId);
570571
LOGP(warning, "Bad HeartBeat packet received: {}-CHIP{} {}/{} (last {}/{})",
571572
s, chip, mFirstOrbitInTF, bunchCrossing, mTimeFrameStartRecords[chipId].mOrbitPrev, mTimeFrameStartRecords[chipId].mBunchCrossingPrev);
@@ -814,21 +815,6 @@ void DataDecoder::computeDigitsTimeBCRst()
814815

815816
//_________________________________________________________________________________________________
816817

817-
void DataDecoder::checkDigitsTime()
818-
{
819-
for (auto& digit : mDigits) {
820-
auto& d = digit.digit;
821-
auto& info = digit.info;
822-
auto tfTime = d.getTime();
823-
if (tfTime == DataDecoder::tfTimeInvalid) {
824-
// add invalid digit time error
825-
mErrors.emplace_back(o2::mch::DecoderError(info.solar, info.ds, info.chip, ErrorInvalidDigitTime));
826-
}
827-
}
828-
}
829-
830-
//_________________________________________________________________________________________________
831-
832818
void DataDecoder::computeDigitsTime()
833819
{
834820
switch (mTimeRecoMode) {

Detectors/MUON/MCH/Raw/Decoder/src/ErrorCodes.cxx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace raw
2020

2121
uint32_t getErrorCodesSize()
2222
{
23-
return 13;
23+
return 15;
2424
}
2525

2626
void append(const char* msg, std::string& to)
@@ -49,12 +49,18 @@ std::string errorCodeAsString(uint32_t ec)
4949
if (ec & ErrorBadClusterSize) {
5050
append("Cluster Size", msg);
5151
}
52-
if (ec & ErrorBadPacketType) {
53-
append("Bad Packet Type", msg);
52+
if (ec & ErrorBadSyncPacket) {
53+
append("Bad Sync Packet", msg);
54+
}
55+
if (ec & ErrorUnexpectedSyncPacket) {
56+
append("Unexpected Sync", msg);
5457
}
5558
if (ec & ErrorBadHeartBeatPacket) {
5659
append("Bad HB Packet", msg);
5760
}
61+
if (ec & ErrorBadDataPacket) {
62+
append("Bad Data Packet", msg);
63+
}
5864
if (ec & ErrorBadIncompleteWord) {
5965
append("Bad Incomplete Word", msg);
6066
}
@@ -70,8 +76,8 @@ std::string errorCodeAsString(uint32_t ec)
7076
if (ec & ErrorUnknownLinkID) {
7177
append("Unknown Link ID", msg);
7278
}
73-
if (ec & ErrorInvalidDigitTime) {
74-
append("Invalid Digit Time", msg);
79+
if (ec & ErrorBadHBTime) {
80+
append("Bad HB Time", msg);
7581
}
7682
if (ec & ErrorNonRecoverableDecodingError) {
7783
append("Non Recoverable", msg);

Detectors/MUON/MCH/Raw/Decoder/src/UserLogicElinkDecoder.cxx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,52 @@ void UserLogicElinkDecoder<ChargeSumMode>::prepareAndSendCluster()
3838
mSamples.clear();
3939
}
4040

41+
template <>
42+
bool UserLogicElinkDecoder<SampleMode>::checkDataHeader()
43+
{
44+
int chipAddMin = mDsId.elinkIndexInGroup() * 2;
45+
int chipAddMax = chipAddMin + 1;
46+
47+
// the chip address from the SAMPA header must be consistent with
48+
// the e-Link index
49+
int chipAdd = mSampaHeader.chipAddress();
50+
if (chipAdd < chipAddMin || chipAdd > chipAddMax) {
51+
return false;
52+
}
53+
54+
// we expect at least 3 10-bit words
55+
int nof10BitWords = mSampaHeader.nof10BitWords();
56+
if (nof10BitWords <= 2) {
57+
return false;
58+
}
59+
60+
return true;
61+
}
62+
63+
template <>
64+
bool UserLogicElinkDecoder<ChargeSumMode>::checkDataHeader()
65+
{
66+
int chipAddMin = mDsId.elinkIndexInGroup() * 2;
67+
int chipAddMax = chipAddMin + 1;
68+
69+
// the chip address from the SAMPA header must be consistent with
70+
// the e-Link index
71+
int chipAdd = mSampaHeader.chipAddress();
72+
if (chipAdd < chipAddMin || chipAdd > chipAddMax) {
73+
return false;
74+
}
75+
76+
// we expect at least 3 10-bit words
77+
int nof10BitWords = mSampaHeader.nof10BitWords();
78+
if (nof10BitWords <= 2) {
79+
return false;
80+
}
81+
// in cluster sum mode the number of 10-bit words must be a multiple of 4
82+
if ((nof10BitWords % 4) != 0) {
83+
return false;
84+
}
85+
86+
return true;
87+
}
88+
4189
} // namespace o2::mch::raw

Detectors/MUON/MCH/Raw/Decoder/src/UserLogicElinkDecoder.h

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class UserLogicElinkDecoder
7373
void completeHeader();
7474
void oneLess10BitWord();
7575
void prepareAndSendCluster();
76+
bool checkDataHeader();
7677
void sendCluster(const SampaCluster& sc) const;
7778
void sendHBPacket();
7879
void sendError(int8_t chip, uint32_t error) const;
@@ -118,10 +119,18 @@ void UserLogicElinkDecoder<CHARGESUM>::append(uint64_t data50, uint8_t error, bo
118119

119120
if (isSync(data50)) {
120121
#ifdef ULDEBUG
121-
debugHeader() << (*this) << fmt::format(" --> SYNC word found {:013x}\n", data50);
122+
debugHeader() << (*this) << fmt::format(" --> SYNC word found {:013x} state={}\n", data50, asString(mState));
122123
#endif
123-
clear();
124-
transition(State::WaitingHeader);
124+
if (mState != State::WaitingHeader && mState != State::WaitingSync) {
125+
#ifdef ULDEBUG
126+
debugHeader() << (*this) << " SYNC word found while decoding payload --> resetting\n";
127+
#endif
128+
sendError(static_cast<int8_t>(mSampaHeader.chipAddress()), static_cast<uint32_t>(ErrorUnexpectedSyncPacket));
129+
reset();
130+
} else {
131+
clear();
132+
transition(State::WaitingHeader);
133+
}
125134
return;
126135
}
127136

@@ -178,14 +187,18 @@ bool UserLogicElinkDecoder<CHARGESUM>::append10(uint10_t data10)
178187
{
179188
bool result = false;
180189
#ifdef ULDEBUG
181-
debugHeader() << (*this) << fmt::format(" --> data10 {:d}\n", data10);
190+
debugHeader() << (*this) << fmt::format(" --> data10 {:d} state {}\n", data10, asString(mState));
182191
#endif
183192
switch (mState) {
184193
case State::WaitingHeader:
185194
setHeaderPart(data10);
186195
if (isHeaderComplete()) {
187196
completeHeader();
188-
if (isSync(mSampaHeader.uint64())) {
197+
if (mSampaHeader.packetType() == SampaPacketType::Sync) {
198+
if (!isSync(mSampaHeader.uint64())) {
199+
mErrorMessage = "badly formatted Sync packet";
200+
sendError(static_cast<int8_t>(mSampaHeader.chipAddress()), static_cast<uint32_t>(ErrorBadSyncPacket));
201+
}
189202
reset();
190203
} else if (mSampaHeader.packetType() == SampaPacketType::HeartBeat) {
191204
if (mSampaHeader.isHeartbeat()) {
@@ -198,9 +211,15 @@ bool UserLogicElinkDecoder<CHARGESUM>::append10(uint10_t data10)
198211
reset();
199212
}
200213
} else {
201-
if (mSampaHeader.nof10BitWords() > 2) {
202-
transition(State::WaitingSize);
214+
if (checkDataHeader()) {
215+
if (mSampaHeader.nof10BitWords() > 2) {
216+
transition(State::WaitingSize);
217+
} else {
218+
reset();
219+
}
203220
} else {
221+
mErrorMessage = "badly formatted Data packet";
222+
sendError(static_cast<int8_t>(mSampaHeader.chipAddress()), static_cast<uint32_t>(ErrorBadDataPacket));
204223
reset();
205224
}
206225
}
@@ -265,6 +284,9 @@ std::string UserLogicElinkDecoder<CHARGESUM>::asString(State s) const
265284
case State::WaitingSample:
266285
return "WaitingSample";
267286
break;
287+
default:
288+
return "Unknown";
289+
break;
268290
};
269291
}
270292

Detectors/MUON/MCH/Raw/Decoder/src/testUserLogicEndpointDecoder.cxx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(SyncInTheMiddleChargeSumModeTwoChannels, V, testTy
367367
DsElecId{361, 6, 2}, 63, {cl1, cl2},
368368
DsElecId{361, 6, 2}, 47, {cl3, cl4},
369369
5);
370-
BOOST_CHECK_EQUAL(r,
371-
"S361-J6-DS2-ch-63-ts-345-q-123456-cs-789\n"
372-
"S361-J6-DS2-ch-63-ts-346-q-789012-cs-345\n");
370+
std::string r2 = "S361-J6-DS2-ch-63-ts-345-q-123456-cs-789\n";
371+
r2 += "S361-J6-DS2-ch-63-ts-346-q-789012-cs-345\n";
372+
r2 += fmt::format("S361-J6-DS2-chip-5-error-{}\n", ErrorUnexpectedSyncPacket);
373+
BOOST_CHECK_EQUAL(r, r2);
373374
}
374375

375376
BOOST_AUTO_TEST_CASE_TEMPLATE(TestCruPageOK, V, testTypes)

Detectors/MUON/MCH/Workflow/src/DataDecoderSpec.cxx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ class DataDecoderTask
243243
}
244244
}
245245
mDecoder->computeDigitsTime();
246-
mDecoder->checkDigitsTime();
247246
auto tEnd = std::chrono::high_resolution_clock::now();
248247
mTimeDecoding += tEnd - tStart;
249248

Detectors/MUON/MCH/Workflow/src/cru-page-reader-workflow.cxx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,10 @@ class FileReaderTask
320320
}
321321

322322
if (mPrint) {
323-
std::cout << "Sending TF" << std::endl
323+
std::cout << "Sending TF " << orbitMin << " (previous " << mLastTForbit << " delta " << (orbitMin - mLastTForbit) << ")" << std::endl
324324
<< std::endl;
325325
}
326+
mLastTForbit = orbitMin;
326327
auto freefct = [](void* data, void* /*hint*/) { free(data); };
327328
pc.outputs().adoptChunk(Output{"RDT", "RAWDATA"}, outBuf, outSize, freefct, nullptr);
328329

@@ -448,7 +449,7 @@ class FileReaderTask
448449
// increment the total buffer size
449450
mTimeFrameSizes[feeID][linkID] += pageSize;
450451

451-
if ((triggerType & 0x800) != 0 && stopBit == 0 && pageCounter == 0 && bc == 0) {
452+
if ((triggerType & 0x800) != 0 && /*stopBit == 0 && pageCounter == 0 &&*/ bc == 0) {
452453
// This is the start of a new TimeFrame, so we need to push a new empty TimeFrame in the queue
453454
if (mPrint) {
454455
std::cout << "tfQueue.size(): " << tfQueue.size() << std::endl;
@@ -615,6 +616,7 @@ class FileReaderTask
615616
bool mFullTF; ///< send full time frames
616617
bool mSaveTF; ///< save individual time frames to file
617618
int mOverlap; ///< overlap between contiguous TimeFrames
619+
int mLastTForbit{0}; ///< first orbit number of last transmitted TimeFrame
618620
bool mPrint = false; ///< print debug messages
619621
o2::dataformats::TFIDInfo mTFIDInfo{}; // struct to modify output headers
620622

0 commit comments

Comments
 (0)