diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index dbb8289793b3aeed18deb52e33abccf7edebb082..6a3fef593e8976cd5b4fe579b93d8e10fa67e904 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -18,6 +18,7 @@ set(SRCS evbuild/EventBuilder.cxx trigger/TimeClusterTrigger.cxx evselector/DigiEventSelector.cxx + unpack/Unpack.cxx detectors/sts/ReadoutConfig.cxx detectors/sts/StsHitfinderChain.cxx detectors/sts/StsReadoutConfigLegacy.cxx @@ -64,6 +65,7 @@ target_include_directories(Algo ${CMAKE_CURRENT_SOURCE_DIR}/global ${CMAKE_CURRENT_SOURCE_DIR}/trigger ${CMAKE_CURRENT_SOURCE_DIR}/evselector + ${CMAKE_CURRENT_SOURCE_DIR}/unpack ${CMAKE_CURRENT_SOURCE_DIR}/detectors/sts ${CMAKE_CURRENT_SOURCE_DIR}/detectors/much ${CMAKE_CURRENT_SOURCE_DIR}/detectors/tof diff --git a/algo/unpack/Unpack.cxx b/algo/unpack/Unpack.cxx new file mode 100644 index 0000000000000000000000000000000000000000..db3a356ac772cbb957ab06f5b2ee7f2efae103de --- /dev/null +++ b/algo/unpack/Unpack.cxx @@ -0,0 +1,282 @@ +/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + + +#include "Unpack.h" + +#include <chrono> + +#include "AlgoFairloggerCompat.h" + +#ifdef WITH_EXECUTION +#include <execution> +#endif + +using namespace std; + +namespace cbm::algo +{ + // ----- Execution ------------------------------------------------------- + Unpack::resultType Unpack::operator()(const fles::Timeslice* timeslice) + { + // --- Output data + resultType result = {}; + CbmDigiTimeslice& digiTs = result.first; + UnpackMonitorData& monitor = result.second; + + // --- Component loop + for (uint64_t comp = 0; comp < timeslice->num_components(); comp++) { + + // System ID of current component + const auto systemId = static_cast<fles::SubsystemIdentifier>(timeslice->descriptor(comp, 0).sys_id); + + // Equipment ID of current component + const uint16_t equipmentId = timeslice->descriptor(comp, 0).eq_id; + + // The current algorithms work for the format versions hard-coded as parameters to MsLoop() below. + // Other versions are not yet supported. + // In the future, different data formats will be supported by instantiating different + // algorithms depending on the version. + + if (systemId == fles::SubsystemIdentifier::STS) { + MsLoop(timeslice, fAlgoSts, comp, equipmentId, &digiTs.fData.fSts.fDigis, monitor, &monitor.fSts, 0x20); + } + if (systemId == fles::SubsystemIdentifier::MUCH) { + MsLoop(timeslice, fAlgoMuch, comp, equipmentId, &digiTs.fData.fMuch.fDigis, monitor, &monitor.fMuch, 0x20); + } + if (systemId == fles::SubsystemIdentifier::RPC) { + MsLoop(timeslice, fAlgoTof, comp, equipmentId, &digiTs.fData.fTof.fDigis, monitor, &monitor.fTof, 0x00); + } + if (systemId == fles::SubsystemIdentifier::T0) { + MsLoop(timeslice, fAlgoBmon, comp, equipmentId, &digiTs.fData.fT0.fDigis, monitor, &monitor.fBmon, 0x00); + } + if (systemId == fles::SubsystemIdentifier::TRD) { + MsLoop(timeslice, fAlgoTrd, comp, equipmentId, &digiTs.fData.fTrd.fDigis, monitor, &monitor.fTrd, 0x01); + } + if (systemId == fles::SubsystemIdentifier::TRD2D) { + MsLoop(timeslice, fAlgoTrd2d, comp, equipmentId, &digiTs.fData.fTrd2d.fDigis, monitor, &monitor.fTrd2d, 0x02); + } + } //# component + + // --- Sorting of output digis. Is required by both digi trigger and event builder. +#ifdef WITH_EXECUTION + std::sort(std::execution::par_unseq, digiTs.fData.fSts.fDigis.begin(), digiTs.fData.fSts.fDigis.end(), + [](CbmStsDigi digi1, CbmStsDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(std::execution::par_unseq, digiTs.fData.fMuch.fDigis.begin(), digiTs.fData.fMuch.fDigis.end(), + [](CbmMuchDigi digi1, CbmMuchDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(std::execution::par_unseq, digiTs.fData.fTof.fDigis.begin(), digiTs.fData.fTof.fDigis.end(), + [](CbmTofDigi digi1, CbmTofDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(std::execution::par_unseq, digiTs.fData.fT0.fDigis.begin(), digiTs.fData.fT0.fDigis.end(), + [](CbmTofDigi digi1, CbmTofDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(std::execution::par_unseq, digiTs.fData.fTrd.fDigis.begin(), digiTs.fData.fTrd.fDigis.end(), + [](CbmTrdDigi digi1, CbmTrdDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(std::execution::par_unseq, digiTs.fData.fTrd2d.fDigis.begin(), digiTs.fData.fTrd2d.fDigis.end(), + [](CbmTrdDigi digi1, CbmTrdDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); +#else + std::sort(digiTs.fData.fSts.fDigis.begin(), digiTs.fData.fSts.fDigis.end(), + [](CbmStsDigi digi1, CbmStsDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(digiTs.fData.fMuch.fDigis.begin(), digiTs.fData.fMuch.fDigis.end(), + [](CbmMuchDigi digi1, CbmMuchDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(digiTs.fData.fTof.fDigis.begin(), digiTs.fData.fTof.fDigis.end(), + [](CbmTofDigi digi1, CbmTofDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(digiTs.fData.fT0.fDigis.begin(), digiTs.fData.fT0.fDigis.end(), + [](CbmTofDigi digi1, CbmTofDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(digiTs.fData.fTrd.fDigis.begin(), digiTs.fData.fTrd.fDigis.end(), + [](CbmTrdDigi digi1, CbmTrdDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); + std::sort(digiTs.fData.fTrd2d.fDigis.begin(), digiTs.fData.fTrd2d.fDigis.end(), + [](CbmTrdDigi digi1, CbmTrdDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); +#endif + return result; + } + // ---------------------------------------------------------------------------- + + // ----------------- Microslice loop ------------------------------------------ + template<class Digi, class UnpackAlgo, class MonitorData> + void Unpack::MsLoop(const fles::Timeslice* timeslice, std::map<uint16_t, UnpackAlgo>& algoMap, const uint64_t comp, + const uint16_t eqId, std::vector<Digi>* digis, UnpackMonitorData& monitor, + std::vector<MonitorData>* monitorMs, uint8_t sys_ver) + { + // --- Component log + size_t numBytesInComp = 0; + size_t numDigisInComp = 0; + + // For profiling + const auto starttime = std::chrono::high_resolution_clock::now(); + + // Get Unpacker + const auto algoIt = algoMap.find(eqId); + assert(algoIt != algoMap.end()); + UnpackAlgo& algo = algoIt->second; + + assert(timeslice->descriptor(comp, 0).sys_ver == sys_ver); + const uint64_t 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); + auto result = algo(msContent, msDescriptor, timeslice->start_time()); + L_(debug) << "Unpack::MsLoop(): Component " << comp << ", microslice " << mslice << ", digis " + << result.first.size() << ", " << result.second.print(); + numBytesInComp += msDescriptor.size; + numDigisInComp += result.first.size(); + digis->insert(digis->end(), result.first.begin(), result.first.end()); + monitorMs->push_back(result.second); + } + // Get elapsed time + const auto endtime = std::chrono::high_resolution_clock::now(); + const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(endtime - starttime); + + L_(debug) << "Unpack(): Component " << comp << ", subsystem " + << fles::to_string(static_cast<fles::SubsystemIdentifier>(timeslice->descriptor(comp, 0).sys_id)) + << ", microslices " << numMsInComp << " input size " << numBytesInComp << " bytes," + << " digis " << numDigisInComp << ", CPU time " << duration.count() / 1000. << " ms"; + + monitor.fNumMs += numMsInComp; + monitor.fNumBytes += numBytesInComp; + monitor.fNumDigis += numDigisInComp; + monitor.fNumCompUsed++; + } + // ---------------------------------------------------------------------------- + + // ----- Initialisation --------------------------------------------------- + bool Unpack::Init() + { + // --- 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 for STS and configure it with parameters + auto equipIdsSts = fStsConfig.GetEquipmentIds(); + for (auto& equip : equipIdsSts) { + std::unique_ptr<UnpackStsPar> par(new UnpackStsPar()); + par->fNumChansPerAsic = numChansPerAsicSts; + par->fNumAsicsPerModule = numAsicsPerModuleSts; + const size_t numElinks = fStsConfig.GetNumElinks(equip); + for (size_t elink = 0; elink < numElinks; elink++) { + UnpackStsElinkPar elinkPar; + auto mapEntry = fStsConfig.Map(equip, elink); + elinkPar.fAddress = mapEntry.first; // Module address for this elink + elinkPar.fAsicNr = mapEntry.second; // ASIC number within module + elinkPar.fTimeOffset = 0.; + elinkPar.fAdcOffset = 1.; + elinkPar.fAdcGain = 1.; + // TODO: Add parameters for time and ADC calibration + par->fElinkParams.push_back(elinkPar); + } + fAlgoSts[equip].SetParams(std::move(par)); + L_(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; + } //# equipments + + // Create one algorithm per component for MUCH and configure it with parameters + auto equipIdsMuch = fMuchConfig.GetEquipmentIds(); + for (auto& equip : equipIdsMuch) { + std::unique_ptr<UnpackMuchPar> par(new UnpackMuchPar()); + 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.; + par->fElinkParams.push_back(elinkPar); + } + fAlgoMuch[equip].SetParams(std::move(par)); + L_(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; + } + + // Create one algorithm per component for TOF and configure it with parameters + auto equipIdsTof = fTofConfig.GetEquipmentIds(); + for (auto& equip : equipIdsTof) { + std::unique_ptr<UnpackTofPar> par(new UnpackTofPar()); + const size_t numElinks = fTofConfig.GetNumElinks(equip); + for (size_t elink = 0; elink < numElinks; elink++) { + UnpackTofElinkPar elinkPar; + elinkPar.fChannelUId = fTofConfig.Map(equip, elink); // Vector of TOF addresses for this elink + elinkPar.fTimeOffset = 0.; + par->fElinkParams.push_back(elinkPar); + } + fAlgoTof[equip].SetParams(std::move(par)); + L_(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; + } + + // Create one algorithm per component for T0 and configure it with parameters + auto equipIdsBmon = fBmonConfig.GetEquipmentIds(); + for (auto& equip : equipIdsBmon) { + std::unique_ptr<UnpackBmonPar> par(new UnpackBmonPar()); + const size_t numElinks = fBmonConfig.GetNumElinks(equip); + for (size_t elink = 0; elink < numElinks; elink++) { + UnpackBmonElinkPar elinkPar; + elinkPar.fChannelUId = fBmonConfig.Map(equip, elink); // Vector of T0 addresses for this elink + elinkPar.fTimeOffset = 0.; + par->fElinkParams.push_back(elinkPar); + } + fAlgoBmon[equip].SetParams(std::move(par)); + L_(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; + } + + // Create one algorithm per component for TRD and configure it with parameters + auto equipIdsTrd = fTrdConfig.GetEquipmentIds(); + for (auto& equip : equipIdsTrd) { + + std::unique_ptr<UnpackTrdPar> par(new UnpackTrdPar()); + const size_t numCrobs = fTrdConfig.GetNumCrobs(equip); + + for (size_t crob = 0; crob < numCrobs; crob++) { + UnpackTrdCrobPar crobPar; + const size_t numElinks = fTrdConfig.GetNumElinks(equip, crob); + + for (size_t elink = 0; elink < numElinks; elink++) { + UnpackTrdElinkPar elinkPar; + auto addresses = fTrdConfig.Map(equip, crob, elink); + elinkPar.fAddress = addresses.first; // Asic address for this elink + elinkPar.fChanAddress = addresses.second; // Channel addresses for this elink + crobPar.fElinkParams.push_back(elinkPar); + } + par->fCrobParams.push_back(crobPar); + } + fAlgoTrd[equip].SetParams(std::move(par)); + L_(info) << "--- Configured equipment " << equip << " with " << numCrobs << " crobs"; + } + + // Create one algorithm per component for TRD2D and configure it with parameters + auto equipIdsTrd2d = fTrd2dConfig.GetEquipmentIds(); + for (auto& equip : equipIdsTrd2d) { + + std::unique_ptr<UnpackTrd2dPar> par(new UnpackTrd2dPar()); + const size_t numAsics = fTrd2dConfig.GetNumAsics(equip); + + for (size_t asic = 0; asic < numAsics; asic++) { + UnpackTrd2dAsicPar asicPar; + const size_t numChans = fTrd2dConfig.GetNumChans(equip, asic); + + for (size_t chan = 0; chan < numChans; chan++) { + UnpackTrd2dChannelPar chanPar; + auto pars = fTrd2dConfig.ChanMap(equip, asic, chan); + chanPar.fPadAddress = std::get<0>(pars); // Pad address for channel + chanPar.fHasPairingR = std::get<1>(pars); // Flag for R or T compoment + chanPar.fDaqOffset = std::get<2>(pars); // Time calibration parameter + asicPar.fChanParams.push_back(chanPar); + } + auto comppars = fTrd2dConfig.CompMap(equip); + par->fModId = comppars.first; + par->fCrobId = comppars.second; + par->fAsicParams.push_back(asicPar); + } + fAlgoTrd2d[equip].SetParams(std::move(par)); + L_(info) << "--- Configured equipment " << equip << " with " << numAsics << " asics"; + } + + L_(info) << "--- Configured " << fAlgoSts.size() << " unpacker algorithms for STS."; + L_(debug) << "Readout map:" << fStsConfig.PrintReadoutMap(); + L_(info) << "--- Configured " << fAlgoMuch.size() << " unpacker algorithms for MUCH."; + L_(info) << "--- Configured " << fAlgoTof.size() << " unpacker algorithms for TOF."; + L_(info) << "--- Configured " << fAlgoTrd.size() << " unpacker algorithms for TRD."; + L_(info) << "--- Configured " << fAlgoTrd2d.size() << " unpacker algorithms for TRD2D."; + L_(info) << "--- Configured " << fAlgoBmon.size() << " unpacker algorithms for T0."; + L_(info) << "=================================================="; + + return true; + } + // ---------------------------------------------------------------------------- + + +} /* namespace cbm::algo */ diff --git a/algo/unpack/Unpack.h b/algo/unpack/Unpack.h new file mode 100644 index 0000000000000000000000000000000000000000..7bf24abfb961f75ad9ac3d76d1963192302ca603 --- /dev/null +++ b/algo/unpack/Unpack.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese, Dominik Smith [committer] */ + + +#ifndef UNPACK_H +#define UNPACK_H 1 + +#include "CbmDigiTimeslice.h" + +#include "TofReadoutConfig.h" +#include "Trd2dReadoutConfig.h" +#include "TrdReadoutConfig.h" + +#include <sstream> +#include <vector> + +#include "BmonReadoutConfig.h" +#include "MuchReadoutConfig.h" +#include "StsReadoutConfigLegacy.h" +#include "UnpackBmon.h" +#include "UnpackMuch.h" +#include "UnpackSts.h" +#include "UnpackTof.h" +#include "UnpackTrd.h" +#include "UnpackTrd2d.h" + +namespace cbm::algo +{ + + /** @struct UnpackMonitorData + ** @author Dominik Smith <d.smith@gsi.de> + ** @since 2 Jun 2023 + ** @brief Monitoring data for unpacking + **/ + struct UnpackMonitorData { + std::vector<UnpackStsMonitorData> fSts; ///< Monitoring data for STS + std::vector<UnpackMuchMonitorData> fMuch; ///< Monitoring data for MUCH + std::vector<UnpackTofMonitorData> fTof; ///< Monitoring data for TOF + std::vector<UnpackBmonMonitorData> fBmon; ///< Monitoring data for T0 + std::vector<UnpackTrdMonitorData> fTrd; ///< Monitoring data for TRD + std::vector<UnpackTrd2dMonitorData> fTrd2d; ///< Monitoring data for TRD2D + size_t fNumMs = 0; + size_t fNumBytes = 0; + size_t fNumDigis = 0; + size_t fNumCompUsed = 0; + std::string print() + { + std::stringstream ss; + ss << "TS stats: num MS " << fNumMs << ", bytes " << fNumBytes << ", digis " << fNumDigis << ", components " + << fNumCompUsed << std::endl; + return ss.str(); + } + }; + + /** @class Unpack + ** @brief Algo class for unpacking digi timeslicess + ** @author Dominik Smith <d.smith@gsi.de> + ** @since 02.06.2023 + ** + **/ + class Unpack { + + public: + typedef std::pair<CbmDigiTimeslice, UnpackMonitorData> resultType; + + /** @brief Algorithm execution + ** @param fles timeslice to unpack + ** @return pair: digi timeslice, monitoring data + **/ + resultType operator()(const fles::Timeslice* timeslice); + + /** @brief Default constructor **/ + Unpack() {}; + + /** @brief Destructor **/ + ~Unpack() {}; + + /** @brief Parameters for STS unpackers **/ + StsReadoutConfigLegacy fStsConfig {}; + + /** @brief Parameters for MUCH unpackers **/ + MuchReadoutConfig fMuchConfig {}; + + /** @brief Parameters for TOF unpackers **/ + TofReadoutConfig fTofConfig {}; + + /** @brief Parameters for T0 unpackers **/ + BmonReadoutConfig fBmonConfig {}; + + /** @brief Parameters for TRD unpackers **/ + TrdReadoutConfig fTrdConfig {}; + + /** @brief Parameters for TRD2D unpackers **/ + Trd2dReadoutConfig fTrd2dConfig {}; + + /** @brief Initialize unpackers and fill parameters from config objects **/ + bool Init(); + + private: // methods + /** @brief Microslice loop **/ + template<class Digi, class UnpackAlgo, class MonitorData> + void MsLoop(const fles::Timeslice* timeslice, std::map<uint16_t, UnpackAlgo>& algoMap, const uint64_t comp, + const uint16_t eqId, std::vector<Digi>* digis, UnpackMonitorData& monitor, + std::vector<MonitorData>* monitorMs, uint8_t sys_ver); + + + private: // members + /** @brief STS unpackers **/ + std::map<uint16_t, UnpackSts> fAlgoSts = {}; + + /** @brief MUCH unpackers **/ + std::map<uint16_t, UnpackMuch> fAlgoMuch = {}; + + /** @brief TOF unpackers **/ + std::map<uint16_t, UnpackTof> fAlgoTof = {}; + + /** @brief T0 unpackers **/ + std::map<uint16_t, UnpackBmon> fAlgoBmon = {}; + + /** @brief TRD unpackers **/ + std::map<uint16_t, UnpackTrd> fAlgoTrd = {}; + + /** @brief TRD2D unpackers **/ + std::map<uint16_t, UnpackTrd2d> fAlgoTrd2d = {}; + }; +} // namespace cbm::algo + +#endif /* UNPACK_H */ diff --git a/reco/tasks/CbmTaskUnpack.cxx b/reco/tasks/CbmTaskUnpack.cxx index f1e06438ab13c4f78a8ea751089dc9ea4abbead4..6724a37b3c8d8f8b86f6898451fb4d372f7ef6d9 100644 --- a/reco/tasks/CbmTaskUnpack.cxx +++ b/reco/tasks/CbmTaskUnpack.cxx @@ -38,21 +38,6 @@ #include <vector> using namespace std; -using cbm::algo::UnpackBmonElinkPar; -using cbm::algo::UnpackBmonPar; -using cbm::algo::UnpackMuchElinkPar; -using cbm::algo::UnpackMuchPar; -using cbm::algo::UnpackStsElinkPar; -using cbm::algo::UnpackStsPar; -using cbm::algo::UnpackTofElinkPar; -using cbm::algo::UnpackTofPar; -using cbm::algo::UnpackTrd2dAsicPar; -using cbm::algo::UnpackTrd2dChannelPar; -using cbm::algo::UnpackTrd2dPar; -using cbm::algo::UnpackTrdCrobPar; -using cbm::algo::UnpackTrdElinkPar; -using cbm::algo::UnpackTrdPar; - // ----- Constructor ----------------------------------------------------- CbmTaskUnpack::CbmTaskUnpack() : FairTask("Unpack") {} @@ -67,29 +52,6 @@ CbmTaskUnpack::~CbmTaskUnpack() // --------------------------------------------------------------------------- -// ----------------- Microslice loop ------------------------------------------ -template<class Digi, class UnpackAlgo> -uint64_t CbmTaskUnpack::MsLoop(const fles::Timeslice* timeslice, UnpackAlgo& algo, const uint64_t comp, - std::vector<Digi>* digis, size_t* numBytesInComp, size_t* numDigisInComp) -{ - const uint64_t 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 = algo(msContent, msDescriptor, timeslice->start_time()); - LOG(debug1) << GetName() << ": Component " << comp << ", microslice " << mslice << ", digis " << result.first.size() - << ", " << result.second.print(); - *numDigisInComp += result.first.size(); -#pragma omp critical(insert_digis) - digis->insert(digis->end(), result.first.begin(), result.first.end()); - } - return numMsInComp; -} -// ---------------------------------------------------------------------------- - - // ----- Execution ------------------------------------------------------- void CbmTaskUnpack::Exec(Option_t*) { @@ -105,179 +67,10 @@ void CbmTaskUnpack::Exec(Option_t*) // --- Timer and counters TStopwatch timer; timer.Start(); - size_t numMs = 0; - size_t numBytes = 0; - size_t numDigis = 0; - uint64_t numCompUsed = 0; - - // --- Component loop -#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); - - // STS - 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); - - // --- Microslice loop - numMsInComp = - MsLoop(timeslice, algoIt->second, comp, &fTimeslice->fData.fSts.fDigis, &numBytesInComp, &numDigisInComp); - - numCompUsed++; - } // system STS - - // MUCH - 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 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); - - // --- Microslice loop - numMsInComp = - MsLoop(timeslice, algoIt->second, comp, &fTimeslice->fData.fMuch.fDigis, &numBytesInComp, &numDigisInComp); - - numCompUsed++; - } // system MUCH - - // TOF - if (systemId == fles::SubsystemIdentifier::RPC) { - const uint16_t equipmentId = timeslice->descriptor(comp, 0).eq_id; - const auto algoIt = fAlgoTof.find(equipmentId); - assert(algoIt != fAlgoTof.end()); - - // The current algorithm works for the TOF data format version XXXX 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 == XXXX); - - // --- Microslice loop - numMsInComp = - MsLoop(timeslice, algoIt->second, comp, &fTimeslice->fData.fTof.fDigis, &numBytesInComp, &numDigisInComp); - - numCompUsed++; - } // system TOF - - // Bmon - if (systemId == fles::SubsystemIdentifier::T0) { - const uint16_t equipmentId = timeslice->descriptor(comp, 0).eq_id; - const auto algoIt = fAlgoBmon.find(equipmentId); - assert(algoIt != fAlgoBmon.end()); - - // The current algorithm works for the T0 data format version XXXX 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 == XXXX); - - // --- Microslice loop - numMsInComp = - MsLoop(timeslice, algoIt->second, comp, &fTimeslice->fData.fT0.fDigis, &numBytesInComp, &numDigisInComp); - - numCompUsed++; - } // system T0 - - // system TRD - if (systemId == fles::SubsystemIdentifier::TRD) { - const uint16_t equipmentId = timeslice->descriptor(comp, 0).eq_id; - const auto algoIt = fAlgoTrd.find(equipmentId); - assert(algoIt != fAlgoTrd.end()); - - // The current algorithm works for the TRD data format version XXX used in 2022. - // 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 == XXX); To do: add something sensible here - - // --- Microslice loop - numMsInComp = - MsLoop(timeslice, algoIt->second, comp, &fTimeslice->fData.fTrd.fDigis, &numBytesInComp, &numDigisInComp); - - numCompUsed++; - } // system TRD - - // system TRD2D - if (systemId == fles::SubsystemIdentifier::TRD2D) { - const uint16_t equipmentId = timeslice->descriptor(comp, 0).eq_id; - const auto algoIt = fAlgoTrd2d.find(equipmentId); - assert(algoIt != fAlgoTrd2d.end()); - - // The current algorithm works for the TRD2D data format version XXX used in 2022. - // 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 == XXX); To do: add something sensible here - - // --- Microslice loop - numMsInComp = - MsLoop(timeslice, algoIt->second, comp, &fTimeslice->fData.fTrd2d.fDigis, &numBytesInComp, &numDigisInComp); - - numCompUsed++; - } // system TRD2D - - - 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 - - // --- Sorting of output digis. Is required by both digi trigger and event builder. -#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(); }); - std::sort(std::execution::par_unseq, fTimeslice->fData.fTof.fDigis.begin(), fTimeslice->fData.fTof.fDigis.end(), - [](CbmTofDigi digi1, CbmTofDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); - std::sort(std::execution::par_unseq, fTimeslice->fData.fT0.fDigis.begin(), fTimeslice->fData.fT0.fDigis.end(), - [](CbmTofDigi digi1, CbmTofDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); - std::sort(std::execution::par_unseq, fTimeslice->fData.fTrd.fDigis.begin(), fTimeslice->fData.fTrd.fDigis.end(), - [](CbmTrdDigi digi1, CbmTrdDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); - std::sort(std::execution::par_unseq, fTimeslice->fData.fTrd2d.fDigis.begin(), fTimeslice->fData.fTrd2d.fDigis.end(), - [](CbmTrdDigi digi1, CbmTrdDigi 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(); }); - std::sort(fTimeslice->fData.fTof.fDigis.begin(), fTimeslice->fData.fTof.fDigis.end(), - [](CbmTofDigi digi1, CbmTofDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); - std::sort(fTimeslice->fData.fT0.fDigis.begin(), fTimeslice->fData.fT0.fDigis.end(), - [](CbmTofDigi digi1, CbmTofDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); - std::sort(fTimeslice->fData.fTrd.fDigis.begin(), fTimeslice->fData.fTrd.fDigis.end(), - [](CbmTrdDigi digi1, CbmTrdDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); - std::sort(fTimeslice->fData.fTrd2d.fDigis.begin(), fTimeslice->fData.fTrd2d.fDigis.end(), - [](CbmTrdDigi digi1, CbmTrdDigi digi2) { return digi1.GetTime() < digi2.GetTime(); }); -#endif + + // --- Unpack the timeslice + auto result = fUnpack(timeslice); + *fTimeslice = std::move(result.first); // --- Timeslice log timer.Stop(); @@ -285,16 +78,17 @@ void CbmTaskUnpack::Exec(Option_t*) logOut << setw(15) << left << GetName() << " ["; logOut << fixed << setw(8) << setprecision(1) << right << timer.RealTime() * 1000. << " ms] "; logOut << "TS " << fNumTs << " (index " << timeslice->index() << ")"; - logOut << ", components " << numCompUsed << " / " << timeslice->num_components() << ", microslices " << numMs; - logOut << ", input rate " << double(numBytes) / timer.RealTime() / 1.e6 << " MB/s"; - logOut << ", digis " << numDigis; + logOut << ", components " << result.second.fNumCompUsed << " / " << timeslice->num_components(); + logOut << ", microslices " << result.second.fNumMs; + logOut << ", input rate " << double(result.second.fNumBytes) / timer.RealTime() / 1.e6 << " MB/s"; + logOut << ", digis " << result.second.fNumDigis; LOG(info) << logOut.str(); // --- Run statistics fNumTs++; - fNumMs += numMs; - fNumBytes += numBytes; - fNumDigis += numDigis; + fNumMs += result.second.fNumMs; + fNumBytes += result.second.fNumBytes; + fNumDigis += result.second.fNumDigis; fTime += timer.RealTime(); } // ---------------------------------------------------------------------------- @@ -345,144 +139,21 @@ InitStatus CbmTaskUnpack::Init() ioman->RegisterAny("DigiTimeslice.", fTimeslice, IsOutputBranchPersistent("DigiTimeslice.")); LOG(info) << "--- Registered branch DigiTimeslice."; - // --- 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 for STS and configure it with parameters - auto equipIdsSts = fStsConfig.GetEquipmentIds(); - for (auto& equip : equipIdsSts) { - std::unique_ptr<UnpackStsPar> par(new UnpackStsPar()); - par->fNumChansPerAsic = numChansPerAsicSts; - par->fNumAsicsPerModule = numAsicsPerModuleSts; - const size_t numElinks = fStsConfig.GetNumElinks(equip); - for (size_t elink = 0; elink < numElinks; elink++) { - UnpackStsElinkPar elinkPar; - auto mapEntry = fStsConfig.Map(equip, elink); - elinkPar.fAddress = mapEntry.first; // Module address for this elink - elinkPar.fAsicNr = mapEntry.second; // ASIC number within module - elinkPar.fTimeOffset = 0.; - elinkPar.fAdcOffset = 1.; - elinkPar.fAdcGain = 1.; - // TODO: Add parameters for time and ADC calibration - par->fElinkParams.push_back(elinkPar); - } - fAlgoSts[equip].SetParams(std::move(par)); - LOG(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; - } //# equipments - - // 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()); - 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.; - par->fElinkParams.push_back(elinkPar); - } - fAlgoMuch[equip].SetParams(std::move(par)); - LOG(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; - } - - // Create one algorithm per component and configure it with parameters - auto equipIdsTof = fTofConfig.GetEquipmentIds(); - for (auto& equip : equipIdsTof) { - std::unique_ptr<UnpackTofPar> par(new UnpackTofPar()); - const size_t numElinks = fTofConfig.GetNumElinks(equip); - for (size_t elink = 0; elink < numElinks; elink++) { - UnpackTofElinkPar elinkPar; - elinkPar.fChannelUId = fTofConfig.Map(equip, elink); // Vector of TOF addresses for this elink - elinkPar.fTimeOffset = 0.; - par->fElinkParams.push_back(elinkPar); - } - fAlgoTof[equip].SetParams(std::move(par)); - LOG(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; - } - - // Create one algorithm per component and configure it with parameters - auto equipIdsBmon = fBmonConfig.GetEquipmentIds(); - for (auto& equip : equipIdsBmon) { - std::unique_ptr<UnpackBmonPar> par(new UnpackBmonPar()); - const size_t numElinks = fBmonConfig.GetNumElinks(equip); - for (size_t elink = 0; elink < numElinks; elink++) { - UnpackBmonElinkPar elinkPar; - elinkPar.fChannelUId = fBmonConfig.Map(equip, elink); // Vector of T0 addresses for this elink - elinkPar.fTimeOffset = 0.; - par->fElinkParams.push_back(elinkPar); - } - fAlgoBmon[equip].SetParams(std::move(par)); - LOG(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks"; - } - - InitTrdReadoutConfig(); - auto equipIdsTrd = fTrdConfig.GetEquipmentIds(); - for (auto& equip : equipIdsTrd) { - - std::unique_ptr<UnpackTrdPar> par(new UnpackTrdPar()); - const size_t numCrobs = fTrdConfig.GetNumCrobs(equip); - - for (size_t crob = 0; crob < numCrobs; crob++) { - UnpackTrdCrobPar crobPar; - const size_t numElinks = fTrdConfig.GetNumElinks(equip, crob); - - for (size_t elink = 0; elink < numElinks; elink++) { - UnpackTrdElinkPar elinkPar; - auto addresses = fTrdConfig.Map(equip, crob, elink); - elinkPar.fAddress = addresses.first; // Asic address for this elink - elinkPar.fChanAddress = addresses.second; // Channel addresses for this elink - crobPar.fElinkParams.push_back(elinkPar); - } - par->fCrobParams.push_back(crobPar); - } - fAlgoTrd[equip].SetParams(std::move(par)); - LOG(info) << "--- Configured equipment " << equip << " with " << numCrobs << " crobs"; - } - - InitTrd2dReadoutConfig(); - auto equipIdsTrd2d = fTrd2dConfig.GetEquipmentIds(); - for (auto& equip : equipIdsTrd2d) { - - std::unique_ptr<UnpackTrd2dPar> par(new UnpackTrd2dPar()); - const size_t numAsics = fTrd2dConfig.GetNumAsics(equip); - - for (size_t asic = 0; asic < numAsics; asic++) { - UnpackTrd2dAsicPar asicPar; - const size_t numChans = fTrd2dConfig.GetNumChans(equip, asic); - - for (size_t chan = 0; chan < numChans; chan++) { - UnpackTrd2dChannelPar chanPar; - auto pars = fTrd2dConfig.ChanMap(equip, asic, chan); - chanPar.fPadAddress = std::get<0>(pars); // Pad address for channel - chanPar.fHasPairingR = std::get<1>(pars); // Flag for R or T compoment - chanPar.fDaqOffset = std::get<2>(pars); // Time calibration parameter - asicPar.fChanParams.push_back(chanPar); - } - auto comppars = fTrd2dConfig.CompMap(equip); - par->fModId = comppars.first; - par->fCrobId = comppars.second; - par->fAsicParams.push_back(asicPar); - } - fAlgoTrd2d[equip].SetParams(std::move(par)); - LOG(info) << "--- Configured equipment " << equip << " with " << numAsics << " asics"; - } - - LOG(info) << "--- Configured " << fAlgoSts.size() << " unpacker algorithms for STS."; - LOG(debug) << "Readout map:" << fStsConfig.PrintReadoutMap(); - LOG(info) << "--- Configured " << fAlgoMuch.size() << " unpacker algorithms for MUCH."; - LOG(info) << "--- Configured " << fAlgoTof.size() << " unpacker algorithms for TOF."; - LOG(info) << "--- Configured " << fAlgoBmon.size() << " unpacker algorithms for T0."; - - LOG(info) << "=================================================="; + // ---- Initialize unpacker + fUnpack.fTrdConfig = InitTrdReadoutConfig(); + fUnpack.fTrd2dConfig = InitTrd2dReadoutConfig(); + fUnpack.Init(); return kSUCCESS; } // ---------------------------------------------------------------------------- // ----- Initialisation --------------------------------------------------- -void CbmTaskUnpack::InitTrd2dReadoutConfig() +cbm::algo::Trd2dReadoutConfig CbmTaskUnpack::InitTrd2dReadoutConfig() { + // Output object + cbm::algo::Trd2dReadoutConfig Trd2dConfig; + // Initialize input files FairParAsciiFileIo asciiInput; std::string digiparfile = Form("%s/parameters/trd/trd_v22h_mcbm.digi.par", std::getenv("VMCWORKDIR")); @@ -504,7 +175,7 @@ void CbmTaskUnpack::InitTrd2dReadoutConfig() memcpy(crob_map[5], cmap, NCROBMOD * sizeof(uint16_t)); // only module Id 5 is used! // Then pass to Trd2dReadoutConfig, will invert to obain map (equipId) -> (module iq, crob id) - fTrd2dConfig.InitComponentMap(crob_map); + Trd2dConfig.InitComponentMap(crob_map); // FASP mapping update wrt the default setting (optional) std::map<uint32_t, uint8_t[NFASPMOD]> fasp_map; @@ -575,12 +246,16 @@ void CbmTaskUnpack::InitTrd2dReadoutConfig() } } - fTrd2dConfig.InitChannelMap(channelMap); + Trd2dConfig.InitChannelMap(channelMap); + return Trd2dConfig; } // ----- Initialisation --------------------------------------------------- -void CbmTaskUnpack::InitTrdReadoutConfig() +cbm::algo::TrdReadoutConfig CbmTaskUnpack::InitTrdReadoutConfig() { + // Output object + cbm::algo::TrdReadoutConfig TrdConfig; + std::string trdparfile = Form("%s/parameters/trd/trd_v21d_mcbm.asic.par", std::getenv("VMCWORKDIR")); CbmTrdParSetAsic trdpar; @@ -631,8 +306,9 @@ void CbmTaskUnpack::InitTrdReadoutConfig() << "address " << address << " key " << criId << " " << unsigned(crobId) << " " << unsigned(elinkId); } } - fTrdConfig.Init(addressMap, channelMap); - LOG(debug) << fTrdConfig.PrintReadoutMap(); + TrdConfig.Init(addressMap, channelMap); + LOG(debug) << TrdConfig.PrintReadoutMap(); + return TrdConfig; } diff --git a/reco/tasks/CbmTaskUnpack.h b/reco/tasks/CbmTaskUnpack.h index e686a2c8162000d14409480d6cd544d636ed09a6..d4262eb6bb9411987fa936c55dcdec3f318a51fb 100644 --- a/reco/tasks/CbmTaskUnpack.h +++ b/reco/tasks/CbmTaskUnpack.h @@ -11,23 +11,13 @@ #include <FairTask.h> -#include "TofReadoutConfig.h" #include "Trd2dReadoutConfig.h" #include "TrdReadoutConfig.h" #include <sstream> #include <vector> -#include "BmonReadoutConfig.h" -#include "EventBuilder.h" -#include "MuchReadoutConfig.h" -#include "StsReadoutConfigLegacy.h" -#include "UnpackBmon.h" -#include "UnpackMuch.h" -#include "UnpackSts.h" -#include "UnpackTof.h" -#include "UnpackTrd.h" -#include "UnpackTrd2d.h" +#include "Unpack.h" class CbmDigiManager; class CbmSourceTs; @@ -76,32 +66,19 @@ private: // methods /** @brief Task initialisation **/ virtual InitStatus Init(); + /** @brief Initialisation of address maps for Trd **/ - virtual void InitTrdReadoutConfig(); + cbm::algo::TrdReadoutConfig InitTrdReadoutConfig(); + /** @brief Initialisation of address maps for Trd2d **/ - virtual void InitTrd2dReadoutConfig(); + cbm::algo::Trd2dReadoutConfig InitTrd2dReadoutConfig(); private: // members CbmSourceTs* fSource = nullptr; - std::map<uint16_t, cbm::algo::UnpackSts> fAlgoSts = {}; - cbm::algo::StsReadoutConfigLegacy fStsConfig {}; - - std::map<uint16_t, cbm::algo::UnpackMuch> fAlgoMuch = {}; - cbm::algo::MuchReadoutConfig fMuchConfig {}; - - std::map<uint16_t, cbm::algo::UnpackTof> fAlgoTof = {}; - cbm::algo::TofReadoutConfig fTofConfig {}; - - std::map<uint16_t, cbm::algo::UnpackBmon> fAlgoBmon = {}; - cbm::algo::BmonReadoutConfig fBmonConfig {}; - - std::map<uint16_t, cbm::algo::UnpackTrd> fAlgoTrd = {}; - cbm::algo::TrdReadoutConfig fTrdConfig {}; - - std::map<uint16_t, cbm::algo::UnpackTrd2d> fAlgoTrd2d = {}; - cbm::algo::Trd2dReadoutConfig fTrd2dConfig {}; + /** @brief Unpacker algorithm **/ + cbm::algo::Unpack fUnpack; size_t fNumTs = 0; size_t fNumMs = 0; @@ -110,12 +87,7 @@ private: // members double fTime = 0.; CbmDigiTimeslice* fTimeslice = nullptr; ///< Output data - //Microslice loop - template<class Digi, class UnpackAlgo> - uint64_t MsLoop(const fles::Timeslice* timeslice, UnpackAlgo& algo, const uint64_t comp, std::vector<Digi>* digis, - size_t* numBytesInComp, size_t* numDigisInComp); - - ClassDef(CbmTaskUnpack, 2); + ClassDef(CbmTaskUnpack, 3); }; #endif /* CBMTASKUNPACK_H */