diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h index 9a57228ddce1e..012059749d995 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/DecodingStat.h @@ -290,6 +290,14 @@ struct GBTLinkDecodingStat { ClassDefNV(GBTLinkDecodingStat, 3); }; +struct ErrorMessage { + uint16_t id = -1; + uint16_t errType = 0; + uint16_t errInfo0 = 0; + uint16_t errInfo1 = 0; + ClassDefNV(ErrorMessage, 1) +}; + } // namespace itsmft } // namespace o2 #endif diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h index 9e3b1daa00a26..85c6b39fdd1b5 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RUDecodeData.h @@ -54,6 +54,8 @@ struct RUDecodeData { bool ROFRampUpStage = false; // flag that the data come from the ROF rate ramp-up stage GBTCalibData calibData{}; // calibration info from GBT calibration word std::unordered_map> chipErrorsTF{}; // vector of chip decoding errors seen in the given TF + std::vector errMsgVecTF; // Specific errors info collected for sending for the whole TF + const RUInfo* ruInfo = nullptr; RUDecodeData() diff --git a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h index 810bff1037513..3a53253da2b42 100644 --- a/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h +++ b/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelDecoder.h @@ -69,8 +69,8 @@ class RawPixelDecoder final : public PixelReader template void fillCalibData(CalibContainer& calib); - template - void collectDecodingErrors(LinkErrors& linkErrors, DecErrors& decErrors); + template + void collectDecodingErrors(LinkErrors& linkErrors, DecErrors& decErrors, ErrMsgs& errInfos); const RUDecodeData* getRUDecode(int ruSW) const { return mRUEntry[ruSW] < 0 ? nullptr : &mRUDecodeVec[mRUEntry[ruSW]]; } const GBTLink* getGBTLink(int i) const { return i < 0 ? nullptr : &mGBTLinks[i]; } @@ -267,8 +267,8 @@ void RawPixelDecoder::fillCalibData(CalibContainer& calib) ///______________________________________________________________________ template -template -void RawPixelDecoder::collectDecodingErrors(LinkErrors& linkErrors, DecErrors& decErrors) +template +void RawPixelDecoder::collectDecodingErrors(LinkErrors& linkErrors, DecErrors& decErrors, ErrMsgs& errInfos) { for (auto& lnk : mGBTLinks) { if (lnk.gbtErrStatUpadated) { @@ -276,11 +276,24 @@ void RawPixelDecoder::collectDecodingErrors(LinkErrors& linkErrors, Dec lnk.gbtErrStatUpadated = false; } } + size_t nerr = 0, nerrMsg = 0; for (auto& ru : mRUDecodeVec) { - for (const auto& err : ru.chipErrorsTF) { - decErrors.emplace_back(ChipError{err.first, err.second.first, err.second.second}); // id, nerrors, errorFlags + nerr += ru.chipErrorsTF.size(); + nerrMsg += ru.errMsgVecTF.size(); + } + if (nerr || nerrMsg) { + decErrors.reserve(nerr); + errInfos.reserve(nerrMsg); + for (auto& ru : mRUDecodeVec) { + for (const auto& err : ru.chipErrorsTF) { + decErrors.emplace_back(ChipError{err.first, err.second.first, err.second.second}); // id, nerrors, errorFlags + } + for (auto& err : ru.errMsgVecTF) { + errInfos.push_back(err); + } + ru.chipErrorsTF.clear(); + ru.errMsgVecTF.clear(); } - ru.chipErrorsTF.clear(); } } diff --git a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h index e6785e4402f37..19f4ca06d0220 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h +++ b/Detectors/ITSMFT/common/reconstruction/src/ITSMFTReconstructionLinkDef.h @@ -55,4 +55,7 @@ #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::itsmft::ClustererParam < o2::detectors::DetID::ITS>> + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::itsmft::ClustererParam < o2::detectors::DetID::MFT>> + ; +#pragma link C++ class o2::itsmft::ErrorMessage + ; +#pragma link C++ class std::vector < o2::itsmft::ErrorMessage> + ; + #endif diff --git a/Detectors/ITSMFT/common/reconstruction/src/RUDecodeData.cxx b/Detectors/ITSMFT/common/reconstruction/src/RUDecodeData.cxx index e81194666fcb8..a9ed2748ec004 100644 --- a/Detectors/ITSMFT/common/reconstruction/src/RUDecodeData.cxx +++ b/Detectors/ITSMFT/common/reconstruction/src/RUDecodeData.cxx @@ -62,6 +62,14 @@ void RUDecodeData::fillChipStatistics(int icab, const ChipPixelData* chipData) auto& chErr = chipErrorsTF[compid]; chErr.first++; chErr.second |= chipData->getErrorFlags(); + + if (chipData->isErrorSet(ChipStat::RepeatingPixel)) { + auto& errMsg = errMsgVecTF.emplace_back(); + errMsg.id = chipData->getChipID(); + errMsg.errType = ChipStat::RepeatingPixel; + errMsg.errInfo0 = chipData->getErrorInfo() & 0xffff; // row + errMsg.errInfo1 = (chipData->getErrorInfo() >> 16) & 0xffff; // row + } } if (action & ChipStat::ErrActDump) { linkHBFToDump[(uint64_t(cableLinkPtr[icab]->subSpec) << 32) + cableLinkPtr[icab]->hbfEntry] = cableLinkPtr[icab]->irHBF.orbit; diff --git a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx index 76bd1ec7454a0..7042cb7433ac5 100644 --- a/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx +++ b/Detectors/ITSMFT/common/workflow/src/STFDecoderSpec.cxx @@ -247,7 +247,8 @@ void STFDecoder::run(ProcessingContext& pc) } auto& linkErrors = pc.outputs().make>(Output{orig, "LinkErrors", 0}); auto& decErrors = pc.outputs().make>(Output{orig, "ChipErrors", 0}); - mDecoder->collectDecodingErrors(linkErrors, decErrors); + auto& errMessages = pc.outputs().make>(Output{orig, "ErrorInfo", 0}); + mDecoder->collectDecodingErrors(linkErrors, decErrors, errMessages); pc.outputs().snapshot(Output{orig, "PHYSTRIG", 0}, mDecoder->getExternalTriggers()); @@ -398,6 +399,7 @@ DataProcessorSpec getSTFDecoderSpec(const STFDecoderInp& inp) outputs.emplace_back(inp.origin, "LinkErrors", 0, Lifetime::Timeframe); outputs.emplace_back(inp.origin, "ChipErrors", 0, Lifetime::Timeframe); + outputs.emplace_back(inp.origin, "ErrorInfo", 0, Lifetime::Timeframe); outputs.emplace_back(inp.origin, "CHIPSSTATUS", 0, Lifetime::Timeframe); if (inp.askSTFDist) { diff --git a/Framework/Core/include/Framework/ServiceRegistry.h b/Framework/Core/include/Framework/ServiceRegistry.h index e3fa23294ee78..2236562e6da75 100644 --- a/Framework/Core/include/Framework/ServiceRegistry.h +++ b/Framework/Core/include/Framework/ServiceRegistry.h @@ -267,33 +267,32 @@ struct ServiceRegistry { /// @deprecated old API to be substituted with the ServiceHandle one template + requires std::is_base_of_v void registerService(C* service, Salt salt = ServiceRegistry::globalDeviceSalt()) { // This only works for concrete implementations of the type T. // We need type elision as we do not want to know all the services in // advance - static_assert(std::is_base_of::value == true, - "Registered service is not derived from declared interface"); constexpr ServiceTypeHash typeHash{TypeIdHelpers::uniqueId()}; ServiceRegistry::registerService(typeHash, reinterpret_cast(service), K, salt, typeid(C).name()); } /// @deprecated old API to be substituted with the ServiceHandle one template + requires std::is_base_of_v void registerService(C const* service, Salt salt = ServiceRegistry::globalDeviceSalt()) { // This only works for concrete implementations of the type T. // We need type elision as we do not want to know all the services in // advance - static_assert(std::is_base_of::value == true, - "Registered service is not derived from declared interface"); constexpr ServiceTypeHash typeHash{TypeIdHelpers::uniqueId()}; this->registerService(typeHash, reinterpret_cast(const_cast(service)), K, salt, typeid(C).name()); } /// Check if service of type T is currently active. template - std::enable_if_t == false, bool> active(Salt salt) const + requires(std::is_const_v == false) + bool active(Salt salt) const { constexpr ServiceTypeHash typeHash{TypeIdHelpers::uniqueId()}; if (this->getPos(typeHash, GLOBAL_CONTEXT_SALT) != -1) { diff --git a/Framework/Core/include/Framework/ServiceRegistryRef.h b/Framework/Core/include/Framework/ServiceRegistryRef.h index fa791cc8c4643..910d4e726c080 100644 --- a/Framework/Core/include/Framework/ServiceRegistryRef.h +++ b/Framework/Core/include/Framework/ServiceRegistryRef.h @@ -72,7 +72,8 @@ class ServiceRegistryRef /// Check if service of type T is currently active. template - std::enable_if_t == false, bool> active() const + requires(std::is_const_v == false) + [[nodiscard]] bool active() const { return mRegistry.active(mSalt); }