Skip to content

Commit

Permalink
Multiple fixes in Alpide decoding/error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
shahor02 committed Apr 14, 2022
1 parent 4e34f61 commit 1160ff2
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,10 @@ class AlpideCoder
uint32_t expectInp = ExpectChipHeader | ExpectChipEmpty; // data must always start with chip header or chip empty flag

chipData.clear();
LOG(debug) << "NewEntry";
while (buffer.next(dataC)) {
//
LOGP(debug, "dataC: {:#x} expect {:#b}", int(dataC), int(expectInp));
// ---------- chip info ?
uint8_t dataCM = dataC & (~MaskChipID);
//
Expand All @@ -161,7 +163,7 @@ class AlpideCoder
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::TruncatedChipEmpty);
#endif
return unexpectedEOF("CHIP_EMPTY:Timestamp");
return unexpectedEOF("CHIP_EMPTY:Timestamp"); // abandon cable data
}
chipData.resetChipID();
expectInp = ExpectChipHeader | ExpectChipEmpty;
Expand All @@ -174,7 +176,7 @@ class AlpideCoder
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::TruncatedChipHeader);
#endif
return unexpectedEOF("CHIP_HEADER");
return unexpectedEOF("CHIP_HEADER"); // abandon cable data
}
expectInp = ExpectRegion; // now expect region info
continue;
Expand All @@ -188,7 +190,6 @@ class AlpideCoder
}

if ((expectInp & ExpectChipTrailer) && dataCM == CHIPTRAILER) { // chip trailer was expected
expectInp = ExpectChipHeader | ExpectChipEmpty;
chipData.setROFlags(dataC & MaskROFlags);
#ifdef ALPIDE_DECODING_STAT
uint8_t roErr = dataC & MaskROFlags;
Expand All @@ -205,10 +206,10 @@ class AlpideCoder
}

if (!chipData.getData().size() && !chipData.isErrorSet()) {
nRightCHits = 0;
colDPrev = 0xffff;
chipData.clear();
continue;
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::TrailerAfterHeader);
#endif
return unexpectedEOF("Trailer after header"); // abandon cable data
}
break;
}
Expand All @@ -222,9 +223,11 @@ class AlpideCoder
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::TruncatedRegion);
#endif
return unexpectedEOF("CHIPDATA");
return unexpectedEOF("CHIPDATA"); // abandon cable data
}
dataS |= dataC;
LOGP(debug, "dataC: {:#x} dataS: {:#x} expect {:#b} in ExpectData", int(dataC), int(dataS), int(expectInp));

// we are decoding the pixel addres, if this is a DATALONG, we will fetch the mask later
uint16_t dColID = (dataS & MaskEncoder) >> 10;
uint16_t pixID = dataS & MaskPixID;
Expand All @@ -237,10 +240,11 @@ class AlpideCoder
// if we start new double column, transfer the hits accumulated in the right column buffer of prev. double column
if (colD != colDPrev) {
if (colD < colDPrev && colDPrev != 0xffff) {
needSorting = true;
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::WrongDColOrder);
chipData.setError(ChipStat::WrongDColOrder); // abandon cable data
#endif
return unexpectedEOF("Wrong column order"); // abandon cable data
needSorting = true; // effectively disabled
}
colDPrev++;
for (int ihr = 0; ihr < nRightCHits; ihr++) {
Expand All @@ -259,11 +263,13 @@ class AlpideCoder
uint8_t hitsPattern = 0;
if (!buffer.next(hitsPattern)) {
chipData.setError(ChipStat::TruncatedLondData);
return unexpectedEOF("CHIP_DATA_LONG:Pattern");
return unexpectedEOF("CHIP_DATA_LONG:Pattern"); // abandon cable data
}
if (hitsPattern & (~MaskHitMap)) {
return unexpectedEOF("CHIP_DATA_LONG:Pattern");
chipData.setError(ChipStat::WrongDataLongPattern);
return unexpectedEOF("CHIP_DATA_LONG:Pattern"); // abandon cable data
}
LOGP(debug, "hitsPattern: {:#b} expect {:#b}", int(hitsPattern), int(expectInp));
}
expectInp = ExpectChipTrailer | ExpectData | ExpectRegion;
continue; // end of DATA(SHORT or LONG) processing
Expand All @@ -287,13 +293,14 @@ class AlpideCoder
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::TruncatedLondData);
#endif
return unexpectedEOF("CHIP_DATA_LONG:Pattern");
return unexpectedEOF("CHIP_DATA_LONG:Pattern"); // abandon cable data
}
LOGP(debug, "hitsPattern: {:#b} expect {:#b}", int(hitsPattern), int(expectInp));
if (hitsPattern & (~MaskHitMap)) {
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::WrongDataLongPattern);
#endif
return unexpectedEOF("CHIP_DATA_LONG:Pattern");
return unexpectedEOF("CHIP_DATA_LONG:Pattern"); // abandon cable data
}
for (int ip = 0; ip < HitMapSize; ip++) {
if (hitsPattern & (0x1 << ip)) {
Expand All @@ -302,7 +309,7 @@ class AlpideCoder
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::WrongRow);
#endif
return unexpectedEOF(fmt::format("Non-existing encoder {} decoded, DataLong was {:x}", pixID, dataS));
return unexpectedEOF(fmt::format("Non-existing encoder {} decoded, DataLong was {:x}", pixID, dataS)); // abandon cable data
}
rightC = ((rowE & 0x1) ? !(addr & 0x1) : (addr & 0x1)); // true for right column / lalse for left
// the real columnt is int colE = colD + rightC;
Expand All @@ -314,11 +321,15 @@ class AlpideCoder
}
}
}
} else if (ChipStat::getAPENonCritical(dataC) >= 0) { // check for recoverable APE, if on: continue with ExpectChipTrailer | ExpectData | ExpectRegion expectation
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::DecErrors(ChipStat::getAPENonCritical(dataC)));
#endif
} else {
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::NoDataFound);
#endif
return unexpectedEOF(fmt::format("Expected DataShort or DataLong mask, got {:x}", dataS));
return unexpectedEOF(fmt::format("Expected DataShort or DataLong mask, got {:x}", dataS)); // abandon cable data
}
expectInp = ExpectChipTrailer | ExpectData | ExpectRegion;
continue; // end of DATA(SHORT or LONG) processing
Expand All @@ -338,8 +349,11 @@ class AlpideCoder
}

if (!dataC) {
buffer.clear(); // 0 padding reached (end of the cable data), no point in continuing
break;
if (expectInp == (ExpectChipHeader | ExpectChipEmpty)) {
continue;
}
chipData.setError(ChipStat::TruncatedBuffer);
return unexpectedEOF("Abandon on 0-padding"); // abandon cable data
}

// in case of BUSY VIOLATION the Trailer may come directly after the Header
Expand All @@ -358,17 +372,11 @@ class AlpideCoder
chipData.setError(ChipStat::DecErrors(codeAPE));
#endif
if (fatalAPE) {
buffer.clear(); // no point in contiunuing with this cable data
} else { // skip eventual padding
while (buffer.next(dataC)) {
if (dataC) { // padding is over, make 1 step back in the buffer
auto currPtr = buffer.getPtr();
buffer.setPtr(--currPtr);
break;
}
}
return unexpectedEOF(fmt::format("APE error {:#02x} [expectation = {:#02x}]", int(dataC), int(expectInp))); // abandon cable data
} else {
LOGP(error, "Code should not have entered here, APE: {:#02x}, expectation: {:#02x}", codeAPE, int(expectInp));
return unexpectedEOF(fmt::format("APE error {:#02x} [expectation = {:#02x}]", int(dataC), int(expectInp))); // abandon cable data
}
return unexpectedEOF(fmt::format("APE error {:#02x} [expectation = 0x{:#02x}]", int(dataC), int(expectInp)));
}
#ifdef ALPIDE_DECODING_STAT
chipData.setError(ChipStat::UnknownWord);
Expand All @@ -381,10 +389,11 @@ class AlpideCoder
std::memcpy(chipData.getRawErrBuff().data(), curPtr - offsBack, offsBack + offsAfter);
chipData.setNBytesInRawBuff(offsBack + offsAfter);
#endif
return unexpectedEOF(fmt::format("Unknown word 0x{:x} [expectation = 0x{:x}]", int(dataC), int(expectInp))); // error
return unexpectedEOF(fmt::format("Unknown word 0x{:x} [expectation = 0x{:x}]", int(dataC), int(expectInp))); // abandon cable data
}

if (needSorting && chipData.getData().size()) { // d.columns were in a wrong order, need to sort the data
if (needSorting && chipData.getData().size()) { // d.columns were in a wrong order, need to sort the data, RS: effectively disabled
LOGP(error, "This code path should have been disabled");
auto& pixData = chipData.getData();
std::sort(pixData.begin(), pixData.end(),
[](PixelData& a, PixelData& b) { return a.getCol() < b.getCol() || (a.getCol() == b.getCol() && a.getRowDirect() < b.getRowDirect()); });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,14 @@ struct ChipStat {
APE_FSM_ERROR, // FSM error (FATAL, SEU error, reached an unknown state)
APE_OCCUPANCY_RATE_LIMIT, // pending detector events limit (FATAL)
APE_OCCUPANCY_RATE_LIMIT_2, // pending detector events limit in packager(FATAL)
APE_LANE_PROTOCOL_ERROR, // lane protocol error
APE_RESERVED_FC, // reserved FC
APE_ERROR_NON_CRITICAL_BYTE, // Error in non critical byte
APE_OOT_NON_CRITICAL, // OOT non-critical
WrongDColOrder, // DColumns non increasing
InterleavedChipData, // Chip data interleaved on the cable
TruncatedBuffer, // truncated buffer, 0 padding
TrailerAfterHeader, // trailer seen after header w/o FE of FD set
NErrorsDefined
};

Expand Down Expand Up @@ -86,8 +92,14 @@ struct ChipStat {
"APE_FSM_ERROR", // FSM error (FATAL, SEU error, reached an unknown state)
"APE_OCCUPANCY_RATE_LIMIT", // pending detector events limit (FATAL)
"APE_OCCUPANCY_RATE_LIMIT_2", // pending detector events limit in packager(FATAL)
"APE_LANE_PROTOCOL_ERROR", // lane protocol error
"APE_RESERVED_FC", // reserved
"APE_ERROR_IN_NON_CRITICAL_BYTE", // Error in non critical byte
"APE_OOT_NON_CRITICAL", // OOT non-critical
"DColumns non-increasing", // DColumns non increasing
"Chip data interleaved on the cable" // Chip data interleaved on the cable
"Chip data interleaved on the cable", // Chip data interleaved on the cable
"TruncatedBuffer", // truncated buffer, 0 padding
"TrailerAfterHeader" // trailer seen after header w/o FE of FD set
};

static constexpr std::array<uint32_t, NErrorsDefined> ErrActions = {
Expand All @@ -114,8 +126,14 @@ struct ChipStat {
ErrActPropagate | ErrActDump, // FSM error (FATAL, SEU error, reached an unknown state)
ErrActPropagate | ErrActDump, // pending detector events limit (FATAL)
ErrActPropagate | ErrActDump, // pending detector events limit in packager(FATAL)
ErrActPropagate | ErrActDump, // lane protocol error
ErrActPropagate | ErrActDump, // reserved FC
ErrActPropagate | ErrActDump, // Error in non critical byte
ErrActPropagate | ErrActDump, // OOT non-critical
ErrActPropagate | ErrActDump, // DColumns non increasing
ErrActPropagate | ErrActDump // Chip data interleaved on the cable
ErrActPropagate | ErrActDump, // Chip data interleaved on the cable
ErrActPropagate | ErrActDump, // Truncated buffer while something was expected
ErrActPropagate | ErrActDump // trailer seen after header w/o FE of FD set
};
uint16_t feeID = -1;
size_t nHits = 0;
Expand All @@ -128,14 +146,23 @@ struct ChipStat {
memset(errorCounts.data(), 0, sizeof(uint32_t) * errorCounts.size());
nHits = 0;
}

static int getAPENonCritical(uint8_t c)
{
if (c == 0xfd || c == 0xfe) {
return APE_STRIP_START + c - 0xf2;
}
return -1;
}

// return APE DecErrors code or -1 if not APE error, set fatal flag if needd
static int getAPECode(uint8_t c, bool& ft)
{
if (c < 0xf2 || c > 0xfa) {
if (c < 0xf2 || c > 0xfe) {
ft = false;
return -1;
}
ft = c >= 0xf4;
ft = c >= 0xf2 && c <= 0xfe;
return APE_STRIP_START + c - 0xf2;
}
uint32_t getNErrors() const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,23 @@ int RUDecodeData::decodeROF(const Mapping& mp)
}
#endif
ret = -1; // discard decoded data
nhits = 0;
}
#ifdef ALPIDE_DECODING_STAT
fillChipStatistics(icab, chipData);
#endif
if (ret >= 0 && chipData->getChipID() < Mapping::getNChips()) { // make sure there was no error | upd: why? if there was a non fatal error, we use chip data
if (nhits) {
doneChips[chipData->getChipID()] = true;
ntot += nhits;
}
if (nhits && chipData->getChipID() < Mapping::getNChips()) {
doneChips[chipData->getChipID()] = true;
ntot += nhits;
if (++nChipsFired < chipsData.size()) { // fetch next free chip
chipData = &chipsData[nChipsFired];
} else {
break; // last chip decoded
}
}
if (ret < 0) {
break; // negative code was returned by decoder: abandon cable data
}
}
}

Expand Down

0 comments on commit 1160ff2

Please sign in to comment.