diff --git a/algo/detectors/much/MuchReadoutConfig.cxx b/algo/detectors/much/MuchReadoutConfig.cxx index 5d06b3295049d8ed0b7cf85f1ee4f6e2ea1544bd..08336576d88166e472b0709efc56eb8104c7701f 100644 --- a/algo/detectors/much/MuchReadoutConfig.cxx +++ b/algo/detectors/much/MuchReadoutConfig.cxx @@ -41,6 +41,49 @@ void MuchReadoutConfig::putParams(FairParamList* l) } */ + // --- Constructor ------------------------------------------------------------------ + MuchReadoutConfig::MuchReadoutConfig() { Init(); } + // ------------------------------------------------------------------------------------ + + + // --- Destructor ----------------------------------------------------------------- + MuchReadoutConfig::~MuchReadoutConfig() {} + // ------------------------------------------------------------------------------------ + + // --- Equipment IDs -------------------------------------------------------------- + std::vector<uint16_t> MuchReadoutConfig::GetEquipmentIds() + { + std::vector<uint16_t> result; + for (auto& entry : fReadoutMap) + result.push_back(entry.first); + return result; + } + // ------------------------------------------------------------------------------------ + + // --- Number of elinks for a component / equipment ------------------------------- + size_t MuchReadoutConfig::GetNumElinks(uint16_t equipmentId) + { + size_t result = 0; + auto it = fReadoutMap.find(equipmentId); + if (it != fReadoutMap.end()) result = fReadoutMap[equipmentId].size(); + return result; + } + // ------------------------------------------------------------------------------------ + + + // --- Mapping (equimentId, elink) -> address[channel] ------------------------------ + std::vector<uint32_t> MuchReadoutConfig::Map(uint16_t equipmentId, uint16_t elinkId) + { + std::vector<uint32_t> result; + auto equipIter = fReadoutMap.find(equipmentId); + if (equipIter != fReadoutMap.end()) { + if (elinkId < equipIter->second.size()) { result = equipIter->second.at(elinkId); } + } + return result; + } + // ------------------------------------------------------------------------------------ + + void MuchReadoutConfig::Init() { // This here refers to the mCBM 2021 setup. diff --git a/algo/detectors/much/MuchReadoutConfig.h b/algo/detectors/much/MuchReadoutConfig.h index debbabbe805dd0c71a1413443d0f1bbf0d370c3f..50f309fd6b0c97c10a91306da4f99f22547c45a2 100644 --- a/algo/detectors/much/MuchReadoutConfig.h +++ b/algo/detectors/much/MuchReadoutConfig.h @@ -20,11 +20,29 @@ namespace cbm::algo class MuchReadoutConfig { public: - /** Standard constructor **/ - MuchReadoutConfig() {}; - - /** Destructor **/ - ~MuchReadoutConfig() {}; + /** @brief Constructor **/ + MuchReadoutConfig(); + + /** @brief Destructor **/ + virtual ~MuchReadoutConfig(); + + /** @brief Equipment in the configuration + ** @return Vector of equipment IDs + **/ + std::vector<uint16_t> GetEquipmentIds(); + + /** @brief Number of elinks of a component + ** @param Equipment ID + ** @return Number of elinks + **/ + size_t GetNumElinks(uint16_t equipmentId); + + /** @brief API: Mapping from component and elink to addresses per channel + ** @param equipId Equipment identifier (component) + ** @param elink Elink number within component + ** @return Vector of MUCH addresses, indexed via channel number + */ + std::vector<uint32_t> Map(uint16_t equipId, uint16_t elink); uint16_t GetNrOfCrobs() { return numComp * numCrobPerComp; } uint16_t GetNrOfFebs() { return GetNrOfCrobs() * kuNbFebsPerCrob; } diff --git a/algo/detectors/much/UnpackMuch.cxx b/algo/detectors/much/UnpackMuch.cxx index c7daa77b09d12b912043129c65cc706e39ec7a16..9f0937facc365059b63e8da4ff0bfe8e3809fe51 100644 --- a/algo/detectors/much/UnpackMuch.cxx +++ b/algo/detectors/much/UnpackMuch.cxx @@ -95,7 +95,7 @@ namespace cbm::algo inline void UnpackMuch::ProcessHitMessage(const stsxyter::Message& message, vector<CbmMuchDigi>& digiVec, UnpackMuchMonitorData& monitor) const { - + /* STS version // --- Check eLink and get parameters uint16_t elink = message.GetLinkIndexHitBinning(); if (elink >= fParams.fElinkParams.size()) { @@ -130,7 +130,8 @@ namespace cbm::algo double charge = elinkPar.fAdcOffset + (message.GetHitAdc() - 1) * elinkPar.fAdcGain; // --- Create output digi - // digiVec.emplace_back(address, channel, messageTime, charge); + digiVec.emplace_back(address, channel, messageTime, charge); +*/ } // -------------------------------------------------------------------------- diff --git a/algo/detectors/much/UnpackMuch.h b/algo/detectors/much/UnpackMuch.h index 22bc306fddbf4d954e938566080539539f424143..c6f3f2334471a677cc75c8a1feb1a493fb0f4152 100644 --- a/algo/detectors/much/UnpackMuch.h +++ b/algo/detectors/much/UnpackMuch.h @@ -29,11 +29,11 @@ namespace cbm::algo ** @brief STS Unpacking parameters for one eLink / ASIC **/ struct UnpackMuchElinkPar { - int32_t fAddress = 0; ///< CbmMuchAddress for the connected module - uint32_t fAsicNr = 0; ///< Number of connected ASIC within the module + std::vector<uint32_t> fAddress; ///< CbmMuchAddress for different channels + //uint32_t fAsicNr = 0; ///< Number of connected ASIC within the module uint64_t fTimeOffset = 0.; ///< Time calibration parameter - double fAdcOffset = 0.; ///< Charge calibration parameter - double fAdcGain = 0.; ///< Charge calibration parameter + //double fAdcOffset = 0.; ///< Charge calibration parameter + //double fAdcGain = 0.; ///< Charge calibration parameter }; diff --git a/reco/tasks/CMakeLists.txt b/reco/tasks/CMakeLists.txt index 9b517ee4dca205ed584cb66f3a954061881dbcff..97edf5cb386d3f2ddd3e09c3355d64a5e3169cef 100644 --- a/reco/tasks/CMakeLists.txt +++ b/reco/tasks/CMakeLists.txt @@ -39,7 +39,7 @@ ${CBMROOT_SOURCE_DIR}/core/data/raw ${CBMROOT_SOURCE_DIR}/algo/evbuild ${CBMROOT_SOURCE_DIR}/algo/trigger ${CBMROOT_SOURCE_DIR}/algo/detectors/sts - +${CBMROOT_SOURCE_DIR}/algo/detectors/much ) set(SYSTEM_INCLUDE_DIRECTORIES diff --git a/reco/tasks/CbmTaskUnpack.cxx b/reco/tasks/CbmTaskUnpack.cxx index 0d38ae69265e5060f1b30249fa6fb0e7beb1a60a..a692c31167758a30ab61d2a88de489ad18c1ee3f 100644 --- a/reco/tasks/CbmTaskUnpack.cxx +++ b/reco/tasks/CbmTaskUnpack.cxx @@ -35,10 +35,11 @@ using namespace std; +using cbm::algo::UnpackMuchElinkPar; +using cbm::algo::UnpackMuchPar; using cbm::algo::UnpackStsElinkPar; using cbm::algo::UnpackStsPar; - // ----- Constructor ----------------------------------------------------- CbmTaskUnpack::CbmTaskUnpack() : FairTask("Unpack") {} // --------------------------------------------------------------------------- @@ -76,7 +77,16 @@ void CbmTaskUnpack::Exec(Option_t*) #pragma omp parallel for schedule(dynamic) shared(timeslice) reduction(+ : numMs, numBytes, numDigis, numCompUsed) for (uint64_t comp = 0; comp < timeslice->num_components(); comp++) { + // --- Component log + size_t numBytesInComp = 0; + size_t numDigisInComp = 0; + uint64_t numMsInComp = 0; + + TStopwatch compTimer; + compTimer.Start(); + 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); @@ -88,14 +98,8 @@ void CbmTaskUnpack::Exec(Option_t*) // algorithms depending on the version. assert(timeslice->descriptor(comp, 0).sys_ver == 0x20); - // --- Component log - size_t numBytesInComp = 0; - size_t numDigisInComp = 0; - TStopwatch compTimer; - compTimer.Start(); - // --- Microslice loop - uint64_t numMsInComp = timeslice->num_microslices(comp); + numMsInComp = timeslice->num_microslices(comp); for (uint64_t mslice = 0; mslice < numMsInComp; mslice++) { const auto msDescriptor = timeslice->descriptor(comp, mslice); const auto msContent = timeslice->content(comp, mslice); @@ -111,17 +115,48 @@ void CbmTaskUnpack::Exec(Option_t*) fTimeslice->fData.fSts.fDigis.insert(fTimeslice->fData.fSts.fDigis.end(), result.first.begin(), result.first.end()); } //# microslice + numCompUsed++; + } // system STS + + if (systemId == fles::SubsystemIdentifier::MUCH) { + const uint16_t equipmentId = timeslice->descriptor(comp, 0).eq_id; + const auto algoIt = fAlgoMuch.find(equipmentId); + assert(algoIt != fAlgoMuch.end()); + + // The current algorithm works for the MUCH data format version XXXX (insert) used in XXXX. + // 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); // set for MUCH - compTimer.Stop(); - LOG(debug) << GetName() << ": Component " << comp << ", microslices " << numMsInComp << " input size " - << numBytesInComp << " bytes, " - << ", digis " << numDigisInComp << ", CPU time " << compTimer.CpuTime() * 1000. << " ms"; + // --- Microslice loop + numMsInComp = timeslice->num_microslices(comp); + for (uint64_t mslice = 0; mslice < numMsInComp; mslice++) { + const auto msDescriptor = timeslice->descriptor(comp, mslice); + const auto msContent = timeslice->content(comp, mslice); + numBytesInComp += msDescriptor.size; + auto result = (algoIt->second)(msContent, msDescriptor, timeslice->start_time()); + LOG(debug1) << GetName() << ": Component " << comp << ", microslice " << mslice << ", digis " + << result.first.size() << ", errors " << result.second.fNumNonHitOrTsbMessage << " | " + << result.second.fNumErrElinkOutOfRange << " | " << result.second.fNumErrInvalidFirstMessage + << " | " << result.second.fNumErrInvalidMsSize << " | " << result.second.fNumErrTimestampOverflow + << " | "; + numDigisInComp += result.first.size(); +#pragma omp critical(insert_much_digis) + fTimeslice->fData.fMuch.fDigis.insert(fTimeslice->fData.fMuch.fDigis.end(), result.first.begin(), + result.first.end()); + } //# microslice numCompUsed++; - numBytes += numBytesInComp; - numDigis += numDigisInComp; - numMs += numMsInComp; + } // system MUCH - } //? system (only STS) + compTimer.Stop(); + LOG(debug) << GetName() << ": Component " << comp << ", microslices " << numMsInComp << " input size " + << numBytesInComp << " bytes, " + << ", digis " << numDigisInComp << ", CPU time " << compTimer.CpuTime() * 1000. << " ms"; + + numBytes += numBytesInComp; + numDigis += numDigisInComp; + numMs += numMsInComp; } //# component @@ -129,9 +164,13 @@ void CbmTaskUnpack::Exec(Option_t*) #ifdef WITH_EXECUTION std::sort(std::execution::par_unseq, fTimeslice->fData.fSts.fDigis.begin(), fTimeslice->fData.fSts.fDigis.end(), [](CbmStsDigi digi1, CbmStsDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(std::execution::par_unseq, fTimeslice->fData.fMuch.fDigis.begin(), fTimeslice->fData.fMuch.fDigis.end(), + [](CbmMuchDigi digi1, CbmMuchDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); #else std::sort(fTimeslice->fData.fSts.fDigis.begin(), fTimeslice->fData.fSts.fDigis.end(), [](CbmStsDigi digi1, CbmStsDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(fTimeslice->fData.fMuch.fDigis.begin(), fTimeslice->fData.fMuch.fDigis.end(), + [](CbmMuchDigi digi1, CbmMuchDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); #endif // --- Timeslice log @@ -202,16 +241,16 @@ InitStatus CbmTaskUnpack::Init() ioman->RegisterAny("DigiTimeslice.", fTimeslice, IsOutputBranchPersistent("DigiTimeslice.")); LOG(info) << "--- Registered branch DigiTimeslice."; - // --- Common parameters for all components - uint32_t numChansPerAsic = 128; // R/O channels per ASIC - uint32_t numAsicsPerModule = 16; // Number of ASICs per module + // --- Common parameters for all components for STS + uint32_t numChansPerAsicSts = 128; // R/O channels per ASIC for STS + uint32_t numAsicsPerModuleSts = 16; // Number of ASICs per module for STS - // Create one algorithm per component and configure it with parameters - auto equipIds = fStsConfig.GetEquipmentIds(); - for (auto& equip : equipIds) { + // Create one algorithm per component for STS and configure it with parameters + auto equipIdsSts = fStsConfig.GetEquipmentIds(); + for (auto& equip : equipIdsSts) { std::unique_ptr<UnpackStsPar> par(new UnpackStsPar()); - par->fNumChansPerAsic = numChansPerAsic; - par->fNumAsicsPerModule = numAsicsPerModule; + par->fNumChansPerAsic = numChansPerAsicSts; + par->fNumAsicsPerModule = numAsicsPerModuleSts; const size_t numElinks = fStsConfig.GetNumElinks(equip); for (size_t elink = 0; elink < numElinks; elink++) { UnpackStsElinkPar elinkPar; @@ -228,6 +267,24 @@ InitStatus CbmTaskUnpack::Init() LOG(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; } //# equipments + // --- Common parameters for all components for MUCH + uint32_t numChansPerAsicMuch = 128; // R/O channels per ASIC for MUCH + + // Create one algorithm per component and configure it with parameters + auto equipIdsMuch = fMuchConfig.GetEquipmentIds(); + for (auto& equip : equipIdsMuch) { + std::unique_ptr<UnpackMuchPar> par(new UnpackMuchPar()); + par->fNumChansPerAsic = numChansPerAsicMuch; + const size_t numElinks = fMuchConfig.GetNumElinks(equip); + for (size_t elink = 0; elink < numElinks; elink++) { + UnpackMuchElinkPar elinkPar; + elinkPar.fAddress = fMuchConfig.Map(equip, elink); // Vector of MUCH addresses for this elink + elinkPar.fTimeOffset = 0.; + } + fAlgoMuch[equip].SetParams(std::move(par)); + LOG(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; + } + LOG(info) << "--- Configured " << fAlgoSts.size() << " unpacker algorithms for STS."; LOG(debug) << "Readout map:" << fStsConfig.PrintReadoutMap(); LOG(info) << "=================================================="; diff --git a/reco/tasks/CbmTaskUnpack.h b/reco/tasks/CbmTaskUnpack.h index 541a749a7bbbcc286d98b8e339aadf5362d498e3..940ee17c3378af45ceffe641bcaf5039d6ff82d6 100644 --- a/reco/tasks/CbmTaskUnpack.h +++ b/reco/tasks/CbmTaskUnpack.h @@ -15,7 +15,9 @@ #include <vector> #include "EventBuilder.h" +#include "MuchReadoutConfig.h" #include "StsReadoutConfig.h" +#include "UnpackMuch.h" #include "UnpackSts.h" class CbmDigiManager; @@ -67,9 +69,14 @@ private: // methods private: // members - CbmSourceTs* fSource = nullptr; + CbmSourceTs* fSource = nullptr; + std::map<uint16_t, cbm::algo::UnpackSts> fAlgoSts = {}; cbm::algo::StsReadoutConfig fStsConfig {}; + + std::map<uint16_t, cbm::algo::UnpackMuch> fAlgoMuch = {}; + cbm::algo::MuchReadoutConfig fMuchConfig {}; + size_t fNumTs = 0; size_t fNumMs = 0; size_t fNumBytes = 0;