Skip to content
Snippets Groups Projects
Unpack.h 6.37 KiB
/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
   SPDX-License-Identifier: GPL-3.0-only
   Authors: Volker Friese, Dominik Smith [committer], Sebastian Heinemann, Felix Weiglhofer */


#ifndef UNPACK_H
#define UNPACK_H 1

#include "CbmDigiTimeslice.h"

#include "tof/TofReadoutConfig.h"
#include "tof/UnpackTof.h"
#include "trd/TrdReadoutConfig.h"
#include "trd/UnpackTrd.h"
#include "trd2d/Trd2dReadoutConfig.h"
#include "trd2d/UnpackTrd2d.h"

#include <optional>
#include <sstream>
#include <vector>

#include "bmon/BmonReadoutConfig.h"
#include "bmon/UnpackBmon.h"
#include "much/MuchReadoutConfig.h"
#include "much/UnpackMuch.h"
#include "rich/RichReadoutConfig.h"
#include "rich/UnpackRich.h"
#include "sts/Digi.h"
#include "sts/StsReadoutConfigLegacy.h"
#include "sts/UnpackSts.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
    std::vector<UnpackRichMonitorData> fRich;    ///< Monitoring data for RICH
    size_t fNumMs       = 0;
    size_t fNumBytes    = 0;
    size_t fNumDigis    = 0;
    size_t fNumCompUsed = 0;
    size_t fNumErrInvalidEqId   = 0;
    size_t fNumErrInvalidSysVer = 0;
    std::string print() const
    {
      std::stringstream ss;
      ss << "TS stats: num MS " << fNumMs << ", bytes " << fNumBytes << ", digis " << fNumDigis << ", components "
         << fNumCompUsed << ", invalidEqIds " << fNumErrInvalidEqId << ", invalidSysVersions " << fNumErrInvalidSysVer
         << 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;
    using Subsystem = fles::Subsystem;

    /** @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 Parameters for RICH unpackers **/
    RichReadoutConfig fRichConfig {};


    /**
     * @brief Set whether to apply walk correction. Must be set before Init(). (default: true)
    **/
    void SetApplyWalkCorrection(bool applyWalkCorrection) { fApplyWalkCorrection = applyWalkCorrection; }

    /** @brief Initialize unpackers and fill parameters from config objects
     * @param subIds: vector of subsystem identifiers to unpack, default: all
     * @see Init()
     **/
    void Init(std::vector<fles::Subsystem> subIds = {
                Subsystem::STS,
                Subsystem::MUCH,
                Subsystem::TOF,
                Subsystem::T0,
                Subsystem::TRD,
                Subsystem::TRD2D,
                Subsystem::RICH,
              });

    bool DetectorEnabled(Subsystem subsystem)
    {
      return std::find(fSubsystems.begin(), fSubsystems.end(), subsystem) != fSubsystems.end();
    }

  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);
    /** @brief Parallel microslice loop **/
    template<class Digi, class UnpackAlgo, class Monitor>
    void ParallelMsLoop(const Subsystem subsystem, std::vector<Digi>& digisOut,
                        std::vector<Monitor>& monitor, const fles::Timeslice& ts,
                        const std::map<u16, UnpackAlgo>& algos, u8 sys_ver);

    std::pair<size_t, size_t> ParallelInit(const fles::Timeslice& ts, Subsystem subsystem,
                                           std::vector<u16>& eqIds, std::vector<fles::MicrosliceDescriptor>& msDesc,
                                           std::vector<const u8*>& msContent);

    /** @brief Sort Digis and add bytes to timer for throughput */
    template<class Digi>
    void DoSort(std::vector<Digi>& digis);


  private:                                                  // members
    bool fApplyWalkCorrection                      = true;  ///< Apply walk correction
    std::vector<Subsystem> fSubsystems = {};    ///< Detector identifiers to unpack

    /** @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 = {};

    /** @brief RICH unpackers **/
    std::map<uint16_t, UnpackRich> fAlgoRich = {};

    /** @brief System time offsets **/
    std::map<Subsystem, int32_t> fSystemTimeOffset = {
      {Subsystem::STS, -970},  {Subsystem::MUCH, -980},
      {Subsystem::RICH, 100},  {Subsystem::TOF, 40},
      {Subsystem::T0, 0},      {Subsystem::TRD, 1300},
      {Subsystem::TRD2D, -510}};
  };
}  // namespace cbm::algo

#endif /* UNPACK_H */