diff --git a/algo/detectors/sts/UnpackSts.cxx b/algo/detectors/sts/UnpackSts.cxx index e1dd3dc806e695d898a71debcd8dde8e68aae02f..eeb33bf047390c30084cfea30bf66dd66a32ef05 100644 --- a/algo/detectors/sts/UnpackSts.cxx +++ b/algo/detectors/sts/UnpackSts.cxx @@ -24,39 +24,40 @@ namespace cbm::algo { // --- Output data - vector<CbmStsDigi> digiVec = {}; - UnpackStsMonitorData monitor = {}; + resultType result = {}; // --- Current Timeslice time and TS_MSB epoch cycle fCurrentTsTime = tTimeslice; auto msTime = msDescr.idx; // Unix time of MS in ns fCurrentCycle = std::ldiv(msTime, fkCycleLength).quot; + // ---Â Number of messages in microslice + auto msSize = msDescr.size; + if (msSize % sizeof(stsxyter::Message) != 0) { + result.second.fNumErrInvalidMsSize++; + return result; + } + const uint32_t numMessages = msSize / sizeof(stsxyter::Message); + if (numMessages < 2) { + result.second.fNumErrInvalidMsSize++; + return result; + } + // --- Interpret MS content as sequence of SMX messages auto message = reinterpret_cast<const stsxyter::Message*>(msContent); // --- The first message in the MS is expected to be of type EPOCH and can be ignored if (message[0].GetMessType() != stsxyter::MessType::Epoch) { - std::cout << "Error: UnpackSts: First message type is " << uint16_t(message[0].GetMessType()) << std::endl; - monitor.fNumErrInvalidFirstMessage++; - return std::make_pair(digiVec, monitor); + result.second.fNumErrInvalidFirstMessage++; + return result; } // --- The second message must be of type ts_msb if (message[1].GetMessType() != stsxyter::MessType::TsMsb) { - std::cout << "Error: UnpackSts: Second message type is " << uint16_t(message[0].GetMessType()) << std::endl; - monitor.fNumErrInvalidFirstMessage++; - return std::make_pair(digiVec, monitor); + result.second.fNumErrInvalidFirstMessage++; + return result; } - ProcessTsmsbMessage(message[1], monitor); - - // ---Â Number of messages in microslice - auto msSize = msDescr.size; - if (msSize % sizeof(stsxyter::Message) != 0) { - monitor.fNumErrInvalidMsSize++; - return std::make_pair(digiVec, monitor); - } - const uint32_t numMessages = msSize / sizeof(stsxyter::Message); + ProcessTsmsbMessage(message[1], result.second); // --- Message loop for (uint32_t messageNr = 2; messageNr < numMessages; messageNr++) { @@ -65,15 +66,15 @@ namespace cbm::algo switch (message[messageNr].GetMessType()) { case stsxyter::MessType::Hit: { - ProcessHitMessage(message[messageNr], digiVec, monitor); + ProcessHitMessage(message[messageNr], result.first, result.second); break; } case stsxyter::MessType::TsMsb: { - ProcessTsmsbMessage(message[messageNr], monitor); + ProcessTsmsbMessage(message[messageNr], result.second); break; } default: { - monitor.fNumNonHitOrTsbMessage++; + result.second.fNumNonHitOrTsbMessage++; break; } @@ -81,14 +82,14 @@ namespace cbm::algo } //# Messages - return std::make_pair(digiVec, monitor); + return result; } // -------------------------------------------------------------------------- // ----- Process hit message -------------------------------------------- - void UnpackSts::ProcessHitMessage(const stsxyter::Message& message, vector<CbmStsDigi>& digiVec, - UnpackStsMonitorData& monitor) const + inline void UnpackSts::ProcessHitMessage(const stsxyter::Message& message, vector<CbmStsDigi>& digiVec, + UnpackStsMonitorData& monitor) const { // --- Check eLink and get parameters @@ -129,7 +130,7 @@ namespace cbm::algo // ----- Process an epoch (TS_MSB) message ------------------------------ - void UnpackSts::ProcessTsmsbMessage(const stsxyter::Message& message, UnpackStsMonitorData& monitor) + inline void UnpackSts::ProcessTsmsbMessage(const stsxyter::Message& message, UnpackStsMonitorData& monitor) { auto epoch = message.GetTsMsbValBinning(); diff --git a/algo/detectors/sts/UnpackSts.h b/algo/detectors/sts/UnpackSts.h index 96e3dd483448b11d642a7926870c3977758171aa..05989d375367dcc617c39b117e3a59c0f97c263f 100644 --- a/algo/detectors/sts/UnpackSts.h +++ b/algo/detectors/sts/UnpackSts.h @@ -57,7 +57,7 @@ namespace cbm::algo struct UnpackStsMonitorData { uint32_t fNumNonHitOrTsbMessage = 0; uint32_t fNumErrElinkOutOfRange = 0; ///< Elink not contained in parameters - uint32_t fNumErrInvalidFirstMessage = 0; ///< First message is not TS_MSB + uint32_t fNumErrInvalidFirstMessage = 0; ///< First message is not TS_MSB or second is not EPOCH uint32_t fNumErrInvalidMsSize = 0; ///< Microslice size is not multiple of message size uint32_t fNumErrTimestampOverflow = 0; ///< Overflow in 64 bit time stamp bool HasErrors() diff --git a/reco/tasks/CbmTaskUnpack.cxx b/reco/tasks/CbmTaskUnpack.cxx index ecca0e5e8884e0354ca259ed18d1faab93ddb8e3..727dca5bd5e9af56aca051c32d65ea5dd5473736 100644 --- a/reco/tasks/CbmTaskUnpack.cxx +++ b/reco/tasks/CbmTaskUnpack.cxx @@ -66,33 +66,42 @@ void CbmTaskUnpack::Exec(Option_t*) TStopwatch compTimer; timer.Start(); size_t numMs = 0; + size_t numBytes = 0; size_t numDigis = 0; // --- Timeslice properties - uint64_t tsIndex = timeslice->index(); - uint64_t tsTime = timeslice->start_time(); - uint64_t numComp = timeslice->num_components(); - uint64_t numCompUsed = 0; + const uint64_t tsIndex = timeslice->index(); + const uint64_t tsTime = timeslice->start_time(); + const uint64_t numComp = timeslice->num_components(); + uint64_t numCompUsed = 0; // --- Component loop for (uint64_t comp = 0; comp < numComp; comp++) { - uint8_t systemId = timeslice->descriptor(comp, 0).sys_id; - if (systemId == static_cast<uint8_t>(fles::SubsystemIdentifier::STS)) { - uint16_t equipmentId = timeslice->descriptor(comp, 0).eq_id; - auto algoIt = fAlgoSts.find(equipmentId); + auto systemId = static_cast<fles::SubsystemIdentifier>(timeslice->descriptor(comp, 0).sys_id); + if (systemId == fles::SubsystemIdentifier::STS) { + const uint16_t equipmentId = timeslice->descriptor(comp, 0).eq_id; + const auto algoIt = fAlgoSts.find(equipmentId); assert(algoIt != fAlgoSts.end()); + // The current algorithm works for the STS data format version 0x20 used in 2021. + // Other versions are not yet supported. + // In the future, different data formats will be supported by instantiating different + // algorithms depending on the version. + assert(timeslice->descriptor(comp, 0).sys_ver == 0x20); + // --- Component log + size_t numBytesInComp = 0; size_t numDigisInComp = 0; compTimer.Start(); // --- Microslice loop uint64_t numMsInComp = timeslice->num_microslices(comp); for (uint64_t mslice = 0; mslice < numMsInComp; mslice++) { - auto msDescriptor = timeslice->descriptor(comp, mslice); - auto msContent = timeslice->content(comp, mslice); - auto result = (algoIt->second)(msContent, msDescriptor, tsTime); + const auto msDescriptor = timeslice->descriptor(comp, mslice); + const auto msContent = timeslice->content(comp, mslice); + numBytesInComp += msDescriptor.size; + auto result = (algoIt->second)(msContent, msDescriptor, tsTime); LOG(debug1) << GetName() << ": Component " << comp << ", microslice " << mslice << ", digis " << result.first.size() << ", errors " << result.second.fNumNonHitOrTsbMessage << " | " << result.second.fNumErrElinkOutOfRange << " | " << result.second.fNumErrInvalidFirstMessage @@ -100,15 +109,17 @@ void CbmTaskUnpack::Exec(Option_t*) << " | "; //std::move(result.first.begin(), result.first.end(), fTimeslice->fData.fSts.fDigis.end()); // TODO: The above usage of std::move does not work (seg. fault). Would need advice. - auto it = fTimeslice->fData.fSts.fDigis.end(); + const auto it = fTimeslice->fData.fSts.fDigis.end(); fTimeslice->fData.fSts.fDigis.insert(it, result.first.begin(), result.first.end()); numDigisInComp += result.first.size(); } //# microslice compTimer.Stop(); - LOG(debug) << GetName() << ": Component " << comp << ", microslices " << numMsInComp << ", digis " - << numDigisInComp << ", CPU time " << compTimer.CpuTime() * 1000. << " ms"; + LOG(debug) << GetName() << ": Component " << comp << ", microslices " << numMsInComp << " input size " + << numBytesInComp << " bytes, " + << ", digis " << numDigisInComp << ", CPU time " << compTimer.CpuTime() * 1000. << " ms"; numCompUsed++; + numBytes += numBytesInComp; numDigis += numDigisInComp; numMs += numMsInComp; @@ -120,16 +131,18 @@ void CbmTaskUnpack::Exec(Option_t*) // --- Timeslice log timer.Stop(); stringstream logOut; - logOut << setw(20) << left << GetName() << " ["; + logOut << setw(15) << left << GetName() << " ["; logOut << fixed << setw(8) << setprecision(1) << right << timer.RealTime() * 1000. << " ms] "; logOut << "TS " << fNumTs << " (index " << tsIndex << ")"; logOut << ", components " << numCompUsed << " / " << numComp << ", microslices " << numMs; + logOut << ", input rate " << double(numBytes) / timer.RealTime() / 1.e6 << " MB/s"; logOut << ", digis " << numDigis; LOG(info) << logOut.str(); // --- Run statistics fNumTs++; fNumMs += numMs; + fNumBytes += numBytes; fNumDigis += numDigis; fTime += timer.RealTime(); } @@ -140,12 +153,15 @@ void CbmTaskUnpack::Exec(Option_t*) void CbmTaskUnpack::Finish() { std::cout << std::endl; + double timePerTs = 1000. * fTime / double(fNumTs); // in ms + double rate = fNumBytes / 1.e6 / fTime; // in MB/s LOG(info) << "====================================="; LOG(info) << GetName() << ": Run summary"; - LOG(info) << "Timeslices : " << fNumTs; - LOG(info) << "Microslices : " << fNumMs; - LOG(info) << "Digis : " << fNumDigis; - LOG(info) << "Time / TS : " << fixed << setprecision(2) << 1000. * fTime / double(fNumTs) << " ms"; + LOG(info) << "Timeslices : " << fNumTs; + LOG(info) << "Microslices : " << fNumMs; + LOG(info) << "Digis : " << fNumDigis; + LOG(info) << "Av. input rate : " << fixed << setprecision(2) << rate << " MB/s"; + LOG(info) << "Time / TS : " << fixed << setprecision(2) << timePerTs << " ms"; LOG(info) << "====================================="; } // ---------------------------------------------------------------------------- @@ -193,7 +209,7 @@ InitStatus CbmTaskUnpack::Init() std::unique_ptr<UnpackStsPar> par(new UnpackStsPar()); par->fNumChansPerAsic = numChansPerAsic; par->fNumAsicsPerModule = numAsicsPerModule; - size_t numElinks = fStsConfig.GetNumElinks(equip); + const size_t numElinks = fStsConfig.GetNumElinks(equip); for (size_t elink = 0; elink < numElinks; elink++) { UnpackStsElinkPar elinkPar; auto mapEntry = fStsConfig.Map(equip, elink); diff --git a/reco/tasks/CbmTaskUnpack.h b/reco/tasks/CbmTaskUnpack.h index 9d5dbbd924c502e162302460457ba6bf9ae0e3b6..541a749a7bbbcc286d98b8e339aadf5362d498e3 100644 --- a/reco/tasks/CbmTaskUnpack.h +++ b/reco/tasks/CbmTaskUnpack.h @@ -72,6 +72,7 @@ private: // members cbm::algo::StsReadoutConfig fStsConfig {}; size_t fNumTs = 0; size_t fNumMs = 0; + size_t fNumBytes = 0; size_t fNumDigis = 0; double fTime = 0.; CbmDigiTimeslice* fTimeslice = nullptr; ///< Output data