From f4496fb30c2dbee5f13360996b405f63af9a1e36 Mon Sep 17 00:00:00 2001
From: Dominik Smith <smith@th.physik.uni-frankfurt.de>
Date: Thu, 13 Apr 2023 13:32:27 +0200
Subject: [PATCH] UnpackMuchXpu: Added unpacker to CbmTaskUnpackXpu.

---
 algo/detectors/much/MuchReadoutConfig.cxx | 25 +++++++++++
 algo/detectors/much/MuchReadoutConfig.h   | 12 ++++++
 algo/detectors/much/UnpackMuchXpu.cxx     |  6 +++
 algo/detectors/much/UnpackMuchXpu.h       |  6 +--
 reco/tasks/CbmTaskUnpack.cxx              |  2 +
 reco/tasks/CbmTaskUnpackXpu.cxx           | 51 +++++++++++++++++++++++
 reco/tasks/CbmTaskUnpackXpu.h             |  6 ++-
 7 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/algo/detectors/much/MuchReadoutConfig.cxx b/algo/detectors/much/MuchReadoutConfig.cxx
index 0469b1d86a..f8d0f65851 100644
--- a/algo/detectors/much/MuchReadoutConfig.cxx
+++ b/algo/detectors/much/MuchReadoutConfig.cxx
@@ -42,6 +42,31 @@ namespace cbm::algo
   }
   // ------------------------------------------------------------------------------------
 
+  // ---   Total number of elinks for MUCH   --------------------------------------------
+  size_t MuchReadoutConfig::GetNumElinks()
+  {
+    size_t result = 0;
+    for (auto& entry : fReadoutMap) {
+      result += entry.second.size();
+    }
+    return result;
+  }
+  // ------------------------------------------------------------------------------------
+
+
+  // ---   Total number of channels for MUCH   ------------------------------------------
+  size_t MuchReadoutConfig::GetNumChans()
+  {
+    size_t result = 0;
+    for (auto& entry : fReadoutMap) {
+      for (auto& chans : entry.second) {
+        result += chans.size();
+      }
+    }
+    return result;
+  }
+  // ------------------------------------------------------------------------------------
+
 
   // ---  Mapping (equimentId, elink) -> address[channel]  ------------------------------
   std::vector<uint32_t> MuchReadoutConfig::Map(uint16_t equipmentId, uint16_t elinkId)
diff --git a/algo/detectors/much/MuchReadoutConfig.h b/algo/detectors/much/MuchReadoutConfig.h
index adeecddc9d..a70d2de1be 100644
--- a/algo/detectors/much/MuchReadoutConfig.h
+++ b/algo/detectors/much/MuchReadoutConfig.h
@@ -38,6 +38,18 @@ namespace cbm::algo
      **/
     size_t GetNumElinks(uint16_t equipmentId);
 
+
+    /** @brief Total number of elinks for MUCH
+     ** @return Number of elinks
+     **/
+    size_t GetNumElinks();
+
+
+    /** @brief Total number of channels for MUCH
+     ** @return Number of channels
+     **/
+    size_t GetNumChans();
+
     /** @brief API: Mapping from component and elink to addresses per channel
      ** @param equipId     Equipment identifier (component)
      ** @param elink       Elink number within component
diff --git a/algo/detectors/much/UnpackMuchXpu.cxx b/algo/detectors/much/UnpackMuchXpu.cxx
index 2cb97bbf25..8fcc81cf3e 100644
--- a/algo/detectors/much/UnpackMuchXpu.cxx
+++ b/algo/detectors/much/UnpackMuchXpu.cxx
@@ -44,6 +44,11 @@ namespace cbm::algo
       auto equip = equipIdsMuch[comp];
       // --- Loop over components in timeslice
       for (uint64_t tsComp = 0; tsComp < ts->num_components(); tsComp++) {
+
+        // --- Skip if TS component is not from MUCH (equipment IDs are non-unique across systems)
+        auto systemId = static_cast<fles::SubsystemIdentifier>(ts->descriptor(tsComp, 0).sys_id);
+        if (systemId != fles::SubsystemIdentifier::MUCH) continue;
+
         if (equip == ts->descriptor(tsComp, 0).eq_id) {
           const uint64_t numMsInComp = ts->num_microslices(tsComp);
           for (uint64_t mslice = 0; mslice < numMsInComp; mslice++) {
@@ -68,6 +73,7 @@ namespace cbm::algo
         }
       }
     }
+
     // --- Total number of microslices
     const uint64_t numMs = messCount.size();
 
diff --git a/algo/detectors/much/UnpackMuchXpu.h b/algo/detectors/much/UnpackMuchXpu.h
index 51468b867a..db3c38c403 100644
--- a/algo/detectors/much/UnpackMuchXpu.h
+++ b/algo/detectors/much/UnpackMuchXpu.h
@@ -45,10 +45,8 @@ namespace cbm::algo
    ** @brief Parameters required for the MUCH unpacking (specific to one component)
    **/
   struct UnpackMuchXpuPar {
-    uint32_t fNumChansPerAsic   = 0;  ///< Number of channels per ASIC
-    uint32_t fNumAsicsPerModule = 0;  ///< Number of ASICS per module
-    uint32_t fNumElinks         = 0;  ///< Number of elinks for this component
-    uint32_t fElinkOffset       = 0;  ///< Elink index offset for this component
+    uint32_t fNumElinks   = 0;  ///< Number of elinks for this component
+    uint32_t fElinkOffset = 0;  ///< Elink index offset for this component
   };
 
 
diff --git a/reco/tasks/CbmTaskUnpack.cxx b/reco/tasks/CbmTaskUnpack.cxx
index a5b8926b88..d4ab231369 100644
--- a/reco/tasks/CbmTaskUnpack.cxx
+++ b/reco/tasks/CbmTaskUnpack.cxx
@@ -415,6 +415,8 @@ InitStatus CbmTaskUnpack::Init()
   }
 
   LOG(info) << "--- Configured " << fAlgoSts.size() << " unpacker algorithms for STS.";
+  LOG(info) << "--- Configured " << fAlgoMuch.size() << " unpacker algorithms for MUCH.";
+
   LOG(debug) << "Readout map:" << fStsConfig.PrintReadoutMap();
   LOG(info) << "--- Configured " << fAlgoMuch.size() << " unpacker algorithms for MUCH.";
   LOG(info) << "--- Configured " << fAlgoTof.size() << " unpacker algorithms for TOF.";
diff --git a/reco/tasks/CbmTaskUnpackXpu.cxx b/reco/tasks/CbmTaskUnpackXpu.cxx
index f095169d69..9ac33d7fdf 100644
--- a/reco/tasks/CbmTaskUnpackXpu.cxx
+++ b/reco/tasks/CbmTaskUnpackXpu.cxx
@@ -33,9 +33,12 @@
 #include <xpu/host.h>
 
 using namespace std;
+using cbm::algo::UnpackMuchXpuElinkPar;
+using cbm::algo::UnpackMuchXpuPar;
 using cbm::algo::UnpackStsXpuElinkPar;
 using cbm::algo::UnpackStsXpuPar;
 
+
 // -----   Constructor   -----------------------------------------------------
 CbmTaskUnpackXpu::CbmTaskUnpackXpu() : FairTask("Unpack") {}
 // ---------------------------------------------------------------------------
@@ -69,13 +72,22 @@ void CbmTaskUnpackXpu::Exec(Option_t*)
   fTimeslice->fData.fSts.fDigis.insert(fTimeslice->fData.fSts.fDigis.end(), resultSts.first.begin(),
                                        resultSts.first.end());
 
+  //Run MUCH unpacker and store result
+  auto resultMuch = fAlgoMuchXpu(timeslice, fMuchConfig);
+  fTimeslice->fData.fMuch.fDigis.insert(fTimeslice->fData.fMuch.fDigis.end(), resultMuch.first.begin(),
+                                        resultMuch.first.end());
+
   // --- 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(); });
 #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
@@ -180,6 +192,45 @@ InitStatus CbmTaskUnpackXpu::Init()
   xpu::copy(fAlgoStsXpu.fParams, xpu::host_to_device);
   xpu::copy(fAlgoStsXpu.fElinkParams, xpu::host_to_device);
 
+  // Initialize parameter buffers for MUCH
+  auto equipIdsMuch           = fMuchConfig.GetEquipmentIds();
+  const size_t numMuchElinks  = fMuchConfig.GetNumElinks();
+  const size_t numMuchChans   = fMuchConfig.GetNumChans();
+  const size_t numMuchComps   = equipIdsMuch.size();
+  fAlgoMuchXpu.fParams        = xpu::hd_buffer<UnpackMuchXpuPar>(numMuchComps);
+  fAlgoMuchXpu.fElinkParams   = xpu::hd_buffer<UnpackMuchXpuElinkPar>(numMuchElinks);
+  fAlgoMuchXpu.fChanAddresses = xpu::hd_buffer<uint32_t>(numMuchChans);
+
+  // Persistent variables to track channel offsets across MUCH components and elinks
+  size_t lastMuchChanOffset = 0;
+  size_t lastMuchNumChans   = 0;
+
+  // Fill parameter buffers for MUCH
+  for (size_t comp = 0; comp < numMuchComps; comp++) {
+    auto equip                = equipIdsMuch[comp];
+    auto params               = fAlgoMuchXpu.fParams.h();
+    auto numElinks            = fMuchConfig.GetNumElinks(equip);
+    params[comp].fNumElinks   = numElinks;
+    params[comp].fElinkOffset = (comp == 0) ? 0 : params[comp - 1].fElinkOffset + params[comp - 1].fNumElinks;
+    for (size_t elink = 0; elink < numElinks; elink++) {
+      UnpackMuchXpuElinkPar& elinkPar = fAlgoMuchXpu.fElinkParams.h()[params[comp].fElinkOffset + elink];
+      auto chanAddresses              = fMuchConfig.Map(equip, elink);
+      size_t numChans                 = chanAddresses.size();
+      elinkPar.fNumChans              = numChans;
+      elinkPar.fTimeOffset            = 0.;
+      elinkPar.fChanOffset            = (comp == 0 && elink == 0) ? 0 : lastMuchChanOffset + lastMuchNumChans;
+      for (size_t chan = 0; chan < numChans; chan++) {
+        fAlgoMuchXpu.fChanAddresses.h()[elinkPar.fChanOffset + chan] = chanAddresses[chan];
+      }
+      lastMuchChanOffset = elinkPar.fChanOffset;
+      lastMuchNumChans   = elinkPar.fNumChans;
+    }
+    LOG(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks";
+  }
+  xpu::copy(fAlgoMuchXpu.fParams, xpu::host_to_device);
+  xpu::copy(fAlgoMuchXpu.fElinkParams, xpu::host_to_device);
+  xpu::copy(fAlgoMuchXpu.fChanAddresses, xpu::host_to_device);
+
   return kSUCCESS;
 }
 // ----------------------------------------------------------------------------
diff --git a/reco/tasks/CbmTaskUnpackXpu.h b/reco/tasks/CbmTaskUnpackXpu.h
index fe51c61dae..aa1a1d46fe 100644
--- a/reco/tasks/CbmTaskUnpackXpu.h
+++ b/reco/tasks/CbmTaskUnpackXpu.h
@@ -15,10 +15,11 @@
 #include <vector>
 
 #include "EventBuilder.h"
+#include "MuchReadoutConfig.h"
 #include "StsReadoutConfig.h"
+#include "UnpackMuchXpu.h"
 #include "UnpackStsXpu.h"
 
-
 class CbmDigiManager;
 class CbmSourceTs;
 
@@ -72,6 +73,9 @@ private:  // members
   cbm::algo::UnpackStsXpu fAlgoStsXpu;
   cbm::algo::StsReadoutConfig fStsConfig {};
 
+  cbm::algo::UnpackMuchXpu fAlgoMuchXpu;
+  cbm::algo::MuchReadoutConfig fMuchConfig {};
+
   size_t fNumTs                = 0;
   size_t fNumMs                = 0;
   size_t fNumBytes             = 0;
-- 
GitLab