From 243463d90270650b4eb9ffaed062609332d2727a Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 2 Mar 2023 11:01:20 -0600 Subject: [PATCH 01/63] Test Rich 1 decoding. --- .../python/AllenConf/rich_reconstruction.py | 25 ++++ configuration/python/AllenSequences/rich.py | 7 ++ device/CMakeLists.txt | 1 + device/rich/CMakeLists.txt | 13 ++ device/rich/decoding/include/RichDecoding.cuh | 97 ++++++++++++++ .../rich/decoding/include/RichDefinitions.cuh | 84 +++++++++++++ .../include/RichPDMDBDecodeMapping.cuh | 117 +++++++++++++++++ .../include/RichTel40CableMapping.cuh | 118 ++++++++++++++++++ device/rich/decoding/src/RichDecoding.cu | 94 ++++++++++++++ main/include/BankMapping.h | 4 +- stream/CMakeLists.txt | 12 +- 11 files changed, 567 insertions(+), 5 deletions(-) create mode 100644 configuration/python/AllenConf/rich_reconstruction.py create mode 100644 configuration/python/AllenSequences/rich.py create mode 100644 device/rich/CMakeLists.txt create mode 100644 device/rich/decoding/include/RichDecoding.cuh create mode 100644 device/rich/decoding/include/RichDefinitions.cuh create mode 100644 device/rich/decoding/include/RichPDMDBDecodeMapping.cuh create mode 100644 device/rich/decoding/include/RichTel40CableMapping.cuh create mode 100644 device/rich/decoding/src/RichDecoding.cu diff --git a/configuration/python/AllenConf/rich_reconstruction.py b/configuration/python/AllenConf/rich_reconstruction.py new file mode 100644 index 00000000000..ba44bc92474 --- /dev/null +++ b/configuration/python/AllenConf/rich_reconstruction.py @@ -0,0 +1,25 @@ +############################################################################### +# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration # +############################################################################### +from AllenCore.algorithms import (data_provider_t, rich_decoding_t) +from AllenConf.utils import initialize_number_of_events +from AllenCore.generator import make_algorithm + + +def decode_rich1(): + number_of_events = initialize_number_of_events() + + rich1_banks = make_algorithm( + data_provider_t, name="rich1_banks", bank_type="Rich1") + + rich1_decoding = make_algorithm( + rich_decoding_t, + name="rich1_decoding", + host_number_of_events_t=number_of_events["host_number_of_events"], + host_raw_bank_version_t=rich1_banks.host_raw_bank_version_t, + dev_rich_raw_input_t=rich1_banks.dev_raw_banks_t, + dev_rich_raw_input_offsets_t=rich1_banks.dev_raw_offsets_t, + dev_rich_raw_input_sizes_t=rich1_banks.dev_raw_sizes_t, + dev_rich_raw_input_types_t=rich1_banks.dev_raw_types_t) + + return rich1_decoding diff --git a/configuration/python/AllenSequences/rich.py b/configuration/python/AllenSequences/rich.py new file mode 100644 index 00000000000..9c1638e93ae --- /dev/null +++ b/configuration/python/AllenSequences/rich.py @@ -0,0 +1,7 @@ +############################################################################### +# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration # +############################################################################### +from AllenConf.rich_reconstruction import decode_rich1 +from AllenCore.generator import generate + +generate(decode_rich1()) diff --git a/device/CMakeLists.txt b/device/CMakeLists.txt index 85d8c0e5db0..e70e3d38ab3 100644 --- a/device/CMakeLists.txt +++ b/device/CMakeLists.txt @@ -22,3 +22,4 @@ add_subdirectory(lumi) add_subdirectory(combiners) add_subdirectory(plume) add_subdirectory(downstream) +add_subdirectory(rich) diff --git a/device/rich/CMakeLists.txt b/device/rich/CMakeLists.txt new file mode 100644 index 00000000000..d65eaf922bf --- /dev/null +++ b/device/rich/CMakeLists.txt @@ -0,0 +1,13 @@ +############################################################################### +# (c) Copyright 2018-2020 CERN for the benefit of the LHCb Collaboration # +############################################################################### +file(GLOB rich_decoding "decoding/src/*cu") + +allen_add_device_library(Rich STATIC + ${rich_decoding} +) + +target_link_libraries(Rich PRIVATE Backend HostEventModel EventModel Utils) + +target_include_directories(Rich PUBLIC + $) diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh new file mode 100644 index 00000000000..65d6ef12296 --- /dev/null +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -0,0 +1,97 @@ +/*****************************************************************************\ +* (c) Copyright 2018-2020 CERN for the benefit of the LHCb Collaboration * +\*****************************************************************************/ +#pragma once + +#include "AlgorithmTypes.cuh" +#include +#include +#include + +namespace Rich { + struct RawBank { + uint32_t source_id = 0; + uint16_t size = 0; + uint8_t const* data = nullptr; + uint8_t const type; + + // For Allen format + __device__ __host__ RawBank(const char* raw_bank, const uint16_t s, const uint8_t t) : + RawBank {*reinterpret_cast(raw_bank), raw_bank + sizeof(uint32_t), s, t} + {} + + // For MEP format + __device__ __host__ RawBank(const uint32_t sid, const char* fragment, const uint16_t s, const uint8_t t) : + source_id {sid}, size {s}, data {reinterpret_cast(fragment)}, type {t} + {} + }; + + template + struct RawEvent { + + uint32_t number_of_raw_banks = 0; + const char* data = nullptr; + const uint32_t* offsets = nullptr; + typename std::conditional_t* sizes = nullptr; + typename std::conditional_t* types = nullptr; + const unsigned event = 0; + + // For Allen format + __device__ __host__ + RawEvent(char const* d, uint32_t const* o, uint32_t const* s, uint32_t const* t, unsigned const event_number) : + offsets {o}, + event {event_number} + { + if constexpr (mep_layout) { + data = d; + number_of_raw_banks = MEP::number_of_banks(o); + sizes = s; + types = t; + } + else { + data = d + offsets[event]; + number_of_raw_banks = reinterpret_cast(data)[0]; + sizes = Allen::bank_sizes(s, event); + types = Allen::bank_types(t, event); + } + } + + __device__ __host__ RawBank raw_bank(unsigned const n) const + { + if constexpr (mep_layout) { + return MEP::raw_bank(data, offsets, sizes, types, event, n); + } + else { + uint32_t const* bank_offsets = reinterpret_cast(data) + 1; + return RawBank {data + (number_of_raw_banks + 2) * sizeof(uint32_t) + bank_offsets[n], sizes[n], types[n]}; + } + } + }; +} // namespace Rich + +namespace rich_decoding { + struct Parameters { + HOST_INPUT(host_number_of_events_t, uint) host_number_of_events; + HOST_INPUT(host_raw_bank_version_t, int) host_raw_bank_version; + MASK_INPUT(dev_event_list_t) dev_event_list; + DEVICE_INPUT(dev_rich_raw_input_t, char) dev_rich_raw_input; + DEVICE_INPUT(dev_rich_raw_input_offsets_t, uint) dev_rich_raw_input_offsets; + DEVICE_INPUT(dev_rich_raw_input_sizes_t, uint) dev_rich_raw_input_sizes; + DEVICE_INPUT(dev_rich_raw_input_types_t, uint) dev_rich_raw_input_types; + }; + + struct rich_decoding_t : public DeviceAlgorithm, Parameters { + void init(); + + void set_arguments_size(ArgumentReferences, const RuntimeOptions&, const Constants&) const; + + void operator()( + const ArgumentReferences&, + const RuntimeOptions&, + const Constants&, + const Allen::Context&) const; + + Rich::Future::DAQ::Allen::Tel40CableMapping m_cableMapping; + Rich::Future::DAQ::Allen::PDMDBDecodeMapping m_decodeMapping; + }; +} // namespace rich_decoding diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh new file mode 100644 index 00000000000..77299a8901b --- /dev/null +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -0,0 +1,84 @@ +#pragma once + +namespace Rich::Future::DAQ { + enum DetectorType : std::int8_t { + InvalidDetector = -1, ///< Unspecified Detector + Rich1 = 0, ///< RICH1 detector + Rich2 = 1, ///< RICH2 detector + Rich = 1 ///< Single RICH detector + }; + + class PackedFrameSizes final { + public: + /// Packed type + using IntType = std::uint8_t; + + private: + // Bits for each Size + static const IntType Bits0 = 4; + static const IntType Bits1 = 4; + // shifts + static const IntType Shift0 = 0; + static const IntType Shift1 = Shift0 + Bits0; + // masks + static const IntType Mask0 = ( IntType )( ( 1 << Bits0 ) - 1 ) << Shift0; + static const IntType Mask1 = ( IntType )( ( 1 << Bits1 ) - 1 ) << Shift1; + // max values + static const IntType Max0 = ( 1 << Bits0 ) - 1; + static const IntType Max1 = ( 1 << Bits1 ) - 1; + + private: + /// Set the overall word + inline void setData( const IntType data ) { m_data = data; } + + /// Set data for given word + inline void set( const IntType value, // + const IntType shift, // + const IntType mask ) { + setData( ( ( value << shift ) & mask ) | ( data() & ~mask ) ); + } + + public: + /// Constructor from two sizes + PackedFrameSizes( const IntType size0, const IntType size1 ) { + set( size0, Shift0, Mask0 ); + set( size1, Shift1, Mask1 ); + } + + /// Contructor from a single word + explicit PackedFrameSizes( const IntType d ) : m_data( d ) {} + + public: + /// Set size0 + inline void setSize0( const IntType size0 ) noexcept { set( size0, Shift0, Mask0 ); } + + /// Set size1 + inline void setSize1( const IntType size1 ) noexcept { set( size1, Shift1, Mask1 ); } + + /// set the size for the give word number + inline void setSize( const IntType size, const IntType word ) noexcept { + if ( 0 == word ) { + setSize0( size ); + } else { + setSize1( size ); + } + } + + public: + /// Get the overall data + inline IntType data() const noexcept { return m_data; } + + /// Get first size word + inline IntType size0() const noexcept { return ( ( data() & Mask0 ) >> Shift0 ); } + + /// Get second size word + inline IntType size1() const noexcept { return ( ( data() & Mask1 ) >> Shift1 ); } + + /// Get the total size + inline auto totalSize() const noexcept { return size0() + size1(); } + + private: + /// The data word + IntType m_data{0}; + }; +} \ No newline at end of file diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh new file mode 100644 index 00000000000..d730717be0e --- /dev/null +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -0,0 +1,117 @@ +#pragma once + +#include +#include + +// STL +#include +#include +#include +#include +#include +#include + +namespace Rich::Future::DAQ::Allen { + + /// Helper class for RICH PDMDB readout mapping + class PDMDBDecodeMapping final { + public: + // data types + + /// The data for each anode + class BitData final { + public: + /// The EC number (0-3) + int8_t ec; + /// The PMT number in EC + int8_t pmtInEC; + /// The Anode index (0-63) + int8_t anode; + + public: + /// Default constructor + BitData() = default; + /// Constructor from values + BitData( const int8_t _ec, // + const int8_t _pmt, // + const int8_t _anode ) + : ec( _ec ), pmtInEC( _pmt ), anode( _anode ) {} + }; + + private: + // defines + + /// Max Number of frames per PDMDB + static constexpr const std::size_t FramesPerPDMDB = 6; + + /// Number of PDMDBs per module + static constexpr const std::size_t PDMDBPerModule = 2; + + /// Max Number of frames per PDM + static constexpr const std::size_t FramesPerPDM = PDMDBPerModule * FramesPerPDMDB; + + /// Number of bits per data frame + static constexpr const std::size_t BitsPerFrame = 86; + + /// Array of Bit Data structs per frame + using FrameData = std::array; + + /// Data for each PDMDB + using PDMDBData = std::array; + + /// Data for each PDM + using PDMData = std::array; + + /// R-Type Module data for each RICH + using RTypeRichData = std::array; // std::array + + private: + // methods + + /// Get the PDMDB data for given RICH, PDMDB and frame + inline const auto& getFrameData( const int8_t rich, // + const int8_t pdmdb, // + const int8_t link, // + const bool isHType ) const noexcept { + // Note as this is called many times from the decoding, avoid runtime range checking + // in optimised builds, as once OK it should never be invalidated. + // This is though tested in the debug builds via the asserts. + if ( !isHType ) { + // R type PMT + return m_pdmDataR[rich][pdmdb][link]; + } else { + return m_pdmDataH[pdmdb][link]; + } + } + + public: + /// mapping version + inline auto version() const noexcept { return m_mappingVer; } + + /// Access the initialisation state + inline auto isInitialised() const noexcept { return m_isInitialised; } + + /// Get PDMDB data for given Tel40 data + inline const auto& getFrameData( const Tel40CableMapping::Tel40LinkData& cData ) const noexcept { + auto rich = (cData.smartID >> 31) ? (cData.smartID >> 20) & 0x1 : (cData.smartID >> 24) & 0x1; + + return getFrameData( rich, cData.pdmdbNum, cData.linkNum, cData.isHType ); + } + + private: + // data + + /// R type data + RTypeRichData m_pdmDataR; // std::array + + /// H type data + PDMData m_pdmDataH; // std::array + + /// Flag to indicate initialisation status + bool m_isInitialised{false}; + + /// Mapping version + int m_mappingVer{-1}; + }; + +} // namespace Rich::Future::DAQ diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh new file mode 100644 index 00000000000..b7195a3ff95 --- /dev/null +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -0,0 +1,118 @@ +#pragma once + +// STL +#include +#include +#include +#include +#include +#include +#include + +namespace Rich::Future::DAQ::Allen { + /// Helper class for RICH PMT data format encoding + class Tel40CableMapping final { + + public: + + /// Struct for storing data for each Tel40 Link + class Tel40LinkData final { + public: + /// RICH SmartID + uint32_t smartID; + /// Source ID + int16_t sourceID; + /// Tel40 connector + int8_t connector; + /// Module Number + int32_t moduleNum; + /// PDMDB number (0,1) + int8_t pdmdbNum; + /// Link number + int8_t linkNum; + /// PMT type + bool isHType{false}; + /// Is Link Active + bool isActive{false}; + + public: + /// Default constructor + Tel40LinkData() = default; + }; + + /// Max number of links(frames) per PDMDB + static constexpr const std::size_t MaxLinksPerPDMDB = 6; + + /// Number of PDMDBs per module + static constexpr const std::size_t PDMDBPerModule = 2; + + /// Array of Tel40 for each link in a PDMDB + using PDMDBLinkData = std::array; + + /// Array of LinkData for each PDMDB in a module + using PDMDBData = std::array; + + /// Tel40 data for each Module + using ModuleTel40Data = std::array; // 300 is totalmodules + + // TODO: The 164 limit should be studied + using Tel40SourceIDs = std::array, 164>, 2>, 2>; + using Tel40SourceMetas = std::array, 164>, 2>, 2>; + + public: + // accessors + + /// Access the initialisation state + inline bool isInitialised() const noexcept { return m_isInitialised; } + + /// Access the Tel40 Link data for given channel ID + const auto& tel40Data( const uint32_t id, // PD ID + const int8_t pdmdb, // PDMDB ID + const int8_t frame // PDMDB Frame + ) const noexcept { + // module number + const auto modN = (id >> 31) ? /* PMT */ (id >> 6) & 0xF : /* HPD */ (id >> 10) & 0x1F;; // TODO: RichSmartID.h:912 + + // return tel40 data + const auto& data = m_tel40ModuleData.at( modN ).at( pdmdb ).at( frame ); + // finally return + return data; + } + + /// Access the Tel40 connection data for a given SourceID + const auto& tel40Data( const int16_t sID ) const { + const auto payload = sID & 0x3FF; + const auto side = (sID >> 10) & 0x1; + const auto rich = (sID >> 11) == 9; // Rich1 is 4, Rich2 is 9. Then, Rich1 is identified with 0, Rich2 is 1. + return m_tel40ConnData.at( rich ).at( side ).at( payload ); + } + + // TODO: Use this when the int / boolean info is needed + const auto& tel40Meta( const int16_t sID ) const { + const auto payload = sID & 0x3FF; + const auto side = (sID >> 10) & 0x1; + const auto rich = (sID >> 11) == 9; // Rich1 is 4, Rich2 is 9. Then, Rich1 is identified with 0, Rich2 is 1. + return m_tel40ConnMeta.at( rich ).at( side ).at( payload ); + } + + /// mapping version + inline auto version() const noexcept { return m_mappingVer; } + + private: + // data + + /// Tel40 connection mapping data + Tel40SourceIDs m_tel40ConnData; + Tel40SourceMetas m_tel40ConnMeta; + + /// Tel40 Module Mapping data + ModuleTel40Data m_tel40ModuleData; + + /// Flag to indicate initialisation status + bool m_isInitialised{false}; + + /// Mapping version + int m_mappingVer{-1}; + }; + +} // namespace Rich::Future::DAQ::Allen \ No newline at end of file diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu new file mode 100644 index 00000000000..ae197bb9f9e --- /dev/null +++ b/device/rich/decoding/src/RichDecoding.cu @@ -0,0 +1,94 @@ +/*****************************************************************************\ +* (c) Copyright 2018-2020 CERN for the benefit of the LHCb Collaboration * +\*****************************************************************************/ +#include +#include +#include + +INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) + +using namespace Rich::Future::DAQ; +using namespace Rich::Future::DAQ::Allen; + +__device__ void rich_decode_bank(const Rich::RawBank& bank) { + std::cout << "Bank: sourceID " << bank.source_id << ", size " << bank.size << "\n"; + std::array connSizes{}; + + auto dataW = bank.data; + auto bankEnd = bank.data + bank.size; + auto iPayloadWord = 0u; + + for ( ; dataW != bankEnd; ++dataW, iPayloadWord += 2 ) { + // Extract the sizes from the packed word + const PackedFrameSizes sizes( *dataW ); + // extract sizes for each packed value + connSizes[iPayloadWord] = sizes.size1(); + connSizes[iPayloadWord + 1] = sizes.size0(); + } + + for (auto s : connSizes) { + std::cout << ((int) s) << ", "; + } + std::cout << "\n"; +} + +template +__global__ void rich_decoding_kernel( + rich_decoding::Parameters parameters, + const unsigned event_start) +{ + const auto event_number = parameters.dev_event_list[blockIdx.x]; + + // Read raw event + const auto raw_event = + Rich::RawEvent {parameters.dev_rich_raw_input, + parameters.dev_rich_raw_input_offsets, + parameters.dev_rich_raw_input_sizes, + parameters.dev_rich_raw_input_types, + event_number + event_start}; + + for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { + const auto bank = raw_event.raw_bank(bank_number); + rich_decode_bank(bank); + } +} + +void rich_decoding::rich_decoding_t::init() { + std::fstream file; + file.open("/home/cnca/dcampora/stack/pdmdbMaps.bin", std::ios::in | std::ios::binary); + auto size = file.tellg(); + file.seekg (0, std::ios::beg); + file.read (reinterpret_cast(&m_decodeMapping), size); + file.close(); + + file.open("/home/cnca/dcampora/stack/tel40Maps.bin", std::ios::in | std::ios::binary); + size = file.tellg(); + file.seekg (0, std::ios::beg); + file.read (reinterpret_cast(&m_cableMapping), size); + file.close(); +} + +void rich_decoding::rich_decoding_t::set_arguments_size( + ArgumentReferences arguments, + const RuntimeOptions&, + const Constants&) const +{} + +void rich_decoding::rich_decoding_t::operator()( + const ArgumentReferences& arguments, + const RuntimeOptions& runtime_options, + const Constants& constants, + const Allen::Context& context) const +{ + const auto bank_version = first(arguments); + std::cout << "Bank version Rich1 decoding " << bank_version << "\n"; + + auto kernel_fn = runtime_options.mep_layout ? rich_decoding_kernel<2, true> : rich_decoding_kernel<2, false>; + + global_function(kernel_fn)(dim3(size(arguments)), 1, context)( + arguments, + std::get<0>(runtime_options.event_interval)); + + // constants.dev_Tel40CableMapping, + // constants.dev_PDMDBDecodeMapping +} diff --git a/main/include/BankMapping.h b/main/include/BankMapping.h index 912e2d64ab4..966b4201e19 100644 --- a/main/include/BankMapping.h +++ b/main/include/BankMapping.h @@ -23,7 +23,9 @@ namespace Allen { {LHCb::RawBank::Calo, BankTypes::ECal}, {LHCb::RawBank::OTError, BankTypes::MCVertices}, // used for PV MC info {LHCb::RawBank::OTRaw, BankTypes::MCTracks}, - {LHCb::RawBank::Plume, BankTypes::Plume}}; // used for track MC info + {LHCb::RawBank::Plume, BankTypes::Plume}, + {LHCb::RawBank::Rich, BankTypes::Rich1} // TODO: Rich maps to Rich1. Rich2 is not yet included. + }; // used for track MC info const std::unordered_map subdetectors = {{SourceIdSys::SourceIdSys_ODIN, BankTypes::ODIN}, {SourceIdSys::SourceIdSys_VELO_A, BankTypes::VP}, diff --git a/stream/CMakeLists.txt b/stream/CMakeLists.txt index 1f3478cd293..9b81272aa95 100644 --- a/stream/CMakeLists.txt +++ b/stream/CMakeLists.txt @@ -41,12 +41,16 @@ target_link_libraries(Stream Gear track_matching MuonCommon - ) + Rich + PUBLIC + Utils + Selections) if(STANDALONE) add_dependencies(Stream checkout_lhcb checkout_gaudi) endif() -foreach(sequence ${BUILD_SEQUENCES}) - generate_sequence(${sequence}) -endforeach() +# TODO: Uncomment +# foreach(sequence ${BUILD_SEQUENCES}) +# generate_sequence(${sequence}) +# endforeach() -- GitLab From f5a8915dc0a8f0f171c7c82e912568977cc3d5dc Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 2 Mar 2023 11:46:36 -0600 Subject: [PATCH 02/63] Allow compilation. --- device/rich/decoding/include/RichTel40CableMapping.cuh | 9 +++++++++ device/rich/decoding/src/RichDecoding.cu | 7 ++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index b7195a3ff95..404cd39171c 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -46,6 +46,15 @@ namespace Rich::Future::DAQ::Allen { /// Number of PDMDBs per module static constexpr const std::size_t PDMDBPerModule = 2; + /// Number of Tel40 connections per MPO + static constexpr const std::size_t ConnectionsPerTel40MPO = 12; + + /// Maximum number of active Tel40 MPOs per Source ID + static constexpr const std::size_t MaxNumberMPOsPerSourceID = 2; + + /// Maximum Number of connections per Tel40 + static constexpr const std::size_t MaxConnectionsPerTel40 = MaxNumberMPOsPerSourceID * ConnectionsPerTel40MPO; + /// Array of Tel40 for each link in a PDMDB using PDMDBLinkData = std::array; diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index ae197bb9f9e..178c32d61e6 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -7,12 +7,9 @@ INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) -using namespace Rich::Future::DAQ; -using namespace Rich::Future::DAQ::Allen; - __device__ void rich_decode_bank(const Rich::RawBank& bank) { std::cout << "Bank: sourceID " << bank.source_id << ", size " << bank.size << "\n"; - std::array connSizes{}; + std::array connSizes{}; auto dataW = bank.data; auto bankEnd = bank.data + bank.size; @@ -20,7 +17,7 @@ __device__ void rich_decode_bank(const Rich::RawBank& bank) { for ( ; dataW != bankEnd; ++dataW, iPayloadWord += 2 ) { // Extract the sizes from the packed word - const PackedFrameSizes sizes( *dataW ); + const Rich::Future::DAQ::PackedFrameSizes sizes( *dataW ); // extract sizes for each packed value connSizes[iPayloadWord] = sizes.size1(); connSizes[iPayloadWord + 1] = sizes.size0(); -- GitLab From 4762bb8f23ac1adc75b9cf3cb4497c28de8ca801 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 2 Mar 2023 14:20:04 -0600 Subject: [PATCH 03/63] Message for loading bin files. --- device/rich/decoding/src/RichDecoding.cu | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 178c32d61e6..6cfe51d8eb2 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -53,14 +53,18 @@ __global__ void rich_decoding_kernel( void rich_decoding::rich_decoding_t::init() { std::fstream file; file.open("/home/cnca/dcampora/stack/pdmdbMaps.bin", std::ios::in | std::ios::binary); + file.seekg (0, std::ios::end); auto size = file.tellg(); file.seekg (0, std::ios::beg); + std::cout << "Loading pdmdbMaps. Size of file " << size << ", size of datatype " << sizeof(m_decodeMapping) << "\n"; file.read (reinterpret_cast(&m_decodeMapping), size); file.close(); file.open("/home/cnca/dcampora/stack/tel40Maps.bin", std::ios::in | std::ios::binary); + file.seekg (0, std::ios::end); size = file.tellg(); file.seekg (0, std::ios::beg); + std::cout << "Loading tel40Maps. Size of file " << size << ", size of datatype " << sizeof(m_cableMapping) << "\n"; file.read (reinterpret_cast(&m_cableMapping), size); file.close(); } -- GitLab From 8b5cf8834b9e6fb779226ae448e00c4e1c4e71ad Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 2 Mar 2023 18:08:46 -0600 Subject: [PATCH 04/63] First attempt at decoding. --- .../include/RichPDMDBDecodeMapping.cuh | 2 +- .../include/RichTel40CableMapping.cuh | 2 +- device/rich/decoding/src/RichDecoding.cu | 189 +++++++++++++++++- 3 files changed, 181 insertions(+), 12 deletions(-) diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index d730717be0e..291f769b859 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -93,7 +93,7 @@ namespace Rich::Future::DAQ::Allen { /// Get PDMDB data for given Tel40 data inline const auto& getFrameData( const Tel40CableMapping::Tel40LinkData& cData ) const noexcept { - auto rich = (cData.smartID >> 31) ? (cData.smartID >> 20) & 0x1 : (cData.smartID >> 24) & 0x1; + auto rich = (cData.smartID >> 20) & 0x1; return getFrameData( rich, cData.pdmdbNum, cData.linkNum, cData.isHType ); } diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index 404cd39171c..218d13e2ac5 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -80,7 +80,7 @@ namespace Rich::Future::DAQ::Allen { const int8_t frame // PDMDB Frame ) const noexcept { // module number - const auto modN = (id >> 31) ? /* PMT */ (id >> 6) & 0xF : /* HPD */ (id >> 10) & 0x1F;; // TODO: RichSmartID.h:912 + const auto modN = (id >> 6) & 0xF; // TODO: RichSmartID.h:912 // return tel40 data const auto& data = m_tel40ModuleData.at( modN ).at( pdmdb ).at( frame ); diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 6cfe51d8eb2..a51499eff64 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -7,15 +7,28 @@ INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) -__device__ void rich_decode_bank(const Rich::RawBank& bank) { +__device__ void rich_decode_bank( + const Rich::RawBank& bank, + const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) +{ std::cout << "Bank: sourceID " << bank.source_id << ", size " << bank.size << "\n"; std::array connSizes{}; + // TODO: Convert into something else + std::vector decodedIDs; + + auto tel40ID = bank.source_id; + const auto& connMeta = m_cableMapping.tel40Meta( tel40ID ); + const auto nSizeWords = std::get<1>(connMeta); + const auto nPackedSizeW = ( nSizeWords / 2 ) + ( nSizeWords % 2 ); + auto dataW = bank.data; auto bankEnd = bank.data + bank.size; auto iPayloadWord = 0u; + auto iWord = 0u; - for ( ; dataW != bankEnd; ++dataW, iPayloadWord += 2 ) { + for ( ; iWord < nPackedSizeW && dataW != bankEnd; ++dataW, ++iWord, iPayloadWord += 2 ) { // Extract the sizes from the packed word const Rich::Future::DAQ::PackedFrameSizes sizes( *dataW ); // extract sizes for each packed value @@ -23,16 +36,172 @@ __device__ void rich_decode_bank(const Rich::RawBank& bank) { connSizes[iPayloadWord + 1] = sizes.size0(); } + const auto& connData = m_cableMapping.tel40Data( tel40ID ); + if (std::get<0>(connMeta)) { + for ( std::size_t iL = 0; iL < connData.size(); ++iL ) { + if ( !connData[iL].isActive ) { + for ( auto i = connData.size() - 1; i > iL; --i ) { connSizes[i] = connSizes[i - 1]; } + connSizes[iL] = 0; + } + } + } + for (auto s : connSizes) { std::cout << ((int) s) << ", "; } std::cout << "\n"; + + // const auto nPayloadWords = [&connSizes] () { + // auto sum = 0u; + // for (const auto i : connSizes) { + // sum += i; + // } + // return sum; + // }; + // decodedIDs.reserve( 8 * nPayloadWords ); + + // finally loop over payload words and decode hits + // note iterator starts from where the above header loop ended... + std::size_t iLink{0}; + while ( dataW != bankEnd && iLink < connSizes.size() ) { + // Do we have any words to decode for this link + if ( connSizes[iLink] > 0 ) { + // Get the Tel40 Data for this connection + const auto& cData = connData[iLink]; + + // get the PDMDB data + const auto& frameData = m_decodeMapping.getFrameData( cData ); + + // Loop over the words for this link + uint16_t iW = 0; + while ( iW < connSizes[iLink] && dataW != bankEnd ) { + + // check MSB for this word + // TODO: Check const auto isNZS = isBitOn( *dataW ); + const auto isNZS = (0x80000000 & *dataW) != 0; + + if ( !isNZS ) { + // ZS decoding... word is bit index + + // load the anode data for this bit + if ( ( std::size_t )( *dataW ) < frameData.size() ) { + + const auto& aData = frameData[*dataW]; + + // TODO: Data 'could' be invalid, e.g. radiation-induced-upsets + // so cannot make this a hard error + + // make a smart ID + auto hitID = cData.smartID; // sets RICH, side, module and PMT type + + // Add the PMT and pixel info + const auto nInMod = ( aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4) ) + aData.pmtInEC; + hitID = hitID | (cData.moduleNum & 0x1FF) << 10; + hitID = hitID | (nInMod & 0xF) << 6; + + const auto col = 32 - 1 - ( aData.anode % 32 ); + const auto row = aData.anode / 32; + hitID |= (col & 0x7) | ((row & 0x7) << 3); + + decodedIDs.emplace_back( hitID ); + } + + // move to next word + ++iW; + ++dataW; + + } else { + // NZS decoding... + + // which half of the payload are we in ? + const bool firstHalf = ( 0 == iW && connSizes[iLink] > 5 ); + // Number of words to decode depends on which half of the payload we are in + const auto nNZSwords = ( firstHalf ? 6 : 5 ); + // bit offset per half + const auto halfBitOffset = ( firstHalf ? 39 : 0 ); + + // look forward last NZS word and read backwards to match frame bit order + for ( auto iNZS = nNZSwords - 1; iNZS >= 0; --iNZS ) { + + // read the NZS word + auto nzsW = *( dataW + iNZS ); + // if word zero clear MSB as this is the NZS flag + if ( 0 == iNZS ) { + // TODO: Check this is correct setBitOff( nzsW ); + nzsW &= 0x7FFFFFFF; + } + + // does this word hold any active bits ? + if ( nzsW > 0 ) { + + // Bit offset for this word + const auto bitOffset = halfBitOffset + ( 8 * ( nNZSwords - 1 - iNZS ) ); + + // word has data so loop over bits to extract + for ( auto iLB = 0; iLB < 8; ++iLB ) { + // is bit on ? + // if ( isBitOn( nzsW, iLB ) ) { + if ( (nzsW & (1 << iLB)) != 0) { + + // form frame bit value + const auto bit = iLB + bitOffset; + + // load the anode data for this bit + if ( ( size_t )( bit ) < frameData.size() ) { + const auto& aData = frameData[bit]; + // TODO: Data 'could' be invalid, e.g. radiation-induced-upsets + // so cannot make this a hard error + + // make a smart ID + auto hitID = cData.smartID; // sets RICH, side, module and PMT type + + // Add the PMT and pixel info + const auto nInMod = ( aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4) ) + aData.pmtInEC; + hitID = hitID | (cData.moduleNum & 0x1FF) << 10; + hitID = hitID | (nInMod & 0xF) << 6; + + const auto col = 32 - 1 - ( aData.anode % 32 ); + const auto row = aData.anode / 32; + hitID |= (col & 0x7) | ((row & 0x7) << 3); + + // sanity assert to ensure this hit is not already present + decodedIDs.emplace_back( hitID ); + } + + } // bit is on + } // loop over word bits + + } // word has any data + + } // loop over all NZS words + + // Finally skip the read NZS words + iW += nNZSwords; + dataW += nNZSwords; + } + } + + } // no data for this link, so just move on + + // move to next Tel40 link + ++iLink; + } // data word loop + + if (decodedIDs.size()) { + std::cout << "Decoded IDs: "; + for (auto i : decodedIDs) { + std::cout << i << ", "; + } + std::cout << "\n"; + } } template __global__ void rich_decoding_kernel( rich_decoding::Parameters parameters, - const unsigned event_start) + const unsigned event_start, + const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) { const auto event_number = parameters.dev_event_list[blockIdx.x]; @@ -44,9 +213,10 @@ __global__ void rich_decoding_kernel( parameters.dev_rich_raw_input_types, event_number + event_start}; + std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); - rich_decode_bank(bank); + rich_decode_bank(bank, m_cableMapping, m_decodeMapping); } } @@ -70,7 +240,7 @@ void rich_decoding::rich_decoding_t::init() { } void rich_decoding::rich_decoding_t::set_arguments_size( - ArgumentReferences arguments, + ArgumentReferences, const RuntimeOptions&, const Constants&) const {} @@ -78,7 +248,7 @@ void rich_decoding::rich_decoding_t::set_arguments_size( void rich_decoding::rich_decoding_t::operator()( const ArgumentReferences& arguments, const RuntimeOptions& runtime_options, - const Constants& constants, + const Constants&, const Allen::Context& context) const { const auto bank_version = first(arguments); @@ -88,8 +258,7 @@ void rich_decoding::rich_decoding_t::operator()( global_function(kernel_fn)(dim3(size(arguments)), 1, context)( arguments, - std::get<0>(runtime_options.event_interval)); - - // constants.dev_Tel40CableMapping, - // constants.dev_PDMDBDecodeMapping + std::get<0>(runtime_options.event_interval), + m_cableMapping, + m_decodeMapping); } -- GitLab From 037dbcfc3c49ea9a8f4d86aab4340659df4934d5 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Fri, 3 Mar 2023 08:05:48 -0600 Subject: [PATCH 05/63] Added kernel to calculate number of hits. --- device/rich/decoding/src/RichDecoding.cu | 179 +++++++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index a51499eff64..87aac9aa7d1 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -7,6 +7,177 @@ INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) +__device__ unsigned rich_calculate_number_of_hits_in_raw_bank( + const Rich::RawBank& bank, + const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) +{ + unsigned number_of_hits = 0; + + std::array connSizes{}; + + auto tel40ID = bank.source_id; + const auto& connMeta = m_cableMapping.tel40Meta( tel40ID ); + const auto nSizeWords = std::get<1>(connMeta); + const auto nPackedSizeW = ( nSizeWords / 2 ) + ( nSizeWords % 2 ); + + auto dataW = bank.data; + auto bankEnd = bank.data + bank.size; + auto iPayloadWord = 0u; + auto iWord = 0u; + + for ( ; iWord < nPackedSizeW && dataW != bankEnd; ++dataW, ++iWord, iPayloadWord += 2 ) { + // Extract the sizes from the packed word + const Rich::Future::DAQ::PackedFrameSizes sizes( *dataW ); + // extract sizes for each packed value + connSizes[iPayloadWord] = sizes.size1(); + connSizes[iPayloadWord + 1] = sizes.size0(); + } + + const auto& connData = m_cableMapping.tel40Data( tel40ID ); + if (std::get<0>(connMeta)) { + for ( std::size_t iL = 0; iL < connData.size(); ++iL ) { + if ( !connData[iL].isActive ) { + for ( auto i = connData.size() - 1; i > iL; --i ) { connSizes[i] = connSizes[i - 1]; } + connSizes[iL] = 0; + } + } + } + + for (auto s : connSizes) { + std::cout << ((int) s) << ", "; + } + std::cout << "\n"; + + // const auto nPayloadWords = [&connSizes] () { + // auto sum = 0u; + // for (const auto i : connSizes) { + // sum += i; + // } + // return sum; + // }; + // decodedIDs.reserve( 8 * nPayloadWords ); + + // finally loop over payload words and decode hits + // note iterator starts from where the above header loop ended... + std::size_t iLink{0}; + while ( dataW != bankEnd && iLink < connSizes.size() ) { + // Do we have any words to decode for this link + if ( connSizes[iLink] > 0 ) { + // Get the Tel40 Data for this connection + const auto& cData = connData[iLink]; + + // get the PDMDB data + const auto& frameData = m_decodeMapping.getFrameData( cData ); + + // Loop over the words for this link + uint16_t iW = 0; + while ( iW < connSizes[iLink] && dataW != bankEnd ) { + + // check MSB for this word + // TODO: Check const auto isNZS = isBitOn( *dataW ); + const auto isNZS = (0x80000000 & *dataW) != 0; + + if ( !isNZS ) { + // ZS decoding... word is bit index + + // load the anode data for this bit + if ( ( std::size_t )( *dataW ) < frameData.size() ) { + number_of_hits++; + } + + // move to next word + ++iW; + ++dataW; + + } else { + // NZS decoding... + + // which half of the payload are we in ? + const bool firstHalf = ( 0 == iW && connSizes[iLink] > 5 ); + // Number of words to decode depends on which half of the payload we are in + const auto nNZSwords = ( firstHalf ? 6 : 5 ); + // bit offset per half + const auto halfBitOffset = ( firstHalf ? 39 : 0 ); + + // look forward last NZS word and read backwards to match frame bit order + for ( auto iNZS = nNZSwords - 1; iNZS >= 0; --iNZS ) { + + // read the NZS word + auto nzsW = *( dataW + iNZS ); + // if word zero clear MSB as this is the NZS flag + if ( 0 == iNZS ) { + // TODO: Check this is correct setBitOff( nzsW ); + nzsW &= 0x7FFFFFFF; + } + + // does this word hold any active bits ? + if ( nzsW > 0 ) { + + // Bit offset for this word + const auto bitOffset = halfBitOffset + ( 8 * ( nNZSwords - 1 - iNZS ) ); + + // word has data so loop over bits to extract + for ( auto iLB = 0; iLB < 8; ++iLB ) { + // is bit on ? + // if ( isBitOn( nzsW, iLB ) ) { + if ( (nzsW & (1 << iLB)) != 0) { + + // form frame bit value + const auto bit = iLB + bitOffset; + + // load the anode data for this bit + if ( ( size_t )( bit ) < frameData.size() ) { + number_of_hits++; + } + + } // bit is on + } // loop over word bits + + } // word has any data + + } // loop over all NZS words + + // Finally skip the read NZS words + iW += nNZSwords; + dataW += nNZSwords; + } + } + + } // no data for this link, so just move on + + // move to next Tel40 link + ++iLink; + } // data word loop + + return number_of_hits; +} + +template +__global__ void rich_calculate_number_of_hits( + rich_decoding::Parameters parameters, + const unsigned event_start, + const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) +{ + const auto event_number = parameters.dev_event_list[blockIdx.x]; + + // Read raw event + const auto raw_event = + Rich::RawEvent {parameters.dev_rich_raw_input, + parameters.dev_rich_raw_input_offsets, + parameters.dev_rich_raw_input_sizes, + parameters.dev_rich_raw_input_types, + event_number + event_start}; + + std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; + for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { + const auto bank = raw_event.raw_bank(bank_number); + const auto number_of_hits_in_raw_bank = rich_calculate_number_of_hits_in_raw_bank(bank, m_cableMapping, m_decodeMapping); + std::cout << "Number of hits in raw bank " << bank_number << ": " << number_of_hits_in_raw_bank << "\n"; + } +} + __device__ void rich_decode_bank( const Rich::RawBank& bank, const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, @@ -254,6 +425,14 @@ void rich_decoding::rich_decoding_t::operator()( const auto bank_version = first(arguments); std::cout << "Bank version Rich1 decoding " << bank_version << "\n"; + auto calculate_number_of_hits_kernel = runtime_options.mep_layout ? rich_calculate_number_of_hits : rich_calculate_number_of_hits; + + global_function(calculate_number_of_hits_kernel)(dim3(size(arguments)), 64, context)( + arguments, + std::get<0>(runtime_options.event_interval), + m_cableMapping, + m_decodeMapping); + auto kernel_fn = runtime_options.mep_layout ? rich_decoding_kernel<2, true> : rich_decoding_kernel<2, false>; global_function(kernel_fn)(dim3(size(arguments)), 1, context)( -- GitLab From 02addf741690b77a87a6a257fe14825e307aa120 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Fri, 3 Mar 2023 08:59:23 -0600 Subject: [PATCH 06/63] Decoding with prefix sum and calculate hits. --- device/rich/CMakeLists.txt | 2 +- device/rich/decoding/include/RichDecoding.cuh | 6 + device/rich/decoding/src/RichDecoding.cu | 114 +++++++++--------- 3 files changed, 63 insertions(+), 59 deletions(-) diff --git a/device/rich/CMakeLists.txt b/device/rich/CMakeLists.txt index d65eaf922bf..49e836d48a6 100644 --- a/device/rich/CMakeLists.txt +++ b/device/rich/CMakeLists.txt @@ -7,7 +7,7 @@ allen_add_device_library(Rich STATIC ${rich_decoding} ) -target_link_libraries(Rich PRIVATE Backend HostEventModel EventModel Utils) +target_link_libraries(Rich PRIVATE Backend HostEventModel EventModel Utils HostPrefixSum) target_include_directories(Rich PUBLIC $) diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index 65d6ef12296..4a2733d004b 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -78,6 +78,12 @@ namespace rich_decoding { DEVICE_INPUT(dev_rich_raw_input_offsets_t, uint) dev_rich_raw_input_offsets; DEVICE_INPUT(dev_rich_raw_input_sizes_t, uint) dev_rich_raw_input_sizes; DEVICE_INPUT(dev_rich_raw_input_types_t, uint) dev_rich_raw_input_types; + DEVICE_OUTPUT(dev_rich_number_of_hits_t, unsigned) dev_rich_number_of_hits; + DEVICE_OUTPUT(dev_rich_hit_offsets_t, unsigned) dev_rich_hit_offsets; + HOST_OUTPUT(host_rich_hit_offsets_t, unsigned) host_rich_hit_offsets; + HOST_OUTPUT(host_rich_total_number_of_hits_t, unsigned) host_rich_total_number_of_hits; + DEVICE_OUTPUT(dev_rich_number_of_inserted_hits_t, unsigned) dev_rich_number_of_inserted_hits; + DEVICE_OUTPUT(dev_smart_ids_t, unsigned) dev_smart_ids; }; struct rich_decoding_t : public DeviceAlgorithm, Parameters { diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 87aac9aa7d1..36a36b5a0ee 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -4,6 +4,7 @@ #include #include #include +#include INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) @@ -44,20 +45,6 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( } } - for (auto s : connSizes) { - std::cout << ((int) s) << ", "; - } - std::cout << "\n"; - - // const auto nPayloadWords = [&connSizes] () { - // auto sum = 0u; - // for (const auto i : connSizes) { - // sum += i; - // } - // return sum; - // }; - // decodedIDs.reserve( 8 * nPayloadWords ); - // finally loop over payload words and decode hits // note iterator starts from where the above header loop ended... std::size_t iLink{0}; @@ -170,24 +157,26 @@ __global__ void rich_calculate_number_of_hits( parameters.dev_rich_raw_input_types, event_number + event_start}; - std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; + // std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); const auto number_of_hits_in_raw_bank = rich_calculate_number_of_hits_in_raw_bank(bank, m_cableMapping, m_decodeMapping); - std::cout << "Number of hits in raw bank " << bank_number << ": " << number_of_hits_in_raw_bank << "\n"; + // std::cout << "Number of hits in raw bank " << bank_number << ": " << number_of_hits_in_raw_bank << "\n"; + if (number_of_hits_in_raw_bank > 0) { + atomicAdd(parameters.dev_rich_number_of_hits + event_number, number_of_hits_in_raw_bank); + } } } __device__ void rich_decode_bank( const Rich::RawBank& bank, const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping, + unsigned* event_inserted_hits, + unsigned* event_smart_ids) { - std::cout << "Bank: sourceID " << bank.source_id << ", size " << bank.size << "\n"; + // std::cout << "Bank: sourceID " << bank.source_id << ", size " << bank.size << "\n"; std::array connSizes{}; - - // TODO: Convert into something else - std::vector decodedIDs; auto tel40ID = bank.source_id; const auto& connMeta = m_cableMapping.tel40Meta( tel40ID ); @@ -217,20 +206,6 @@ __device__ void rich_decode_bank( } } - for (auto s : connSizes) { - std::cout << ((int) s) << ", "; - } - std::cout << "\n"; - - // const auto nPayloadWords = [&connSizes] () { - // auto sum = 0u; - // for (const auto i : connSizes) { - // sum += i; - // } - // return sum; - // }; - // decodedIDs.reserve( 8 * nPayloadWords ); - // finally loop over payload words and decode hits // note iterator starts from where the above header loop ended... std::size_t iLink{0}; @@ -274,7 +249,8 @@ __device__ void rich_decode_bank( const auto row = aData.anode / 32; hitID |= (col & 0x7) | ((row & 0x7) << 3); - decodedIDs.emplace_back( hitID ); + const auto insert_index = atomicAdd(event_inserted_hits, 1); + event_smart_ids[insert_index] = hitID; } // move to next word @@ -335,8 +311,8 @@ __device__ void rich_decode_bank( const auto row = aData.anode / 32; hitID |= (col & 0x7) | ((row & 0x7) << 3); - // sanity assert to ensure this hit is not already present - decodedIDs.emplace_back( hitID ); + const auto insert_index = atomicAdd(event_inserted_hits, 1); + event_smart_ids[insert_index] = hitID; } } // bit is on @@ -357,17 +333,9 @@ __device__ void rich_decode_bank( // move to next Tel40 link ++iLink; } // data word loop - - if (decodedIDs.size()) { - std::cout << "Decoded IDs: "; - for (auto i : decodedIDs) { - std::cout << i << ", "; - } - std::cout << "\n"; - } } -template +template __global__ void rich_decoding_kernel( rich_decoding::Parameters parameters, const unsigned event_start, @@ -376,6 +344,9 @@ __global__ void rich_decoding_kernel( { const auto event_number = parameters.dev_event_list[blockIdx.x]; + auto event_inserted_hits = parameters.dev_rich_number_of_inserted_hits + event_number; + auto event_smart_ids = parameters.dev_smart_ids + parameters.dev_rich_hit_offsets[event_number]; + // Read raw event const auto raw_event = Rich::RawEvent {parameters.dev_rich_raw_input, @@ -384,10 +355,10 @@ __global__ void rich_decoding_kernel( parameters.dev_rich_raw_input_types, event_number + event_start}; - std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; + // std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); - rich_decode_bank(bank, m_cableMapping, m_decodeMapping); + rich_decode_bank(bank, m_cableMapping, m_decodeMapping, event_inserted_hits, event_smart_ids); } } @@ -411,10 +382,16 @@ void rich_decoding::rich_decoding_t::init() { } void rich_decoding::rich_decoding_t::set_arguments_size( - ArgumentReferences, + ArgumentReferences arguments, const RuntimeOptions&, const Constants&) const -{} +{ + set_size(arguments, size(arguments)); + set_size(arguments, size(arguments) + 1); + set_size(arguments, size(arguments) + 1); + set_size(arguments, 1); + set_size(arguments, size(arguments)); +} void rich_decoding::rich_decoding_t::operator()( const ArgumentReferences& arguments, @@ -425,19 +402,40 @@ void rich_decoding::rich_decoding_t::operator()( const auto bank_version = first(arguments); std::cout << "Bank version Rich1 decoding " << bank_version << "\n"; - auto calculate_number_of_hits_kernel = runtime_options.mep_layout ? rich_calculate_number_of_hits : rich_calculate_number_of_hits; - - global_function(calculate_number_of_hits_kernel)(dim3(size(arguments)), 64, context)( + // Calculate number of hits into dev_rich_number_of_hits_t + Allen::memset_async(arguments, 0, context); + global_function(runtime_options.mep_layout ? rich_calculate_number_of_hits : rich_calculate_number_of_hits) + (dim3(size(arguments)), 64, context)( arguments, std::get<0>(runtime_options.event_interval), m_cableMapping, m_decodeMapping); - - auto kernel_fn = runtime_options.mep_layout ? rich_decoding_kernel<2, true> : rich_decoding_kernel<2, false>; - - global_function(kernel_fn)(dim3(size(arguments)), 1, context)( + + // Copy to host + data(arguments)[0] = 0; + Allen::copy(arguments, context, size(arguments), 1, 0); + + // Prefix sum + host_prefix_sum::host_prefix_sum_impl( + data(arguments), + size(arguments), + data(arguments)); + + // Copy prefix summed container to device + Allen::copy_async(arguments, context); + + // Decode RICH hits + Allen::memset_async(arguments, 0, context); + resize(arguments, first(arguments)); + + global_function(runtime_options.mep_layout ? rich_decoding_kernel : rich_decoding_kernel) + (dim3(size(arguments)), 1, context)( arguments, std::get<0>(runtime_options.event_interval), m_cableMapping, m_decodeMapping); + + // Print output + print(arguments); + // print(arguments); } -- GitLab From 79eb0754f47a07ce2d86decc2c71802ca24f2981 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Fri, 3 Mar 2023 11:20:20 -0600 Subject: [PATCH 07/63] First seemingly working correctly decoding of RICH. --- .../rich/decoding/include/RichDefinitions.cuh | 77 +++++++++++++++++++ device/rich/decoding/src/RichDecoding.cu | 30 +++++--- 2 files changed, 95 insertions(+), 12 deletions(-) diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index 77299a8901b..f7c0820b0c7 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -1,5 +1,82 @@ #pragma once +namespace RichSmartID { + // Number of bits for each data field in the word + static constexpr const unsigned BitsPixelCol = 3; ///< Number of bits for MaPMT pixel column + static constexpr const unsigned BitsPixelRow = 3; ///< Number of bits for MaPMT pixel row + static constexpr const unsigned BitsPDNumInMod = 4; ///< Number of bits for MaPMT 'number in module' + static constexpr const unsigned BitsPDMod = 9; ///< Number of bits for MaPMT module + static constexpr const unsigned BitsPanel = 1; ///< Number of bits for MaPMT panel + static constexpr const unsigned BitsRich = 1; ///< Number of bits for RICH detector + static constexpr const unsigned BitsPixelSubRowIsSet = 1; + static constexpr const unsigned BitsPixelColIsSet = 1; + static constexpr const unsigned BitsPixelRowIsSet = 1; + static constexpr const unsigned BitsPDIsSet = 1; + static constexpr const unsigned BitsPanelIsSet = 1; + static constexpr const unsigned BitsRichIsSet = 1; + static constexpr const unsigned BitsLargePixel = 1; + + // The shifts + static constexpr const unsigned ShiftPixelCol = 0; + static constexpr const unsigned ShiftPixelRow = ShiftPixelCol + BitsPixelCol; + static constexpr const unsigned ShiftPDNumInMod = ShiftPixelRow + BitsPixelRow; + static constexpr const unsigned ShiftPDMod = ShiftPDNumInMod + BitsPDNumInMod; + static constexpr const unsigned ShiftPanel = ShiftPDMod + BitsPDMod; + static constexpr const unsigned ShiftRich = ShiftPanel + BitsPanel; + static constexpr const unsigned ShiftPixelSubRowIsSet = ShiftRich + BitsRich; + static constexpr const unsigned ShiftPixelColIsSet = ShiftPixelSubRowIsSet + BitsPixelSubRowIsSet; + static constexpr const unsigned ShiftPixelRowIsSet = ShiftPixelColIsSet + BitsPixelColIsSet; + static constexpr const unsigned ShiftPDIsSet = ShiftPixelRowIsSet + BitsPixelRowIsSet; + static constexpr const unsigned ShiftPanelIsSet = ShiftPDIsSet + BitsPDIsSet; + static constexpr const unsigned ShiftRichIsSet = ShiftPanelIsSet + BitsPanelIsSet; + static constexpr const unsigned ShiftLargePixel = ShiftRichIsSet + BitsRichIsSet; + + // The masks + static constexpr const unsigned MaskPixelCol = ( unsigned )( ( 1 << BitsPixelCol ) - 1 ) << ShiftPixelCol; + static constexpr const unsigned MaskPixelRow = ( unsigned )( ( 1 << BitsPixelRow ) - 1 ) << ShiftPixelRow; + static constexpr const unsigned MaskPDNumInMod = ( unsigned )( ( 1 << BitsPDNumInMod ) - 1 ) + << ShiftPDNumInMod; + static constexpr const unsigned MaskPDMod = ( unsigned )( ( 1 << BitsPDMod ) - 1 ) << ShiftPDMod; + static constexpr const unsigned MaskPanel = ( unsigned )( ( 1 << BitsPanel ) - 1 ) << ShiftPanel; + static constexpr const unsigned MaskRich = ( unsigned )( ( 1 << BitsRich ) - 1 ) << ShiftRich; + static constexpr const unsigned MaskPixelSubRowIsSet = ( unsigned )( ( 1 << BitsPixelSubRowIsSet ) - 1 ) + << ShiftPixelSubRowIsSet; + static constexpr const unsigned MaskPixelColIsSet = ( unsigned )( ( 1 << BitsPixelColIsSet ) - 1 ) + << ShiftPixelColIsSet; + static constexpr const unsigned MaskPixelRowIsSet = ( unsigned )( ( 1 << BitsPixelRowIsSet ) - 1 ) + << ShiftPixelRowIsSet; + static constexpr const unsigned MaskPDIsSet = ( unsigned )( ( 1 << BitsPDIsSet ) - 1 ) << ShiftPDIsSet; + static constexpr const unsigned MaskPanelIsSet = ( unsigned )( ( 1 << BitsPanelIsSet ) - 1 ) + << ShiftPanelIsSet; + static constexpr const unsigned MaskRichIsSet = ( unsigned )( ( 1 << BitsRichIsSet ) - 1 ) + << ShiftRichIsSet; + static constexpr const unsigned MaskLargePixel = ( unsigned )( ( 1 << BitsLargePixel ) - 1 ) + << ShiftLargePixel; + + // Max Values + static constexpr const unsigned MaxPixelCol = ( unsigned )( 1 << BitsPixelCol ) - 1; + static constexpr const unsigned MaxPixelRow = ( unsigned )( 1 << BitsPixelRow ) - 1; + static constexpr const unsigned MaxPDNumInMod = ( unsigned )( 1 << BitsPDNumInMod ) - 1; + static constexpr const unsigned MaxPDMod = ( unsigned )( 1 << BitsPDMod ) - 1; + static constexpr const unsigned MaxPanel = ( unsigned )( 1 << BitsPanel ) - 1; + static constexpr const unsigned MaxRich = ( unsigned )( 1 << BitsRich ) - 1; + + constexpr inline unsigned bits( const unsigned key, + const unsigned value, + const unsigned shift, + const unsigned mask ) noexcept { + return ( ( value << shift ) & mask ) | ( key & ~mask ); + } + + constexpr inline unsigned bits( const unsigned key, + const unsigned value, // + const unsigned shift, // + const unsigned mask, // + const unsigned okMask ) noexcept { + return ( ( value << shift ) & mask ) | ( key & ~mask ) | okMask; + } +} + namespace Rich::Future::DAQ { enum DetectorType : std::int8_t { InvalidDetector = -1, ///< Unspecified Detector diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 36a36b5a0ee..a0763ea9fd7 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -242,12 +242,15 @@ __device__ void rich_decode_bank( // Add the PMT and pixel info const auto nInMod = ( aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4) ) + aData.pmtInEC; - hitID = hitID | (cData.moduleNum & 0x1FF) << 10; - hitID = hitID | (nInMod & 0xF) << 6; + hitID = RichSmartID::bits(hitID, cData.moduleNum, RichSmartID::ShiftPDMod, RichSmartID::MaskPDMod, RichSmartID::MaskPDIsSet ); + hitID = RichSmartID::bits(hitID, nInMod, RichSmartID::ShiftPDNumInMod, RichSmartID::MaskPDNumInMod); + // std::cout << "hitID after setPD_EC_PMT " << ((unsigned) hitID) << "\n"; - const auto col = 32 - 1 - ( aData.anode % 32 ); - const auto row = aData.anode / 32; - hitID |= (col & 0x7) | ((row & 0x7) << 3); + const auto row = aData.anode / 8; + const auto col = 8 - 1 - ( aData.anode % 8 ); + hitID = RichSmartID::bits( hitID, row, RichSmartID::ShiftPixelRow, RichSmartID::MaskPixelRow, RichSmartID::MaskPixelRowIsSet ); + hitID = RichSmartID::bits( hitID, col, RichSmartID::ShiftPixelCol, RichSmartID::MaskPixelCol, RichSmartID::MaskPixelColIsSet ); + // std::cout << "hitID after Anode " << hitID << "\n"; const auto insert_index = atomicAdd(event_inserted_hits, 1); event_smart_ids[insert_index] = hitID; @@ -304,12 +307,15 @@ __device__ void rich_decode_bank( // Add the PMT and pixel info const auto nInMod = ( aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4) ) + aData.pmtInEC; - hitID = hitID | (cData.moduleNum & 0x1FF) << 10; - hitID = hitID | (nInMod & 0xF) << 6; - - const auto col = 32 - 1 - ( aData.anode % 32 ); - const auto row = aData.anode / 32; - hitID |= (col & 0x7) | ((row & 0x7) << 3); + hitID = RichSmartID::bits(hitID, cData.moduleNum, RichSmartID::ShiftPDMod, RichSmartID::MaskPDMod, RichSmartID::MaskPDIsSet ); + hitID = RichSmartID::bits(hitID, nInMod, RichSmartID::ShiftPDNumInMod, RichSmartID::MaskPDNumInMod); + // std::cout << "hitID after setPD_EC_PMT " << ((unsigned) hitID) << "\n"; + + const auto row = aData.anode / 8; + const auto col = 8 - 1 - ( aData.anode % 8 ); + hitID = RichSmartID::bits( hitID, row, RichSmartID::ShiftPixelRow, RichSmartID::MaskPixelRow, RichSmartID::MaskPixelRowIsSet ); + hitID = RichSmartID::bits( hitID, col, RichSmartID::ShiftPixelCol, RichSmartID::MaskPixelCol, RichSmartID::MaskPixelColIsSet ); + // std::cout << "hitID after Anode " << hitID << "\n"; const auto insert_index = atomicAdd(event_inserted_hits, 1); event_smart_ids[insert_index] = hitID; @@ -437,5 +443,5 @@ void rich_decoding::rich_decoding_t::operator()( // Print output print(arguments); - // print(arguments); + print(arguments); } -- GitLab From a23da6b7078d4eb195e00736810e7b9f165bf1d0 Mon Sep 17 00:00:00 2001 From: Christian Asch Date: Mon, 6 Mar 2023 06:49:53 -0600 Subject: [PATCH 08/63] Added the necessary declaration specifiers to make the code compile with CUDA --- device/rich/decoding/include/RichDefinitions.cuh | 8 ++++---- device/rich/decoding/include/RichPDMDBDecodeMapping.cuh | 4 ++-- device/rich/decoding/include/RichTel40CableMapping.cuh | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index f7c0820b0c7..77f810cd017 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -123,7 +123,7 @@ namespace Rich::Future::DAQ { } /// Contructor from a single word - explicit PackedFrameSizes( const IntType d ) : m_data( d ) {} + __device__ explicit PackedFrameSizes( const IntType d ) : m_data( d ) {} public: /// Set size0 @@ -143,13 +143,13 @@ namespace Rich::Future::DAQ { public: /// Get the overall data - inline IntType data() const noexcept { return m_data; } + __host__ __device__ inline IntType data() const noexcept { return m_data; } /// Get first size word - inline IntType size0() const noexcept { return ( ( data() & Mask0 ) >> Shift0 ); } + __host__ __device__ inline IntType size0() const noexcept { return ( ( data() & Mask0 ) >> Shift0 ); } /// Get second size word - inline IntType size1() const noexcept { return ( ( data() & Mask1 ) >> Shift1 ); } + __host__ __device__ inline IntType size1() const noexcept { return ( ( data() & Mask1 ) >> Shift1 ); } /// Get the total size inline auto totalSize() const noexcept { return size0() + size1(); } diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index 291f769b859..018c7c128aa 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -69,7 +69,7 @@ namespace Rich::Future::DAQ::Allen { // methods /// Get the PDMDB data for given RICH, PDMDB and frame - inline const auto& getFrameData( const int8_t rich, // + __device__ inline const auto& getFrameData( const int8_t rich, // const int8_t pdmdb, // const int8_t link, // const bool isHType ) const noexcept { @@ -92,7 +92,7 @@ namespace Rich::Future::DAQ::Allen { inline auto isInitialised() const noexcept { return m_isInitialised; } /// Get PDMDB data for given Tel40 data - inline const auto& getFrameData( const Tel40CableMapping::Tel40LinkData& cData ) const noexcept { + __device__ inline const auto& getFrameData( const Tel40CableMapping::Tel40LinkData& cData ) const noexcept { auto rich = (cData.smartID >> 20) & 0x1; return getFrameData( rich, cData.pdmdbNum, cData.linkNum, cData.isHType ); diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index 218d13e2ac5..d6ae2143656 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -89,7 +89,7 @@ namespace Rich::Future::DAQ::Allen { } /// Access the Tel40 connection data for a given SourceID - const auto& tel40Data( const int16_t sID ) const { + __device__ const auto& tel40Data( const int16_t sID ) const { const auto payload = sID & 0x3FF; const auto side = (sID >> 10) & 0x1; const auto rich = (sID >> 11) == 9; // Rich1 is 4, Rich2 is 9. Then, Rich1 is identified with 0, Rich2 is 1. @@ -97,7 +97,7 @@ namespace Rich::Future::DAQ::Allen { } // TODO: Use this when the int / boolean info is needed - const auto& tel40Meta( const int16_t sID ) const { + __device__ const auto& tel40Meta( const int16_t sID ) const { const auto payload = sID & 0x3FF; const auto side = (sID >> 10) & 0x1; const auto rich = (sID >> 11) == 9; // Rich1 is 4, Rich2 is 9. Then, Rich1 is identified with 0, Rich2 is 1. -- GitLab From a78276496d6ab1d4cf4e40d169a1e79dc569e524 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Mon, 6 Mar 2023 08:39:01 -0600 Subject: [PATCH 09/63] Fix formatting. --- device/rich/decoding/include/RichDecoding.cuh | 4 +- .../rich/decoding/include/RichDefinitions.cuh | 180 +++++++------- .../include/RichPDMDBDecodeMapping.cuh | 39 +-- .../include/RichTel40CableMapping.cuh | 31 +-- device/rich/decoding/src/RichDecoding.cu | 234 ++++++++++-------- 5 files changed, 262 insertions(+), 226 deletions(-) diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index 4a2733d004b..b695e1d032a 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -97,7 +97,7 @@ namespace rich_decoding { const Constants&, const Allen::Context&) const; - Rich::Future::DAQ::Allen::Tel40CableMapping m_cableMapping; - Rich::Future::DAQ::Allen::PDMDBDecodeMapping m_decodeMapping; + Rich::Future::DAQ::Allen::Tel40CableMapping m_cableMapping; + Rich::Future::DAQ::Allen::PDMDBDecodeMapping m_decodeMapping; }; } // namespace rich_decoding diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index 77f810cd017..66fc13d7456 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -2,87 +2,82 @@ namespace RichSmartID { // Number of bits for each data field in the word - static constexpr const unsigned BitsPixelCol = 3; ///< Number of bits for MaPMT pixel column - static constexpr const unsigned BitsPixelRow = 3; ///< Number of bits for MaPMT pixel row - static constexpr const unsigned BitsPDNumInMod = 4; ///< Number of bits for MaPMT 'number in module' - static constexpr const unsigned BitsPDMod = 9; ///< Number of bits for MaPMT module - static constexpr const unsigned BitsPanel = 1; ///< Number of bits for MaPMT panel - static constexpr const unsigned BitsRich = 1; ///< Number of bits for RICH detector + static constexpr const unsigned BitsPixelCol = 3; ///< Number of bits for MaPMT pixel column + static constexpr const unsigned BitsPixelRow = 3; ///< Number of bits for MaPMT pixel row + static constexpr const unsigned BitsPDNumInMod = 4; ///< Number of bits for MaPMT 'number in module' + static constexpr const unsigned BitsPDMod = 9; ///< Number of bits for MaPMT module + static constexpr const unsigned BitsPanel = 1; ///< Number of bits for MaPMT panel + static constexpr const unsigned BitsRich = 1; ///< Number of bits for RICH detector static constexpr const unsigned BitsPixelSubRowIsSet = 1; - static constexpr const unsigned BitsPixelColIsSet = 1; - static constexpr const unsigned BitsPixelRowIsSet = 1; - static constexpr const unsigned BitsPDIsSet = 1; - static constexpr const unsigned BitsPanelIsSet = 1; - static constexpr const unsigned BitsRichIsSet = 1; - static constexpr const unsigned BitsLargePixel = 1; + static constexpr const unsigned BitsPixelColIsSet = 1; + static constexpr const unsigned BitsPixelRowIsSet = 1; + static constexpr const unsigned BitsPDIsSet = 1; + static constexpr const unsigned BitsPanelIsSet = 1; + static constexpr const unsigned BitsRichIsSet = 1; + static constexpr const unsigned BitsLargePixel = 1; // The shifts - static constexpr const unsigned ShiftPixelCol = 0; - static constexpr const unsigned ShiftPixelRow = ShiftPixelCol + BitsPixelCol; - static constexpr const unsigned ShiftPDNumInMod = ShiftPixelRow + BitsPixelRow; - static constexpr const unsigned ShiftPDMod = ShiftPDNumInMod + BitsPDNumInMod; - static constexpr const unsigned ShiftPanel = ShiftPDMod + BitsPDMod; - static constexpr const unsigned ShiftRich = ShiftPanel + BitsPanel; + static constexpr const unsigned ShiftPixelCol = 0; + static constexpr const unsigned ShiftPixelRow = ShiftPixelCol + BitsPixelCol; + static constexpr const unsigned ShiftPDNumInMod = ShiftPixelRow + BitsPixelRow; + static constexpr const unsigned ShiftPDMod = ShiftPDNumInMod + BitsPDNumInMod; + static constexpr const unsigned ShiftPanel = ShiftPDMod + BitsPDMod; + static constexpr const unsigned ShiftRich = ShiftPanel + BitsPanel; static constexpr const unsigned ShiftPixelSubRowIsSet = ShiftRich + BitsRich; - static constexpr const unsigned ShiftPixelColIsSet = ShiftPixelSubRowIsSet + BitsPixelSubRowIsSet; - static constexpr const unsigned ShiftPixelRowIsSet = ShiftPixelColIsSet + BitsPixelColIsSet; - static constexpr const unsigned ShiftPDIsSet = ShiftPixelRowIsSet + BitsPixelRowIsSet; - static constexpr const unsigned ShiftPanelIsSet = ShiftPDIsSet + BitsPDIsSet; - static constexpr const unsigned ShiftRichIsSet = ShiftPanelIsSet + BitsPanelIsSet; - static constexpr const unsigned ShiftLargePixel = ShiftRichIsSet + BitsRichIsSet; + static constexpr const unsigned ShiftPixelColIsSet = ShiftPixelSubRowIsSet + BitsPixelSubRowIsSet; + static constexpr const unsigned ShiftPixelRowIsSet = ShiftPixelColIsSet + BitsPixelColIsSet; + static constexpr const unsigned ShiftPDIsSet = ShiftPixelRowIsSet + BitsPixelRowIsSet; + static constexpr const unsigned ShiftPanelIsSet = ShiftPDIsSet + BitsPDIsSet; + static constexpr const unsigned ShiftRichIsSet = ShiftPanelIsSet + BitsPanelIsSet; + static constexpr const unsigned ShiftLargePixel = ShiftRichIsSet + BitsRichIsSet; // The masks - static constexpr const unsigned MaskPixelCol = ( unsigned )( ( 1 << BitsPixelCol ) - 1 ) << ShiftPixelCol; - static constexpr const unsigned MaskPixelRow = ( unsigned )( ( 1 << BitsPixelRow ) - 1 ) << ShiftPixelRow; - static constexpr const unsigned MaskPDNumInMod = ( unsigned )( ( 1 << BitsPDNumInMod ) - 1 ) - << ShiftPDNumInMod; - static constexpr const unsigned MaskPDMod = ( unsigned )( ( 1 << BitsPDMod ) - 1 ) << ShiftPDMod; - static constexpr const unsigned MaskPanel = ( unsigned )( ( 1 << BitsPanel ) - 1 ) << ShiftPanel; - static constexpr const unsigned MaskRich = ( unsigned )( ( 1 << BitsRich ) - 1 ) << ShiftRich; - static constexpr const unsigned MaskPixelSubRowIsSet = ( unsigned )( ( 1 << BitsPixelSubRowIsSet ) - 1 ) - << ShiftPixelSubRowIsSet; - static constexpr const unsigned MaskPixelColIsSet = ( unsigned )( ( 1 << BitsPixelColIsSet ) - 1 ) - << ShiftPixelColIsSet; - static constexpr const unsigned MaskPixelRowIsSet = ( unsigned )( ( 1 << BitsPixelRowIsSet ) - 1 ) - << ShiftPixelRowIsSet; - static constexpr const unsigned MaskPDIsSet = ( unsigned )( ( 1 << BitsPDIsSet ) - 1 ) << ShiftPDIsSet; - static constexpr const unsigned MaskPanelIsSet = ( unsigned )( ( 1 << BitsPanelIsSet ) - 1 ) - << ShiftPanelIsSet; - static constexpr const unsigned MaskRichIsSet = ( unsigned )( ( 1 << BitsRichIsSet ) - 1 ) - << ShiftRichIsSet; - static constexpr const unsigned MaskLargePixel = ( unsigned )( ( 1 << BitsLargePixel ) - 1 ) - << ShiftLargePixel; + static constexpr const unsigned MaskPixelCol = (unsigned) ((1 << BitsPixelCol) - 1) << ShiftPixelCol; + static constexpr const unsigned MaskPixelRow = (unsigned) ((1 << BitsPixelRow) - 1) << ShiftPixelRow; + static constexpr const unsigned MaskPDNumInMod = (unsigned) ((1 << BitsPDNumInMod) - 1) << ShiftPDNumInMod; + static constexpr const unsigned MaskPDMod = (unsigned) ((1 << BitsPDMod) - 1) << ShiftPDMod; + static constexpr const unsigned MaskPanel = (unsigned) ((1 << BitsPanel) - 1) << ShiftPanel; + static constexpr const unsigned MaskRich = (unsigned) ((1 << BitsRich) - 1) << ShiftRich; + static constexpr const unsigned MaskPixelSubRowIsSet = (unsigned) ((1 << BitsPixelSubRowIsSet) - 1) + << ShiftPixelSubRowIsSet; + static constexpr const unsigned MaskPixelColIsSet = (unsigned) ((1 << BitsPixelColIsSet) - 1) << ShiftPixelColIsSet; + static constexpr const unsigned MaskPixelRowIsSet = (unsigned) ((1 << BitsPixelRowIsSet) - 1) << ShiftPixelRowIsSet; + static constexpr const unsigned MaskPDIsSet = (unsigned) ((1 << BitsPDIsSet) - 1) << ShiftPDIsSet; + static constexpr const unsigned MaskPanelIsSet = (unsigned) ((1 << BitsPanelIsSet) - 1) << ShiftPanelIsSet; + static constexpr const unsigned MaskRichIsSet = (unsigned) ((1 << BitsRichIsSet) - 1) << ShiftRichIsSet; + static constexpr const unsigned MaskLargePixel = (unsigned) ((1 << BitsLargePixel) - 1) << ShiftLargePixel; // Max Values - static constexpr const unsigned MaxPixelCol = ( unsigned )( 1 << BitsPixelCol ) - 1; - static constexpr const unsigned MaxPixelRow = ( unsigned )( 1 << BitsPixelRow ) - 1; - static constexpr const unsigned MaxPDNumInMod = ( unsigned )( 1 << BitsPDNumInMod ) - 1; - static constexpr const unsigned MaxPDMod = ( unsigned )( 1 << BitsPDMod ) - 1; - static constexpr const unsigned MaxPanel = ( unsigned )( 1 << BitsPanel ) - 1; - static constexpr const unsigned MaxRich = ( unsigned )( 1 << BitsRich ) - 1; - - constexpr inline unsigned bits( const unsigned key, - const unsigned value, - const unsigned shift, - const unsigned mask ) noexcept { - return ( ( value << shift ) & mask ) | ( key & ~mask ); + static constexpr const unsigned MaxPixelCol = (unsigned) (1 << BitsPixelCol) - 1; + static constexpr const unsigned MaxPixelRow = (unsigned) (1 << BitsPixelRow) - 1; + static constexpr const unsigned MaxPDNumInMod = (unsigned) (1 << BitsPDNumInMod) - 1; + static constexpr const unsigned MaxPDMod = (unsigned) (1 << BitsPDMod) - 1; + static constexpr const unsigned MaxPanel = (unsigned) (1 << BitsPanel) - 1; + static constexpr const unsigned MaxRich = (unsigned) (1 << BitsRich) - 1; + + constexpr inline unsigned + bits(const unsigned key, const unsigned value, const unsigned shift, const unsigned mask) noexcept + { + return ((value << shift) & mask) | (key & ~mask); } - constexpr inline unsigned bits( const unsigned key, - const unsigned value, // - const unsigned shift, // - const unsigned mask, // - const unsigned okMask ) noexcept { - return ( ( value << shift ) & mask ) | ( key & ~mask ) | okMask; + constexpr inline unsigned bits( + const unsigned key, + const unsigned value, // + const unsigned shift, // + const unsigned mask, // + const unsigned okMask) noexcept + { + return ((value << shift) & mask) | (key & ~mask) | okMask; } -} +} // namespace RichSmartID namespace Rich::Future::DAQ { enum DetectorType : std::int8_t { InvalidDetector = -1, ///< Unspecified Detector - Rich1 = 0, ///< RICH1 detector - Rich2 = 1, ///< RICH2 detector - Rich = 1 ///< Single RICH detector + Rich1 = 0, ///< RICH1 detector + Rich2 = 1, ///< RICH2 detector + Rich = 1 ///< Single RICH detector }; class PackedFrameSizes final { @@ -98,46 +93,51 @@ namespace Rich::Future::DAQ { static const IntType Shift0 = 0; static const IntType Shift1 = Shift0 + Bits0; // masks - static const IntType Mask0 = ( IntType )( ( 1 << Bits0 ) - 1 ) << Shift0; - static const IntType Mask1 = ( IntType )( ( 1 << Bits1 ) - 1 ) << Shift1; + static const IntType Mask0 = (IntType) ((1 << Bits0) - 1) << Shift0; + static const IntType Mask1 = (IntType) ((1 << Bits1) - 1) << Shift1; // max values - static const IntType Max0 = ( 1 << Bits0 ) - 1; - static const IntType Max1 = ( 1 << Bits1 ) - 1; + static const IntType Max0 = (1 << Bits0) - 1; + static const IntType Max1 = (1 << Bits1) - 1; private: /// Set the overall word - inline void setData( const IntType data ) { m_data = data; } + inline void setData(const IntType data) { m_data = data; } /// Set data for given word - inline void set( const IntType value, // - const IntType shift, // - const IntType mask ) { - setData( ( ( value << shift ) & mask ) | ( data() & ~mask ) ); + inline void set( + const IntType value, // + const IntType shift, // + const IntType mask) + { + setData(((value << shift) & mask) | (data() & ~mask)); } public: /// Constructor from two sizes - PackedFrameSizes( const IntType size0, const IntType size1 ) { - set( size0, Shift0, Mask0 ); - set( size1, Shift1, Mask1 ); + PackedFrameSizes(const IntType size0, const IntType size1) + { + set(size0, Shift0, Mask0); + set(size1, Shift1, Mask1); } /// Contructor from a single word - __device__ explicit PackedFrameSizes( const IntType d ) : m_data( d ) {} + __device__ explicit PackedFrameSizes(const IntType d) : m_data(d) {} public: /// Set size0 - inline void setSize0( const IntType size0 ) noexcept { set( size0, Shift0, Mask0 ); } + inline void setSize0(const IntType size0) noexcept { set(size0, Shift0, Mask0); } /// Set size1 - inline void setSize1( const IntType size1 ) noexcept { set( size1, Shift1, Mask1 ); } + inline void setSize1(const IntType size1) noexcept { set(size1, Shift1, Mask1); } /// set the size for the give word number - inline void setSize( const IntType size, const IntType word ) noexcept { - if ( 0 == word ) { - setSize0( size ); - } else { - setSize1( size ); + inline void setSize(const IntType size, const IntType word) noexcept + { + if (0 == word) { + setSize0(size); + } + else { + setSize1(size); } } @@ -146,16 +146,16 @@ namespace Rich::Future::DAQ { __host__ __device__ inline IntType data() const noexcept { return m_data; } /// Get first size word - __host__ __device__ inline IntType size0() const noexcept { return ( ( data() & Mask0 ) >> Shift0 ); } + __host__ __device__ inline IntType size0() const noexcept { return ((data() & Mask0) >> Shift0); } /// Get second size word - __host__ __device__ inline IntType size1() const noexcept { return ( ( data() & Mask1 ) >> Shift1 ); } + __host__ __device__ inline IntType size1() const noexcept { return ((data() & Mask1) >> Shift1); } /// Get the total size inline auto totalSize() const noexcept { return size0() + size1(); } private: /// The data word - IntType m_data{0}; + IntType m_data {0}; }; -} \ No newline at end of file +} // namespace Rich::Future::DAQ \ No newline at end of file diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index 018c7c128aa..3e5c25e7de8 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -32,10 +32,13 @@ namespace Rich::Future::DAQ::Allen { /// Default constructor BitData() = default; /// Constructor from values - BitData( const int8_t _ec, // - const int8_t _pmt, // - const int8_t _anode ) - : ec( _ec ), pmtInEC( _pmt ), anode( _anode ) {} + BitData( + const int8_t _ec, // + const int8_t _pmt, // + const int8_t _anode) : + ec(_ec), + pmtInEC(_pmt), anode(_anode) + {} }; private: @@ -69,17 +72,20 @@ namespace Rich::Future::DAQ::Allen { // methods /// Get the PDMDB data for given RICH, PDMDB and frame - __device__ inline const auto& getFrameData( const int8_t rich, // - const int8_t pdmdb, // - const int8_t link, // - const bool isHType ) const noexcept { + __device__ inline const auto& getFrameData( + const int8_t rich, // + const int8_t pdmdb, // + const int8_t link, // + const bool isHType) const noexcept + { // Note as this is called many times from the decoding, avoid runtime range checking // in optimised builds, as once OK it should never be invalidated. // This is though tested in the debug builds via the asserts. - if ( !isHType ) { + if (!isHType) { // R type PMT return m_pdmDataR[rich][pdmdb][link]; - } else { + } + else { return m_pdmDataH[pdmdb][link]; } } @@ -92,10 +98,11 @@ namespace Rich::Future::DAQ::Allen { inline auto isInitialised() const noexcept { return m_isInitialised; } /// Get PDMDB data for given Tel40 data - __device__ inline const auto& getFrameData( const Tel40CableMapping::Tel40LinkData& cData ) const noexcept { + __device__ inline const auto& getFrameData(const Tel40CableMapping::Tel40LinkData& cData) const noexcept + { auto rich = (cData.smartID >> 20) & 0x1; - - return getFrameData( rich, cData.pdmdbNum, cData.linkNum, cData.isHType ); + + return getFrameData(rich, cData.pdmdbNum, cData.linkNum, cData.isHType); } private: @@ -108,10 +115,10 @@ namespace Rich::Future::DAQ::Allen { PDMData m_pdmDataH; // std::array /// Flag to indicate initialisation status - bool m_isInitialised{false}; + bool m_isInitialised {false}; /// Mapping version - int m_mappingVer{-1}; + int m_mappingVer {-1}; }; -} // namespace Rich::Future::DAQ +} // namespace Rich::Future::DAQ::Allen diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index d6ae2143656..836d8751ac2 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -14,7 +14,6 @@ namespace Rich::Future::DAQ::Allen { class Tel40CableMapping final { public: - /// Struct for storing data for each Tel40 Link class Tel40LinkData final { public: @@ -31,9 +30,9 @@ namespace Rich::Future::DAQ::Allen { /// Link number int8_t linkNum; /// PMT type - bool isHType{false}; + bool isHType {false}; /// Is Link Active - bool isActive{false}; + bool isActive {false}; public: /// Default constructor @@ -75,33 +74,37 @@ namespace Rich::Future::DAQ::Allen { inline bool isInitialised() const noexcept { return m_isInitialised; } /// Access the Tel40 Link data for given channel ID - const auto& tel40Data( const uint32_t id, // PD ID - const int8_t pdmdb, // PDMDB ID - const int8_t frame // PDMDB Frame - ) const noexcept { + const auto& tel40Data( + const uint32_t id, // PD ID + const int8_t pdmdb, // PDMDB ID + const int8_t frame // PDMDB Frame + ) const noexcept + { // module number const auto modN = (id >> 6) & 0xF; // TODO: RichSmartID.h:912 // return tel40 data - const auto& data = m_tel40ModuleData.at( modN ).at( pdmdb ).at( frame ); + const auto& data = m_tel40ModuleData.at(modN).at(pdmdb).at(frame); // finally return return data; } /// Access the Tel40 connection data for a given SourceID - __device__ const auto& tel40Data( const int16_t sID ) const { + __device__ const auto& tel40Data(const int16_t sID) const + { const auto payload = sID & 0x3FF; const auto side = (sID >> 10) & 0x1; const auto rich = (sID >> 11) == 9; // Rich1 is 4, Rich2 is 9. Then, Rich1 is identified with 0, Rich2 is 1. - return m_tel40ConnData.at( rich ).at( side ).at( payload ); + return m_tel40ConnData.at(rich).at(side).at(payload); } // TODO: Use this when the int / boolean info is needed - __device__ const auto& tel40Meta( const int16_t sID ) const { + __device__ const auto& tel40Meta(const int16_t sID) const + { const auto payload = sID & 0x3FF; const auto side = (sID >> 10) & 0x1; const auto rich = (sID >> 11) == 9; // Rich1 is 4, Rich2 is 9. Then, Rich1 is identified with 0, Rich2 is 1. - return m_tel40ConnMeta.at( rich ).at( side ).at( payload ); + return m_tel40ConnMeta.at(rich).at(side).at(payload); } /// mapping version @@ -118,10 +121,10 @@ namespace Rich::Future::DAQ::Allen { ModuleTel40Data m_tel40ModuleData; /// Flag to indicate initialisation status - bool m_isInitialised{false}; + bool m_isInitialised {false}; /// Mapping version - int m_mappingVer{-1}; + int m_mappingVer {-1}; }; } // namespace Rich::Future::DAQ::Allen \ No newline at end of file diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index a0763ea9fd7..57bb2cb0b3f 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -15,31 +15,36 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( { unsigned number_of_hits = 0; - std::array connSizes{}; + std::array< + Rich::Future::DAQ::PackedFrameSizes::IntType, + Rich::Future::DAQ::Allen::Tel40CableMapping::MaxConnectionsPerTel40> + connSizes {}; auto tel40ID = bank.source_id; - const auto& connMeta = m_cableMapping.tel40Meta( tel40ID ); + const auto& connMeta = m_cableMapping.tel40Meta(tel40ID); const auto nSizeWords = std::get<1>(connMeta); - const auto nPackedSizeW = ( nSizeWords / 2 ) + ( nSizeWords % 2 ); + const auto nPackedSizeW = (nSizeWords / 2) + (nSizeWords % 2); auto dataW = bank.data; auto bankEnd = bank.data + bank.size; auto iPayloadWord = 0u; auto iWord = 0u; - for ( ; iWord < nPackedSizeW && dataW != bankEnd; ++dataW, ++iWord, iPayloadWord += 2 ) { + for (; iWord < nPackedSizeW && dataW != bankEnd; ++dataW, ++iWord, iPayloadWord += 2) { // Extract the sizes from the packed word - const Rich::Future::DAQ::PackedFrameSizes sizes( *dataW ); + const Rich::Future::DAQ::PackedFrameSizes sizes(*dataW); // extract sizes for each packed value connSizes[iPayloadWord] = sizes.size1(); connSizes[iPayloadWord + 1] = sizes.size0(); } - const auto& connData = m_cableMapping.tel40Data( tel40ID ); + const auto& connData = m_cableMapping.tel40Data(tel40ID); if (std::get<0>(connMeta)) { - for ( std::size_t iL = 0; iL < connData.size(); ++iL ) { - if ( !connData[iL].isActive ) { - for ( auto i = connData.size() - 1; i > iL; --i ) { connSizes[i] = connSizes[i - 1]; } + for (std::size_t iL = 0; iL < connData.size(); ++iL) { + if (!connData[iL].isActive) { + for (auto i = connData.size() - 1; i > iL; --i) { + connSizes[i] = connSizes[i - 1]; + } connSizes[iL] = 0; } } @@ -47,74 +52,74 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( // finally loop over payload words and decode hits // note iterator starts from where the above header loop ended... - std::size_t iLink{0}; - while ( dataW != bankEnd && iLink < connSizes.size() ) { + std::size_t iLink {0}; + while (dataW != bankEnd && iLink < connSizes.size()) { // Do we have any words to decode for this link - if ( connSizes[iLink] > 0 ) { + if (connSizes[iLink] > 0) { // Get the Tel40 Data for this connection const auto& cData = connData[iLink]; // get the PDMDB data - const auto& frameData = m_decodeMapping.getFrameData( cData ); + const auto& frameData = m_decodeMapping.getFrameData(cData); // Loop over the words for this link uint16_t iW = 0; - while ( iW < connSizes[iLink] && dataW != bankEnd ) { + while (iW < connSizes[iLink] && dataW != bankEnd) { // check MSB for this word // TODO: Check const auto isNZS = isBitOn( *dataW ); const auto isNZS = (0x80000000 & *dataW) != 0; - if ( !isNZS ) { + if (!isNZS) { // ZS decoding... word is bit index // load the anode data for this bit - if ( ( std::size_t )( *dataW ) < frameData.size() ) { + if ((std::size_t)(*dataW) < frameData.size()) { number_of_hits++; } // move to next word ++iW; ++dataW; - - } else { + } + else { // NZS decoding... // which half of the payload are we in ? - const bool firstHalf = ( 0 == iW && connSizes[iLink] > 5 ); + const bool firstHalf = (0 == iW && connSizes[iLink] > 5); // Number of words to decode depends on which half of the payload we are in - const auto nNZSwords = ( firstHalf ? 6 : 5 ); + const auto nNZSwords = (firstHalf ? 6 : 5); // bit offset per half - const auto halfBitOffset = ( firstHalf ? 39 : 0 ); + const auto halfBitOffset = (firstHalf ? 39 : 0); // look forward last NZS word and read backwards to match frame bit order - for ( auto iNZS = nNZSwords - 1; iNZS >= 0; --iNZS ) { + for (auto iNZS = nNZSwords - 1; iNZS >= 0; --iNZS) { // read the NZS word - auto nzsW = *( dataW + iNZS ); + auto nzsW = *(dataW + iNZS); // if word zero clear MSB as this is the NZS flag - if ( 0 == iNZS ) { + if (0 == iNZS) { // TODO: Check this is correct setBitOff( nzsW ); nzsW &= 0x7FFFFFFF; } // does this word hold any active bits ? - if ( nzsW > 0 ) { + if (nzsW > 0) { // Bit offset for this word - const auto bitOffset = halfBitOffset + ( 8 * ( nNZSwords - 1 - iNZS ) ); + const auto bitOffset = halfBitOffset + (8 * (nNZSwords - 1 - iNZS)); // word has data so loop over bits to extract - for ( auto iLB = 0; iLB < 8; ++iLB ) { + for (auto iLB = 0; iLB < 8; ++iLB) { // is bit on ? // if ( isBitOn( nzsW, iLB ) ) { - if ( (nzsW & (1 << iLB)) != 0) { + if ((nzsW & (1 << iLB)) != 0) { // form frame bit value const auto bit = iLB + bitOffset; // load the anode data for this bit - if ( ( size_t )( bit ) < frameData.size() ) { + if ((size_t) (bit) < frameData.size()) { number_of_hits++; } @@ -150,17 +155,18 @@ __global__ void rich_calculate_number_of_hits( const auto event_number = parameters.dev_event_list[blockIdx.x]; // Read raw event - const auto raw_event = - Rich::RawEvent {parameters.dev_rich_raw_input, - parameters.dev_rich_raw_input_offsets, - parameters.dev_rich_raw_input_sizes, - parameters.dev_rich_raw_input_types, - event_number + event_start}; + const auto raw_event = Rich::RawEvent { + parameters.dev_rich_raw_input, + parameters.dev_rich_raw_input_offsets, + parameters.dev_rich_raw_input_sizes, + parameters.dev_rich_raw_input_types, + event_number + event_start}; // std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); - const auto number_of_hits_in_raw_bank = rich_calculate_number_of_hits_in_raw_bank(bank, m_cableMapping, m_decodeMapping); + const auto number_of_hits_in_raw_bank = + rich_calculate_number_of_hits_in_raw_bank(bank, m_cableMapping, m_decodeMapping); // std::cout << "Number of hits in raw bank " << bank_number << ": " << number_of_hits_in_raw_bank << "\n"; if (number_of_hits_in_raw_bank > 0) { atomicAdd(parameters.dev_rich_number_of_hits + event_number, number_of_hits_in_raw_bank); @@ -176,31 +182,36 @@ __device__ void rich_decode_bank( unsigned* event_smart_ids) { // std::cout << "Bank: sourceID " << bank.source_id << ", size " << bank.size << "\n"; - std::array connSizes{}; + std::array< + Rich::Future::DAQ::PackedFrameSizes::IntType, + Rich::Future::DAQ::Allen::Tel40CableMapping::MaxConnectionsPerTel40> + connSizes {}; auto tel40ID = bank.source_id; - const auto& connMeta = m_cableMapping.tel40Meta( tel40ID ); + const auto& connMeta = m_cableMapping.tel40Meta(tel40ID); const auto nSizeWords = std::get<1>(connMeta); - const auto nPackedSizeW = ( nSizeWords / 2 ) + ( nSizeWords % 2 ); + const auto nPackedSizeW = (nSizeWords / 2) + (nSizeWords % 2); auto dataW = bank.data; auto bankEnd = bank.data + bank.size; auto iPayloadWord = 0u; auto iWord = 0u; - for ( ; iWord < nPackedSizeW && dataW != bankEnd; ++dataW, ++iWord, iPayloadWord += 2 ) { + for (; iWord < nPackedSizeW && dataW != bankEnd; ++dataW, ++iWord, iPayloadWord += 2) { // Extract the sizes from the packed word - const Rich::Future::DAQ::PackedFrameSizes sizes( *dataW ); + const Rich::Future::DAQ::PackedFrameSizes sizes(*dataW); // extract sizes for each packed value connSizes[iPayloadWord] = sizes.size1(); connSizes[iPayloadWord + 1] = sizes.size0(); } - const auto& connData = m_cableMapping.tel40Data( tel40ID ); + const auto& connData = m_cableMapping.tel40Data(tel40ID); if (std::get<0>(connMeta)) { - for ( std::size_t iL = 0; iL < connData.size(); ++iL ) { - if ( !connData[iL].isActive ) { - for ( auto i = connData.size() - 1; i > iL; --i ) { connSizes[i] = connSizes[i - 1]; } + for (std::size_t iL = 0; iL < connData.size(); ++iL) { + if (!connData[iL].isActive) { + for (auto i = connData.size() - 1; i > iL; --i) { + connSizes[i] = connSizes[i - 1]; + } connSizes[iL] = 0; } } @@ -208,29 +219,29 @@ __device__ void rich_decode_bank( // finally loop over payload words and decode hits // note iterator starts from where the above header loop ended... - std::size_t iLink{0}; - while ( dataW != bankEnd && iLink < connSizes.size() ) { + std::size_t iLink {0}; + while (dataW != bankEnd && iLink < connSizes.size()) { // Do we have any words to decode for this link - if ( connSizes[iLink] > 0 ) { + if (connSizes[iLink] > 0) { // Get the Tel40 Data for this connection const auto& cData = connData[iLink]; // get the PDMDB data - const auto& frameData = m_decodeMapping.getFrameData( cData ); + const auto& frameData = m_decodeMapping.getFrameData(cData); // Loop over the words for this link uint16_t iW = 0; - while ( iW < connSizes[iLink] && dataW != bankEnd ) { + while (iW < connSizes[iLink] && dataW != bankEnd) { // check MSB for this word // TODO: Check const auto isNZS = isBitOn( *dataW ); const auto isNZS = (0x80000000 & *dataW) != 0; - if ( !isNZS ) { + if (!isNZS) { // ZS decoding... word is bit index // load the anode data for this bit - if ( ( std::size_t )( *dataW ) < frameData.size() ) { + if ((std::size_t)(*dataW) < frameData.size()) { const auto& aData = frameData[*dataW]; @@ -241,15 +252,18 @@ __device__ void rich_decode_bank( auto hitID = cData.smartID; // sets RICH, side, module and PMT type // Add the PMT and pixel info - const auto nInMod = ( aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4) ) + aData.pmtInEC; - hitID = RichSmartID::bits(hitID, cData.moduleNum, RichSmartID::ShiftPDMod, RichSmartID::MaskPDMod, RichSmartID::MaskPDIsSet ); + const auto nInMod = (aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; + hitID = RichSmartID::bits( + hitID, cData.moduleNum, RichSmartID::ShiftPDMod, RichSmartID::MaskPDMod, RichSmartID::MaskPDIsSet); hitID = RichSmartID::bits(hitID, nInMod, RichSmartID::ShiftPDNumInMod, RichSmartID::MaskPDNumInMod); // std::cout << "hitID after setPD_EC_PMT " << ((unsigned) hitID) << "\n"; const auto row = aData.anode / 8; - const auto col = 8 - 1 - ( aData.anode % 8 ); - hitID = RichSmartID::bits( hitID, row, RichSmartID::ShiftPixelRow, RichSmartID::MaskPixelRow, RichSmartID::MaskPixelRowIsSet ); - hitID = RichSmartID::bits( hitID, col, RichSmartID::ShiftPixelCol, RichSmartID::MaskPixelCol, RichSmartID::MaskPixelColIsSet ); + const auto col = 8 - 1 - (aData.anode % 8); + hitID = RichSmartID::bits( + hitID, row, RichSmartID::ShiftPixelRow, RichSmartID::MaskPixelRow, RichSmartID::MaskPixelRowIsSet); + hitID = RichSmartID::bits( + hitID, col, RichSmartID::ShiftPixelCol, RichSmartID::MaskPixelCol, RichSmartID::MaskPixelColIsSet); // std::cout << "hitID after Anode " << hitID << "\n"; const auto insert_index = atomicAdd(event_inserted_hits, 1); @@ -259,45 +273,45 @@ __device__ void rich_decode_bank( // move to next word ++iW; ++dataW; - - } else { + } + else { // NZS decoding... // which half of the payload are we in ? - const bool firstHalf = ( 0 == iW && connSizes[iLink] > 5 ); + const bool firstHalf = (0 == iW && connSizes[iLink] > 5); // Number of words to decode depends on which half of the payload we are in - const auto nNZSwords = ( firstHalf ? 6 : 5 ); + const auto nNZSwords = (firstHalf ? 6 : 5); // bit offset per half - const auto halfBitOffset = ( firstHalf ? 39 : 0 ); + const auto halfBitOffset = (firstHalf ? 39 : 0); // look forward last NZS word and read backwards to match frame bit order - for ( auto iNZS = nNZSwords - 1; iNZS >= 0; --iNZS ) { + for (auto iNZS = nNZSwords - 1; iNZS >= 0; --iNZS) { // read the NZS word - auto nzsW = *( dataW + iNZS ); + auto nzsW = *(dataW + iNZS); // if word zero clear MSB as this is the NZS flag - if ( 0 == iNZS ) { + if (0 == iNZS) { // TODO: Check this is correct setBitOff( nzsW ); nzsW &= 0x7FFFFFFF; } // does this word hold any active bits ? - if ( nzsW > 0 ) { + if (nzsW > 0) { // Bit offset for this word - const auto bitOffset = halfBitOffset + ( 8 * ( nNZSwords - 1 - iNZS ) ); + const auto bitOffset = halfBitOffset + (8 * (nNZSwords - 1 - iNZS)); // word has data so loop over bits to extract - for ( auto iLB = 0; iLB < 8; ++iLB ) { + for (auto iLB = 0; iLB < 8; ++iLB) { // is bit on ? // if ( isBitOn( nzsW, iLB ) ) { - if ( (nzsW & (1 << iLB)) != 0) { + if ((nzsW & (1 << iLB)) != 0) { // form frame bit value const auto bit = iLB + bitOffset; // load the anode data for this bit - if ( ( size_t )( bit ) < frameData.size() ) { + if ((size_t) (bit) < frameData.size()) { const auto& aData = frameData[bit]; // TODO: Data 'could' be invalid, e.g. radiation-induced-upsets // so cannot make this a hard error @@ -306,15 +320,30 @@ __device__ void rich_decode_bank( auto hitID = cData.smartID; // sets RICH, side, module and PMT type // Add the PMT and pixel info - const auto nInMod = ( aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4) ) + aData.pmtInEC; - hitID = RichSmartID::bits(hitID, cData.moduleNum, RichSmartID::ShiftPDMod, RichSmartID::MaskPDMod, RichSmartID::MaskPDIsSet ); + const auto nInMod = (aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; + hitID = RichSmartID::bits( + hitID, + cData.moduleNum, + RichSmartID::ShiftPDMod, + RichSmartID::MaskPDMod, + RichSmartID::MaskPDIsSet); hitID = RichSmartID::bits(hitID, nInMod, RichSmartID::ShiftPDNumInMod, RichSmartID::MaskPDNumInMod); // std::cout << "hitID after setPD_EC_PMT " << ((unsigned) hitID) << "\n"; const auto row = aData.anode / 8; - const auto col = 8 - 1 - ( aData.anode % 8 ); - hitID = RichSmartID::bits( hitID, row, RichSmartID::ShiftPixelRow, RichSmartID::MaskPixelRow, RichSmartID::MaskPixelRowIsSet ); - hitID = RichSmartID::bits( hitID, col, RichSmartID::ShiftPixelCol, RichSmartID::MaskPixelCol, RichSmartID::MaskPixelColIsSet ); + const auto col = 8 - 1 - (aData.anode % 8); + hitID = RichSmartID::bits( + hitID, + row, + RichSmartID::ShiftPixelRow, + RichSmartID::MaskPixelRow, + RichSmartID::MaskPixelRowIsSet); + hitID = RichSmartID::bits( + hitID, + col, + RichSmartID::ShiftPixelCol, + RichSmartID::MaskPixelCol, + RichSmartID::MaskPixelColIsSet); // std::cout << "hitID after Anode " << hitID << "\n"; const auto insert_index = atomicAdd(event_inserted_hits, 1); @@ -354,12 +383,12 @@ __global__ void rich_decoding_kernel( auto event_smart_ids = parameters.dev_smart_ids + parameters.dev_rich_hit_offsets[event_number]; // Read raw event - const auto raw_event = - Rich::RawEvent {parameters.dev_rich_raw_input, - parameters.dev_rich_raw_input_offsets, - parameters.dev_rich_raw_input_sizes, - parameters.dev_rich_raw_input_types, - event_number + event_start}; + const auto raw_event = Rich::RawEvent { + parameters.dev_rich_raw_input, + parameters.dev_rich_raw_input_offsets, + parameters.dev_rich_raw_input_sizes, + parameters.dev_rich_raw_input_types, + event_number + event_start}; // std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { @@ -368,22 +397,23 @@ __global__ void rich_decoding_kernel( } } -void rich_decoding::rich_decoding_t::init() { +void rich_decoding::rich_decoding_t::init() +{ std::fstream file; file.open("/home/cnca/dcampora/stack/pdmdbMaps.bin", std::ios::in | std::ios::binary); - file.seekg (0, std::ios::end); + file.seekg(0, std::ios::end); auto size = file.tellg(); - file.seekg (0, std::ios::beg); + file.seekg(0, std::ios::beg); std::cout << "Loading pdmdbMaps. Size of file " << size << ", size of datatype " << sizeof(m_decodeMapping) << "\n"; - file.read (reinterpret_cast(&m_decodeMapping), size); + file.read(reinterpret_cast(&m_decodeMapping), size); file.close(); file.open("/home/cnca/dcampora/stack/tel40Maps.bin", std::ios::in | std::ios::binary); - file.seekg (0, std::ios::end); + file.seekg(0, std::ios::end); size = file.tellg(); - file.seekg (0, std::ios::beg); + file.seekg(0, std::ios::beg); std::cout << "Loading tel40Maps. Size of file " << size << ", size of datatype " << sizeof(m_cableMapping) << "\n"; - file.read (reinterpret_cast(&m_cableMapping), size); + file.read(reinterpret_cast(&m_cableMapping), size); file.close(); } @@ -410,16 +440,15 @@ void rich_decoding::rich_decoding_t::operator()( // Calculate number of hits into dev_rich_number_of_hits_t Allen::memset_async(arguments, 0, context); - global_function(runtime_options.mep_layout ? rich_calculate_number_of_hits : rich_calculate_number_of_hits) - (dim3(size(arguments)), 64, context)( - arguments, - std::get<0>(runtime_options.event_interval), - m_cableMapping, - m_decodeMapping); - + global_function( + runtime_options.mep_layout ? rich_calculate_number_of_hits : rich_calculate_number_of_hits)( + dim3(size(arguments)), 64, context)( + arguments, std::get<0>(runtime_options.event_interval), m_cableMapping, m_decodeMapping); + // Copy to host data(arguments)[0] = 0; - Allen::copy(arguments, context, size(arguments), 1, 0); + Allen::copy( + arguments, context, size(arguments), 1, 0); // Prefix sum host_prefix_sum::host_prefix_sum_impl( @@ -433,14 +462,11 @@ void rich_decoding::rich_decoding_t::operator()( // Decode RICH hits Allen::memset_async(arguments, 0, context); resize(arguments, first(arguments)); - - global_function(runtime_options.mep_layout ? rich_decoding_kernel : rich_decoding_kernel) - (dim3(size(arguments)), 1, context)( - arguments, - std::get<0>(runtime_options.event_interval), - m_cableMapping, - m_decodeMapping); - + + global_function(runtime_options.mep_layout ? rich_decoding_kernel : rich_decoding_kernel)( + dim3(size(arguments)), 1, context)( + arguments, std::get<0>(runtime_options.event_interval), m_cableMapping, m_decodeMapping); + // Print output print(arguments); print(arguments); -- GitLab From f20f94c0cbb7ce5c6888313385795809c8dbaec6 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Mon, 6 Mar 2023 13:28:51 -0600 Subject: [PATCH 10/63] Refactor RawEvent and RawBank to a common place, used by RICH and Calo. --- device/calo/decoding/include/CaloDecode.cuh | 1 - device/calo/decoding/src/CaloDecode.cu | 10 ++- .../event_model/calo/include/CaloRawEvent.cuh | 78 ------------------- device/rich/decoding/include/RichDecoding.cuh | 61 --------------- device/rich/decoding/src/RichDecoding.cu | 8 +- main/include/MEPTools.h | 61 +++++++++++++++ 6 files changed, 71 insertions(+), 148 deletions(-) delete mode 100644 device/event_model/calo/include/CaloRawEvent.cuh diff --git a/device/calo/decoding/include/CaloDecode.cuh b/device/calo/decoding/include/CaloDecode.cuh index 099db76c8f4..eb1e93ab8e8 100644 --- a/device/calo/decoding/include/CaloDecode.cuh +++ b/device/calo/decoding/include/CaloDecode.cuh @@ -4,7 +4,6 @@ #pragma once -#include "CaloRawEvent.cuh" #include "CaloGeometry.cuh" #include "CaloDigit.cuh" #include "AlgorithmTypes.cuh" diff --git a/device/calo/decoding/src/CaloDecode.cu b/device/calo/decoding/src/CaloDecode.cu index 2c5f79b90b5..2abdd75ed1b 100644 --- a/device/calo/decoding/src/CaloDecode.cu +++ b/device/calo/decoding/src/CaloDecode.cu @@ -34,10 +34,11 @@ namespace { for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { auto raw_bank = raw_event.raw_bank(bank_number); + const auto raw_bank_end = raw_bank.data + raw_bank.size; if constexpr (decoding_version < 4) { // old decoding - while (raw_bank.data < raw_bank.end) { + while (raw_bank.data < raw_bank_end) { uint32_t word = *raw_bank.data; uint16_t trig_size = word & 0x7F; uint16_t code = (word >> 14) & 0x1FF; @@ -100,8 +101,9 @@ namespace { auto raw_bank_fiberCheck = raw_event_fiberCheck.raw_bank(bank_number); - auto get_data = [](uint32_t const* raw_data) { - auto d = *raw_data; + auto get_data = [](uint8_t const* raw_data) { + const auto raw_data_u32 = reinterpret_cast(raw_data); + auto d = *raw_data_u32; if constexpr (decoding_version == 4) { // big endian d = ((d >> 24) & 0x000000FF) | ((d >> 8) & 0x0000FF00) | ((d << 8) & 0x00FF0000) | ((d << 24) & 0xFF000000); } @@ -235,7 +237,7 @@ __global__ void calo_decode_dispatch( auto ecal_geometry = CaloGeometry(raw_ecal_geometry); auto const ecal_digits_offset = parameters.dev_ecal_digits_offsets[event_number]; - decode, decoding_version>( + decode, decoding_version>( parameters.dev_ecal_raw_input, parameters.dev_ecal_raw_input_offsets, parameters.dev_ecal_raw_input_sizes, diff --git a/device/event_model/calo/include/CaloRawEvent.cuh b/device/event_model/calo/include/CaloRawEvent.cuh deleted file mode 100644 index 71f4886e0d7..00000000000 --- a/device/event_model/calo/include/CaloRawEvent.cuh +++ /dev/null @@ -1,78 +0,0 @@ -/*****************************************************************************\ -* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration * -* * -* This software is distributed under the terms of the Apache License * -* version 2 (Apache-2.0), copied verbatim in the file "LICENSE". * -* * -* In applying this licence, CERN does not waive the privileges and immunities * -* granted to it by virtue of its status as an Intergovernmental Organization * -* or submit itself to any jurisdiction. * -\*****************************************************************************/ -#pragma once - -#include -#include "BackendCommon.h" -#include "MEPTools.h" - -namespace Calo { - - struct RawBank { - uint32_t source_id = 0; - uint32_t const* data = nullptr; - uint32_t const* end = nullptr; - uint8_t const type; - - // For Allen format - __device__ __host__ RawBank(const char* raw_bank, const uint16_t s, const uint8_t t) : - RawBank {*reinterpret_cast(raw_bank), raw_bank + sizeof(uint32_t), s, t} - {} - - // For MEP format - __device__ __host__ RawBank(const uint32_t sid, const char* fragment, const uint16_t s, const uint8_t t) : - source_id {sid}, data {reinterpret_cast(fragment)}, - end {reinterpret_cast(fragment + s)}, type {t} - {} - }; - - template - struct RawEvent { - - uint32_t number_of_raw_banks = 0; - const char* data = nullptr; - const uint32_t* offsets = nullptr; - typename std::conditional_t* sizes = nullptr; - typename std::conditional_t* types = nullptr; - const unsigned event = 0; - - // For Allen format - __device__ __host__ - RawEvent(char const* d, uint32_t const* o, uint32_t const* s, uint32_t const* t, unsigned const event_number) : - offsets {o}, - event {event_number} - { - if constexpr (mep_layout) { - data = d; - number_of_raw_banks = MEP::number_of_banks(o); - sizes = s; - types = t; - } - else { - data = d + offsets[event]; - number_of_raw_banks = reinterpret_cast(data)[0]; - sizes = Allen::bank_sizes(s, event); - types = Allen::bank_types(t, event); - } - } - - __device__ __host__ RawBank raw_bank(unsigned const n) const - { - if constexpr (mep_layout) { - return MEP::raw_bank(data, offsets, sizes, types, event, n); - } - else { - uint32_t const* bank_offsets = reinterpret_cast(data) + 1; - return RawBank {data + (number_of_raw_banks + 2) * sizeof(uint32_t) + bank_offsets[n], sizes[n], types[n]}; - } - } - }; -} // namespace Calo diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index b695e1d032a..98c9e25934d 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -8,67 +8,6 @@ #include #include -namespace Rich { - struct RawBank { - uint32_t source_id = 0; - uint16_t size = 0; - uint8_t const* data = nullptr; - uint8_t const type; - - // For Allen format - __device__ __host__ RawBank(const char* raw_bank, const uint16_t s, const uint8_t t) : - RawBank {*reinterpret_cast(raw_bank), raw_bank + sizeof(uint32_t), s, t} - {} - - // For MEP format - __device__ __host__ RawBank(const uint32_t sid, const char* fragment, const uint16_t s, const uint8_t t) : - source_id {sid}, size {s}, data {reinterpret_cast(fragment)}, type {t} - {} - }; - - template - struct RawEvent { - - uint32_t number_of_raw_banks = 0; - const char* data = nullptr; - const uint32_t* offsets = nullptr; - typename std::conditional_t* sizes = nullptr; - typename std::conditional_t* types = nullptr; - const unsigned event = 0; - - // For Allen format - __device__ __host__ - RawEvent(char const* d, uint32_t const* o, uint32_t const* s, uint32_t const* t, unsigned const event_number) : - offsets {o}, - event {event_number} - { - if constexpr (mep_layout) { - data = d; - number_of_raw_banks = MEP::number_of_banks(o); - sizes = s; - types = t; - } - else { - data = d + offsets[event]; - number_of_raw_banks = reinterpret_cast(data)[0]; - sizes = Allen::bank_sizes(s, event); - types = Allen::bank_types(t, event); - } - } - - __device__ __host__ RawBank raw_bank(unsigned const n) const - { - if constexpr (mep_layout) { - return MEP::raw_bank(data, offsets, sizes, types, event, n); - } - else { - uint32_t const* bank_offsets = reinterpret_cast(data) + 1; - return RawBank {data + (number_of_raw_banks + 2) * sizeof(uint32_t) + bank_offsets[n], sizes[n], types[n]}; - } - } - }; -} // namespace Rich - namespace rich_decoding { struct Parameters { HOST_INPUT(host_number_of_events_t, uint) host_number_of_events; diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 57bb2cb0b3f..893e4af6358 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -9,7 +9,7 @@ INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( - const Rich::RawBank& bank, + const Allen::RawBank& bank, const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) { @@ -155,7 +155,7 @@ __global__ void rich_calculate_number_of_hits( const auto event_number = parameters.dev_event_list[blockIdx.x]; // Read raw event - const auto raw_event = Rich::RawEvent { + const auto raw_event = Allen::RawEvent { parameters.dev_rich_raw_input, parameters.dev_rich_raw_input_offsets, parameters.dev_rich_raw_input_sizes, @@ -175,7 +175,7 @@ __global__ void rich_calculate_number_of_hits( } __device__ void rich_decode_bank( - const Rich::RawBank& bank, + const Allen::RawBank& bank, const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping, unsigned* event_inserted_hits, @@ -383,7 +383,7 @@ __global__ void rich_decoding_kernel( auto event_smart_ids = parameters.dev_smart_ids + parameters.dev_rich_hit_offsets[event_number]; // Read raw event - const auto raw_event = Rich::RawEvent { + const auto raw_event = Allen::RawEvent { parameters.dev_rich_raw_input, parameters.dev_rich_raw_input_offsets, parameters.dev_rich_raw_input_sizes, diff --git a/main/include/MEPTools.h b/main/include/MEPTools.h index 372eabde89e..cf70332edc7 100644 --- a/main/include/MEPTools.h +++ b/main/include/MEPTools.h @@ -220,3 +220,64 @@ namespace MEP { } }; } // namespace MEP + +namespace Allen { + struct RawBank { + uint32_t source_id = 0; + uint16_t size = 0; + uint8_t const* data = nullptr; + uint8_t const type; + + // For Allen format + __device__ __host__ RawBank(const char* raw_bank, const uint16_t s, const uint8_t t) : + RawBank {*reinterpret_cast(raw_bank), raw_bank + sizeof(uint32_t), s, t} + {} + + // For MEP format + __device__ __host__ RawBank(const uint32_t sid, const char* fragment, const uint16_t s, const uint8_t t) : + source_id {sid}, size {s}, data {reinterpret_cast(fragment)}, type {t} + {} + }; + + template + struct RawEvent { + + uint32_t number_of_raw_banks = 0; + const char* data = nullptr; + const uint32_t* offsets = nullptr; + typename std::conditional_t* sizes = nullptr; + typename std::conditional_t* types = nullptr; + const unsigned event = 0; + + // For Allen format + __device__ __host__ + RawEvent(char const* d, uint32_t const* o, uint32_t const* s, uint32_t const* t, unsigned const event_number) : + offsets {o}, + event {event_number} + { + if constexpr (mep_layout) { + data = d; + number_of_raw_banks = MEP::number_of_banks(o); + sizes = s; + types = t; + } + else { + data = d + offsets[event]; + number_of_raw_banks = reinterpret_cast(data)[0]; + sizes = Allen::bank_sizes(s, event); + types = Allen::bank_types(t, event); + } + } + + __device__ __host__ RawBank raw_bank(unsigned const n) const + { + if constexpr (mep_layout) { + return MEP::raw_bank(data, offsets, sizes, types, event, n); + } + else { + uint32_t const* bank_offsets = reinterpret_cast(data) + 1; + return RawBank {data + (number_of_raw_banks + 2) * sizeof(uint32_t) + bank_offsets[n], sizes[n], types[n]}; + } + } + }; +} // namespace Allen -- GitLab From cb93dbb8eb76064946eb13ec9f6ad332cc7d0c92 Mon Sep 17 00:00:00 2001 From: Christian Asch Date: Mon, 6 Mar 2023 14:09:01 -0600 Subject: [PATCH 11/63] Now runs correctly on GPU and generates the correct ids --- device/rich/decoding/include/RichDecoding.cuh | 4 +- .../include/RichPDMDBDecodeMapping.cuh | 5 +- device/rich/decoding/src/RichDecoding.cu | 50 +++++++++++-------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index 98c9e25934d..8191304669f 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -36,7 +36,7 @@ namespace rich_decoding { const Constants&, const Allen::Context&) const; - Rich::Future::DAQ::Allen::Tel40CableMapping m_cableMapping; - Rich::Future::DAQ::Allen::PDMDBDecodeMapping m_decodeMapping; + Rich::Future::DAQ::Allen::Tel40CableMapping * m_cableMapping; // Free this data + Rich::Future::DAQ::Allen::PDMDBDecodeMapping * m_decodeMapping; // Free this data }; } // namespace rich_decoding diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index 3e5c25e7de8..1b5c9cea6b9 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -119,6 +119,9 @@ namespace Rich::Future::DAQ::Allen { /// Mapping version int m_mappingVer {-1}; - }; + void * dummy_pointer; // Needed to have the same size as the original GAUDI data type (RichPDMDBDecodeMapping.h) + struct dummy {} dummy; // Needed to have the same size as the original GAUDI data type (RichPDMDBDecodeMapping.h) + }; + } // namespace Rich::Future::DAQ::Allen diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 893e4af6358..c1cc34ad63d 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -10,8 +10,8 @@ INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( const Allen::RawBank& bank, - const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) + const Rich::Future::DAQ::Allen::Tel40CableMapping* m_cableMapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping) { unsigned number_of_hits = 0; @@ -21,7 +21,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( connSizes {}; auto tel40ID = bank.source_id; - const auto& connMeta = m_cableMapping.tel40Meta(tel40ID); + const auto& connMeta = m_cableMapping->tel40Meta(tel40ID); const auto nSizeWords = std::get<1>(connMeta); const auto nPackedSizeW = (nSizeWords / 2) + (nSizeWords % 2); @@ -38,7 +38,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( connSizes[iPayloadWord + 1] = sizes.size0(); } - const auto& connData = m_cableMapping.tel40Data(tel40ID); + const auto& connData = m_cableMapping->tel40Data(tel40ID); if (std::get<0>(connMeta)) { for (std::size_t iL = 0; iL < connData.size(); ++iL) { if (!connData[iL].isActive) { @@ -60,7 +60,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( const auto& cData = connData[iLink]; // get the PDMDB data - const auto& frameData = m_decodeMapping.getFrameData(cData); + const auto& frameData = m_decodeMapping->getFrameData(cData); // Loop over the words for this link uint16_t iW = 0; @@ -149,8 +149,8 @@ template __global__ void rich_calculate_number_of_hits( rich_decoding::Parameters parameters, const unsigned event_start, - const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) + const Rich::Future::DAQ::Allen::Tel40CableMapping* m_cableMapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping) { const auto event_number = parameters.dev_event_list[blockIdx.x]; @@ -176,8 +176,8 @@ __global__ void rich_calculate_number_of_hits( __device__ void rich_decode_bank( const Allen::RawBank& bank, - const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping, + const Rich::Future::DAQ::Allen::Tel40CableMapping* m_cableMapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping, unsigned* event_inserted_hits, unsigned* event_smart_ids) { @@ -188,7 +188,7 @@ __device__ void rich_decode_bank( connSizes {}; auto tel40ID = bank.source_id; - const auto& connMeta = m_cableMapping.tel40Meta(tel40ID); + const auto& connMeta = m_cableMapping->tel40Meta(tel40ID); const auto nSizeWords = std::get<1>(connMeta); const auto nPackedSizeW = (nSizeWords / 2) + (nSizeWords % 2); @@ -205,7 +205,7 @@ __device__ void rich_decode_bank( connSizes[iPayloadWord + 1] = sizes.size0(); } - const auto& connData = m_cableMapping.tel40Data(tel40ID); + const auto& connData = m_cableMapping->tel40Data(tel40ID); if (std::get<0>(connMeta)) { for (std::size_t iL = 0; iL < connData.size(); ++iL) { if (!connData[iL].isActive) { @@ -227,7 +227,7 @@ __device__ void rich_decode_bank( const auto& cData = connData[iLink]; // get the PDMDB data - const auto& frameData = m_decodeMapping.getFrameData(cData); + const auto& frameData = m_decodeMapping->getFrameData(cData); // Loop over the words for this link uint16_t iW = 0; @@ -374,8 +374,8 @@ template __global__ void rich_decoding_kernel( rich_decoding::Parameters parameters, const unsigned event_start, - const Rich::Future::DAQ::Allen::Tel40CableMapping& m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping& m_decodeMapping) + const Rich::Future::DAQ::Allen::Tel40CableMapping* m_cableMapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping) { const auto event_number = parameters.dev_event_list[blockIdx.x]; @@ -400,21 +400,31 @@ __global__ void rich_decoding_kernel( void rich_decoding::rich_decoding_t::init() { std::fstream file; - file.open("/home/cnca/dcampora/stack/pdmdbMaps.bin", std::ios::in | std::ios::binary); + file.open("/home/casch/Downloads/pdmdbMaps.bin", std::ios::in | std::ios::binary); file.seekg(0, std::ios::end); auto size = file.tellg(); file.seekg(0, std::ios::beg); - std::cout << "Loading pdmdbMaps. Size of file " << size << ", size of datatype " << sizeof(m_decodeMapping) << "\n"; - file.read(reinterpret_cast(&m_decodeMapping), size); + std::cout << "Loading pdmdbMaps. Size of file " << size << ", size of datatype " << sizeof(*m_decodeMapping) << "\n"; + + Rich::Future::DAQ::Allen::PDMDBDecodeMapping hostDecodeMapping; + file.read(reinterpret_cast(&hostDecodeMapping), size); file.close(); + Allen::malloc(reinterpret_cast(&m_decodeMapping), size); + Allen::memcpy(m_decodeMapping, &hostDecodeMapping, size, Allen::memcpyHostToDevice); - file.open("/home/cnca/dcampora/stack/tel40Maps.bin", std::ios::in | std::ios::binary); + file.open("/home/casch/Downloads/tel40Maps.bin", std::ios::in | std::ios::binary); file.seekg(0, std::ios::end); size = file.tellg(); file.seekg(0, std::ios::beg); - std::cout << "Loading tel40Maps. Size of file " << size << ", size of datatype " << sizeof(m_cableMapping) << "\n"; - file.read(reinterpret_cast(&m_cableMapping), size); + + std::cout << "Loading tel40Maps. Size of file " << size << ", size of datatype " << sizeof(*m_cableMapping) << "\n"; + Rich::Future::DAQ::Allen::Tel40CableMapping hostCableMapping; + file.read(reinterpret_cast(&hostCableMapping), size); file.close(); + + Allen::malloc(reinterpret_cast(&m_cableMapping), size); + Allen::memcpy(m_cableMapping, &hostCableMapping, size, Allen::memcpyHostToDevice); + } void rich_decoding::rich_decoding_t::set_arguments_size( -- GitLab From 80c9d733ebd9147a636f2e14e2cd3eb73e9f29da Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Mon, 6 Mar 2023 15:08:18 -0600 Subject: [PATCH 12/63] Add rich geometry files, point to those in init. --- .../include/RichPDMDBDecodeMapping.cuh | 14 ++++------ .../include/RichTel40CableMapping.cuh | 23 ++++++++++------ device/rich/decoding/src/RichDecoding.cu | 26 +++++------------- .../detector_configuration/rich_pdmdbmaps.bin | Bin 0 -> 9296 bytes .../detector_configuration/rich_tel40maps.bin | Bin 0 -> 314760 bytes 5 files changed, 26 insertions(+), 37 deletions(-) create mode 100644 input/detector_configuration/rich_pdmdbmaps.bin create mode 100644 input/detector_configuration/rich_tel40maps.bin diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index 1b5c9cea6b9..a6134afddc1 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -66,13 +66,13 @@ namespace Rich::Future::DAQ::Allen { using PDMData = std::array; /// R-Type Module data for each RICH - using RTypeRichData = std::array; // std::array + using RTypeRichData = std::array; private: // methods /// Get the PDMDB data for given RICH, PDMDB and frame - __device__ inline const auto& getFrameData( + __host__ __device__ inline const auto& getFrameData( const int8_t rich, // const int8_t pdmdb, // const int8_t link, // @@ -92,16 +92,15 @@ namespace Rich::Future::DAQ::Allen { public: /// mapping version - inline auto version() const noexcept { return m_mappingVer; } + __host__ __device__ inline auto version() const noexcept { return m_mappingVer; } /// Access the initialisation state - inline auto isInitialised() const noexcept { return m_isInitialised; } + __host__ __device__ inline auto isInitialised() const noexcept { return m_isInitialised; } /// Get PDMDB data for given Tel40 data - __device__ inline const auto& getFrameData(const Tel40CableMapping::Tel40LinkData& cData) const noexcept + __host__ __device__ inline const auto& getFrameData(const Tel40CableMapping::Tel40LinkData& cData) const noexcept { auto rich = (cData.smartID >> 20) & 0x1; - return getFrameData(rich, cData.pdmdbNum, cData.linkNum, cData.isHType); } @@ -119,9 +118,6 @@ namespace Rich::Future::DAQ::Allen { /// Mapping version int m_mappingVer {-1}; - - void * dummy_pointer; // Needed to have the same size as the original GAUDI data type (RichPDMDBDecodeMapping.h) - struct dummy {} dummy; // Needed to have the same size as the original GAUDI data type (RichPDMDBDecodeMapping.h) }; } // namespace Rich::Future::DAQ::Allen diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index 836d8751ac2..79a596a65db 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -19,12 +19,12 @@ namespace Rich::Future::DAQ::Allen { public: /// RICH SmartID uint32_t smartID; + /// Module Number + int32_t moduleNum; /// Source ID int16_t sourceID; /// Tel40 connector int8_t connector; - /// Module Number - int32_t moduleNum; /// PDMDB number (0,1) int8_t pdmdbNum; /// Link number @@ -39,20 +39,26 @@ namespace Rich::Future::DAQ::Allen { Tel40LinkData() = default; }; + class Tel40MetaData final { + public: + uint32_t nActiveLinks; + bool hasInactiveLinks; + }; + /// Max number of links(frames) per PDMDB - static constexpr const std::size_t MaxLinksPerPDMDB = 6; + static constexpr const uint64_t MaxLinksPerPDMDB = 6; /// Number of PDMDBs per module - static constexpr const std::size_t PDMDBPerModule = 2; + static constexpr const uint64_t PDMDBPerModule = 2; /// Number of Tel40 connections per MPO - static constexpr const std::size_t ConnectionsPerTel40MPO = 12; + static constexpr const uint64_t ConnectionsPerTel40MPO = 12; /// Maximum number of active Tel40 MPOs per Source ID - static constexpr const std::size_t MaxNumberMPOsPerSourceID = 2; + static constexpr const uint64_t MaxNumberMPOsPerSourceID = 2; /// Maximum Number of connections per Tel40 - static constexpr const std::size_t MaxConnectionsPerTel40 = MaxNumberMPOsPerSourceID * ConnectionsPerTel40MPO; + static constexpr const uint64_t MaxConnectionsPerTel40 = MaxNumberMPOsPerSourceID * ConnectionsPerTel40MPO; /// Array of Tel40 for each link in a PDMDB using PDMDBLinkData = std::array; @@ -63,9 +69,8 @@ namespace Rich::Future::DAQ::Allen { /// Tel40 data for each Module using ModuleTel40Data = std::array; // 300 is totalmodules - // TODO: The 164 limit should be studied using Tel40SourceIDs = std::array, 164>, 2>, 2>; - using Tel40SourceMetas = std::array, 164>, 2>, 2>; + using Tel40SourceMetas = std::array, 2>, 2>; public: // accessors diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index c1cc34ad63d..55b79355aa5 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -14,15 +14,11 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping) { unsigned number_of_hits = 0; - - std::array< - Rich::Future::DAQ::PackedFrameSizes::IntType, - Rich::Future::DAQ::Allen::Tel40CableMapping::MaxConnectionsPerTel40> - connSizes {}; + std::array connSizes {}; auto tel40ID = bank.source_id; const auto& connMeta = m_cableMapping->tel40Meta(tel40ID); - const auto nSizeWords = std::get<1>(connMeta); + const auto nSizeWords = connMeta.nActiveLinks; const auto nPackedSizeW = (nSizeWords / 2) + (nSizeWords % 2); auto dataW = bank.data; @@ -39,7 +35,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( } const auto& connData = m_cableMapping->tel40Data(tel40ID); - if (std::get<0>(connMeta)) { + if (connMeta.hasInactiveLinks) { for (std::size_t iL = 0; iL < connData.size(); ++iL) { if (!connData[iL].isActive) { for (auto i = connData.size() - 1; i > iL; --i) { @@ -162,12 +158,10 @@ __global__ void rich_calculate_number_of_hits( parameters.dev_rich_raw_input_types, event_number + event_start}; - // std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); const auto number_of_hits_in_raw_bank = rich_calculate_number_of_hits_in_raw_bank(bank, m_cableMapping, m_decodeMapping); - // std::cout << "Number of hits in raw bank " << bank_number << ": " << number_of_hits_in_raw_bank << "\n"; if (number_of_hits_in_raw_bank > 0) { atomicAdd(parameters.dev_rich_number_of_hits + event_number, number_of_hits_in_raw_bank); } @@ -181,7 +175,6 @@ __device__ void rich_decode_bank( unsigned* event_inserted_hits, unsigned* event_smart_ids) { - // std::cout << "Bank: sourceID " << bank.source_id << ", size " << bank.size << "\n"; std::array< Rich::Future::DAQ::PackedFrameSizes::IntType, Rich::Future::DAQ::Allen::Tel40CableMapping::MaxConnectionsPerTel40> @@ -189,7 +182,7 @@ __device__ void rich_decode_bank( auto tel40ID = bank.source_id; const auto& connMeta = m_cableMapping->tel40Meta(tel40ID); - const auto nSizeWords = std::get<1>(connMeta); + const auto nSizeWords = connMeta.nActiveLinks; const auto nPackedSizeW = (nSizeWords / 2) + (nSizeWords % 2); auto dataW = bank.data; @@ -206,7 +199,7 @@ __device__ void rich_decode_bank( } const auto& connData = m_cableMapping->tel40Data(tel40ID); - if (std::get<0>(connMeta)) { + if (connMeta.hasInactiveLinks) { for (std::size_t iL = 0; iL < connData.size(); ++iL) { if (!connData[iL].isActive) { for (auto i = connData.size() - 1; i > iL; --i) { @@ -256,7 +249,6 @@ __device__ void rich_decode_bank( hitID = RichSmartID::bits( hitID, cData.moduleNum, RichSmartID::ShiftPDMod, RichSmartID::MaskPDMod, RichSmartID::MaskPDIsSet); hitID = RichSmartID::bits(hitID, nInMod, RichSmartID::ShiftPDNumInMod, RichSmartID::MaskPDNumInMod); - // std::cout << "hitID after setPD_EC_PMT " << ((unsigned) hitID) << "\n"; const auto row = aData.anode / 8; const auto col = 8 - 1 - (aData.anode % 8); @@ -264,7 +256,6 @@ __device__ void rich_decode_bank( hitID, row, RichSmartID::ShiftPixelRow, RichSmartID::MaskPixelRow, RichSmartID::MaskPixelRowIsSet); hitID = RichSmartID::bits( hitID, col, RichSmartID::ShiftPixelCol, RichSmartID::MaskPixelCol, RichSmartID::MaskPixelColIsSet); - // std::cout << "hitID after Anode " << hitID << "\n"; const auto insert_index = atomicAdd(event_inserted_hits, 1); event_smart_ids[insert_index] = hitID; @@ -328,7 +319,6 @@ __device__ void rich_decode_bank( RichSmartID::MaskPDMod, RichSmartID::MaskPDIsSet); hitID = RichSmartID::bits(hitID, nInMod, RichSmartID::ShiftPDNumInMod, RichSmartID::MaskPDNumInMod); - // std::cout << "hitID after setPD_EC_PMT " << ((unsigned) hitID) << "\n"; const auto row = aData.anode / 8; const auto col = 8 - 1 - (aData.anode % 8); @@ -344,7 +334,6 @@ __device__ void rich_decode_bank( RichSmartID::ShiftPixelCol, RichSmartID::MaskPixelCol, RichSmartID::MaskPixelColIsSet); - // std::cout << "hitID after Anode " << hitID << "\n"; const auto insert_index = atomicAdd(event_inserted_hits, 1); event_smart_ids[insert_index] = hitID; @@ -390,7 +379,6 @@ __global__ void rich_decoding_kernel( parameters.dev_rich_raw_input_types, event_number + event_start}; - // std::cout << "Number of raw banks: " << raw_event.number_of_raw_banks << "\n"; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); rich_decode_bank(bank, m_cableMapping, m_decodeMapping, event_inserted_hits, event_smart_ids); @@ -400,7 +388,7 @@ __global__ void rich_decoding_kernel( void rich_decoding::rich_decoding_t::init() { std::fstream file; - file.open("/home/casch/Downloads/pdmdbMaps.bin", std::ios::in | std::ios::binary); + file.open("../input/detector_configuration/rich_pdmdbmaps.bin", std::ios::in | std::ios::binary); file.seekg(0, std::ios::end); auto size = file.tellg(); file.seekg(0, std::ios::beg); @@ -412,7 +400,7 @@ void rich_decoding::rich_decoding_t::init() Allen::malloc(reinterpret_cast(&m_decodeMapping), size); Allen::memcpy(m_decodeMapping, &hostDecodeMapping, size, Allen::memcpyHostToDevice); - file.open("/home/casch/Downloads/tel40Maps.bin", std::ios::in | std::ios::binary); + file.open("../input/detector_configuration/rich_tel40maps.bin", std::ios::in | std::ios::binary); file.seekg(0, std::ios::end); size = file.tellg(); file.seekg(0, std::ios::beg); diff --git a/input/detector_configuration/rich_pdmdbmaps.bin b/input/detector_configuration/rich_pdmdbmaps.bin new file mode 100644 index 0000000000000000000000000000000000000000..f13aba7b331e39b34e1a128b67a4571097f15285 GIT binary patch literal 9296 zcmeI1>sB($8HDQ~C?bM_3MdG8K8tt+mHWS{FEvAUva^yOxd2$o8k(M-u6oBFyPiLP z{y>+&26P2IL66Wgv;+>IUtkmZ1a^TVU(R z;2ZiN@_tXe6FL4NK8Y`A1~s7}vCi zU0@8ffHu$rCO{pi0l!cW>Ox!49#n&X{Hg^J*vQEc%Lvj9uxFK$d1q(T`v`0*d7h*!(5!b|w7!xC+&&*Ki-zD~l3nJd8YND4YvN!Y-9=-@=aYE_?_-LQB{e4u!rj7AC^6 z&=t;vp3qjLDV-mQ4HmO)5p71b;=nF(L^OyUqDJf!btzt%*d{8(7L_s-B_T-Ve%qv` z)R?L2ji8&oE2Du&z$x57w>doM~gmHEV(h43uQg_$tTy^_00sHu>XDeMW`!j_bu zv^$!luGErh$_w{WPuiD8(zTSLG=)u}DpZ7qbR#`WV`(aVNfT)pz>>DlX%NkkF*4Vl=-i)O+vF6s9@oG)2 z8*5?Bq$}gwx-;I54EtmCEn6>E&FWfPmaLvdYtPztA?@AKr6_%s`bs12jRzG2E~Ini zhSYI!p6ZUJ+K?jQLTXC`DJFEJNcfR5z04tBMa6*;u|q|>zKwx#Zbasjl*Wn_?Wa;x z+I0$4j9is+*21~}3w3>CVvLL&_lz4O4n*D9crmVxsWCI2jZdSSMKgj7Kab)}&(YRq$if?&oZZ1R>{cd;c6Fc&+>@$00@7c$8*B;v~yKVREiCwpA_OID9yXKa;XV$X% zP$?%}PoByz z@q%oZzY; zqkt`OzgUUc6T4zx+!iyLj9C|tj=*Pd4Boyya(6dI@~V)k#Qt9 zzz%qfLe3DZf;(Uvxikmh26%!@i4{ZzPr+-j2_7M};{zD~WBVH-iWlHHQoF*#U+@WB zrpibmQdY*s27Cnn!qK<^7tezAzF@sCSnmtg`-1hpV7)I`?+e!Zg7v;&y)Rhr3)cIB zYz_YVm9YKqjfv&+F`Kt+zW?5yYTV_j15|1kTFbKB0Z0_{8|zfAvWo5Sp-2MD<0~pFLRe@M=Li zid|XK{)GQ4e9$S!S&@aXgP?>o?i45+yWCns878g&>kphR}o(loY5USRvFPoFcSh z1u{Y|0v&=LLNOA*hiHUNgis`t4}b`vNdBMrx>_dN3B9uq%&dYxzA}?cG#sQnNF*MZ zlGr~ve?tCb{>vbMGV^~eam-UFKob5ExO@k=lxJn|FJeTDiL(+POiG#%){t0x1t1cM zCrA%*2!;r8nC8UwYwf`Q??70_-#Z6z7wbTh@bdlN>p&9n zRkyM|DSblwMCA$alU*mZ4va`9pAb7pVi;7h>Rh6wV!*tFGhtFvm93I1{c{}%Q7M9b zY?RC;>?wIuph?h407?RyK&a5D6}TzZfl!;0(F9k8%LL*C<&1=J!C4CIvcg{BS-U0q z3K0w63GfOd3n{CY{42m^1;3Uh2)i$-*>8!-LfjrhVg3SYp$wH0xa^eVB?(bx6~0rf z16icPjLL(A_JJu$@-IrX@l)`Zf?|Yayp}j75a*#x_yb&mIf`{)g)od!i7L)YHZdu2 sMkq#*#0q4DUxZ==XM|sbVyxGJIJbVS9auZCc3|zm|8SuA@3i>+2S9OjQ2+n{ literal 0 HcmV?d00001 diff --git a/input/detector_configuration/rich_tel40maps.bin b/input/detector_configuration/rich_tel40maps.bin new file mode 100644 index 0000000000000000000000000000000000000000..d0a1df420e21e5ea60253d983a484688452e765c GIT binary patch literal 314760 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 Date: Tue, 7 Mar 2023 08:40:56 -0600 Subject: [PATCH 13/63] Use consumers for Rich geometries. --- .../include/Dumpers/Identifiers.h | 14 ++++ Rec/Allen/python/Allen/config.py | 20 +++--- device/rich/decoding/include/RichDecoding.cuh | 5 -- device/rich/decoding/src/RichDecoding.cu | 71 ++++++------------- integration/non_event_data/src/Updater.cpp | 4 +- main/src/RegisterConsumers.cpp | 16 ++++- stream/sequence/include/Constants.cuh | 12 +++- 7 files changed, 76 insertions(+), 66 deletions(-) diff --git a/Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h b/Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h index a688507b0f4..ca5f7d41a5c 100644 --- a/Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h +++ b/Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h @@ -87,5 +87,19 @@ namespace Allen { inline static std::string const id = "EcalGeometry"; }; + /** @class RichPDMDBMapping + * Identifier for the Muon lookup tables for Allen + */ + struct RichPDMDBMapping : Identifier { + inline static std::string const id = "RichPDMDBMapping"; + }; + + /** @class RichCableMapping + * Identifier for the Muon lookup tables for Allen + */ + struct RichCableMapping : Identifier { + inline static std::string const id = "RichCableMapping"; + }; + } // namespace NonEventData } // namespace Allen diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index 03c42d64297..53a932c0280 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -109,15 +109,17 @@ def setup_allen_non_event_data_service(allen_event_loop=False, data (geometries etc.) """ converter_types = { - 'VP': [(DumpBeamline, 'DeviceBeamline', 'beamline'), - (DumpVPGeometry, 'DeviceVPGeometry', 'velo_geometry')], - 'UT': [(DumpUTGeometry, 'DeviceUTGeometry', 'ut_geometry'), - (DumpUTLookupTables, 'DeviceUTLookupTables', 'ut_tables')], - 'ECal': [(DumpCaloGeometry, 'DeviceCaloGeometry', 'ecal_geometry')], - 'Magnet': [(DumpMagneticField, 'DeviceMagneticField', 'polarity')], - 'FTCluster': [(DumpFTGeometry, 'DeviceFTGeometry', 'scifi_geometry')], - 'Muon': [(DumpMuonGeometry, 'DeviceMuonGeometry', 'muon_geometry'), - (DumpMuonTable, 'DeviceMuonTable', 'muon_tables')] + 'VP': [(DumpBeamline, 'DumpBeamline', 'beamline'), + (DumpVPGeometry, 'DumpVPGeometry', 'velo_geometry')], + 'UT': [(DumpUTGeometry, 'DumpUTGeometry', 'ut_geometry'), + (DumpUTLookupTables, 'DumpUTLookupTables', 'ut_tables')], + 'ECal': [(DumpCaloGeometry, 'DumpCaloGeometry', 'ecal_geometry')], + 'Magnet': [(DumpMagneticField, 'DumpMagneticField', 'polarity')], + 'FTCluster': [(DumpFTGeometry, 'DumpFTGeometry', 'scifi_geometry')], + 'Muon': [(DumpMuonGeometry, 'DumpMuonGeometry', 'muon_geometry'), + (DumpMuonTable, 'DumpMuonTable', 'muon_tables'), + 'Rich': [(DumpMuonTable, 'rich_pdmdbmaps'), + (DumpMuonTable, 'rich_tel40maps')]] } detector_names = { diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index 8191304669f..77796ecc0dc 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -26,8 +26,6 @@ namespace rich_decoding { }; struct rich_decoding_t : public DeviceAlgorithm, Parameters { - void init(); - void set_arguments_size(ArgumentReferences, const RuntimeOptions&, const Constants&) const; void operator()( @@ -35,8 +33,5 @@ namespace rich_decoding { const RuntimeOptions&, const Constants&, const Allen::Context&) const; - - Rich::Future::DAQ::Allen::Tel40CableMapping * m_cableMapping; // Free this data - Rich::Future::DAQ::Allen::PDMDBDecodeMapping * m_decodeMapping; // Free this data }; } // namespace rich_decoding diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 55b79355aa5..5eac8591107 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -10,14 +10,14 @@ INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( const Allen::RawBank& bank, - const Rich::Future::DAQ::Allen::Tel40CableMapping* m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping) + const Rich::Future::DAQ::Allen::Tel40CableMapping* cable_mapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* pdmdb_mapping) { unsigned number_of_hits = 0; std::array connSizes {}; auto tel40ID = bank.source_id; - const auto& connMeta = m_cableMapping->tel40Meta(tel40ID); + const auto& connMeta = cable_mapping->tel40Meta(tel40ID); const auto nSizeWords = connMeta.nActiveLinks; const auto nPackedSizeW = (nSizeWords / 2) + (nSizeWords % 2); @@ -34,7 +34,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( connSizes[iPayloadWord + 1] = sizes.size0(); } - const auto& connData = m_cableMapping->tel40Data(tel40ID); + const auto& connData = cable_mapping->tel40Data(tel40ID); if (connMeta.hasInactiveLinks) { for (std::size_t iL = 0; iL < connData.size(); ++iL) { if (!connData[iL].isActive) { @@ -56,7 +56,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( const auto& cData = connData[iLink]; // get the PDMDB data - const auto& frameData = m_decodeMapping->getFrameData(cData); + const auto& frameData = pdmdb_mapping->getFrameData(cData); // Loop over the words for this link uint16_t iW = 0; @@ -145,8 +145,8 @@ template __global__ void rich_calculate_number_of_hits( rich_decoding::Parameters parameters, const unsigned event_start, - const Rich::Future::DAQ::Allen::Tel40CableMapping* m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping) + const Rich::Future::DAQ::Allen::Tel40CableMapping* cable_mapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* pdmdb_mapping) { const auto event_number = parameters.dev_event_list[blockIdx.x]; @@ -161,7 +161,7 @@ __global__ void rich_calculate_number_of_hits( for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); const auto number_of_hits_in_raw_bank = - rich_calculate_number_of_hits_in_raw_bank(bank, m_cableMapping, m_decodeMapping); + rich_calculate_number_of_hits_in_raw_bank(bank, cable_mapping, pdmdb_mapping); if (number_of_hits_in_raw_bank > 0) { atomicAdd(parameters.dev_rich_number_of_hits + event_number, number_of_hits_in_raw_bank); } @@ -170,8 +170,8 @@ __global__ void rich_calculate_number_of_hits( __device__ void rich_decode_bank( const Allen::RawBank& bank, - const Rich::Future::DAQ::Allen::Tel40CableMapping* m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping, + const Rich::Future::DAQ::Allen::Tel40CableMapping* cable_mapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* pdmdb_mapping, unsigned* event_inserted_hits, unsigned* event_smart_ids) { @@ -181,7 +181,7 @@ __device__ void rich_decode_bank( connSizes {}; auto tel40ID = bank.source_id; - const auto& connMeta = m_cableMapping->tel40Meta(tel40ID); + const auto& connMeta = cable_mapping->tel40Meta(tel40ID); const auto nSizeWords = connMeta.nActiveLinks; const auto nPackedSizeW = (nSizeWords / 2) + (nSizeWords % 2); @@ -198,7 +198,7 @@ __device__ void rich_decode_bank( connSizes[iPayloadWord + 1] = sizes.size0(); } - const auto& connData = m_cableMapping->tel40Data(tel40ID); + const auto& connData = cable_mapping->tel40Data(tel40ID); if (connMeta.hasInactiveLinks) { for (std::size_t iL = 0; iL < connData.size(); ++iL) { if (!connData[iL].isActive) { @@ -220,7 +220,7 @@ __device__ void rich_decode_bank( const auto& cData = connData[iLink]; // get the PDMDB data - const auto& frameData = m_decodeMapping->getFrameData(cData); + const auto& frameData = pdmdb_mapping->getFrameData(cData); // Loop over the words for this link uint16_t iW = 0; @@ -363,8 +363,8 @@ template __global__ void rich_decoding_kernel( rich_decoding::Parameters parameters, const unsigned event_start, - const Rich::Future::DAQ::Allen::Tel40CableMapping* m_cableMapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* m_decodeMapping) + const Rich::Future::DAQ::Allen::Tel40CableMapping* cable_mapping, + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* pdmdb_mapping) { const auto event_number = parameters.dev_event_list[blockIdx.x]; @@ -381,40 +381,10 @@ __global__ void rich_decoding_kernel( for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); - rich_decode_bank(bank, m_cableMapping, m_decodeMapping, event_inserted_hits, event_smart_ids); + rich_decode_bank(bank, cable_mapping, pdmdb_mapping, event_inserted_hits, event_smart_ids); } } -void rich_decoding::rich_decoding_t::init() -{ - std::fstream file; - file.open("../input/detector_configuration/rich_pdmdbmaps.bin", std::ios::in | std::ios::binary); - file.seekg(0, std::ios::end); - auto size = file.tellg(); - file.seekg(0, std::ios::beg); - std::cout << "Loading pdmdbMaps. Size of file " << size << ", size of datatype " << sizeof(*m_decodeMapping) << "\n"; - - Rich::Future::DAQ::Allen::PDMDBDecodeMapping hostDecodeMapping; - file.read(reinterpret_cast(&hostDecodeMapping), size); - file.close(); - Allen::malloc(reinterpret_cast(&m_decodeMapping), size); - Allen::memcpy(m_decodeMapping, &hostDecodeMapping, size, Allen::memcpyHostToDevice); - - file.open("../input/detector_configuration/rich_tel40maps.bin", std::ios::in | std::ios::binary); - file.seekg(0, std::ios::end); - size = file.tellg(); - file.seekg(0, std::ios::beg); - - std::cout << "Loading tel40Maps. Size of file " << size << ", size of datatype " << sizeof(*m_cableMapping) << "\n"; - Rich::Future::DAQ::Allen::Tel40CableMapping hostCableMapping; - file.read(reinterpret_cast(&hostCableMapping), size); - file.close(); - - Allen::malloc(reinterpret_cast(&m_cableMapping), size); - Allen::memcpy(m_cableMapping, &hostCableMapping, size, Allen::memcpyHostToDevice); - -} - void rich_decoding::rich_decoding_t::set_arguments_size( ArgumentReferences arguments, const RuntimeOptions&, @@ -430,18 +400,21 @@ void rich_decoding::rich_decoding_t::set_arguments_size( void rich_decoding::rich_decoding_t::operator()( const ArgumentReferences& arguments, const RuntimeOptions& runtime_options, - const Constants&, + const Constants& constants, const Allen::Context& context) const { const auto bank_version = first(arguments); std::cout << "Bank version Rich1 decoding " << bank_version << "\n"; + auto cable_mapping = reinterpret_cast(constants.dev_rich_cable_mapping); + auto pdmdb_mapping = reinterpret_cast(constants.dev_rich_pdmdb_mapping); + // Calculate number of hits into dev_rich_number_of_hits_t Allen::memset_async(arguments, 0, context); global_function( runtime_options.mep_layout ? rich_calculate_number_of_hits : rich_calculate_number_of_hits)( dim3(size(arguments)), 64, context)( - arguments, std::get<0>(runtime_options.event_interval), m_cableMapping, m_decodeMapping); + arguments, std::get<0>(runtime_options.event_interval), cable_mapping, pdmdb_mapping); // Copy to host data(arguments)[0] = 0; @@ -463,7 +436,7 @@ void rich_decoding::rich_decoding_t::operator()( global_function(runtime_options.mep_layout ? rich_decoding_kernel : rich_decoding_kernel)( dim3(size(arguments)), 1, context)( - arguments, std::get<0>(runtime_options.event_interval), m_cableMapping, m_decodeMapping); + arguments, std::get<0>(runtime_options.event_interval), cable_mapping, pdmdb_mapping); // Print output print(arguments); diff --git a/integration/non_event_data/src/Updater.cpp b/integration/non_event_data/src/Updater.cpp index d5f28bdf691..3ad84319ac1 100644 --- a/integration/non_event_data/src/Updater.cpp +++ b/integration/non_event_data/src/Updater.cpp @@ -55,7 +55,9 @@ namespace Allen { tuple {NonEventData::SciFiGeometry {}, std::string("scifi_geometry.bin")}, tuple {NonEventData::ECalGeometry {}, std::string("ecal_geometry.bin")}, tuple {NonEventData::MuonGeometry {}, std::string("muon_geometry.bin")}, - tuple {NonEventData::MuonLookupTables {}, std::string("muon_tables.bin")}}; + tuple {NonEventData::MuonLookupTables {}, std::string("muon_tables.bin")}, + tuple {NonEventData::RichPDMDBMapping {}, std::string("rich_pdmdbmaps.bin")}, + tuple {NonEventData::RichCableMapping {}, std::string("rich_tel40maps.bin")}}; for_each(producers, [this, &geometry_producer](const auto& p) { using id_t = typename std::remove_reference_t(p))>; diff --git a/main/src/RegisterConsumers.cpp b/main/src/RegisterConsumers.cpp index 265f5340fe0..d189f07a5d8 100644 --- a/main/src/RegisterConsumers.cpp +++ b/main/src/RegisterConsumers.cpp @@ -68,7 +68,21 @@ void register_consumers( return std::make_unique( constants.host_muon_lookup_tables_raw, constants.dev_muon_lookup_tables_raw, constants.dev_muon_tables); }, - BankTypes::MUON)); + BankTypes::MUON), + std::make_tuple( + Allen::NonEventData::RichPDMDBMapping {}, + [&constants]() { + return std::make_unique( + constants.host_rich_pdmdb_mapping, constants.dev_rich_pdmdb_mapping); + }, + BankTypes::Rich1), + std::make_tuple( + Allen::NonEventData::RichCableMapping {}, + [&constants]() { + return std::make_unique( + constants.host_rich_cable_mapping, constants.dev_rich_cable_mapping); + }, + BankTypes::Rich1)); const auto unconditional_consumers = std::make_tuple(std::make_tuple(Allen::NonEventData::MagneticField {}, [&constants]() { diff --git a/stream/sequence/include/Constants.cuh b/stream/sequence/include/Constants.cuh index fb4a9af333c..fd5ac6d5ed3 100644 --- a/stream/sequence/include/Constants.cuh +++ b/stream/sequence/include/Constants.cuh @@ -36,6 +36,11 @@ namespace MatchUpstreamMuon { namespace TrackMatchingConsts { struct MagnetParametrization; } +namespace Rich::Future::DAQ::Allen { + class PDMDBDecodeMapping; + class Tel40CableMapping; +} + /** * @brief Struct intended as a singleton with constants defined on GPU. @@ -47,7 +52,6 @@ namespace TrackMatchingConsts { * The pointers are hard-coded. Feel free to write more as needed. */ struct Constants { - gsl::span dev_velo_candidate_ks; gsl::span dev_velo_sp_patterns; gsl::span dev_velo_sp_fx; @@ -137,6 +141,12 @@ struct Constants { // Kalman filter ParKalmanFilter::KalmanParametrizations* dev_kalman_params = nullptr; + // Rich + std::vector host_rich_pdmdb_mapping; + std::vector host_rich_cable_mapping; + char* dev_rich_pdmdb_mapping; + char* dev_rich_cable_mapping; + /** * @brief Reserves and initializes constants. */ -- GitLab From 4f2d17928ed77c674a839bfc43d6a391601977f5 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 08:48:12 -0600 Subject: [PATCH 14/63] Move temporary to allen buffer. --- device/rich/decoding/include/RichDecoding.cuh | 1 - device/rich/decoding/src/RichDecoding.cu | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index 77796ecc0dc..f80ff3eb2bf 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -21,7 +21,6 @@ namespace rich_decoding { DEVICE_OUTPUT(dev_rich_hit_offsets_t, unsigned) dev_rich_hit_offsets; HOST_OUTPUT(host_rich_hit_offsets_t, unsigned) host_rich_hit_offsets; HOST_OUTPUT(host_rich_total_number_of_hits_t, unsigned) host_rich_total_number_of_hits; - DEVICE_OUTPUT(dev_rich_number_of_inserted_hits_t, unsigned) dev_rich_number_of_inserted_hits; DEVICE_OUTPUT(dev_smart_ids_t, unsigned) dev_smart_ids; }; diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 5eac8591107..3a5cbdc38bd 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -364,11 +364,12 @@ __global__ void rich_decoding_kernel( rich_decoding::Parameters parameters, const unsigned event_start, const Rich::Future::DAQ::Allen::Tel40CableMapping* cable_mapping, - const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* pdmdb_mapping) + const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* pdmdb_mapping, + unsigned* dev_rich_number_of_inserted_hits) { const auto event_number = parameters.dev_event_list[blockIdx.x]; - auto event_inserted_hits = parameters.dev_rich_number_of_inserted_hits + event_number; + auto event_inserted_hits = dev_rich_number_of_inserted_hits + event_number; auto event_smart_ids = parameters.dev_smart_ids + parameters.dev_rich_hit_offsets[event_number]; // Read raw event @@ -394,7 +395,6 @@ void rich_decoding::rich_decoding_t::set_arguments_size( set_size(arguments, size(arguments) + 1); set_size(arguments, size(arguments) + 1); set_size(arguments, 1); - set_size(arguments, size(arguments)); } void rich_decoding::rich_decoding_t::operator()( @@ -431,12 +431,13 @@ void rich_decoding::rich_decoding_t::operator()( Allen::copy_async(arguments, context); // Decode RICH hits - Allen::memset_async(arguments, 0, context); + auto dev_rich_number_of_inserted_hits = make_device_buffer(arguments, size(arguments)); + Allen::memset_async(dev_rich_number_of_inserted_hits.data(), 0, dev_rich_number_of_inserted_hits.size_bytes(), context); resize(arguments, first(arguments)); global_function(runtime_options.mep_layout ? rich_decoding_kernel : rich_decoding_kernel)( dim3(size(arguments)), 1, context)( - arguments, std::get<0>(runtime_options.event_interval), cable_mapping, pdmdb_mapping); + arguments, std::get<0>(runtime_options.event_interval), cable_mapping, pdmdb_mapping, dev_rich_number_of_inserted_hits.data()); // Print output print(arguments); -- GitLab From 1cc06707e155dc2e0fae94a7c6d28942606f7515 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 10:51:45 -0600 Subject: [PATCH 15/63] Compile with Gaudi-Allen. --- Dumpers/BinaryDumpers/CMakeLists.txt | 3 ++- Rec/Allen/CMakeLists.txt | 1 + Rec/Allen/python/Allen/config.py | 13 +++++++------ mdf/test/test_mep_banks.cpp | 9 ++++----- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Dumpers/BinaryDumpers/CMakeLists.txt b/Dumpers/BinaryDumpers/CMakeLists.txt index f6ea56e1bac..4c463407875 100644 --- a/Dumpers/BinaryDumpers/CMakeLists.txt +++ b/Dumpers/BinaryDumpers/CMakeLists.txt @@ -24,7 +24,8 @@ gaudi_add_library(BinaryDumpers LHCb::LHCbDetLib LHCb::MagnetLib LHCb::MuonDAQLib - LHCb::RecEvent) + LHCb::RecEvent + LHCb::RichFutureDAQLib) gaudi_add_module(BinaryDumpersModule SOURCES diff --git a/Rec/Allen/CMakeLists.txt b/Rec/Allen/CMakeLists.txt index 45fb5a1ac53..81fc4c5eff1 100755 --- a/Rec/Allen/CMakeLists.txt +++ b/Rec/Allen/CMakeLists.txt @@ -98,6 +98,7 @@ gaudi_add_module(AllenAlgorithms Utils WrapperInterface mdf + Rich Gaudi::GaudiAlgLib LHCb::DAQEventLib LHCb::VPDetLib diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index 53a932c0280..2bf77082885 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -18,9 +18,10 @@ from PyConf.control_flow import CompositeNode, NodeLogic from PyConf.application import all_nodes_and_algs from PyConf.application import configure_input, configure from PyConf.Algorithms import ( - DumpBeamline, DumpCaloGeometry, DumpMagneticField, DumpVPGeometry, - DumpFTGeometry, DumpUTGeometry, DumpUTLookupTables, DumpMuonGeometry, - DumpMuonTable, AllenODINProducer) + AllenTESProducer, DumpBeamline, DumpCaloGeometry, DumpMagneticField, + DumpVPGeometry, DumpFTGeometry, DumpUTGeometry, DumpUTLookupTables, + DumpMuonGeometry, DumpMuonTable, AllenODINProducer, DumpRichPDMDBMaps, + DumpRichCableMapping) from DDDB.CheckDD4Hep import UseDD4Hep @@ -117,9 +118,9 @@ def setup_allen_non_event_data_service(allen_event_loop=False, 'Magnet': [(DumpMagneticField, 'DumpMagneticField', 'polarity')], 'FTCluster': [(DumpFTGeometry, 'DumpFTGeometry', 'scifi_geometry')], 'Muon': [(DumpMuonGeometry, 'DumpMuonGeometry', 'muon_geometry'), - (DumpMuonTable, 'DumpMuonTable', 'muon_tables'), - 'Rich': [(DumpMuonTable, 'rich_pdmdbmaps'), - (DumpMuonTable, 'rich_tel40maps')]] + (DumpMuonTable, 'DumpMuonTable', 'muon_tables')], + 'Rich': [(DumpRichPDMDBMaps, 'rich_pdmdbmaps'), + (DumpRichCableMapping, 'rich_tel40maps')] } detector_names = { diff --git a/mdf/test/test_mep_banks.cpp b/mdf/test/test_mep_banks.cpp index 85c3e91dee4..9932690e5a9 100644 --- a/mdf/test/test_mep_banks.cpp +++ b/mdf/test/test_mep_banks.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -472,8 +471,8 @@ struct compare { { const auto allen_raw_event = - Calo::RawEvent(allen_banks.data(), allen_offsets.data(), allen_sizes.data(), allen_types.data(), i_event); - const auto mep_raw_event = Calo::RawEvent( + Allen::RawEvent(allen_banks.data(), allen_offsets.data(), allen_sizes.data(), allen_types.data(), i_event); + const auto mep_raw_event = Allen::RawEvent( mep_fragments.data(), mep_offsets.data(), mep_sizes.data(), mep_types.data(), i_event); auto const mep_n_banks = mep_raw_event.number_of_raw_banks; @@ -483,8 +482,8 @@ struct compare { // Read raw bank auto const mep_bank = mep_raw_event.raw_bank(bank); auto const allen_bank = allen_raw_event.raw_bank(bank); - auto mep_len = mep_bank.end - mep_bank.data; - auto allen_len = allen_bank.end - allen_bank.data; + auto mep_len = mep_bank.size; + auto allen_len = allen_bank.size; REQUIRE(mep_len == allen_len); REQUIRE(mep_bank.type == allen_bank.type); -- GitLab From c537097909f523951cbd80d2f7c569b71c1572ac Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 12:06:21 -0600 Subject: [PATCH 16/63] Solve warning. --- device/calo/decoding/src/CaloDecode.cu | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/device/calo/decoding/src/CaloDecode.cu b/device/calo/decoding/src/CaloDecode.cu index 2abdd75ed1b..be1677571ce 100644 --- a/device/calo/decoding/src/CaloDecode.cu +++ b/device/calo/decoding/src/CaloDecode.cu @@ -34,10 +34,9 @@ namespace { for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { auto raw_bank = raw_event.raw_bank(bank_number); - const auto raw_bank_end = raw_bank.data + raw_bank.size; if constexpr (decoding_version < 4) { // old decoding - + const auto raw_bank_end = raw_bank.data + raw_bank.size; while (raw_bank.data < raw_bank_end) { uint32_t word = *raw_bank.data; uint16_t trig_size = word & 0x7F; -- GitLab From f147d809c864c5ad9db0de5d4ef269e9702b0ffa Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 12:16:03 -0600 Subject: [PATCH 17/63] Add RICH2 decoding. --- .../python/AllenConf/rich_reconstruction.py | 19 +++++++++++++++++++ configuration/python/AllenSequences/rich.py | 13 +++++++++++-- device/rich/decoding/src/RichDecoding.cu | 4 +++- main/src/RegisterConsumers.cpp | 16 +++++++++++++++- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/configuration/python/AllenConf/rich_reconstruction.py b/configuration/python/AllenConf/rich_reconstruction.py index ba44bc92474..5a090907221 100644 --- a/configuration/python/AllenConf/rich_reconstruction.py +++ b/configuration/python/AllenConf/rich_reconstruction.py @@ -23,3 +23,22 @@ def decode_rich1(): dev_rich_raw_input_types_t=rich1_banks.dev_raw_types_t) return rich1_decoding + + +def decode_rich2(): + number_of_events = initialize_number_of_events() + + rich2_banks = make_algorithm( + data_provider_t, name="rich2_banks", bank_type="Rich2") + + rich2_decoding = make_algorithm( + rich_decoding_t, + name="rich2_decoding", + host_number_of_events_t=number_of_events["host_number_of_events"], + host_raw_bank_version_t=rich2_banks.host_raw_bank_version_t, + dev_rich_raw_input_t=rich2_banks.dev_raw_banks_t, + dev_rich_raw_input_offsets_t=rich2_banks.dev_raw_offsets_t, + dev_rich_raw_input_sizes_t=rich2_banks.dev_raw_sizes_t, + dev_rich_raw_input_types_t=rich2_banks.dev_raw_types_t) + + return rich2_decoding diff --git a/configuration/python/AllenSequences/rich.py b/configuration/python/AllenSequences/rich.py index 9c1638e93ae..a8d329715b0 100644 --- a/configuration/python/AllenSequences/rich.py +++ b/configuration/python/AllenSequences/rich.py @@ -1,7 +1,16 @@ ############################################################################### # (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration # ############################################################################### -from AllenConf.rich_reconstruction import decode_rich1 +from AllenConf.rich_reconstruction import decode_rich1, decode_rich2 from AllenCore.generator import generate +from PyConf.control_flow import NodeLogic, CompositeNode -generate(decode_rich1()) +rich_decoding = CompositeNode( + "RichDecoding", [ + decode_rich1(), + decode_rich2() + ], + NodeLogic.NONLAZY_AND, + force_order=False) + +generate(rich_decoding) diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 3a5cbdc38bd..446dc59d4c7 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -404,7 +404,9 @@ void rich_decoding::rich_decoding_t::operator()( const Allen::Context& context) const { const auto bank_version = first(arguments); - std::cout << "Bank version Rich1 decoding " << bank_version << "\n"; + if (bank_version != 10) { + throw StrException("Rich bank version not supported (" + std::to_string(bank_version) + ")"); + } auto cable_mapping = reinterpret_cast(constants.dev_rich_cable_mapping); auto pdmdb_mapping = reinterpret_cast(constants.dev_rich_pdmdb_mapping); diff --git a/main/src/RegisterConsumers.cpp b/main/src/RegisterConsumers.cpp index d189f07a5d8..fe4752da70d 100644 --- a/main/src/RegisterConsumers.cpp +++ b/main/src/RegisterConsumers.cpp @@ -82,7 +82,21 @@ void register_consumers( return std::make_unique( constants.host_rich_cable_mapping, constants.dev_rich_cable_mapping); }, - BankTypes::Rich1)); + BankTypes::Rich1), + std::make_tuple( + Allen::NonEventData::RichPDMDBMapping {}, + [&constants]() { + return std::make_unique( + constants.host_rich_pdmdb_mapping, constants.dev_rich_pdmdb_mapping); + }, + BankTypes::Rich2), + std::make_tuple( + Allen::NonEventData::RichCableMapping {}, + [&constants]() { + return std::make_unique( + constants.host_rich_cable_mapping, constants.dev_rich_cable_mapping); + }, + BankTypes::Rich2)); const auto unconditional_consumers = std::make_tuple(std::make_tuple(Allen::NonEventData::MagneticField {}, [&constants]() { -- GitLab From 85f1f8bea4f3fb5cf36f128af33829fcd8f88abf Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 12:53:53 -0600 Subject: [PATCH 18/63] Use class for RichSmartID. --- device/rich/decoding/include/RichDecoding.cuh | 2 +- .../rich/decoding/include/RichDefinitions.cuh | 206 ++++++++---------- device/rich/decoding/src/RichDecoding.cu | 64 +++--- 3 files changed, 124 insertions(+), 148 deletions(-) diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index f80ff3eb2bf..4bfd4628c1a 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -21,7 +21,7 @@ namespace rich_decoding { DEVICE_OUTPUT(dev_rich_hit_offsets_t, unsigned) dev_rich_hit_offsets; HOST_OUTPUT(host_rich_hit_offsets_t, unsigned) host_rich_hit_offsets; HOST_OUTPUT(host_rich_total_number_of_hits_t, unsigned) host_rich_total_number_of_hits; - DEVICE_OUTPUT(dev_smart_ids_t, unsigned) dev_smart_ids; + DEVICE_OUTPUT(dev_smart_ids_t, Allen::RichSmartID) dev_smart_ids; }; struct rich_decoding_t : public DeviceAlgorithm, Parameters { diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index 66fc13d7456..faa74d1c5c3 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -1,76 +1,97 @@ #pragma once -namespace RichSmartID { - // Number of bits for each data field in the word - static constexpr const unsigned BitsPixelCol = 3; ///< Number of bits for MaPMT pixel column - static constexpr const unsigned BitsPixelRow = 3; ///< Number of bits for MaPMT pixel row - static constexpr const unsigned BitsPDNumInMod = 4; ///< Number of bits for MaPMT 'number in module' - static constexpr const unsigned BitsPDMod = 9; ///< Number of bits for MaPMT module - static constexpr const unsigned BitsPanel = 1; ///< Number of bits for MaPMT panel - static constexpr const unsigned BitsRich = 1; ///< Number of bits for RICH detector - static constexpr const unsigned BitsPixelSubRowIsSet = 1; - static constexpr const unsigned BitsPixelColIsSet = 1; - static constexpr const unsigned BitsPixelRowIsSet = 1; - static constexpr const unsigned BitsPDIsSet = 1; - static constexpr const unsigned BitsPanelIsSet = 1; - static constexpr const unsigned BitsRichIsSet = 1; - static constexpr const unsigned BitsLargePixel = 1; - - // The shifts - static constexpr const unsigned ShiftPixelCol = 0; - static constexpr const unsigned ShiftPixelRow = ShiftPixelCol + BitsPixelCol; - static constexpr const unsigned ShiftPDNumInMod = ShiftPixelRow + BitsPixelRow; - static constexpr const unsigned ShiftPDMod = ShiftPDNumInMod + BitsPDNumInMod; - static constexpr const unsigned ShiftPanel = ShiftPDMod + BitsPDMod; - static constexpr const unsigned ShiftRich = ShiftPanel + BitsPanel; - static constexpr const unsigned ShiftPixelSubRowIsSet = ShiftRich + BitsRich; - static constexpr const unsigned ShiftPixelColIsSet = ShiftPixelSubRowIsSet + BitsPixelSubRowIsSet; - static constexpr const unsigned ShiftPixelRowIsSet = ShiftPixelColIsSet + BitsPixelColIsSet; - static constexpr const unsigned ShiftPDIsSet = ShiftPixelRowIsSet + BitsPixelRowIsSet; - static constexpr const unsigned ShiftPanelIsSet = ShiftPDIsSet + BitsPDIsSet; - static constexpr const unsigned ShiftRichIsSet = ShiftPanelIsSet + BitsPanelIsSet; - static constexpr const unsigned ShiftLargePixel = ShiftRichIsSet + BitsRichIsSet; - - // The masks - static constexpr const unsigned MaskPixelCol = (unsigned) ((1 << BitsPixelCol) - 1) << ShiftPixelCol; - static constexpr const unsigned MaskPixelRow = (unsigned) ((1 << BitsPixelRow) - 1) << ShiftPixelRow; - static constexpr const unsigned MaskPDNumInMod = (unsigned) ((1 << BitsPDNumInMod) - 1) << ShiftPDNumInMod; - static constexpr const unsigned MaskPDMod = (unsigned) ((1 << BitsPDMod) - 1) << ShiftPDMod; - static constexpr const unsigned MaskPanel = (unsigned) ((1 << BitsPanel) - 1) << ShiftPanel; - static constexpr const unsigned MaskRich = (unsigned) ((1 << BitsRich) - 1) << ShiftRich; - static constexpr const unsigned MaskPixelSubRowIsSet = (unsigned) ((1 << BitsPixelSubRowIsSet) - 1) - << ShiftPixelSubRowIsSet; - static constexpr const unsigned MaskPixelColIsSet = (unsigned) ((1 << BitsPixelColIsSet) - 1) << ShiftPixelColIsSet; - static constexpr const unsigned MaskPixelRowIsSet = (unsigned) ((1 << BitsPixelRowIsSet) - 1) << ShiftPixelRowIsSet; - static constexpr const unsigned MaskPDIsSet = (unsigned) ((1 << BitsPDIsSet) - 1) << ShiftPDIsSet; - static constexpr const unsigned MaskPanelIsSet = (unsigned) ((1 << BitsPanelIsSet) - 1) << ShiftPanelIsSet; - static constexpr const unsigned MaskRichIsSet = (unsigned) ((1 << BitsRichIsSet) - 1) << ShiftRichIsSet; - static constexpr const unsigned MaskLargePixel = (unsigned) ((1 << BitsLargePixel) - 1) << ShiftLargePixel; - - // Max Values - static constexpr const unsigned MaxPixelCol = (unsigned) (1 << BitsPixelCol) - 1; - static constexpr const unsigned MaxPixelRow = (unsigned) (1 << BitsPixelRow) - 1; - static constexpr const unsigned MaxPDNumInMod = (unsigned) (1 << BitsPDNumInMod) - 1; - static constexpr const unsigned MaxPDMod = (unsigned) (1 << BitsPDMod) - 1; - static constexpr const unsigned MaxPanel = (unsigned) (1 << BitsPanel) - 1; - static constexpr const unsigned MaxRich = (unsigned) (1 << BitsRich) - 1; - - constexpr inline unsigned - bits(const unsigned key, const unsigned value, const unsigned shift, const unsigned mask) noexcept - { - return ((value << shift) & mask) | (key & ~mask); - } - - constexpr inline unsigned bits( - const unsigned key, - const unsigned value, // - const unsigned shift, // - const unsigned mask, // - const unsigned okMask) noexcept - { - return ((value << shift) & mask) | (key & ~mask) | okMask; - } -} // namespace RichSmartID +#include +#include + +namespace Allen { + class RichSmartID { + uint32_t m_key; + + public: + RichSmartID() = default; + + RichSmartID(uint32_t key) : m_key(key) {} + + // Number of bits for each data field in the word + static constexpr const unsigned BitsPixelCol = 3; ///< Number of bits for MaPMT pixel column + static constexpr const unsigned BitsPixelRow = 3; ///< Number of bits for MaPMT pixel row + static constexpr const unsigned BitsPDNumInMod = 4; ///< Number of bits for MaPMT 'number in module' + static constexpr const unsigned BitsPDMod = 9; ///< Number of bits for MaPMT module + static constexpr const unsigned BitsPanel = 1; ///< Number of bits for MaPMT panel + static constexpr const unsigned BitsRich = 1; ///< Number of bits for RICH detector + static constexpr const unsigned BitsPixelSubRowIsSet = 1; + static constexpr const unsigned BitsPixelColIsSet = 1; + static constexpr const unsigned BitsPixelRowIsSet = 1; + static constexpr const unsigned BitsPDIsSet = 1; + static constexpr const unsigned BitsPanelIsSet = 1; + static constexpr const unsigned BitsRichIsSet = 1; + static constexpr const unsigned BitsLargePixel = 1; + + // The shifts + static constexpr const unsigned ShiftPixelCol = 0; + static constexpr const unsigned ShiftPixelRow = ShiftPixelCol + BitsPixelCol; + static constexpr const unsigned ShiftPDNumInMod = ShiftPixelRow + BitsPixelRow; + static constexpr const unsigned ShiftPDMod = ShiftPDNumInMod + BitsPDNumInMod; + static constexpr const unsigned ShiftPanel = ShiftPDMod + BitsPDMod; + static constexpr const unsigned ShiftRich = ShiftPanel + BitsPanel; + static constexpr const unsigned ShiftPixelSubRowIsSet = ShiftRich + BitsRich; + static constexpr const unsigned ShiftPixelColIsSet = ShiftPixelSubRowIsSet + BitsPixelSubRowIsSet; + static constexpr const unsigned ShiftPixelRowIsSet = ShiftPixelColIsSet + BitsPixelColIsSet; + static constexpr const unsigned ShiftPDIsSet = ShiftPixelRowIsSet + BitsPixelRowIsSet; + static constexpr const unsigned ShiftPanelIsSet = ShiftPDIsSet + BitsPDIsSet; + static constexpr const unsigned ShiftRichIsSet = ShiftPanelIsSet + BitsPanelIsSet; + static constexpr const unsigned ShiftLargePixel = ShiftRichIsSet + BitsRichIsSet; + + // The masks + static constexpr const unsigned MaskPixelCol = (unsigned) ((1 << BitsPixelCol) - 1) << ShiftPixelCol; + static constexpr const unsigned MaskPixelRow = (unsigned) ((1 << BitsPixelRow) - 1) << ShiftPixelRow; + static constexpr const unsigned MaskPDNumInMod = (unsigned) ((1 << BitsPDNumInMod) - 1) << ShiftPDNumInMod; + static constexpr const unsigned MaskPDMod = (unsigned) ((1 << BitsPDMod) - 1) << ShiftPDMod; + static constexpr const unsigned MaskPanel = (unsigned) ((1 << BitsPanel) - 1) << ShiftPanel; + static constexpr const unsigned MaskRich = (unsigned) ((1 << BitsRich) - 1) << ShiftRich; + static constexpr const unsigned MaskPixelSubRowIsSet = (unsigned) ((1 << BitsPixelSubRowIsSet) - 1) + << ShiftPixelSubRowIsSet; + static constexpr const unsigned MaskPixelColIsSet = (unsigned) ((1 << BitsPixelColIsSet) - 1) << ShiftPixelColIsSet; + static constexpr const unsigned MaskPixelRowIsSet = (unsigned) ((1 << BitsPixelRowIsSet) - 1) << ShiftPixelRowIsSet; + static constexpr const unsigned MaskPDIsSet = (unsigned) ((1 << BitsPDIsSet) - 1) << ShiftPDIsSet; + static constexpr const unsigned MaskPanelIsSet = (unsigned) ((1 << BitsPanelIsSet) - 1) << ShiftPanelIsSet; + static constexpr const unsigned MaskRichIsSet = (unsigned) ((1 << BitsRichIsSet) - 1) << ShiftRichIsSet; + static constexpr const unsigned MaskLargePixel = (unsigned) ((1 << BitsLargePixel) - 1) << ShiftLargePixel; + + // Max Values + static constexpr const unsigned MaxPixelCol = (unsigned) (1 << BitsPixelCol) - 1; + static constexpr const unsigned MaxPixelRow = (unsigned) (1 << BitsPixelRow) - 1; + static constexpr const unsigned MaxPDNumInMod = (unsigned) (1 << BitsPDNumInMod) - 1; + static constexpr const unsigned MaxPDMod = (unsigned) (1 << BitsPDMod) - 1; + static constexpr const unsigned MaxPanel = (unsigned) (1 << BitsPanel) - 1; + static constexpr const unsigned MaxRich = (unsigned) (1 << BitsRich) - 1; + + __host__ __device__ constexpr inline void + setData(const unsigned value, const unsigned shift, const unsigned mask) noexcept + { + m_key = ((value << shift) & mask) | (m_key & ~mask); + } + + __host__ __device__ constexpr inline void setData( + const unsigned value, // + const unsigned shift, // + const unsigned mask, // + const unsigned okMask) noexcept + { + m_key = ((value << shift) & mask) | (m_key & ~mask) | okMask; + } + + __host__ __device__ constexpr inline unsigned getData(const unsigned shift, const unsigned mask) const noexcept + { + return (m_key << shift) & mask; + } + + __host__ __device__ constexpr inline auto key() const noexcept { return m_key; } + + /// ostream operator + __host__ friend std::ostream& operator<<(std::ostream& str, const RichSmartID& id) { return str << id.key(); } + }; // namespace RichSmartID +} // namespace Allen namespace Rich::Future::DAQ { enum DetectorType : std::int8_t { @@ -99,49 +120,10 @@ namespace Rich::Future::DAQ { static const IntType Max0 = (1 << Bits0) - 1; static const IntType Max1 = (1 << Bits1) - 1; - private: - /// Set the overall word - inline void setData(const IntType data) { m_data = data; } - - /// Set data for given word - inline void set( - const IntType value, // - const IntType shift, // - const IntType mask) - { - setData(((value << shift) & mask) | (data() & ~mask)); - } - public: - /// Constructor from two sizes - PackedFrameSizes(const IntType size0, const IntType size1) - { - set(size0, Shift0, Mask0); - set(size1, Shift1, Mask1); - } - /// Contructor from a single word - __device__ explicit PackedFrameSizes(const IntType d) : m_data(d) {} + __host__ __device__ explicit PackedFrameSizes(const IntType d) : m_data(d) {} - public: - /// Set size0 - inline void setSize0(const IntType size0) noexcept { set(size0, Shift0, Mask0); } - - /// Set size1 - inline void setSize1(const IntType size1) noexcept { set(size1, Shift1, Mask1); } - - /// set the size for the give word number - inline void setSize(const IntType size, const IntType word) noexcept - { - if (0 == word) { - setSize0(size); - } - else { - setSize1(size); - } - } - - public: /// Get the overall data __host__ __device__ inline IntType data() const noexcept { return m_data; } @@ -152,7 +134,7 @@ namespace Rich::Future::DAQ { __host__ __device__ inline IntType size1() const noexcept { return ((data() & Mask1) >> Shift1); } /// Get the total size - inline auto totalSize() const noexcept { return size0() + size1(); } + __host__ __device__ inline auto totalSize() const noexcept { return size0() + size1(); } private: /// The data word diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 446dc59d4c7..dd3653ca5d7 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -14,7 +14,10 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* pdmdb_mapping) { unsigned number_of_hits = 0; - std::array connSizes {}; + std::array< + Rich::Future::DAQ::PackedFrameSizes::IntType, + Rich::Future::DAQ::Allen::Tel40CableMapping::MaxConnectionsPerTel40> + connSizes {}; auto tel40ID = bank.source_id; const auto& connMeta = cable_mapping->tel40Meta(tel40ID); @@ -173,7 +176,7 @@ __device__ void rich_decode_bank( const Rich::Future::DAQ::Allen::Tel40CableMapping* cable_mapping, const Rich::Future::DAQ::Allen::PDMDBDecodeMapping* pdmdb_mapping, unsigned* event_inserted_hits, - unsigned* event_smart_ids) + Allen::RichSmartID* event_smart_ids) { std::array< Rich::Future::DAQ::PackedFrameSizes::IntType, @@ -242,20 +245,17 @@ __device__ void rich_decode_bank( // so cannot make this a hard error // make a smart ID - auto hitID = cData.smartID; // sets RICH, side, module and PMT type + auto hitID = Allen::RichSmartID {cData.smartID}; // sets RICH, side, module and PMT type // Add the PMT and pixel info - const auto nInMod = (aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; - hitID = RichSmartID::bits( - hitID, cData.moduleNum, RichSmartID::ShiftPDMod, RichSmartID::MaskPDMod, RichSmartID::MaskPDIsSet); - hitID = RichSmartID::bits(hitID, nInMod, RichSmartID::ShiftPDNumInMod, RichSmartID::MaskPDNumInMod); + const auto nInMod = (aData.ec * (0 != ((hitID.key() >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; + hitID.setData(cData.moduleNum, Allen::RichSmartID::ShiftPDMod, Allen::RichSmartID::MaskPDMod, Allen::RichSmartID::MaskPDIsSet); + hitID.setData(nInMod, Allen::RichSmartID::ShiftPDNumInMod, Allen::RichSmartID::MaskPDNumInMod); const auto row = aData.anode / 8; const auto col = 8 - 1 - (aData.anode % 8); - hitID = RichSmartID::bits( - hitID, row, RichSmartID::ShiftPixelRow, RichSmartID::MaskPixelRow, RichSmartID::MaskPixelRowIsSet); - hitID = RichSmartID::bits( - hitID, col, RichSmartID::ShiftPixelCol, RichSmartID::MaskPixelCol, RichSmartID::MaskPixelColIsSet); + hitID.setData(row, Allen::RichSmartID::ShiftPixelRow, Allen::RichSmartID::MaskPixelRow, Allen::RichSmartID::MaskPixelRowIsSet); + hitID.setData(col, Allen::RichSmartID::ShiftPixelCol, Allen::RichSmartID::MaskPixelCol, Allen::RichSmartID::MaskPixelColIsSet); const auto insert_index = atomicAdd(event_inserted_hits, 1); event_smart_ids[insert_index] = hitID; @@ -308,32 +308,20 @@ __device__ void rich_decode_bank( // so cannot make this a hard error // make a smart ID - auto hitID = cData.smartID; // sets RICH, side, module and PMT type + auto hitID = Allen::RichSmartID {cData.smartID}; // sets RICH, side, module and PMT type // Add the PMT and pixel info - const auto nInMod = (aData.ec * (0 != ((hitID >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; - hitID = RichSmartID::bits( - hitID, - cData.moduleNum, - RichSmartID::ShiftPDMod, - RichSmartID::MaskPDMod, - RichSmartID::MaskPDIsSet); - hitID = RichSmartID::bits(hitID, nInMod, RichSmartID::ShiftPDNumInMod, RichSmartID::MaskPDNumInMod); + const auto nInMod = (aData.ec * (0 != ((hitID.key() >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; + hitID.setData( + cData.moduleNum, Allen::RichSmartID::ShiftPDMod, Allen::RichSmartID::MaskPDMod, Allen::RichSmartID::MaskPDIsSet); + hitID.setData(nInMod, Allen::RichSmartID::ShiftPDNumInMod, Allen::RichSmartID::MaskPDNumInMod); const auto row = aData.anode / 8; const auto col = 8 - 1 - (aData.anode % 8); - hitID = RichSmartID::bits( - hitID, - row, - RichSmartID::ShiftPixelRow, - RichSmartID::MaskPixelRow, - RichSmartID::MaskPixelRowIsSet); - hitID = RichSmartID::bits( - hitID, - col, - RichSmartID::ShiftPixelCol, - RichSmartID::MaskPixelCol, - RichSmartID::MaskPixelColIsSet); + hitID.setData( + row, Allen::RichSmartID::ShiftPixelRow, Allen::RichSmartID::MaskPixelRow, Allen::RichSmartID::MaskPixelRowIsSet); + hitID.setData( + col, Allen::RichSmartID::ShiftPixelCol, Allen::RichSmartID::MaskPixelCol, Allen::RichSmartID::MaskPixelColIsSet); const auto insert_index = atomicAdd(event_inserted_hits, 1); event_smart_ids[insert_index] = hitID; @@ -409,7 +397,8 @@ void rich_decoding::rich_decoding_t::operator()( } auto cable_mapping = reinterpret_cast(constants.dev_rich_cable_mapping); - auto pdmdb_mapping = reinterpret_cast(constants.dev_rich_pdmdb_mapping); + auto pdmdb_mapping = + reinterpret_cast(constants.dev_rich_pdmdb_mapping); // Calculate number of hits into dev_rich_number_of_hits_t Allen::memset_async(arguments, 0, context); @@ -434,12 +423,17 @@ void rich_decoding::rich_decoding_t::operator()( // Decode RICH hits auto dev_rich_number_of_inserted_hits = make_device_buffer(arguments, size(arguments)); - Allen::memset_async(dev_rich_number_of_inserted_hits.data(), 0, dev_rich_number_of_inserted_hits.size_bytes(), context); + Allen::memset_async( + dev_rich_number_of_inserted_hits.data(), 0, dev_rich_number_of_inserted_hits.size_bytes(), context); resize(arguments, first(arguments)); global_function(runtime_options.mep_layout ? rich_decoding_kernel : rich_decoding_kernel)( dim3(size(arguments)), 1, context)( - arguments, std::get<0>(runtime_options.event_interval), cable_mapping, pdmdb_mapping, dev_rich_number_of_inserted_hits.data()); + arguments, + std::get<0>(runtime_options.event_interval), + cable_mapping, + pdmdb_mapping, + dev_rich_number_of_inserted_hits.data()); // Print output print(arguments); -- GitLab From 0e55ba429ecc770163e639592d1c676b2ebd4c6e Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 14:07:43 -0600 Subject: [PATCH 19/63] Add host device attributes to RichSmartID constructors. --- device/rich/decoding/include/RichDefinitions.cuh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index faa74d1c5c3..d3d67a96d58 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -8,9 +8,9 @@ namespace Allen { uint32_t m_key; public: - RichSmartID() = default; + __host__ __device__ RichSmartID() = default; - RichSmartID(uint32_t key) : m_key(key) {} + __host__ __device__ RichSmartID(uint32_t key) : m_key(key) {} // Number of bits for each data field in the word static constexpr const unsigned BitsPixelCol = 3; ///< Number of bits for MaPMT pixel column -- GitLab From 37811c9b3e68e0f11429505eb0a7d1ae83fa3723 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 14:32:40 -0600 Subject: [PATCH 20/63] Added Rich no ut configuration. --- .../python/AllenSequences/hlt1_rich_no_ut.py | 18 ++++++++++++++++++ device/rich/decoding/src/RichDecoding.cu | 8 ++++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 configuration/python/AllenSequences/hlt1_rich_no_ut.py diff --git a/configuration/python/AllenSequences/hlt1_rich_no_ut.py b/configuration/python/AllenSequences/hlt1_rich_no_ut.py new file mode 100644 index 00000000000..f6ec2a13f26 --- /dev/null +++ b/configuration/python/AllenSequences/hlt1_rich_no_ut.py @@ -0,0 +1,18 @@ +############################################################################### +# (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration # +############################################################################### +from AllenConf.HLT1 import setup_hlt1_node +from AllenCore.generator import generate +from AllenConf.rich_reconstruction import decode_rich1, decode_rich2 +from PyConf.control_flow import NodeLogic, CompositeNode + +hlt1_and_rich_decoding = CompositeNode( + "HLT1AndRichDecoding", [ + setup_hlt1_node(with_ut=False), + decode_rich1(), + decode_rich2() + ], + NodeLogic.NONLAZY_AND, + force_order=False) + +generate(hlt1_and_rich_decoding) diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index dd3653ca5d7..3fada4bd9c8 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -404,7 +404,7 @@ void rich_decoding::rich_decoding_t::operator()( Allen::memset_async(arguments, 0, context); global_function( runtime_options.mep_layout ? rich_calculate_number_of_hits : rich_calculate_number_of_hits)( - dim3(size(arguments)), 64, context)( + dim3(size(arguments)), 128, context)( arguments, std::get<0>(runtime_options.event_interval), cable_mapping, pdmdb_mapping); // Copy to host @@ -428,7 +428,7 @@ void rich_decoding::rich_decoding_t::operator()( resize(arguments, first(arguments)); global_function(runtime_options.mep_layout ? rich_decoding_kernel : rich_decoding_kernel)( - dim3(size(arguments)), 1, context)( + dim3(size(arguments)), 128, context)( arguments, std::get<0>(runtime_options.event_interval), cable_mapping, @@ -436,6 +436,6 @@ void rich_decoding::rich_decoding_t::operator()( dev_rich_number_of_inserted_hits.data()); // Print output - print(arguments); - print(arguments); + // print(arguments); + // print(arguments); } -- GitLab From 868192bc4769556da9e67dc7c7d515e2b4a0ed70 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 15:38:45 -0600 Subject: [PATCH 21/63] Fix CaloDecode logic to using 32-bit raw bank pointer. --- device/calo/decoding/src/CaloDecode.cu | 59 +++++++++++++------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/device/calo/decoding/src/CaloDecode.cu b/device/calo/decoding/src/CaloDecode.cu index be1677571ce..ce4aa3b71c5 100644 --- a/device/calo/decoding/src/CaloDecode.cu +++ b/device/calo/decoding/src/CaloDecode.cu @@ -34,30 +34,31 @@ namespace { for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { auto raw_bank = raw_event.raw_bank(bank_number); + auto raw_bank_data_u32 = reinterpret_cast(raw_bank.data); if constexpr (decoding_version < 4) { // old decoding - const auto raw_bank_end = raw_bank.data + raw_bank.size; - while (raw_bank.data < raw_bank_end) { - uint32_t word = *raw_bank.data; + const auto raw_bank_end = reinterpret_cast(raw_bank.data + raw_bank.size); + while (raw_bank_data_u32 < raw_bank_end) { + uint32_t word = *raw_bank_data_u32; uint16_t trig_size = word & 0x7F; uint16_t code = (word >> 14) & 0x1FF; // Skip header and trigger words - raw_bank.data += 1 + (trig_size + 3) / 4; + raw_bank_data_u32 += 1 + (trig_size + 3) / 4; // pattern bits - unsigned int pattern = *raw_bank.data; + unsigned int pattern = *raw_bank_data_u32; // Loop over all cards in this front-env sub-bank. - uint32_t last_data = *(raw_bank.data + 1); - raw_bank.data += 2; + uint32_t last_data = *(raw_bank_data_u32 + 1); + raw_bank_data_u32 += 2; int16_t offset = 0; for (unsigned int bit_num = 0; 32 > bit_num; ++bit_num) { if (31 < offset) { offset -= 32; - last_data = *raw_bank.data; - raw_bank.data += 1; + last_data = *raw_bank_data_u32; + raw_bank_data_u32 += 1; } int adc; if (0 == (pattern & (1 << bit_num))) { //.. short coding @@ -70,8 +71,8 @@ namespace { if (28 == offset) adc &= 0xF; //== clean-up extra bits offset += 12; if (32 < offset) { //.. get the extra bits on next word - last_data = *raw_bank.data; - raw_bank.data += 1; + last_data = *raw_bank_data_u32; + raw_bank_data_u32 += 1; offset -= 32; int temp = (last_data << (12 - offset)) & 0xFFF; adc += temp; @@ -99,9 +100,9 @@ namespace { } auto raw_bank_fiberCheck = raw_event_fiberCheck.raw_bank(bank_number); + auto raw_bank_fiberCheck_data_u32 = reinterpret_cast(raw_bank_fiberCheck.data); - auto get_data = [](uint8_t const* raw_data) { - const auto raw_data_u32 = reinterpret_cast(raw_data); + auto get_data = [](uint32_t const* raw_data_u32) { auto d = *raw_data_u32; if constexpr (decoding_version == 4) { // big endian d = ((d >> 24) & 0x000000FF) | ((d >> 8) & 0x0000FF00) | ((d << 8) & 0x00FF0000) | ((d << 24) & 0xFF000000); @@ -109,7 +110,7 @@ namespace { return d; }; - uint32_t pattern = *(raw_bank.data); + uint32_t pattern = *(raw_bank_data_u32); int offset = 0; uint32_t lastData = pattern; @@ -120,10 +121,10 @@ namespace { for (int ifeb = 0; ifeb < 3; ifeb++) { // First, remove 3 LLTs if (ifeb == 0) { - raw_bank.data += 3; - raw_bank_fiberCheck.data += 3; + raw_bank_data_u32 += 3; + raw_bank_fiberCheck_data_u32 += 3; } - lastData = get_data(raw_bank.data); + lastData = get_data(raw_bank_data_u32); int nADC = 0; bool isFiberOff = false; @@ -133,12 +134,12 @@ namespace { // ... and readout data for (unsigned int bitNum = 0; 32 > bitNum; bitNum++) { if (nADC % 8 == 0) { // Check fibers pattern, 1 fiber corresponds to 8 ADC (96b) - if (offset == 32) raw_bank_fiberCheck.data += 1; - uint32_t pattern1 = get_data(raw_bank_fiberCheck.data); - raw_bank_fiberCheck.data += 1; - uint32_t pattern2 = get_data(raw_bank_fiberCheck.data); - raw_bank_fiberCheck.data += 1; - uint32_t pattern3 = get_data(raw_bank_fiberCheck.data); + if (offset == 32) raw_bank_fiberCheck_data_u32 += 1; + uint32_t pattern1 = get_data(raw_bank_fiberCheck_data_u32); + raw_bank_fiberCheck_data_u32 += 1; + uint32_t pattern2 = get_data(raw_bank_fiberCheck_data_u32); + raw_bank_fiberCheck_data_u32 += 1; + uint32_t pattern3 = get_data(raw_bank_fiberCheck_data_u32); if (pattern1 == fibMask1 && pattern2 == fibMask2 && pattern3 == fibMask3) isFiberOff = true; else @@ -146,8 +147,8 @@ namespace { } if (31 < offset) { offset -= 32; - raw_bank.data += 1; - lastData = get_data(raw_bank.data); + raw_bank_data_u32 += 1; + lastData = get_data(raw_bank_data_u32); } int adc = 0; @@ -159,16 +160,16 @@ namespace { adc = ((lastData >> (20 - offset)) & 0xfff); if (28 == offset) { //.. get the extra bits on next word - raw_bank.data += 1; - lastData = get_data(raw_bank.data); + raw_bank_data_u32 += 1; + lastData = get_data(raw_bank_data_u32); int temp = (lastData >> (offset - 4)) & 0xFF; offset -= 32; adc = (adc << 8) + temp; } if (24 == offset) { //.. get the extra bits on next word - raw_bank.data += 1; - lastData = get_data(raw_bank.data); + raw_bank_data_u32 += 1; + lastData = get_data(raw_bank_data_u32); int temp = (lastData >> (offset + 4)) & 0xF; offset -= 32; adc = (adc << 4) + temp; -- GitLab From 32c670217a02a3ee97214ef795b8d688777cf8e6 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 15:54:21 -0600 Subject: [PATCH 22/63] Add hlt1_pp_rich_no_ut throughput job. --- scripts/ci/test_config.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/ci/test_config.yaml b/scripts/ci/test_config.yaml index 7b7356813f5..e97151c2f88 100644 --- a/scripts/ci/test_config.yaml +++ b/scripts/ci/test_config.yaml @@ -52,6 +52,10 @@ minimal: - hlt1_pp_forward_then_matching dataset: "upgrade_mc_minbias_scifi_v5_retinacluster_000_v1_newLHCbID_new_UT_geometry" geometry: "geometry_dddb-20180815_sim-20180530-vc-md100_new_UT_geometry" + - type: "throughput" + sequence: + - hlt1_pp_rich_no_ut + dataset: "Run_0000248711_HLT20840_20221011-113809-426" - type: "efficiency" sequence: -- GitLab From 218b104724fe6230741ee5061155aed59e085340 Mon Sep 17 00:00:00 2001 From: Gitlab CI Date: Tue, 7 Mar 2023 21:55:35 +0000 Subject: [PATCH 23/63] Fixed formatting patch generated by https://gitlab.cern.ch/lhcb/Allen/-/jobs/28015367 --- .../python/AllenConf/rich_reconstruction.py | 4 +- .../python/AllenSequences/hlt1_rich_no_ut.py | 9 ++- configuration/python/AllenSequences/rich.py | 5 +- .../rich/decoding/include/RichDefinitions.cuh | 6 +- .../include/RichPDMDBDecodeMapping.cuh | 2 +- .../include/RichTel40CableMapping.cuh | 2 +- device/rich/decoding/src/RichDecoding.cu | 59 ++++++++++++------- main/include/BankMapping.h | 2 +- stream/sequence/include/Constants.cuh | 3 +- 9 files changed, 53 insertions(+), 39 deletions(-) diff --git a/configuration/python/AllenConf/rich_reconstruction.py b/configuration/python/AllenConf/rich_reconstruction.py index 5a090907221..933e2d12d8b 100644 --- a/configuration/python/AllenConf/rich_reconstruction.py +++ b/configuration/python/AllenConf/rich_reconstruction.py @@ -11,7 +11,7 @@ def decode_rich1(): rich1_banks = make_algorithm( data_provider_t, name="rich1_banks", bank_type="Rich1") - + rich1_decoding = make_algorithm( rich_decoding_t, name="rich1_decoding", @@ -30,7 +30,7 @@ def decode_rich2(): rich2_banks = make_algorithm( data_provider_t, name="rich2_banks", bank_type="Rich2") - + rich2_decoding = make_algorithm( rich_decoding_t, name="rich2_decoding", diff --git a/configuration/python/AllenSequences/hlt1_rich_no_ut.py b/configuration/python/AllenSequences/hlt1_rich_no_ut.py index f6ec2a13f26..6483e241771 100644 --- a/configuration/python/AllenSequences/hlt1_rich_no_ut.py +++ b/configuration/python/AllenSequences/hlt1_rich_no_ut.py @@ -7,11 +7,10 @@ from AllenConf.rich_reconstruction import decode_rich1, decode_rich2 from PyConf.control_flow import NodeLogic, CompositeNode hlt1_and_rich_decoding = CompositeNode( - "HLT1AndRichDecoding", [ - setup_hlt1_node(with_ut=False), - decode_rich1(), - decode_rich2() - ], + "HLT1AndRichDecoding", + [setup_hlt1_node(with_ut=False), + decode_rich1(), + decode_rich2()], NodeLogic.NONLAZY_AND, force_order=False) diff --git a/configuration/python/AllenSequences/rich.py b/configuration/python/AllenSequences/rich.py index a8d329715b0..cc2001f76ee 100644 --- a/configuration/python/AllenSequences/rich.py +++ b/configuration/python/AllenSequences/rich.py @@ -6,10 +6,7 @@ from AllenCore.generator import generate from PyConf.control_flow import NodeLogic, CompositeNode rich_decoding = CompositeNode( - "RichDecoding", [ - decode_rich1(), - decode_rich2() - ], + "RichDecoding", [decode_rich1(), decode_rich2()], NodeLogic.NONLAZY_AND, force_order=False) diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index d3d67a96d58..c5a0e99f715 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -9,7 +9,7 @@ namespace Allen { public: __host__ __device__ RichSmartID() = default; - + __host__ __device__ RichSmartID(uint32_t key) : m_key(key) {} // Number of bits for each data field in the word @@ -114,8 +114,8 @@ namespace Rich::Future::DAQ { static const IntType Shift0 = 0; static const IntType Shift1 = Shift0 + Bits0; // masks - static const IntType Mask0 = (IntType) ((1 << Bits0) - 1) << Shift0; - static const IntType Mask1 = (IntType) ((1 << Bits1) - 1) << Shift1; + static const IntType Mask0 = (IntType)((1 << Bits0) - 1) << Shift0; + static const IntType Mask1 = (IntType)((1 << Bits1) - 1) << Shift1; // max values static const IntType Max0 = (1 << Bits0) - 1; static const IntType Max1 = (1 << Bits1) - 1; diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index a6134afddc1..f2820723f1a 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -119,5 +119,5 @@ namespace Rich::Future::DAQ::Allen { /// Mapping version int m_mappingVer {-1}; }; - + } // namespace Rich::Future::DAQ::Allen diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index 79a596a65db..97112620569 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -83,7 +83,7 @@ namespace Rich::Future::DAQ::Allen { const uint32_t id, // PD ID const int8_t pdmdb, // PDMDB ID const int8_t frame // PDMDB Frame - ) const noexcept + ) const noexcept { // module number const auto modN = (id >> 6) & 0xF; // TODO: RichSmartID.h:912 diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 3fada4bd9c8..46e899e9ea3 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -118,7 +118,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( const auto bit = iLB + bitOffset; // load the anode data for this bit - if ((size_t) (bit) < frameData.size()) { + if ((size_t)(bit) < frameData.size()) { number_of_hits++; } @@ -154,12 +154,11 @@ __global__ void rich_calculate_number_of_hits( const auto event_number = parameters.dev_event_list[blockIdx.x]; // Read raw event - const auto raw_event = Allen::RawEvent { - parameters.dev_rich_raw_input, - parameters.dev_rich_raw_input_offsets, - parameters.dev_rich_raw_input_sizes, - parameters.dev_rich_raw_input_types, - event_number + event_start}; + const auto raw_event = Allen::RawEvent {parameters.dev_rich_raw_input, + parameters.dev_rich_raw_input_offsets, + parameters.dev_rich_raw_input_sizes, + parameters.dev_rich_raw_input_types, + event_number + event_start}; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); @@ -249,13 +248,25 @@ __device__ void rich_decode_bank( // Add the PMT and pixel info const auto nInMod = (aData.ec * (0 != ((hitID.key() >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; - hitID.setData(cData.moduleNum, Allen::RichSmartID::ShiftPDMod, Allen::RichSmartID::MaskPDMod, Allen::RichSmartID::MaskPDIsSet); + hitID.setData( + cData.moduleNum, + Allen::RichSmartID::ShiftPDMod, + Allen::RichSmartID::MaskPDMod, + Allen::RichSmartID::MaskPDIsSet); hitID.setData(nInMod, Allen::RichSmartID::ShiftPDNumInMod, Allen::RichSmartID::MaskPDNumInMod); const auto row = aData.anode / 8; const auto col = 8 - 1 - (aData.anode % 8); - hitID.setData(row, Allen::RichSmartID::ShiftPixelRow, Allen::RichSmartID::MaskPixelRow, Allen::RichSmartID::MaskPixelRowIsSet); - hitID.setData(col, Allen::RichSmartID::ShiftPixelCol, Allen::RichSmartID::MaskPixelCol, Allen::RichSmartID::MaskPixelColIsSet); + hitID.setData( + row, + Allen::RichSmartID::ShiftPixelRow, + Allen::RichSmartID::MaskPixelRow, + Allen::RichSmartID::MaskPixelRowIsSet); + hitID.setData( + col, + Allen::RichSmartID::ShiftPixelCol, + Allen::RichSmartID::MaskPixelCol, + Allen::RichSmartID::MaskPixelColIsSet); const auto insert_index = atomicAdd(event_inserted_hits, 1); event_smart_ids[insert_index] = hitID; @@ -302,7 +313,7 @@ __device__ void rich_decode_bank( const auto bit = iLB + bitOffset; // load the anode data for this bit - if ((size_t) (bit) < frameData.size()) { + if ((size_t)(bit) < frameData.size()) { const auto& aData = frameData[bit]; // TODO: Data 'could' be invalid, e.g. radiation-induced-upsets // so cannot make this a hard error @@ -313,15 +324,24 @@ __device__ void rich_decode_bank( // Add the PMT and pixel info const auto nInMod = (aData.ec * (0 != ((hitID.key() >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; hitID.setData( - cData.moduleNum, Allen::RichSmartID::ShiftPDMod, Allen::RichSmartID::MaskPDMod, Allen::RichSmartID::MaskPDIsSet); + cData.moduleNum, + Allen::RichSmartID::ShiftPDMod, + Allen::RichSmartID::MaskPDMod, + Allen::RichSmartID::MaskPDIsSet); hitID.setData(nInMod, Allen::RichSmartID::ShiftPDNumInMod, Allen::RichSmartID::MaskPDNumInMod); const auto row = aData.anode / 8; const auto col = 8 - 1 - (aData.anode % 8); hitID.setData( - row, Allen::RichSmartID::ShiftPixelRow, Allen::RichSmartID::MaskPixelRow, Allen::RichSmartID::MaskPixelRowIsSet); + row, + Allen::RichSmartID::ShiftPixelRow, + Allen::RichSmartID::MaskPixelRow, + Allen::RichSmartID::MaskPixelRowIsSet); hitID.setData( - col, Allen::RichSmartID::ShiftPixelCol, Allen::RichSmartID::MaskPixelCol, Allen::RichSmartID::MaskPixelColIsSet); + col, + Allen::RichSmartID::ShiftPixelCol, + Allen::RichSmartID::MaskPixelCol, + Allen::RichSmartID::MaskPixelColIsSet); const auto insert_index = atomicAdd(event_inserted_hits, 1); event_smart_ids[insert_index] = hitID; @@ -361,12 +381,11 @@ __global__ void rich_decoding_kernel( auto event_smart_ids = parameters.dev_smart_ids + parameters.dev_rich_hit_offsets[event_number]; // Read raw event - const auto raw_event = Allen::RawEvent { - parameters.dev_rich_raw_input, - parameters.dev_rich_raw_input_offsets, - parameters.dev_rich_raw_input_sizes, - parameters.dev_rich_raw_input_types, - event_number + event_start}; + const auto raw_event = Allen::RawEvent {parameters.dev_rich_raw_input, + parameters.dev_rich_raw_input_offsets, + parameters.dev_rich_raw_input_sizes, + parameters.dev_rich_raw_input_types, + event_number + event_start}; for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { const auto bank = raw_event.raw_bank(bank_number); diff --git a/main/include/BankMapping.h b/main/include/BankMapping.h index 966b4201e19..2ecae8519c8 100644 --- a/main/include/BankMapping.h +++ b/main/include/BankMapping.h @@ -25,7 +25,7 @@ namespace Allen { {LHCb::RawBank::OTRaw, BankTypes::MCTracks}, {LHCb::RawBank::Plume, BankTypes::Plume}, {LHCb::RawBank::Rich, BankTypes::Rich1} // TODO: Rich maps to Rich1. Rich2 is not yet included. - }; // used for track MC info + }; // used for track MC info const std::unordered_map subdetectors = {{SourceIdSys::SourceIdSys_ODIN, BankTypes::ODIN}, {SourceIdSys::SourceIdSys_VELO_A, BankTypes::VP}, diff --git a/stream/sequence/include/Constants.cuh b/stream/sequence/include/Constants.cuh index fd5ac6d5ed3..6f1d72e37ed 100644 --- a/stream/sequence/include/Constants.cuh +++ b/stream/sequence/include/Constants.cuh @@ -39,8 +39,7 @@ namespace TrackMatchingConsts { namespace Rich::Future::DAQ::Allen { class PDMDBDecodeMapping; class Tel40CableMapping; -} - +} // namespace Rich::Future::DAQ::Allen /** * @brief Struct intended as a singleton with constants defined on GPU. -- GitLab From a5bffa314a4a484ab118d3b6b994d02fd1a22756 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 22:57:57 +0100 Subject: [PATCH 24/63] Add Apache2 license. --- device/rich/decoding/include/RichDefinitions.cuh | 10 ++++++++++ .../rich/decoding/include/RichPDMDBDecodeMapping.cuh | 10 ++++++++++ device/rich/decoding/include/RichTel40CableMapping.cuh | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index c5a0e99f715..dc989dd0893 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -1,3 +1,13 @@ +/*****************************************************************************\ +* (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the Apache License * +* version 2 (Apache-2.0), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ #pragma once #include diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index f2820723f1a..63ab1f73797 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -1,3 +1,13 @@ +/*****************************************************************************\ +* (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the Apache License * +* version 2 (Apache-2.0), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ #pragma once #include diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index 97112620569..5fc15e808e3 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -1,3 +1,13 @@ +/*****************************************************************************\ +* (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the Apache License * +* version 2 (Apache-2.0), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ #pragma once // STL -- GitLab From 796ec25ba3616cadc786fb8dc6317802ceb06ca2 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 16:11:34 -0600 Subject: [PATCH 25/63] Uncomment build sequences. --- stream/CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/stream/CMakeLists.txt b/stream/CMakeLists.txt index 9b81272aa95..764b898ab68 100644 --- a/stream/CMakeLists.txt +++ b/stream/CMakeLists.txt @@ -50,7 +50,6 @@ if(STANDALONE) add_dependencies(Stream checkout_lhcb checkout_gaudi) endif() -# TODO: Uncomment -# foreach(sequence ${BUILD_SEQUENCES}) -# generate_sequence(${sequence}) -# endforeach() +foreach(sequence ${BUILD_SEQUENCES}) + generate_sequence(${sequence}) +endforeach() -- GitLab From cc79e4a1f8e627ac3f0cc4b827c7dd5441425bd8 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 16:13:37 -0600 Subject: [PATCH 26/63] Modify test to run with correct geometry. --- scripts/ci/test_config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ci/test_config.yaml b/scripts/ci/test_config.yaml index e97151c2f88..4b8a0da5017 100644 --- a/scripts/ci/test_config.yaml +++ b/scripts/ci/test_config.yaml @@ -56,6 +56,7 @@ minimal: sequence: - hlt1_pp_rich_no_ut dataset: "Run_0000248711_HLT20840_20221011-113809-426" + geometry: "MiniBrunel_2018_MinBias_FTv4_DIGI_ecalv4_scifiv7_muonv3" - type: "efficiency" sequence: -- GitLab From 4445643b3d957f929555dcb21a067904ae26bd3e Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 7 Mar 2023 18:43:52 -0600 Subject: [PATCH 27/63] Move hlt1 rich configuration. --- .../AllenSequences/{hlt1_rich_no_ut.py => hlt1_pp_rich_no_ut.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename configuration/python/AllenSequences/{hlt1_rich_no_ut.py => hlt1_pp_rich_no_ut.py} (100%) diff --git a/configuration/python/AllenSequences/hlt1_rich_no_ut.py b/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py similarity index 100% rename from configuration/python/AllenSequences/hlt1_rich_no_ut.py rename to configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py -- GitLab From 598e7c7239f56c23bed68287b4fa45d71a8d4707 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Wed, 8 Mar 2023 08:29:34 -0600 Subject: [PATCH 28/63] Refactor code. --- device/rich/decoding/include/RichDecoding.cuh | 4 +--- .../rich/decoding/include/RichPDMDBDecodeMapping.cuh | 12 ++++++------ .../rich/decoding/include/RichTel40CableMapping.cuh | 6 +++--- device/rich/decoding/src/RichDecoding.cu | 5 +++-- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index 4bfd4628c1a..fdd0828b22a 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -4,9 +4,7 @@ #pragma once #include "AlgorithmTypes.cuh" -#include -#include -#include +#include namespace rich_decoding { struct Parameters { diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index 63ab1f73797..775799f4421 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -40,9 +40,9 @@ namespace Rich::Future::DAQ::Allen { public: /// Default constructor - BitData() = default; + __host__ __device__ BitData() = default; /// Constructor from values - BitData( + __host__ __device__ BitData( const int8_t _ec, // const int8_t _pmt, // const int8_t _anode) : @@ -86,7 +86,7 @@ namespace Rich::Future::DAQ::Allen { const int8_t rich, // const int8_t pdmdb, // const int8_t link, // - const bool isHType) const noexcept + const bool isHType) const { // Note as this is called many times from the decoding, avoid runtime range checking // in optimised builds, as once OK it should never be invalidated. @@ -102,13 +102,13 @@ namespace Rich::Future::DAQ::Allen { public: /// mapping version - __host__ __device__ inline auto version() const noexcept { return m_mappingVer; } + __host__ __device__ inline auto version() const { return m_mappingVer; } /// Access the initialisation state - __host__ __device__ inline auto isInitialised() const noexcept { return m_isInitialised; } + __host__ __device__ inline auto isInitialised() const { return m_isInitialised; } /// Get PDMDB data for given Tel40 data - __host__ __device__ inline const auto& getFrameData(const Tel40CableMapping::Tel40LinkData& cData) const noexcept + __host__ __device__ inline const auto& getFrameData(const Tel40CableMapping::Tel40LinkData& cData) const { auto rich = (cData.smartID >> 20) & 0x1; return getFrameData(rich, cData.pdmdbNum, cData.linkNum, cData.isHType); diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index 5fc15e808e3..3421fc79923 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -86,14 +86,14 @@ namespace Rich::Future::DAQ::Allen { // accessors /// Access the initialisation state - inline bool isInitialised() const noexcept { return m_isInitialised; } + inline bool isInitialised() const { return m_isInitialised; } /// Access the Tel40 Link data for given channel ID const auto& tel40Data( const uint32_t id, // PD ID const int8_t pdmdb, // PDMDB ID const int8_t frame // PDMDB Frame - ) const noexcept + ) const { // module number const auto modN = (id >> 6) & 0xF; // TODO: RichSmartID.h:912 @@ -123,7 +123,7 @@ namespace Rich::Future::DAQ::Allen { } /// mapping version - inline auto version() const noexcept { return m_mappingVer; } + inline auto version() const { return m_mappingVer; } private: // data diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 46e899e9ea3..0b9b0cdde1c 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -2,9 +2,10 @@ * (c) Copyright 2018-2020 CERN for the benefit of the LHCb Collaboration * \*****************************************************************************/ #include -#include -#include #include +#include +#include +#include INSTANTIATE_ALGORITHM(rich_decoding::rich_decoding_t) -- GitLab From e8f9004f9f86851533846b8e87968e9c29efc688 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Wed, 8 Mar 2023 11:03:14 -0600 Subject: [PATCH 29/63] Add property with number of threads in block in RICH decoding. --- configuration/python/AllenConf/rich_reconstruction.py | 6 ++++-- device/rich/decoding/include/RichDecoding.cuh | 4 ++++ device/rich/decoding/src/RichDecoding.cu | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/configuration/python/AllenConf/rich_reconstruction.py b/configuration/python/AllenConf/rich_reconstruction.py index 933e2d12d8b..343d3760b41 100644 --- a/configuration/python/AllenConf/rich_reconstruction.py +++ b/configuration/python/AllenConf/rich_reconstruction.py @@ -20,7 +20,8 @@ def decode_rich1(): dev_rich_raw_input_t=rich1_banks.dev_raw_banks_t, dev_rich_raw_input_offsets_t=rich1_banks.dev_raw_offsets_t, dev_rich_raw_input_sizes_t=rich1_banks.dev_raw_sizes_t, - dev_rich_raw_input_types_t=rich1_banks.dev_raw_types_t) + dev_rich_raw_input_types_t=rich1_banks.dev_raw_types_t, + block_dim_x=128) return rich1_decoding @@ -39,6 +40,7 @@ def decode_rich2(): dev_rich_raw_input_t=rich2_banks.dev_raw_banks_t, dev_rich_raw_input_offsets_t=rich2_banks.dev_raw_offsets_t, dev_rich_raw_input_sizes_t=rich2_banks.dev_raw_sizes_t, - dev_rich_raw_input_types_t=rich2_banks.dev_raw_types_t) + dev_rich_raw_input_types_t=rich2_banks.dev_raw_types_t, + block_dim_x=128) return rich2_decoding diff --git a/device/rich/decoding/include/RichDecoding.cuh b/device/rich/decoding/include/RichDecoding.cuh index fdd0828b22a..67c60dd7d25 100644 --- a/device/rich/decoding/include/RichDecoding.cuh +++ b/device/rich/decoding/include/RichDecoding.cuh @@ -20,6 +20,7 @@ namespace rich_decoding { HOST_OUTPUT(host_rich_hit_offsets_t, unsigned) host_rich_hit_offsets; HOST_OUTPUT(host_rich_total_number_of_hits_t, unsigned) host_rich_total_number_of_hits; DEVICE_OUTPUT(dev_smart_ids_t, Allen::RichSmartID) dev_smart_ids; + PROPERTY(block_dim_x_t, "block_dim_x", "block dimension x", unsigned) block_dim_x; }; struct rich_decoding_t : public DeviceAlgorithm, Parameters { @@ -30,5 +31,8 @@ namespace rich_decoding { const RuntimeOptions&, const Constants&, const Allen::Context&) const; + + private: + Property m_block_dim_x {this, 64}; }; } // namespace rich_decoding diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 0b9b0cdde1c..03e953e5d7e 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -424,7 +424,7 @@ void rich_decoding::rich_decoding_t::operator()( Allen::memset_async(arguments, 0, context); global_function( runtime_options.mep_layout ? rich_calculate_number_of_hits : rich_calculate_number_of_hits)( - dim3(size(arguments)), 128, context)( + dim3(size(arguments)), property(), context)( arguments, std::get<0>(runtime_options.event_interval), cable_mapping, pdmdb_mapping); // Copy to host @@ -448,7 +448,7 @@ void rich_decoding::rich_decoding_t::operator()( resize(arguments, first(arguments)); global_function(runtime_options.mep_layout ? rich_decoding_kernel : rich_decoding_kernel)( - dim3(size(arguments)), 128, context)( + dim3(size(arguments)), property(), context)( arguments, std::get<0>(runtime_options.event_interval), cable_mapping, -- GitLab From 991b0a493eec2e7e7cb29fd5496e9d6f15a75a84 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Wed, 8 Mar 2023 14:18:43 -0600 Subject: [PATCH 30/63] Use [] instead of at. Add verbosity print. --- .../decoding/include/RichPDMDBDecodeMapping.cuh | 2 +- .../decoding/include/RichTel40CableMapping.cuh | 16 +++++----------- device/rich/decoding/src/RichDecoding.cu | 8 +++++--- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index 775799f4421..a42d0f1389b 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -110,7 +110,7 @@ namespace Rich::Future::DAQ::Allen { /// Get PDMDB data for given Tel40 data __host__ __device__ inline const auto& getFrameData(const Tel40CableMapping::Tel40LinkData& cData) const { - auto rich = (cData.smartID >> 20) & 0x1; + const auto rich = cData.smartID.getData(::Allen::RichSmartID::ShiftRich, ::Allen::RichSmartID::MaskRich); return getFrameData(rich, cData.pdmdbNum, cData.linkNum, cData.isHType); } diff --git a/device/rich/decoding/include/RichTel40CableMapping.cuh b/device/rich/decoding/include/RichTel40CableMapping.cuh index 3421fc79923..303d6051224 100644 --- a/device/rich/decoding/include/RichTel40CableMapping.cuh +++ b/device/rich/decoding/include/RichTel40CableMapping.cuh @@ -10,14 +10,8 @@ \*****************************************************************************/ #pragma once -// STL #include -#include -#include -#include -#include -#include -#include +#include namespace Rich::Future::DAQ::Allen { /// Helper class for RICH PMT data format encoding @@ -28,7 +22,7 @@ namespace Rich::Future::DAQ::Allen { class Tel40LinkData final { public: /// RICH SmartID - uint32_t smartID; + ::Allen::RichSmartID smartID; /// Module Number int32_t moduleNum; /// Source ID @@ -99,7 +93,7 @@ namespace Rich::Future::DAQ::Allen { const auto modN = (id >> 6) & 0xF; // TODO: RichSmartID.h:912 // return tel40 data - const auto& data = m_tel40ModuleData.at(modN).at(pdmdb).at(frame); + const auto& data = m_tel40ModuleData[modN][pdmdb][frame]; // finally return return data; } @@ -110,7 +104,7 @@ namespace Rich::Future::DAQ::Allen { const auto payload = sID & 0x3FF; const auto side = (sID >> 10) & 0x1; const auto rich = (sID >> 11) == 9; // Rich1 is 4, Rich2 is 9. Then, Rich1 is identified with 0, Rich2 is 1. - return m_tel40ConnData.at(rich).at(side).at(payload); + return m_tel40ConnData[rich][side][payload]; } // TODO: Use this when the int / boolean info is needed @@ -119,7 +113,7 @@ namespace Rich::Future::DAQ::Allen { const auto payload = sID & 0x3FF; const auto side = (sID >> 10) & 0x1; const auto rich = (sID >> 11) == 9; // Rich1 is 4, Rich2 is 9. Then, Rich1 is identified with 0, Rich2 is 1. - return m_tel40ConnMeta.at(rich).at(side).at(payload); + return m_tel40ConnMeta[rich][side][payload]; } /// mapping version diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 03e953e5d7e..1e6ef650f4b 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -455,7 +455,9 @@ void rich_decoding::rich_decoding_t::operator()( pdmdb_mapping, dev_rich_number_of_inserted_hits.data()); - // Print output - // print(arguments); - // print(arguments); + if (property() >= logger::debug) { + // Print output + print(arguments); + print(arguments); + } } -- GitLab From 2f3c605f1dc086c1b38489878e8c0d72e86d7738 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Wed, 8 Mar 2023 14:30:37 -0600 Subject: [PATCH 31/63] Add Rich to test_mep_banks. --- Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h | 4 ++-- mdf/test/test_mep_banks.cpp | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h b/Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h index ca5f7d41a5c..e07143f5c30 100644 --- a/Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h +++ b/Dumpers/BinaryDumpers/include/Dumpers/Identifiers.h @@ -88,14 +88,14 @@ namespace Allen { }; /** @class RichPDMDBMapping - * Identifier for the Muon lookup tables for Allen + * Identifier for the RICH PDMDB decode mapping for Allen */ struct RichPDMDBMapping : Identifier { inline static std::string const id = "RichPDMDBMapping"; }; /** @class RichCableMapping - * Identifier for the Muon lookup tables for Allen + * Identifier for the RICH cable mapping for Allen */ struct RichCableMapping : Identifier { inline static std::string const id = "RichCableMapping"; diff --git a/mdf/test/test_mep_banks.cpp b/mdf/test/test_mep_banks.cpp index 9932690e5a9..32c5063785c 100644 --- a/mdf/test/test_mep_banks.cpp +++ b/mdf/test/test_mep_banks.cpp @@ -508,6 +508,8 @@ using SciFiTag = BTTag; using UTTag = BTTag; using MuonTag = BTTag; using ECalTag = BTTag; +using Rich1Tag = BTTag; +using Rich2Tag = BTTag; /** * @brief Check banks @@ -575,7 +577,7 @@ void check_banks(BanksAndOffsets const& mep_data, BanksAndOffsets const& allen_d // Main test case, multiple bank types are checked // VeloTag, UTTag, SciFiTag, -TEMPLATE_TEST_CASE("MEP vs MDF", "[MEP MDF]", ECalTag, MuonTag, VeloTag, SciFiTag, ODINTag) +TEMPLATE_TEST_CASE("MEP vs MDF", "[MEP MDF]", ECalTag, MuonTag, VeloTag, SciFiTag, ODINTag, Rich1Tag, Rich2Tag) { if (!s_config.run) return; -- GitLab From c116e2cfbbec46e88af0b39668bc44936b794c51 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Wed, 8 Mar 2023 15:25:31 -0600 Subject: [PATCH 32/63] Add binary dumpers for Rich datatypes. --- .../src/DumpRichCableMapping.cpp | 78 +++++++++++++++++++ .../src/DumpRichPDMDBMapping.cpp | 78 +++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp create mode 100644 Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp diff --git a/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp b/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp new file mode 100644 index 00000000000..424f805def0 --- /dev/null +++ b/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp @@ -0,0 +1,78 @@ +/*****************************************************************************\ +* (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration * +\*****************************************************************************/ + +// Gaudi Array properties ( must be first ...) +#include "GaudiKernel/ParsersFactory.h" +#include "GaudiKernel/StdArrayAsProperty.h" + +// Rich Kernel +#include "RichFutureKernel/RichAlgBase.h" + +// Gaudi Functional +#include "LHCbAlgs/Transformer.h" + +// Rich Utils +#include "RichFutureUtils/RichDecodedData.h" +#include "RichUtils/RichException.h" +#include "RichUtils/RichHashMap.h" +#include "RichUtils/RichMap.h" +#include "RichUtils/RichSmartIDSorter.h" + +// RICH DAQ +#include "RichFutureDAQ/RichPDMDBDecodeMapping.h" +#include "RichFutureDAQ/RichPackedFrameSizes.h" +#include "RichFutureDAQ/RichTel40CableMapping.h" + +// Dumper +#include "Dumper.h" +#include + +namespace { + struct RichCableMapping { + RichCableMapping() = default; + RichCableMapping(std::vector& data, const Tel40CableMapping& tel40Maps) + { + Allen::Tel40CableMapping allenTel40Maps {tel40Maps}; + DumpUtils::Writer output {}; + output.write(allenTel40Maps); + data = output.buffer(); + } + }; +} // namespace + +/** + * @brief Dump cable mapping for the RICH detector. + */ +class DumpRichCableMapping final + : public Allen::Dumpers::Dumper> { +public: + DumpRichCableMapping(const std::string& name, ISvcLocator* svcLoc); + + void operator()(const RichCableMapping& MuonTable) const override; + + StatusCode initialize() override; + +private: + std::vector m_data; +}; + +DECLARE_COMPONENT(DumpRichCableMapping) + +DumpRichCableMapping::DumpRichCableMapping(const std::string& name, ISvcLocator* svcLoc) : + Dumper(name, svcLoc, {KeyValue {"RichCableMappingLocation", location(name, "cablemapping")}}) +{} + +StatusCode DumpRichCableMapping::initialize() +{ + return Dumper::initialize().andThen([&] { + register_producer(Allen::NonEventData::RichCableMapping::id, "rich_tel40maps", m_data); + addConditionDerivation({MuonTableCond}, inputLocation(), [&](DeMuonDetector const& det) { + auto cable_mapping = RichCableMapping {m_data, det}; + dump(); + return cable_mapping; + }); + }); +} + +void DumpRichCableMapping::operator()(const RichCableMapping&) const {} diff --git a/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp b/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp new file mode 100644 index 00000000000..3a90d51dc5a --- /dev/null +++ b/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp @@ -0,0 +1,78 @@ +/*****************************************************************************\ +* (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration * +\*****************************************************************************/ + +// Gaudi Array properties ( must be first ...) +#include "GaudiKernel/ParsersFactory.h" +#include "GaudiKernel/StdArrayAsProperty.h" + +// Rich Kernel +#include "RichFutureKernel/RichAlgBase.h" + +// Gaudi Functional +#include "LHCbAlgs/Transformer.h" + +// Rich Utils +#include "RichFutureUtils/RichDecodedData.h" +#include "RichUtils/RichException.h" +#include "RichUtils/RichHashMap.h" +#include "RichUtils/RichMap.h" +#include "RichUtils/RichSmartIDSorter.h" + +// RICH DAQ +#include "RichFutureDAQ/RichPDMDBDecodeMapping.h" +#include "RichFutureDAQ/RichPackedFrameSizes.h" +#include "RichFutureDAQ/RichTel40CableMapping.h" + +// Dumper +#include "Dumper.h" +#include + +namespace { + struct RichPDMDBMapping { + RichPDMDBMapping() = default; + RichPDMDBMapping(std::vector& data, const Tel40CableMapping& tel40Maps) + { + Allen::PDMDBDecodeMapping allenTel40Maps {tel40Maps}; + DumpUtils::Writer output {}; + output.write(allenTel40Maps); + data = output.buffer(); + } + }; +} // namespace + +/** + * @brief Dump cable mapping for the RICH detector. + */ +class DumpRichPDMDBMapping final + : public Allen::Dumpers::Dumper> { +public: + DumpRichPDMDBMapping(const std::string& name, ISvcLocator* svcLoc); + + void operator()(const RichPDMDBMapping& MuonTable) const override; + + StatusCode initialize() override; + +private: + std::vector m_data; +}; + +DECLARE_COMPONENT(DumpRichPDMDBMapping) + +DumpRichPDMDBMapping::DumpRichPDMDBMapping(const std::string& name, ISvcLocator* svcLoc) : + Dumper(name, svcLoc, {KeyValue {"RichPDMDBMappingLocation", location(name, "pdmdbmapping")}}) +{} + +StatusCode DumpRichPDMDBMapping::initialize() +{ + return Dumper::initialize().andThen([&] { + register_producer(Allen::NonEventData::RichPDMDBMapping::id, "rich_pdmdbmaps", m_data); + addConditionDerivation({MuonTableCond}, inputLocation(), [&](DeMuonDetector const& det) { + auto pdmdb_mapping = RichPDMDBMapping {m_data, det}; + dump(); + return pdmdb_mapping; + }); + }); +} + +void DumpRichPDMDBMapping::operator()(const RichPDMDBMapping&) const {} -- GitLab From c30c7bd6fa18ffb1f5b10398a1ca11c9718b08cc Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 9 Mar 2023 13:44:27 -0600 Subject: [PATCH 33/63] Use a default compare method in test_mep_banks. --- mdf/test/test_mep_banks.cpp | 80 ++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/mdf/test/test_mep_banks.cpp b/mdf/test/test_mep_banks.cpp index 32c5063785c..f9565d99bba 100644 --- a/mdf/test/test_mep_banks.cpp +++ b/mdf/test/test_mep_banks.cpp @@ -240,6 +240,44 @@ int main(int argc, char* argv[]) template struct compare { + void operator()( + const int, + gsl::span mep_fragments, + gsl::span mep_offsets, + gsl::span mep_sizes, + gsl::span mep_types, + gsl::span allen_banks, + gsl::span allen_offsets, + gsl::span allen_sizes, + gsl::span allen_types, + unsigned const i_event) + { + + const auto allen_raw_event = + Allen::RawEvent(allen_banks.data(), allen_offsets.data(), allen_sizes.data(), allen_types.data(), i_event); + const auto mep_raw_event = Allen::RawEvent( + mep_fragments.data(), mep_offsets.data(), mep_sizes.data(), mep_types.data(), i_event); + auto const mep_n_banks = mep_raw_event.number_of_raw_banks; + + REQUIRE(mep_n_banks == allen_raw_event.number_of_raw_banks); + + for (unsigned bank = 0; bank < mep_n_banks; ++bank) { + // Read raw bank + auto const mep_bank = mep_raw_event.raw_bank(bank); + auto const allen_bank = allen_raw_event.raw_bank(bank); + auto mep_len = mep_bank.size; + auto allen_len = allen_bank.size; + REQUIRE(mep_len == allen_len); + + REQUIRE(mep_bank.type == allen_bank.type); + + auto top5_mask = (allen_bank.source_id >> 11 == 0) ? 0x7FF : 0xFFFF; + REQUIRE((mep_bank.source_id & top5_mask) == allen_bank.source_id); + for (long j = 0; j < mep_len; ++j) { + REQUIRE(allen_bank.data[j] == mep_bank.data[j]); + } + } + } }; template @@ -455,48 +493,6 @@ struct compare { } }; -template -struct compare { - void operator()( - const int, - gsl::span mep_fragments, - gsl::span mep_offsets, - gsl::span mep_sizes, - gsl::span mep_types, - gsl::span allen_banks, - gsl::span allen_offsets, - gsl::span allen_sizes, - gsl::span allen_types, - unsigned const i_event) - { - - const auto allen_raw_event = - Allen::RawEvent(allen_banks.data(), allen_offsets.data(), allen_sizes.data(), allen_types.data(), i_event); - const auto mep_raw_event = Allen::RawEvent( - mep_fragments.data(), mep_offsets.data(), mep_sizes.data(), mep_types.data(), i_event); - auto const mep_n_banks = mep_raw_event.number_of_raw_banks; - - REQUIRE(mep_n_banks == allen_raw_event.number_of_raw_banks); - - for (unsigned bank = 0; bank < mep_n_banks; ++bank) { - // Read raw bank - auto const mep_bank = mep_raw_event.raw_bank(bank); - auto const allen_bank = allen_raw_event.raw_bank(bank); - auto mep_len = mep_bank.size; - auto allen_len = allen_bank.size; - REQUIRE(mep_len == allen_len); - - REQUIRE(mep_bank.type == allen_bank.type); - - auto top5_mask = (allen_bank.source_id >> 11 == 0) ? 0x7FF : 0xFFFF; - REQUIRE((mep_bank.source_id & top5_mask) == allen_bank.source_id); - for (long j = 0; j < mep_len; ++j) { - REQUIRE(allen_bank.data[j] == mep_bank.data[j]); - } - } - } -}; - template struct BTTag { inline static const BankTypes BT = BT_; -- GitLab From 0b9d178e6e94cd7aedd1045d6c20b78946578463 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 9 Mar 2023 13:48:21 -0600 Subject: [PATCH 34/63] Remove size_t. --- .../rich/decoding/include/RichPDMDBDecodeMapping.cuh | 8 ++++---- device/rich/decoding/src/RichDecoding.cu | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh index a42d0f1389b..0235452a8ff 100644 --- a/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh +++ b/device/rich/decoding/include/RichPDMDBDecodeMapping.cuh @@ -55,16 +55,16 @@ namespace Rich::Future::DAQ::Allen { // defines /// Max Number of frames per PDMDB - static constexpr const std::size_t FramesPerPDMDB = 6; + static constexpr const unsigned FramesPerPDMDB = 6; /// Number of PDMDBs per module - static constexpr const std::size_t PDMDBPerModule = 2; + static constexpr const unsigned PDMDBPerModule = 2; /// Max Number of frames per PDM - static constexpr const std::size_t FramesPerPDM = PDMDBPerModule * FramesPerPDMDB; + static constexpr const unsigned FramesPerPDM = PDMDBPerModule * FramesPerPDMDB; /// Number of bits per data frame - static constexpr const std::size_t BitsPerFrame = 86; + static constexpr const unsigned BitsPerFrame = 86; /// Array of Bit Data structs per frame using FrameData = std::array; diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 1e6ef650f4b..09cf56e84f3 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -40,7 +40,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( const auto& connData = cable_mapping->tel40Data(tel40ID); if (connMeta.hasInactiveLinks) { - for (std::size_t iL = 0; iL < connData.size(); ++iL) { + for (unsigned iL = 0; iL < connData.size(); ++iL) { if (!connData[iL].isActive) { for (auto i = connData.size() - 1; i > iL; --i) { connSizes[i] = connSizes[i - 1]; @@ -52,7 +52,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( // finally loop over payload words and decode hits // note iterator starts from where the above header loop ended... - std::size_t iLink {0}; + unsigned iLink {0}; while (dataW != bankEnd && iLink < connSizes.size()) { // Do we have any words to decode for this link if (connSizes[iLink] > 0) { @@ -74,7 +74,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( // ZS decoding... word is bit index // load the anode data for this bit - if ((std::size_t)(*dataW) < frameData.size()) { + if ((unsigned)(*dataW) < frameData.size()) { number_of_hits++; } @@ -203,7 +203,7 @@ __device__ void rich_decode_bank( const auto& connData = cable_mapping->tel40Data(tel40ID); if (connMeta.hasInactiveLinks) { - for (std::size_t iL = 0; iL < connData.size(); ++iL) { + for (unsigned iL = 0; iL < connData.size(); ++iL) { if (!connData[iL].isActive) { for (auto i = connData.size() - 1; i > iL; --i) { connSizes[i] = connSizes[i - 1]; @@ -215,7 +215,7 @@ __device__ void rich_decode_bank( // finally loop over payload words and decode hits // note iterator starts from where the above header loop ended... - std::size_t iLink {0}; + unsigned iLink {0}; while (dataW != bankEnd && iLink < connSizes.size()) { // Do we have any words to decode for this link if (connSizes[iLink] > 0) { @@ -237,7 +237,7 @@ __device__ void rich_decode_bank( // ZS decoding... word is bit index // load the anode data for this bit - if ((std::size_t)(*dataW) < frameData.size()) { + if ((unsigned)(*dataW) < frameData.size()) { const auto& aData = frameData[*dataW]; -- GitLab From b76b68cce2a676b1b63d3ba1cc0b3d614cfe15f8 Mon Sep 17 00:00:00 2001 From: Gitlab CI Date: Thu, 9 Mar 2023 19:49:14 +0000 Subject: [PATCH 35/63] Fixed formatting patch generated by https://gitlab.cern.ch/lhcb/Allen/-/jobs/28075381 --- device/rich/decoding/src/RichDecoding.cu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 09cf56e84f3..d1732dab1c6 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -74,7 +74,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( // ZS decoding... word is bit index // load the anode data for this bit - if ((unsigned)(*dataW) < frameData.size()) { + if ((unsigned) (*dataW) < frameData.size()) { number_of_hits++; } @@ -237,7 +237,7 @@ __device__ void rich_decode_bank( // ZS decoding... word is bit index // load the anode data for this bit - if ((unsigned)(*dataW) < frameData.size()) { + if ((unsigned) (*dataW) < frameData.size()) { const auto& aData = frameData[*dataW]; -- GitLab From 25cd9e912ba045f6e1d81ff3fa0cfbaebe173331 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Mon, 13 Mar 2023 14:59:03 -0600 Subject: [PATCH 36/63] Attempt to add Rich condition derivation to dumpers. --- Dumpers/BinaryDumpers/CMakeLists.txt | 2 ++ .../BinaryDumpers/src/DumpRichCableMapping.cpp | 16 ++++++++-------- .../BinaryDumpers/src/DumpRichPDMDBMapping.cpp | 16 ++++++---------- Rec/Allen/python/Allen/config.py | 6 +++--- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/Dumpers/BinaryDumpers/CMakeLists.txt b/Dumpers/BinaryDumpers/CMakeLists.txt index 4c463407875..37508a25ac4 100644 --- a/Dumpers/BinaryDumpers/CMakeLists.txt +++ b/Dumpers/BinaryDumpers/CMakeLists.txt @@ -46,6 +46,8 @@ gaudi_add_module(BinaryDumpersModule src/DumpUTHits.cpp src/DumpUTLookupTables.cpp src/DumpVPGeometry.cpp + src/DumpRichCableMapping.cpp + src/DumpRichPDMDBMapping.cpp src/PVDumper.cpp src/ProvideConstants.cpp src/TestMuonTable.cpp diff --git a/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp b/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp index 424f805def0..bc60b45d079 100644 --- a/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp +++ b/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp @@ -20,7 +20,6 @@ #include "RichUtils/RichSmartIDSorter.h" // RICH DAQ -#include "RichFutureDAQ/RichPDMDBDecodeMapping.h" #include "RichFutureDAQ/RichPackedFrameSizes.h" #include "RichFutureDAQ/RichTel40CableMapping.h" @@ -31,9 +30,9 @@ namespace { struct RichCableMapping { RichCableMapping() = default; - RichCableMapping(std::vector& data, const Tel40CableMapping& tel40Maps) + RichCableMapping(std::vector& data, const Rich::Future::DAQ::Tel40CableMapping& tel40Maps) { - Allen::Tel40CableMapping allenTel40Maps {tel40Maps}; + Rich::Future::DAQ::Allen::Tel40CableMapping allenTel40Maps {tel40Maps}; DumpUtils::Writer output {}; output.write(allenTel40Maps); data = output.buffer(); @@ -49,7 +48,7 @@ class DumpRichCableMapping final public: DumpRichCableMapping(const std::string& name, ISvcLocator* svcLoc); - void operator()(const RichCableMapping& MuonTable) const override; + void operator()(const RichCableMapping&) const override; StatusCode initialize() override; @@ -67,10 +66,11 @@ StatusCode DumpRichCableMapping::initialize() { return Dumper::initialize().andThen([&] { register_producer(Allen::NonEventData::RichCableMapping::id, "rich_tel40maps", m_data); - addConditionDerivation({MuonTableCond}, inputLocation(), [&](DeMuonDetector const& det) { - auto cable_mapping = RichCableMapping {m_data, det}; - dump(); - return cable_mapping; + addConditionDerivation(Rich::Future::DAQ::Tel40CableMapping::ConditionPaths, inputLocation(), + [&](const Rich::Future::DAQ::Tel40CableMapping& det) { + auto rich_cable_mapping = RichCableMapping {m_data, det}; + dump(); + return rich_cable_mapping; }); }); } diff --git a/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp b/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp index 3a90d51dc5a..2ba6c6697b4 100644 --- a/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp +++ b/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp @@ -22,7 +22,6 @@ // RICH DAQ #include "RichFutureDAQ/RichPDMDBDecodeMapping.h" #include "RichFutureDAQ/RichPackedFrameSizes.h" -#include "RichFutureDAQ/RichTel40CableMapping.h" // Dumper #include "Dumper.h" @@ -31,9 +30,9 @@ namespace { struct RichPDMDBMapping { RichPDMDBMapping() = default; - RichPDMDBMapping(std::vector& data, const Tel40CableMapping& tel40Maps) + RichPDMDBMapping(std::vector& data, const Rich::Future::DAQ::PDMDBDecodeMapping& tel40Maps) { - Allen::PDMDBDecodeMapping allenTel40Maps {tel40Maps}; + Rich::Future::DAQ::Allen::PDMDBDecodeMapping allenTel40Maps {tel40Maps}; DumpUtils::Writer output {}; output.write(allenTel40Maps); data = output.buffer(); @@ -49,7 +48,7 @@ class DumpRichPDMDBMapping final public: DumpRichPDMDBMapping(const std::string& name, ISvcLocator* svcLoc); - void operator()(const RichPDMDBMapping& MuonTable) const override; + void operator()(const RichPDMDBMapping&) const override; StatusCode initialize() override; @@ -65,13 +64,10 @@ DumpRichPDMDBMapping::DumpRichPDMDBMapping(const std::string& name, ISvcLocator* StatusCode DumpRichPDMDBMapping::initialize() { - return Dumper::initialize().andThen([&] { + return Dumper::initialize().andThen([&, this] { register_producer(Allen::NonEventData::RichPDMDBMapping::id, "rich_pdmdbmaps", m_data); - addConditionDerivation({MuonTableCond}, inputLocation(), [&](DeMuonDetector const& det) { - auto pdmdb_mapping = RichPDMDBMapping {m_data, det}; - dump(); - return pdmdb_mapping; - }); + Rich::Future::DAQ::PDMDBDecodeMapping::addConditionDerivation(this, inputLocation()); + dump(); }); } diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index 2bf77082885..6bfc0d714e9 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -20,7 +20,7 @@ from PyConf.application import configure_input, configure from PyConf.Algorithms import ( AllenTESProducer, DumpBeamline, DumpCaloGeometry, DumpMagneticField, DumpVPGeometry, DumpFTGeometry, DumpUTGeometry, DumpUTLookupTables, - DumpMuonGeometry, DumpMuonTable, AllenODINProducer, DumpRichPDMDBMaps, + DumpMuonGeometry, DumpMuonTable, AllenODINProducer, DumpRichPDMDBMapping, DumpRichCableMapping) from DDDB.CheckDD4Hep import UseDD4Hep @@ -119,8 +119,8 @@ def setup_allen_non_event_data_service(allen_event_loop=False, 'FTCluster': [(DumpFTGeometry, 'DumpFTGeometry', 'scifi_geometry')], 'Muon': [(DumpMuonGeometry, 'DumpMuonGeometry', 'muon_geometry'), (DumpMuonTable, 'DumpMuonTable', 'muon_tables')], - 'Rich': [(DumpRichPDMDBMaps, 'rich_pdmdbmaps'), - (DumpRichCableMapping, 'rich_tel40maps')] + 'Rich1': [(DumpRichPDMDBMaps, 'rich_pdmdbmaps'), + (DumpRichCableMapping, 'rich_tel40maps')] } detector_names = { -- GitLab From c914b66cc15e686404042b15f8c299c20646cfe5 Mon Sep 17 00:00:00 2001 From: Gitlab CI Date: Mon, 13 Mar 2023 21:01:19 +0000 Subject: [PATCH 37/63] Fixed formatting patch generated by https://gitlab.cern.ch/lhcb/Allen/-/jobs/28158426 --- Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp | 6 ++++-- Rec/Allen/python/Allen/config.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp b/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp index bc60b45d079..c2d1e7bc31f 100644 --- a/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp +++ b/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp @@ -66,12 +66,14 @@ StatusCode DumpRichCableMapping::initialize() { return Dumper::initialize().andThen([&] { register_producer(Allen::NonEventData::RichCableMapping::id, "rich_tel40maps", m_data); - addConditionDerivation(Rich::Future::DAQ::Tel40CableMapping::ConditionPaths, inputLocation(), + addConditionDerivation( + Rich::Future::DAQ::Tel40CableMapping::ConditionPaths, + inputLocation(), [&](const Rich::Future::DAQ::Tel40CableMapping& det) { auto rich_cable_mapping = RichCableMapping {m_data, det}; dump(); return rich_cable_mapping; - }); + }); }); } diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index 6bfc0d714e9..f7227f2dda3 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -119,7 +119,7 @@ def setup_allen_non_event_data_service(allen_event_loop=False, 'FTCluster': [(DumpFTGeometry, 'DumpFTGeometry', 'scifi_geometry')], 'Muon': [(DumpMuonGeometry, 'DumpMuonGeometry', 'muon_geometry'), (DumpMuonTable, 'DumpMuonTable', 'muon_tables')], - 'Rich1': [(DumpRichPDMDBMaps, 'rich_pdmdbmaps'), + 'Rich1': [(DumpRichPDMDBMapping, 'rich_pdmdbmaps'), (DumpRichCableMapping, 'rich_tel40maps')] } -- GitLab From 89ad43b39fca6651a77d6eda5486d36417da9bb4 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Wed, 15 Mar 2023 10:09:00 -0600 Subject: [PATCH 38/63] Added test for RichSmartIDs. --- Rec/Allen/CMakeLists.txt | 2 + Rec/Allen/src/TestRichSmartIDs.cpp | 75 +++++++++++++++++++ .../python/AllenConf/rich_reconstruction.py | 45 ++++------- .../AllenSequences/hlt1_pp_rich_no_ut.py | 6 +- configuration/python/AllenSequences/rich.py | 4 +- .../rich/decoding/include/RichDefinitions.cuh | 3 + 6 files changed, 99 insertions(+), 36 deletions(-) create mode 100644 Rec/Allen/src/TestRichSmartIDs.cpp diff --git a/Rec/Allen/CMakeLists.txt b/Rec/Allen/CMakeLists.txt index 81fc4c5eff1..7cd74ebd9bd 100755 --- a/Rec/Allen/CMakeLists.txt +++ b/Rec/Allen/CMakeLists.txt @@ -29,6 +29,7 @@ gaudi_add_module(AllenWrapper src/CompareRecAllenFTClusters.cpp src/CompareRecAllenVPHits.cpp src/TestVeloClusters.cpp + src/TestRichSmartIDs.cpp LINK AllenLib Backend @@ -51,6 +52,7 @@ gaudi_add_module(AllenWrapper MuonCommon EventModel Gear + Rich Gaudi::GaudiAlgLib LHCb::DAQEventLib LHCb::RecEvent diff --git a/Rec/Allen/src/TestRichSmartIDs.cpp b/Rec/Allen/src/TestRichSmartIDs.cpp new file mode 100644 index 00000000000..ed630f36119 --- /dev/null +++ b/Rec/Allen/src/TestRichSmartIDs.cpp @@ -0,0 +1,75 @@ +/***************************************************************************** \ + * (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +\*****************************************************************************/ +// Gaudi +#include "GaudiAlg/Consumer.h" + +// LHCb +#include "Event/PrHits.h" +#include "RichFutureUtils/RichDecodedData.h" + +// Allen +#include "RichDefinitions.cuh" + +class TestRichSmartIDs final : public Gaudi::Functional::Consumer< + void( + const std::vector&, + const std::vector&, + const Rich::Future::DAQ::DecodedData&)> { + +public: + /// Standard constructor + TestRichSmartIDs(const std::string& name, ISvcLocator* pSvcLocator); + + /// Algorithm execution + void operator()( + const std::vector&, + const std::vector&, + const Rich::Future::DAQ::DecodedData&) const override; +}; + +DECLARE_COMPONENT(TestRichSmartIDs) + +TestRichSmartIDs::TestRichSmartIDs(const std::string& name, ISvcLocator* pSvcLocator) : + Consumer( + name, + pSvcLocator, + {KeyValue {"rich1_smart_ids", ""}, + KeyValue {"rich2_smart_ids", ""}, + KeyValue {"DecodedDataLocation", Rich::Future::DAQ::DecodedDataLocation::Default}}) +{} + +void TestRichSmartIDs::operator()( + const std::vector& rich1_smart_ids, + const std::vector& rich2_smart_ids, + const Rich::Future::DAQ::DecodedData& decodedIDs) const +{ + info() << "Running TestRichSmartIDs..." << endmsg; + + std::vector allenIDs; + allenIDs.insert(allenIDs.end(), rich1_smart_ids.begin(), rich1_smart_ids.end()); + allenIDs.insert(allenIDs.end(), rich2_smart_ids.begin(), rich2_smart_ids.end()); + + std::vector recIDs; + for ( const auto& rD : decodedIDs ) { + for ( const auto& pD : rD ) { + for ( const auto& mD : pD ) { + for ( const auto& pd : mD ) { + const auto& IDs = pd.smartIDs(); + recIDs.insert(recIDs.end(), IDs.begin(), IDs.end()); + } + } + } + } + + if (recIDs.size() != allenIDs.size()) { + error() << "Allen and Rec Rich Smart ID containers are not the same size" << endmsg; + } + + for (const auto smart_id : recIDs) { + const auto allen_smart_id = Allen::RichSmartID{smart_id.key()}; + if (std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { + error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; + } + } +} diff --git a/configuration/python/AllenConf/rich_reconstruction.py b/configuration/python/AllenConf/rich_reconstruction.py index 343d3760b41..6583db8baca 100644 --- a/configuration/python/AllenConf/rich_reconstruction.py +++ b/configuration/python/AllenConf/rich_reconstruction.py @@ -6,41 +6,24 @@ from AllenConf.utils import initialize_number_of_events from AllenCore.generator import make_algorithm -def decode_rich1(): +def decode_rich(rich_detector : int): number_of_events = initialize_number_of_events() - rich1_banks = make_algorithm( - data_provider_t, name="rich1_banks", bank_type="Rich1") + rich_banks = make_algorithm( + data_provider_t, name="rich_banks", bank_type="Rich" + str(rich_detector)) - rich1_decoding = make_algorithm( + rich_decoding = make_algorithm( rich_decoding_t, - name="rich1_decoding", + name=f"rich{str(rich_detector)}_decoding", host_number_of_events_t=number_of_events["host_number_of_events"], - host_raw_bank_version_t=rich1_banks.host_raw_bank_version_t, - dev_rich_raw_input_t=rich1_banks.dev_raw_banks_t, - dev_rich_raw_input_offsets_t=rich1_banks.dev_raw_offsets_t, - dev_rich_raw_input_sizes_t=rich1_banks.dev_raw_sizes_t, - dev_rich_raw_input_types_t=rich1_banks.dev_raw_types_t, + host_raw_bank_version_t=rich_banks.host_raw_bank_version_t, + dev_rich_raw_input_t=rich_banks.dev_raw_banks_t, + dev_rich_raw_input_offsets_t=rich_banks.dev_raw_offsets_t, + dev_rich_raw_input_sizes_t=rich_banks.dev_raw_sizes_t, + dev_rich_raw_input_types_t=rich_banks.dev_raw_types_t, block_dim_x=128) - return rich1_decoding - - -def decode_rich2(): - number_of_events = initialize_number_of_events() - - rich2_banks = make_algorithm( - data_provider_t, name="rich2_banks", bank_type="Rich2") - - rich2_decoding = make_algorithm( - rich_decoding_t, - name="rich2_decoding", - host_number_of_events_t=number_of_events["host_number_of_events"], - host_raw_bank_version_t=rich2_banks.host_raw_bank_version_t, - dev_rich_raw_input_t=rich2_banks.dev_raw_banks_t, - dev_rich_raw_input_offsets_t=rich2_banks.dev_raw_offsets_t, - dev_rich_raw_input_sizes_t=rich2_banks.dev_raw_sizes_t, - dev_rich_raw_input_types_t=rich2_banks.dev_raw_types_t, - block_dim_x=128) - - return rich2_decoding + return { + "dev_smart_ids": rich1_decoding.dev_smart_ids_t, + "dev_rich_hit_offsets": rich1_decoding.dev_rich_hit_offsets_t + } diff --git a/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py b/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py index 6483e241771..fba967c605f 100644 --- a/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py +++ b/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py @@ -3,14 +3,14 @@ ############################################################################### from AllenConf.HLT1 import setup_hlt1_node from AllenCore.generator import generate -from AllenConf.rich_reconstruction import decode_rich1, decode_rich2 +from AllenConf.rich_reconstruction import decode_rich from PyConf.control_flow import NodeLogic, CompositeNode hlt1_and_rich_decoding = CompositeNode( "HLT1AndRichDecoding", [setup_hlt1_node(with_ut=False), - decode_rich1(), - decode_rich2()], + decode_rich(1), + decode_rich(2)], NodeLogic.NONLAZY_AND, force_order=False) diff --git a/configuration/python/AllenSequences/rich.py b/configuration/python/AllenSequences/rich.py index cc2001f76ee..e5967e7279d 100644 --- a/configuration/python/AllenSequences/rich.py +++ b/configuration/python/AllenSequences/rich.py @@ -1,12 +1,12 @@ ############################################################################### # (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration # ############################################################################### -from AllenConf.rich_reconstruction import decode_rich1, decode_rich2 +from AllenConf.rich_reconstruction import decode_rich from AllenCore.generator import generate from PyConf.control_flow import NodeLogic, CompositeNode rich_decoding = CompositeNode( - "RichDecoding", [decode_rich1(), decode_rich2()], + "RichDecoding", [decode_rich(1), decode_rich(2)], NodeLogic.NONLAZY_AND, force_order=False) diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index dc989dd0893..5a91c466514 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -12,6 +12,7 @@ #include #include +#include "BackendCommon.h" namespace Allen { class RichSmartID { @@ -98,6 +99,8 @@ namespace Allen { __host__ __device__ constexpr inline auto key() const noexcept { return m_key; } + __host__ __device__ constexpr inline bool operator==(const RichSmartID& other) const noexcept { return m_key == other.key(); } + /// ostream operator __host__ friend std::ostream& operator<<(std::ostream& str, const RichSmartID& id) { return str << id.key(); } }; // namespace RichSmartID -- GitLab From ccffff1b6e9231878ae3270c3543c25634560825 Mon Sep 17 00:00:00 2001 From: Gitlab CI Date: Wed, 15 Mar 2023 16:09:21 +0000 Subject: [PATCH 39/63] Fixed formatting patch generated by https://gitlab.cern.ch/lhcb/Allen/-/jobs/28214788 --- Rec/Allen/src/TestRichSmartIDs.cpp | 25 +++++++++---------- .../rich/decoding/include/RichDefinitions.cuh | 5 +++- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Rec/Allen/src/TestRichSmartIDs.cpp b/Rec/Allen/src/TestRichSmartIDs.cpp index ed630f36119..58dc5131a11 100644 --- a/Rec/Allen/src/TestRichSmartIDs.cpp +++ b/Rec/Allen/src/TestRichSmartIDs.cpp @@ -11,11 +11,10 @@ // Allen #include "RichDefinitions.cuh" -class TestRichSmartIDs final : public Gaudi::Functional::Consumer< - void( - const std::vector&, - const std::vector&, - const Rich::Future::DAQ::DecodedData&)> { +class TestRichSmartIDs final : public Gaudi::Functional::Consumer&, + const std::vector&, + const Rich::Future::DAQ::DecodedData&)> { public: /// Standard constructor @@ -40,9 +39,9 @@ TestRichSmartIDs::TestRichSmartIDs(const std::string& name, ISvcLocator* pSvcLoc {} void TestRichSmartIDs::operator()( - const std::vector& rich1_smart_ids, - const std::vector& rich2_smart_ids, - const Rich::Future::DAQ::DecodedData& decodedIDs) const + const std::vector& rich1_smart_ids, + const std::vector& rich2_smart_ids, + const Rich::Future::DAQ::DecodedData& decodedIDs) const { info() << "Running TestRichSmartIDs..." << endmsg; @@ -51,10 +50,10 @@ void TestRichSmartIDs::operator()( allenIDs.insert(allenIDs.end(), rich2_smart_ids.begin(), rich2_smart_ids.end()); std::vector recIDs; - for ( const auto& rD : decodedIDs ) { - for ( const auto& pD : rD ) { - for ( const auto& mD : pD ) { - for ( const auto& pd : mD ) { + for (const auto& rD : decodedIDs) { + for (const auto& pD : rD) { + for (const auto& mD : pD) { + for (const auto& pd : mD) { const auto& IDs = pd.smartIDs(); recIDs.insert(recIDs.end(), IDs.begin(), IDs.end()); } @@ -67,7 +66,7 @@ void TestRichSmartIDs::operator()( } for (const auto smart_id : recIDs) { - const auto allen_smart_id = Allen::RichSmartID{smart_id.key()}; + const auto allen_smart_id = Allen::RichSmartID {smart_id.key()}; if (std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; } diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index 5a91c466514..29c75a0d621 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -99,7 +99,10 @@ namespace Allen { __host__ __device__ constexpr inline auto key() const noexcept { return m_key; } - __host__ __device__ constexpr inline bool operator==(const RichSmartID& other) const noexcept { return m_key == other.key(); } + __host__ __device__ constexpr inline bool operator==(const RichSmartID& other) const noexcept + { + return m_key == other.key(); + } /// ostream operator __host__ friend std::ostream& operator<<(std::ostream& str, const RichSmartID& id) { return str << id.key(); } -- GitLab From 1c3e8844e3ecf576414770d18ccedbec6603258b Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 1 Jun 2023 10:45:29 +0200 Subject: [PATCH 40/63] Adapt RICH decoding code. --- configuration/python/AllenConf/HLT1.py | 14 +++++++++++++- .../python/AllenConf/hlt1_reconstruction.py | 8 ++++++++ .../python/AllenConf/rich_reconstruction.py | 6 +++--- .../python/AllenSequences/hlt1_pp_rich_no_ut.py | 10 +--------- configuration/python/AllenSequences/rich.py | 4 ++-- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/configuration/python/AllenConf/HLT1.py b/configuration/python/AllenConf/HLT1.py index d2052e3c0c9..1d9ea74e618 100644 --- a/configuration/python/AllenConf/HLT1.py +++ b/configuration/python/AllenConf/HLT1.py @@ -630,6 +630,7 @@ def setup_hlt1_node(enablePhysics=True, with_calo=True, with_muon=True, with_v0s=True, + with_rich=False, enableBGI=False, velo_open=False, enableDownstream=False, @@ -645,7 +646,8 @@ def setup_hlt1_node(enablePhysics=True, with_muon=with_muon, enableDownstream=enableDownstream, tracking_type=tracking_type, - velo_open=velo_open) + velo_open=velo_open, + with_rich=with_rich) hlt1_config['reconstruction'] = reconstructed_objects @@ -852,6 +854,16 @@ def setup_hlt1_node(enablePhysics=True, NodeLogic.NONLAZY_AND, force_order=False) + if with_rich: + hlt1_node = CompositeNode( + "AllenWithRich", [ + hlt1_node, + reconstructed_objects["decoded_rich1"]["dev_smart_ids"].producer, + reconstructed_objects["decoded_rich2"]["dev_smart_ids"].producer + ], + NodeLogic.NONLAZY_AND, + force_order=True) + if enableRateValidator: hlt1_node = CompositeNode( "AllenRateValidation", [ diff --git a/configuration/python/AllenConf/hlt1_reconstruction.py b/configuration/python/AllenConf/hlt1_reconstruction.py index e41d039b6e0..94cca3dc55b 100644 --- a/configuration/python/AllenConf/hlt1_reconstruction.py +++ b/configuration/python/AllenConf/hlt1_reconstruction.py @@ -29,6 +29,7 @@ def hlt1_reconstruction(algorithm_name='', with_muon=True, velo_open=False, enableDownstream=False): + with_rich=False): decoded_velo = decode_velo() decoded_scifi = decode_scifi() velo_tracks = make_velo_tracks(decoded_velo) @@ -208,6 +209,13 @@ def hlt1_reconstruction(algorithm_name='', "v0_pairs": v0_pairs }) + if with_rich: + from AllenConf.rich_reconstruction import decode_rich + output.update({ + "decoded_rich1": decode_rich(1), + "decoded_rich2": decode_rich(2) + }) + return output diff --git a/configuration/python/AllenConf/rich_reconstruction.py b/configuration/python/AllenConf/rich_reconstruction.py index 6583db8baca..f1a8ee9b0bc 100644 --- a/configuration/python/AllenConf/rich_reconstruction.py +++ b/configuration/python/AllenConf/rich_reconstruction.py @@ -10,7 +10,7 @@ def decode_rich(rich_detector : int): number_of_events = initialize_number_of_events() rich_banks = make_algorithm( - data_provider_t, name="rich_banks", bank_type="Rich" + str(rich_detector)) + data_provider_t, name=f"rich{str(rich_detector)}_banks", bank_type="Rich" + str(rich_detector)) rich_decoding = make_algorithm( rich_decoding_t, @@ -24,6 +24,6 @@ def decode_rich(rich_detector : int): block_dim_x=128) return { - "dev_smart_ids": rich1_decoding.dev_smart_ids_t, - "dev_rich_hit_offsets": rich1_decoding.dev_rich_hit_offsets_t + "dev_smart_ids": rich_decoding.dev_smart_ids_t, + "dev_rich_hit_offsets": rich_decoding.dev_rich_hit_offsets_t } diff --git a/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py b/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py index fba967c605f..61cf0b0d2f8 100644 --- a/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py +++ b/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py @@ -6,12 +6,4 @@ from AllenCore.generator import generate from AllenConf.rich_reconstruction import decode_rich from PyConf.control_flow import NodeLogic, CompositeNode -hlt1_and_rich_decoding = CompositeNode( - "HLT1AndRichDecoding", - [setup_hlt1_node(with_ut=False), - decode_rich(1), - decode_rich(2)], - NodeLogic.NONLAZY_AND, - force_order=False) - -generate(hlt1_and_rich_decoding) +generate(setup_hlt1_node(with_ut=False, with_rich=True)) diff --git a/configuration/python/AllenSequences/rich.py b/configuration/python/AllenSequences/rich.py index e5967e7279d..2f52449c687 100644 --- a/configuration/python/AllenSequences/rich.py +++ b/configuration/python/AllenSequences/rich.py @@ -6,8 +6,8 @@ from AllenCore.generator import generate from PyConf.control_flow import NodeLogic, CompositeNode rich_decoding = CompositeNode( - "RichDecoding", [decode_rich(1), decode_rich(2)], + "RichDecoding", [decode_rich(1)["dev_smart_ids"].producer, decode_rich(2)["dev_smart_ids"].producer], NodeLogic.NONLAZY_AND, - force_order=False) + force_order=True) generate(rich_decoding) -- GitLab From bc78a53a4adb99bd82b0973b2e51e91625e68891 Mon Sep 17 00:00:00 2001 From: Gitlab CI Date: Thu, 1 Jun 2023 08:46:14 +0000 Subject: [PATCH 41/63] Fixed formatting patch generated by https://gitlab.cern.ch/lhcb/Allen/-/jobs/29947935 --- configuration/python/AllenConf/HLT1.py | 7 ++++--- configuration/python/AllenSequences/rich.py | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/configuration/python/AllenConf/HLT1.py b/configuration/python/AllenConf/HLT1.py index 1d9ea74e618..fa5872a376b 100644 --- a/configuration/python/AllenConf/HLT1.py +++ b/configuration/python/AllenConf/HLT1.py @@ -857,9 +857,10 @@ def setup_hlt1_node(enablePhysics=True, if with_rich: hlt1_node = CompositeNode( "AllenWithRich", [ - hlt1_node, - reconstructed_objects["decoded_rich1"]["dev_smart_ids"].producer, - reconstructed_objects["decoded_rich2"]["dev_smart_ids"].producer + hlt1_node, reconstructed_objects["decoded_rich1"] + ["dev_smart_ids"].producer, + reconstructed_objects["decoded_rich2"]["dev_smart_ids"]. + producer ], NodeLogic.NONLAZY_AND, force_order=True) diff --git a/configuration/python/AllenSequences/rich.py b/configuration/python/AllenSequences/rich.py index 2f52449c687..4a7f7ba37e5 100644 --- a/configuration/python/AllenSequences/rich.py +++ b/configuration/python/AllenSequences/rich.py @@ -6,7 +6,10 @@ from AllenCore.generator import generate from PyConf.control_flow import NodeLogic, CompositeNode rich_decoding = CompositeNode( - "RichDecoding", [decode_rich(1)["dev_smart_ids"].producer, decode_rich(2)["dev_smart_ids"].producer], + "RichDecoding", [ + decode_rich(1)["dev_smart_ids"].producer, + decode_rich(2)["dev_smart_ids"].producer + ], NodeLogic.NONLAZY_AND, force_order=True) -- GitLab From 71679e6ae4eab68ff65cbe379fb7210a9d2f9a9b Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Fri, 2 Jun 2023 15:51:41 +0200 Subject: [PATCH 42/63] Add Rich to the default transposition. --- Dumpers/BinaryDumpers/src/AllenUpdater.h | 2 +- Dumpers/BinaryDumpers/src/TransposeRawBanks.cpp | 3 ++- Rec/Allen/python/Allen/config.py | 4 ++-- Rec/Allen/src/TestRichSmartIDs.cpp | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Dumpers/BinaryDumpers/src/AllenUpdater.h b/Dumpers/BinaryDumpers/src/AllenUpdater.h index 7b2a5d21843..bf77b78deba 100644 --- a/Dumpers/BinaryDumpers/src/AllenUpdater.h +++ b/Dumpers/BinaryDumpers/src/AllenUpdater.h @@ -83,7 +83,7 @@ public: private: Gaudi::Property m_triggerEventLoop {this, "TriggerEventLoop", false}; - Gaudi::Property> m_bankTypes {this, "BankTypes", {"VP", "UT", "FTCluster", "ECal", "Muon"}}; + Gaudi::Property> m_bankTypes {this, "BankTypes", {"VP", "UT", "FTCluster", "ECal", "Muon", "Rich1", "Rich2"}}; std::map< std::string, std::tuple>>> diff --git a/Dumpers/BinaryDumpers/src/TransposeRawBanks.cpp b/Dumpers/BinaryDumpers/src/TransposeRawBanks.cpp index a4b88eb1030..9d179a530e7 100644 --- a/Dumpers/BinaryDumpers/src/TransposeRawBanks.cpp +++ b/Dumpers/BinaryDumpers/src/TransposeRawBanks.cpp @@ -72,7 +72,8 @@ private: LHCb::RawBank::Calo, LHCb::RawBank::Muon, LHCb::RawBank::ODIN, - LHCb::RawBank::Plume}}; + LHCb::RawBank::Plume, + LHCb::RawBank::Rich}}; std::array m_histos; }; diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index f7227f2dda3..4ec4b78d421 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -119,8 +119,8 @@ def setup_allen_non_event_data_service(allen_event_loop=False, 'FTCluster': [(DumpFTGeometry, 'DumpFTGeometry', 'scifi_geometry')], 'Muon': [(DumpMuonGeometry, 'DumpMuonGeometry', 'muon_geometry'), (DumpMuonTable, 'DumpMuonTable', 'muon_tables')], - 'Rich1': [(DumpRichPDMDBMapping, 'rich_pdmdbmaps'), - (DumpRichCableMapping, 'rich_tel40maps')] + 'Rich': [(DumpRichPDMDBMapping, 'DumpRichPDMDBMapping', 'rich_pdmdbmaps'), + (DumpRichCableMapping, 'DumpRichCableMapping', 'rich_tel40maps')], } detector_names = { diff --git a/Rec/Allen/src/TestRichSmartIDs.cpp b/Rec/Allen/src/TestRichSmartIDs.cpp index 58dc5131a11..195d5f79292 100644 --- a/Rec/Allen/src/TestRichSmartIDs.cpp +++ b/Rec/Allen/src/TestRichSmartIDs.cpp @@ -35,7 +35,7 @@ TestRichSmartIDs::TestRichSmartIDs(const std::string& name, ISvcLocator* pSvcLoc pSvcLocator, {KeyValue {"rich1_smart_ids", ""}, KeyValue {"rich2_smart_ids", ""}, - KeyValue {"DecodedDataLocation", Rich::Future::DAQ::DecodedDataLocation::Default}}) + KeyValue {"RichDecodedData", Rich::Future::DAQ::DecodedDataLocation::Default}}) {} void TestRichSmartIDs::operator()( -- GitLab From bba421efa9a7bf5db6e8f054a6dc2347f922e9f5 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Fri, 2 Jun 2023 15:52:31 +0200 Subject: [PATCH 43/63] Add empty test for now. --- Rec/Allen/src/TestAllenRichPixels.cpp | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Rec/Allen/src/TestAllenRichPixels.cpp diff --git a/Rec/Allen/src/TestAllenRichPixels.cpp b/Rec/Allen/src/TestAllenRichPixels.cpp new file mode 100644 index 00000000000..78643959336 --- /dev/null +++ b/Rec/Allen/src/TestAllenRichPixels.cpp @@ -0,0 +1,44 @@ +/***************************************************************************** \ + * (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +\*****************************************************************************/ +// Gaudi +#include "GaudiAlg/Consumer.h" + +// LHCb +#include "Event/PrHits.h" + +// Allen +#include "RichDecoding.cuh" +#include "RichPDMDBDecodeMapping.h" + +class TestAllenRichPixels final : public Gaudi::Functional::Consumer< + void(const std::vector&, const std::vector&, const Rich::Future::DAQ::DecodedData&)> { + +public: + /// Standard constructor + TestAllenRichPixels(const std::string& name, ISvcLocator* pSvcLocator); + + /// Algorithm execution + void operator()(const std::vector&, const std::vector&, const Rich::Future::DAQ::DecodedData&) const override; +}; + +DECLARE_COMPONENT(TestAllenRichPixels) + +TestAllenRichPixels::TestAllenRichPixels(const std::string& name, ISvcLocator* pSvcLocator) : + Consumer( + name, + pSvcLocator, + {KeyValue {"rich1_smart_ids", ""}, + KeyValue {"rich2_smart_ids", ""}, + KeyValue {"RichDecodedData", Rich::Future::DAQ::DecodedDataLocation::Default}}) +{} + +void TestAllenRichPixels::operator()( + const std::vector& allen_rich1_smart_ids, + const std::vector& allen_rich2_smart_ids, + const Rich::Future::DAQ::DecodedData& rec_rich_pixels) const +{ + // info() + // error() + info() << "Testing Allen Rich pixels\n"; +} -- GitLab From 788df0b72b895f517c25d1576b1a5ad5cba619e8 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Fri, 9 Jun 2023 12:31:06 +0200 Subject: [PATCH 44/63] Latest changes. --- Rec/Allen/python/Allen/config.py | 4 +++- configuration/python/AllenCore/gaudi_allen_generator.py | 2 ++ main/include/BankMapping.h | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index 4ec4b78d421..46024c40f60 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -119,7 +119,9 @@ def setup_allen_non_event_data_service(allen_event_loop=False, 'FTCluster': [(DumpFTGeometry, 'DumpFTGeometry', 'scifi_geometry')], 'Muon': [(DumpMuonGeometry, 'DumpMuonGeometry', 'muon_geometry'), (DumpMuonTable, 'DumpMuonTable', 'muon_tables')], - 'Rich': [(DumpRichPDMDBMapping, 'DumpRichPDMDBMapping', 'rich_pdmdbmaps'), + 'Rich1': [(DumpRichPDMDBMapping, 'DumpRichPDMDBMapping', 'rich_pdmdbmaps'), + (DumpRichCableMapping, 'DumpRichCableMapping', 'rich_tel40maps')], + 'Rich2': [(DumpRichPDMDBMapping, 'DumpRichPDMDBMapping', 'rich_pdmdbmaps'), (DumpRichCableMapping, 'DumpRichCableMapping', 'rich_tel40maps')], } diff --git a/configuration/python/AllenCore/gaudi_allen_generator.py b/configuration/python/AllenCore/gaudi_allen_generator.py index 35ecf243041..a5bc08b4672 100644 --- a/configuration/python/AllenCore/gaudi_allen_generator.py +++ b/configuration/python/AllenCore/gaudi_allen_generator.py @@ -66,6 +66,8 @@ def make_algorithm(algorithm, name, *args, **kwargs): rawbank_list = ["Calo", "EcalPacked"] elif bank_type == "VP": rawbank_list = ["VP", "VPRetinaCluster"] + elif "Rich" in bank_type: + rawbank_list = ["Rich"] elif bank_type: rawbank_list = [bank_type] diff --git a/main/include/BankMapping.h b/main/include/BankMapping.h index 2ecae8519c8..12ea7cd7bd8 100644 --- a/main/include/BankMapping.h +++ b/main/include/BankMapping.h @@ -24,8 +24,8 @@ namespace Allen { {LHCb::RawBank::OTError, BankTypes::MCVertices}, // used for PV MC info {LHCb::RawBank::OTRaw, BankTypes::MCTracks}, {LHCb::RawBank::Plume, BankTypes::Plume}, - {LHCb::RawBank::Rich, BankTypes::Rich1} // TODO: Rich maps to Rich1. Rich2 is not yet included. - }; // used for track MC info + {LHCb::RawBank::Rich, BankTypes::Rich1} // TODO: What about Rich2? + }; const std::unordered_map subdetectors = {{SourceIdSys::SourceIdSys_ODIN, BankTypes::ODIN}, {SourceIdSys::SourceIdSys_VELO_A, BankTypes::VP}, -- GitLab From d9562c03f65ed2bfc43c33cc10c8e06a6ac9a7cd Mon Sep 17 00:00:00 2001 From: Christian Asch Date: Thu, 15 Jun 2023 09:38:49 -0600 Subject: [PATCH 45/63] Fixed bug in get method of RichSmartID in RichDefinitions.cuh --- device/rich/decoding/include/RichDefinitions.cuh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index 29c75a0d621..a89d0db1613 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -94,7 +94,7 @@ namespace Allen { __host__ __device__ constexpr inline unsigned getData(const unsigned shift, const unsigned mask) const noexcept { - return (m_key << shift) & mask; + return (m_key & mask) >> shift; } __host__ __device__ constexpr inline auto key() const noexcept { return m_key; } -- GitLab From 06293348ea03a9f8cdfa6eb9d01961ef8b90d653 Mon Sep 17 00:00:00 2001 From: Roel Aaij Date: Fri, 9 Jun 2023 16:29:52 +0200 Subject: [PATCH 46/63] WIP: Fix Allen-in-Moore running of RICH decoding --- .../src/DumpRichCableMapping.cpp | 10 ++- .../src/DumpRichPDMDBMapping.cpp | 13 +++- Rec/Allen/python/Allen/config.py | 59 ++++++++++----- main/include/BankMapping.h | 31 ++++---- main/include/TESProvider.h | 73 ++++++++++--------- main/src/Transpose.cpp | 8 +- 6 files changed, 118 insertions(+), 76 deletions(-) diff --git a/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp b/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp index c2d1e7bc31f..98b05126be9 100644 --- a/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp +++ b/Dumpers/BinaryDumpers/src/DumpRichCableMapping.cpp @@ -66,13 +66,17 @@ StatusCode DumpRichCableMapping::initialize() { return Dumper::initialize().andThen([&] { register_producer(Allen::NonEventData::RichCableMapping::id, "rich_tel40maps", m_data); + + Rich::Future::DAQ::Tel40CableMapping::addConditionDerivation( + this, Rich::Future::DAQ::Tel40CableMapping::DefaultConditionKey); + addConditionDerivation( - Rich::Future::DAQ::Tel40CableMapping::ConditionPaths, + {Rich::Future::DAQ::Tel40CableMapping::DefaultConditionKey}, inputLocation(), [&](const Rich::Future::DAQ::Tel40CableMapping& det) { - auto rich_cable_mapping = RichCableMapping {m_data, det}; + auto cableMapping = RichCableMapping {m_data, det}; dump(); - return rich_cable_mapping; + return cableMapping; }); }); } diff --git a/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp b/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp index 2ba6c6697b4..516cd8c973b 100644 --- a/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp +++ b/Dumpers/BinaryDumpers/src/DumpRichPDMDBMapping.cpp @@ -66,8 +66,17 @@ StatusCode DumpRichPDMDBMapping::initialize() { return Dumper::initialize().andThen([&, this] { register_producer(Allen::NonEventData::RichPDMDBMapping::id, "rich_pdmdbmaps", m_data); - Rich::Future::DAQ::PDMDBDecodeMapping::addConditionDerivation(this, inputLocation()); - dump(); + Rich::Future::DAQ::PDMDBDecodeMapping::addConditionDerivation( + this, Rich::Future::DAQ::PDMDBDecodeMapping::DefaultConditionKey); + + addConditionDerivation( + {Rich::Future::DAQ::PDMDBDecodeMapping::DefaultConditionKey}, + inputLocation(), + [&](const Rich::Future::DAQ::PDMDBDecodeMapping& det) { + RichPDMDBMapping mapping {m_data, det}; + dump(); + return mapping; + }); }); } diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index 46024c40f60..bb3c494e437 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -110,19 +110,24 @@ def setup_allen_non_event_data_service(allen_event_loop=False, data (geometries etc.) """ converter_types = { - 'VP': [(DumpBeamline, 'DumpBeamline', 'beamline'), - (DumpVPGeometry, 'DumpVPGeometry', 'velo_geometry')], - 'UT': [(DumpUTGeometry, 'DumpUTGeometry', 'ut_geometry'), - (DumpUTLookupTables, 'DumpUTLookupTables', 'ut_tables')], - 'ECal': [(DumpCaloGeometry, 'DumpCaloGeometry', 'ecal_geometry')], - 'Magnet': [(DumpMagneticField, 'DumpMagneticField', 'polarity')], - 'FTCluster': [(DumpFTGeometry, 'DumpFTGeometry', 'scifi_geometry')], - 'Muon': [(DumpMuonGeometry, 'DumpMuonGeometry', 'muon_geometry'), - (DumpMuonTable, 'DumpMuonTable', 'muon_tables')], - 'Rich1': [(DumpRichPDMDBMapping, 'DumpRichPDMDBMapping', 'rich_pdmdbmaps'), - (DumpRichCableMapping, 'DumpRichCableMapping', 'rich_tel40maps')], - 'Rich2': [(DumpRichPDMDBMapping, 'DumpRichPDMDBMapping', 'rich_pdmdbmaps'), - (DumpRichCableMapping, 'DumpRichCableMapping', 'rich_tel40maps')], + frozenset({'VP'}): [(DumpBeamline, 'DumpBeamline', 'beamline'), + (DumpVPGeometry, 'DumpVPGeometry', + 'velo_geometry')], + frozenset({'UT'}): [(DumpUTGeometry, 'DumpUTGeometry', 'ut_geometry'), + (DumpUTLookupTables, 'DumpUTLookupTables', + 'ut_tables')], + frozenset({'ECal'}): [(DumpCaloGeometry, 'DumpCaloGeometry', + 'ecal_geometry')], + frozenset({'Magnet'}): [(DumpMagneticField, 'DumpMagneticField', + 'polarity')], + frozenset({'FTCluster'}): [(DumpFTGeometry, 'DumpFTGeometry', + 'scifi_geometry')], + frozenset({'Muon'}): [(DumpMuonGeometry, 'DumpMuonGeometry', + 'muon_geometry'), + (DumpMuonTable, 'DumpMuonTable', 'muon_tables')], + frozenset({'Rich1', 'Rich2'}): + [(DumpRichPDMDBMapping, 'DumpRichPDMDBMapping', 'rich_pdmdbmaps'), + (DumpRichCableMapping, 'DumpRichCableMapping', 'rich_tel40maps')], } detector_names = { @@ -172,13 +177,27 @@ def setup_allen_non_event_data_service(allen_event_loop=False, if allen_event_loop: algorithm_converters.append(AllenODINProducer()) - converters = [(bt, t, tn, f) for bt, convs in converter_types.items() - for t, tn, f in convs if bt in bank_types] - for bt, converter_type, converter_name, filename in converters: - converter = converter_type( - name=converter_name, - DumpToFile=dump_geometry, - OutputDirectory=out_dir) + converters = {(bts, t, tn, f) + for bts, convs in converter_types.items() + for t, tn, f in convs if bts.intersection(bank_types)} + for bts, converter_type, converter_name, filename in converters: + converter_id = converter_type.getDefaultProperties().get('ID', None) + if converter_id is not None: + converter = converter_type() + # An algorithm that needs a TESProducer + producer = AllenTESProducer( + name='AllenTESProducer_%s' % '_'.join(bts), + Filename=filename if dump_geometry else "", + OutputDirectory=out_dir, + InputID=converter.OutputID, + InputData=converter.Converted, + ID=converter_id) + algorithm_producers.append(producer) + else: + converter = converter_type( + name=converter_name, + DumpToFile=dump_geometry, + OutputDirectory=out_dir) algorithm_converters.append(converter) converters_node = CompositeNode( diff --git a/main/include/BankMapping.h b/main/include/BankMapping.h index 12ea7cd7bd8..b41f173edae 100644 --- a/main/include/BankMapping.h +++ b/main/include/BankMapping.h @@ -10,22 +10,21 @@ #include "BankTypes.h" namespace Allen { - const std::unordered_map bank_mapping = { - {LHCb::RawBank::VP, BankTypes::VP}, - {LHCb::RawBank::Velo, BankTypes::VP}, - {LHCb::RawBank::VPRetinaCluster, BankTypes::VP}, - {LHCb::RawBank::UT, BankTypes::UT}, - {LHCb::RawBank::FTCluster, BankTypes::FT}, - {LHCb::RawBank::Muon, BankTypes::MUON}, - {LHCb::RawBank::ODIN, BankTypes::ODIN}, - {LHCb::RawBank::HcalPacked, BankTypes::HCal}, - {LHCb::RawBank::EcalPacked, BankTypes::ECal}, - {LHCb::RawBank::Calo, BankTypes::ECal}, - {LHCb::RawBank::OTError, BankTypes::MCVertices}, // used for PV MC info - {LHCb::RawBank::OTRaw, BankTypes::MCTracks}, - {LHCb::RawBank::Plume, BankTypes::Plume}, - {LHCb::RawBank::Rich, BankTypes::Rich1} // TODO: What about Rich2? - }; + const std::unordered_map> bank_mapping = { + {LHCb::RawBank::VP, {BankTypes::VP}}, + {LHCb::RawBank::Velo, {BankTypes::VP}}, + {LHCb::RawBank::VPRetinaCluster, {BankTypes::VP}}, + {LHCb::RawBank::UT, {BankTypes::UT}}, + {LHCb::RawBank::FTCluster, {BankTypes::FT}}, + {LHCb::RawBank::Muon, {BankTypes::MUON}}, + {LHCb::RawBank::ODIN, {BankTypes::ODIN}}, + {LHCb::RawBank::HcalPacked, {BankTypes::HCal}}, + {LHCb::RawBank::EcalPacked, {BankTypes::ECal}}, + {LHCb::RawBank::Calo, {BankTypes::ECal}}, + {LHCb::RawBank::Rich, {BankTypes::Rich1, BankTypes::Rich2}}, + {LHCb::RawBank::OTError, {BankTypes::MCVertices}}, // used for PV MC info + {LHCb::RawBank::OTRaw, {BankTypes::MCTracks}}, + {LHCb::RawBank::Plume, {BankTypes::Plume}}}; // used for track MC info const std::unordered_map subdetectors = {{SourceIdSys::SourceIdSys_ODIN, BankTypes::ODIN}, {SourceIdSys::SourceIdSys_VELO_A, BankTypes::VP}, diff --git a/main/include/TESProvider.h b/main/include/TESProvider.h index 33c7e2b6769..69380768fb8 100644 --- a/main/include/TESProvider.h +++ b/main/include/TESProvider.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "SciFiRaw.cuh" @@ -65,40 +66,44 @@ public: return 1; } - // Offsets to events (we only process one event) - auto& offsets = m_offsets[allen_bank_index]; - offsets[0] = 0; - offsets[1] = banks.data.size(); - - // Bank sizes - auto const n_banks = reinterpret_cast(banks.data.data())[0]; - - auto& sizes_offsets = m_sizes[allen_bank_index]; - sizes_offsets.resize(2 + n_banks / 2 + 1); - // Only 1 event, so a single offset is enough. The offset - // counts uint16_t and is a uint32_t itself. - sizes_offsets[0] = 2; - uint16_t* sizes = reinterpret_cast(&sizes_offsets[1]); - std::copy_n(banks.sizes.begin(), banks.sizes.size(), sizes); - - auto& types_offsets = m_types[allen_bank_index]; - types_offsets.resize(2 + n_banks / 4 + 1); - // Only 1 event, so a single offset offset is enough. The offset - // counts uint8_t and is a uint32_t itself. - types_offsets[0] = 4; - uint8_t* types = reinterpret_cast(&types_offsets[1]); - std::copy_n(banks.types.begin(), banks.types.size(), types); - - // bank content - auto data_size = static_cast>(banks.data.size()); - gsl::span b {banks.data.data(), data_size}; - - m_banks_and_offsets[allen_bank_index] = {{std::move(b)}, - {offsets.data(), 2u}, - static_cast(data_size), - {sizes_offsets.data(), sizes_offsets.size()}, - {types_offsets.data(), types_offsets.size()}, - banks.version}; + for (auto allen_bank_type : it->second) { + auto allen_bank_index = to_integral(allen_bank_type); + + // Offsets to events (we only process one event) + auto& offsets = m_offsets[allen_bank_index]; + offsets[0] = 0; + offsets[1] = banks.data.size(); + + // Bank sizes + auto const n_banks = reinterpret_cast(banks.data.data())[0]; + + auto& sizes_offsets = m_sizes[allen_bank_index]; + sizes_offsets.resize(2 + n_banks / 2 + 1); + // Only 1 event, so a single offset is enough. The offset + // counts uint16_t and is a uint32_t itself. + sizes_offsets[0] = 2; + uint16_t* sizes = reinterpret_cast(&sizes_offsets[1]); + std::copy_n(banks.sizes.begin(), banks.sizes.size(), sizes); + + auto& types_offsets = m_types[allen_bank_index]; + types_offsets.resize(2 + n_banks / 4 + 1); + // Only 1 event, so a single offset offset is enough. The offset + // counts uint8_t and is a uint32_t itself. + types_offsets[0] = 4; + uint8_t* types = reinterpret_cast(&types_offsets[1]); + std::copy_n(banks.types.begin(), banks.types.size(), types); + + // bank content + auto data_size = static_cast>(banks.data.size()); + gsl::span b {banks.data.data(), data_size}; + + m_banks_and_offsets[allen_bank_index] = {{std::move(b)}, + {offsets.data(), 2u}, + static_cast(data_size), + {sizes_offsets.data(), sizes_offsets.size()}, + {types_offsets.data(), types_offsets.size()}, + banks.version}; + } } return 0; diff --git a/main/src/Transpose.cpp b/main/src/Transpose.cpp index dc9cea7f3ab..0957d3815d8 100644 --- a/main/src/Transpose.cpp +++ b/main/src/Transpose.cpp @@ -17,7 +17,13 @@ std::array Allen::bank_ids() std::array ids; for (auto bt : LHCb::RawBank::types()) { auto it = Allen::bank_mapping.find(bt); - ids[bt] = (it != Allen::bank_mapping.end() ? to_integral(it->second) : -1); + if (it != Allen::bank_mapping.end()) { + for (auto allen_bt : it->second) { + ids[bt] = static_cast(allen_bt); + } + } else { + ids[bt] = -1; + } } return ids; } -- GitLab From 4618c542982fc1ab98e0f75f8da4795004f2bb9d Mon Sep 17 00:00:00 2001 From: Gitlab CI Date: Tue, 8 Aug 2023 04:30:22 +0000 Subject: [PATCH 47/63] Fixed formatting patch generated by https://gitlab.cern.ch/lhcb/Allen/-/jobs/31598489 --- Dumpers/BinaryDumpers/src/AllenUpdater.h | 4 +++- Rec/Allen/src/TestAllenRichPixels.cpp | 11 ++++++++--- main/src/Transpose.cpp | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Dumpers/BinaryDumpers/src/AllenUpdater.h b/Dumpers/BinaryDumpers/src/AllenUpdater.h index bf77b78deba..7e27da48d63 100644 --- a/Dumpers/BinaryDumpers/src/AllenUpdater.h +++ b/Dumpers/BinaryDumpers/src/AllenUpdater.h @@ -83,7 +83,9 @@ public: private: Gaudi::Property m_triggerEventLoop {this, "TriggerEventLoop", false}; - Gaudi::Property> m_bankTypes {this, "BankTypes", {"VP", "UT", "FTCluster", "ECal", "Muon", "Rich1", "Rich2"}}; + Gaudi::Property> m_bankTypes {this, + "BankTypes", + {"VP", "UT", "FTCluster", "ECal", "Muon", "Rich1", "Rich2"}}; std::map< std::string, std::tuple>>> diff --git a/Rec/Allen/src/TestAllenRichPixels.cpp b/Rec/Allen/src/TestAllenRichPixels.cpp index 78643959336..e14d9bbf7fc 100644 --- a/Rec/Allen/src/TestAllenRichPixels.cpp +++ b/Rec/Allen/src/TestAllenRichPixels.cpp @@ -11,15 +11,20 @@ #include "RichDecoding.cuh" #include "RichPDMDBDecodeMapping.h" -class TestAllenRichPixels final : public Gaudi::Functional::Consumer< - void(const std::vector&, const std::vector&, const Rich::Future::DAQ::DecodedData&)> { +class TestAllenRichPixels final : public Gaudi::Functional::Consumer&, + const std::vector&, + const Rich::Future::DAQ::DecodedData&)> { public: /// Standard constructor TestAllenRichPixels(const std::string& name, ISvcLocator* pSvcLocator); /// Algorithm execution - void operator()(const std::vector&, const std::vector&, const Rich::Future::DAQ::DecodedData&) const override; + void operator()( + const std::vector&, + const std::vector&, + const Rich::Future::DAQ::DecodedData&) const override; }; DECLARE_COMPONENT(TestAllenRichPixels) diff --git a/main/src/Transpose.cpp b/main/src/Transpose.cpp index 0957d3815d8..63bf9896187 100644 --- a/main/src/Transpose.cpp +++ b/main/src/Transpose.cpp @@ -21,7 +21,8 @@ std::array Allen::bank_ids() for (auto allen_bt : it->second) { ids[bt] = static_cast(allen_bt); } - } else { + } + else { ids[bt] = -1; } } -- GitLab From bfe54bdfddb0f2b94cba5906164966c8ef453637 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 8 Aug 2023 06:40:32 +0200 Subject: [PATCH 48/63] Proper test. --- Rec/Allen/src/TestAllenRichPixels.cpp | 29 +++++++++-- Rec/Allen/src/TestRichSmartIDs.cpp | 74 --------------------------- 2 files changed, 26 insertions(+), 77 deletions(-) delete mode 100644 Rec/Allen/src/TestRichSmartIDs.cpp diff --git a/Rec/Allen/src/TestAllenRichPixels.cpp b/Rec/Allen/src/TestAllenRichPixels.cpp index e14d9bbf7fc..2a8204522e6 100644 --- a/Rec/Allen/src/TestAllenRichPixels.cpp +++ b/Rec/Allen/src/TestAllenRichPixels.cpp @@ -43,7 +43,30 @@ void TestAllenRichPixels::operator()( const std::vector& allen_rich2_smart_ids, const Rich::Future::DAQ::DecodedData& rec_rich_pixels) const { - // info() - // error() - info() << "Testing Allen Rich pixels\n"; + std::vector allenIDs; + allenIDs.insert(allenIDs.end(), rich1_smart_ids.begin(), rich1_smart_ids.end()); + allenIDs.insert(allenIDs.end(), rich2_smart_ids.begin(), rich2_smart_ids.end()); + + std::vector recIDs; + for (const auto& rD : decodedIDs) { + for (const auto& pD : rD) { + for (const auto& mD : pD) { + for (const auto& pd : mD) { + const auto& IDs = pd.smartIDs(); + recIDs.insert(recIDs.end(), IDs.begin(), IDs.end()); + } + } + } + } + + if (recIDs.size() != allenIDs.size()) { + error() << "Allen and Rec Rich Smart ID containers are not the same size" << endmsg; + } + + for (const auto smart_id : recIDs) { + const auto allen_smart_id = Allen::RichSmartID {smart_id.key()}; + if (std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { + error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; + } + } } diff --git a/Rec/Allen/src/TestRichSmartIDs.cpp b/Rec/Allen/src/TestRichSmartIDs.cpp deleted file mode 100644 index 195d5f79292..00000000000 --- a/Rec/Allen/src/TestRichSmartIDs.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/***************************************************************************** \ - * (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * -\*****************************************************************************/ -// Gaudi -#include "GaudiAlg/Consumer.h" - -// LHCb -#include "Event/PrHits.h" -#include "RichFutureUtils/RichDecodedData.h" - -// Allen -#include "RichDefinitions.cuh" - -class TestRichSmartIDs final : public Gaudi::Functional::Consumer&, - const std::vector&, - const Rich::Future::DAQ::DecodedData&)> { - -public: - /// Standard constructor - TestRichSmartIDs(const std::string& name, ISvcLocator* pSvcLocator); - - /// Algorithm execution - void operator()( - const std::vector&, - const std::vector&, - const Rich::Future::DAQ::DecodedData&) const override; -}; - -DECLARE_COMPONENT(TestRichSmartIDs) - -TestRichSmartIDs::TestRichSmartIDs(const std::string& name, ISvcLocator* pSvcLocator) : - Consumer( - name, - pSvcLocator, - {KeyValue {"rich1_smart_ids", ""}, - KeyValue {"rich2_smart_ids", ""}, - KeyValue {"RichDecodedData", Rich::Future::DAQ::DecodedDataLocation::Default}}) -{} - -void TestRichSmartIDs::operator()( - const std::vector& rich1_smart_ids, - const std::vector& rich2_smart_ids, - const Rich::Future::DAQ::DecodedData& decodedIDs) const -{ - info() << "Running TestRichSmartIDs..." << endmsg; - - std::vector allenIDs; - allenIDs.insert(allenIDs.end(), rich1_smart_ids.begin(), rich1_smart_ids.end()); - allenIDs.insert(allenIDs.end(), rich2_smart_ids.begin(), rich2_smart_ids.end()); - - std::vector recIDs; - for (const auto& rD : decodedIDs) { - for (const auto& pD : rD) { - for (const auto& mD : pD) { - for (const auto& pd : mD) { - const auto& IDs = pd.smartIDs(); - recIDs.insert(recIDs.end(), IDs.begin(), IDs.end()); - } - } - } - } - - if (recIDs.size() != allenIDs.size()) { - error() << "Allen and Rec Rich Smart ID containers are not the same size" << endmsg; - } - - for (const auto smart_id : recIDs) { - const auto allen_smart_id = Allen::RichSmartID {smart_id.key()}; - if (std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { - error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; - } - } -} -- GitLab From 350815cb64f3fcdb7837ba4f4e1432d45c887782 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 8 Aug 2023 07:37:53 +0200 Subject: [PATCH 49/63] Compiles with stack. --- Rec/Allen/CMakeLists.txt | 4 ++-- Rec/Allen/src/TestAllenRichPixels.cpp | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Rec/Allen/CMakeLists.txt b/Rec/Allen/CMakeLists.txt index 7cd74ebd9bd..bf3adffe1c7 100755 --- a/Rec/Allen/CMakeLists.txt +++ b/Rec/Allen/CMakeLists.txt @@ -25,11 +25,11 @@ gaudi_add_module(AllenWrapper src/ProvideRuntimeOptions.cpp src/CompareRecAllenCaloDigits.cpp src/CompareRecAllenMuonHits.cpp - src/CompareRecAllenUTHitsMCCheck.cpp + src/CompareRecAllenUTHitsMCCheck.cpp src/CompareRecAllenFTClusters.cpp src/CompareRecAllenVPHits.cpp src/TestVeloClusters.cpp - src/TestRichSmartIDs.cpp + src/TestAllenRichPixels.cpp LINK AllenLib Backend diff --git a/Rec/Allen/src/TestAllenRichPixels.cpp b/Rec/Allen/src/TestAllenRichPixels.cpp index 2a8204522e6..0857360f37c 100644 --- a/Rec/Allen/src/TestAllenRichPixels.cpp +++ b/Rec/Allen/src/TestAllenRichPixels.cpp @@ -6,10 +6,11 @@ // LHCb #include "Event/PrHits.h" +#include "RichFutureUtils/RichDecodedData.h" // Allen #include "RichDecoding.cuh" -#include "RichPDMDBDecodeMapping.h" +#include "RichPDMDBDecodeMapping.cuh" class TestAllenRichPixels final : public Gaudi::Functional::Consumer&, @@ -44,11 +45,11 @@ void TestAllenRichPixels::operator()( const Rich::Future::DAQ::DecodedData& rec_rich_pixels) const { std::vector allenIDs; - allenIDs.insert(allenIDs.end(), rich1_smart_ids.begin(), rich1_smart_ids.end()); - allenIDs.insert(allenIDs.end(), rich2_smart_ids.begin(), rich2_smart_ids.end()); + allenIDs.insert(allenIDs.end(), allen_rich1_smart_ids.begin(), allen_rich1_smart_ids.end()); + allenIDs.insert(allenIDs.end(), allen_rich2_smart_ids.begin(), allen_rich2_smart_ids.end()); std::vector recIDs; - for (const auto& rD : decodedIDs) { + for (const auto& rD : rec_rich_pixels) { for (const auto& pD : rD) { for (const auto& mD : pD) { for (const auto& pd : mD) { @@ -64,7 +65,7 @@ void TestAllenRichPixels::operator()( } for (const auto smart_id : recIDs) { - const auto allen_smart_id = Allen::RichSmartID {smart_id.key()}; + const auto allen_smart_id = Allen::RichSmartID {static_cast(smart_id.key())}; if (std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; } -- GitLab From 7ab8cdf940fc9a746aeee13bd46411bf79022e70 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Tue, 8 Aug 2023 15:00:32 +0200 Subject: [PATCH 50/63] Move to a 64-bit RichSmartID key. --- Rec/Allen/src/TestAllenRichPixels.cpp | 4 ++-- device/rich/decoding/include/RichDefinitions.cuh | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Rec/Allen/src/TestAllenRichPixels.cpp b/Rec/Allen/src/TestAllenRichPixels.cpp index 0857360f37c..2b537cb99f6 100644 --- a/Rec/Allen/src/TestAllenRichPixels.cpp +++ b/Rec/Allen/src/TestAllenRichPixels.cpp @@ -65,8 +65,8 @@ void TestAllenRichPixels::operator()( } for (const auto smart_id : recIDs) { - const auto allen_smart_id = Allen::RichSmartID {static_cast(smart_id.key())}; - if (std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { + const auto allen_smart_id = Allen::RichSmartID {smart_id.key()}; + if (smart_id.isValid() && std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; } } diff --git a/device/rich/decoding/include/RichDefinitions.cuh b/device/rich/decoding/include/RichDefinitions.cuh index a89d0db1613..6aaef71ee32 100644 --- a/device/rich/decoding/include/RichDefinitions.cuh +++ b/device/rich/decoding/include/RichDefinitions.cuh @@ -16,12 +16,12 @@ namespace Allen { class RichSmartID { - uint32_t m_key; + uint64_t m_key; public: __host__ __device__ RichSmartID() = default; - __host__ __device__ RichSmartID(uint32_t key) : m_key(key) {} + __host__ __device__ RichSmartID(uint64_t key) : m_key(key) {} // Number of bits for each data field in the word static constexpr const unsigned BitsPixelCol = 3; ///< Number of bits for MaPMT pixel column @@ -80,7 +80,7 @@ namespace Allen { __host__ __device__ constexpr inline void setData(const unsigned value, const unsigned shift, const unsigned mask) noexcept { - m_key = ((value << shift) & mask) | (m_key & ~mask); + m_key = ((static_cast(value) << shift) & mask) | (m_key & ~mask); } __host__ __device__ constexpr inline void setData( @@ -89,10 +89,10 @@ namespace Allen { const unsigned mask, // const unsigned okMask) noexcept { - m_key = ((value << shift) & mask) | (m_key & ~mask) | okMask; + m_key = ((static_cast(value) << shift) & mask) | (m_key & ~mask) | okMask; } - __host__ __device__ constexpr inline unsigned getData(const unsigned shift, const unsigned mask) const noexcept + __host__ __device__ constexpr inline uint64_t getData(const unsigned shift, const unsigned mask) const noexcept { return (m_key & mask) >> shift; } -- GitLab From 329473ca266c40b58a130c7276088641c2ada04d Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Wed, 9 Aug 2023 09:10:01 +0200 Subject: [PATCH 51/63] Update test. --- Rec/Allen/src/TestAllenRichPixels.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rec/Allen/src/TestAllenRichPixels.cpp b/Rec/Allen/src/TestAllenRichPixels.cpp index 2b537cb99f6..71fdf13752c 100644 --- a/Rec/Allen/src/TestAllenRichPixels.cpp +++ b/Rec/Allen/src/TestAllenRichPixels.cpp @@ -66,7 +66,7 @@ void TestAllenRichPixels::operator()( for (const auto smart_id : recIDs) { const auto allen_smart_id = Allen::RichSmartID {smart_id.key()}; - if (smart_id.isValid() && std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { + if (smart_id.pixelDataAreValid() && std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; } } -- GitLab From 6135475138fcda31bbea9de3d39cc42892125768 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 28 Sep 2023 16:52:18 +0200 Subject: [PATCH 52/63] Fix test. --- Rec/Allen/src/TestAllenRichPixels.cpp | 16 +- configuration/python/AllenConf/HLT1.py | 6 +- .../python/AllenConf/hlt1_reconstruction.py | 3 +- .../python/AllenConf/rich_reconstruction.py | 6 +- configuration/python/AllenSequences/rich.py | 3 +- device/rich/decoding/src/RichDecoding.cu | 147 ++++++++++-------- 6 files changed, 90 insertions(+), 91 deletions(-) diff --git a/Rec/Allen/src/TestAllenRichPixels.cpp b/Rec/Allen/src/TestAllenRichPixels.cpp index 71fdf13752c..37886a57587 100644 --- a/Rec/Allen/src/TestAllenRichPixels.cpp +++ b/Rec/Allen/src/TestAllenRichPixels.cpp @@ -13,7 +13,6 @@ #include "RichPDMDBDecodeMapping.cuh" class TestAllenRichPixels final : public Gaudi::Functional::Consumer&, const std::vector&, const Rich::Future::DAQ::DecodedData&)> { @@ -23,7 +22,6 @@ public: /// Algorithm execution void operator()( - const std::vector&, const std::vector&, const Rich::Future::DAQ::DecodedData&) const override; }; @@ -34,20 +32,14 @@ TestAllenRichPixels::TestAllenRichPixels(const std::string& name, ISvcLocator* p Consumer( name, pSvcLocator, - {KeyValue {"rich1_smart_ids", ""}, - KeyValue {"rich2_smart_ids", ""}, + {KeyValue {"rich_smart_ids", ""}, KeyValue {"RichDecodedData", Rich::Future::DAQ::DecodedDataLocation::Default}}) {} void TestAllenRichPixels::operator()( - const std::vector& allen_rich1_smart_ids, - const std::vector& allen_rich2_smart_ids, + const std::vector& allen_rich_smart_ids, const Rich::Future::DAQ::DecodedData& rec_rich_pixels) const { - std::vector allenIDs; - allenIDs.insert(allenIDs.end(), allen_rich1_smart_ids.begin(), allen_rich1_smart_ids.end()); - allenIDs.insert(allenIDs.end(), allen_rich2_smart_ids.begin(), allen_rich2_smart_ids.end()); - std::vector recIDs; for (const auto& rD : rec_rich_pixels) { for (const auto& pD : rD) { @@ -60,13 +52,13 @@ void TestAllenRichPixels::operator()( } } - if (recIDs.size() != allenIDs.size()) { + if (recIDs.size() != allen_rich_smart_ids.size()) { error() << "Allen and Rec Rich Smart ID containers are not the same size" << endmsg; } for (const auto smart_id : recIDs) { const auto allen_smart_id = Allen::RichSmartID {smart_id.key()}; - if (smart_id.pixelDataAreValid() && std::find(allenIDs.begin(), allenIDs.end(), allen_smart_id) == allenIDs.end()) { + if (smart_id.pixelDataAreValid() && std::find(allen_rich_smart_ids.begin(), allen_rich_smart_ids.end(), allen_smart_id) == allen_rich_smart_ids.end()) { error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; } } diff --git a/configuration/python/AllenConf/HLT1.py b/configuration/python/AllenConf/HLT1.py index fa5872a376b..0c72be83b62 100644 --- a/configuration/python/AllenConf/HLT1.py +++ b/configuration/python/AllenConf/HLT1.py @@ -857,10 +857,8 @@ def setup_hlt1_node(enablePhysics=True, if with_rich: hlt1_node = CompositeNode( "AllenWithRich", [ - hlt1_node, reconstructed_objects["decoded_rich1"] - ["dev_smart_ids"].producer, - reconstructed_objects["decoded_rich2"]["dev_smart_ids"]. - producer + hlt1_node, reconstructed_objects["decoded_rich"] + ["dev_smart_ids"].producer ], NodeLogic.NONLAZY_AND, force_order=True) diff --git a/configuration/python/AllenConf/hlt1_reconstruction.py b/configuration/python/AllenConf/hlt1_reconstruction.py index 94cca3dc55b..50cc08adc0f 100644 --- a/configuration/python/AllenConf/hlt1_reconstruction.py +++ b/configuration/python/AllenConf/hlt1_reconstruction.py @@ -212,8 +212,7 @@ def hlt1_reconstruction(algorithm_name='', if with_rich: from AllenConf.rich_reconstruction import decode_rich output.update({ - "decoded_rich1": decode_rich(1), - "decoded_rich2": decode_rich(2) + "decoded_rich": decode_rich() }) return output diff --git a/configuration/python/AllenConf/rich_reconstruction.py b/configuration/python/AllenConf/rich_reconstruction.py index f1a8ee9b0bc..a5474f82a65 100644 --- a/configuration/python/AllenConf/rich_reconstruction.py +++ b/configuration/python/AllenConf/rich_reconstruction.py @@ -6,15 +6,15 @@ from AllenConf.utils import initialize_number_of_events from AllenCore.generator import make_algorithm -def decode_rich(rich_detector : int): +def decode_rich(): number_of_events = initialize_number_of_events() rich_banks = make_algorithm( - data_provider_t, name=f"rich{str(rich_detector)}_banks", bank_type="Rich" + str(rich_detector)) + data_provider_t, name=f"rich_banks", bank_type="Rich1") rich_decoding = make_algorithm( rich_decoding_t, - name=f"rich{str(rich_detector)}_decoding", + name=f"rich_decoding", host_number_of_events_t=number_of_events["host_number_of_events"], host_raw_bank_version_t=rich_banks.host_raw_bank_version_t, dev_rich_raw_input_t=rich_banks.dev_raw_banks_t, diff --git a/configuration/python/AllenSequences/rich.py b/configuration/python/AllenSequences/rich.py index 4a7f7ba37e5..458d8a17c41 100644 --- a/configuration/python/AllenSequences/rich.py +++ b/configuration/python/AllenSequences/rich.py @@ -7,8 +7,7 @@ from PyConf.control_flow import NodeLogic, CompositeNode rich_decoding = CompositeNode( "RichDecoding", [ - decode_rich(1)["dev_smart_ids"].producer, - decode_rich(2)["dev_smart_ids"].producer + decode_rich()["dev_smart_ids"].producer ], NodeLogic.NONLAZY_AND, force_order=True) diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index d1732dab1c6..1442073dbf4 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -67,15 +67,20 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( while (iW < connSizes[iLink] && dataW != bankEnd) { // check MSB for this word - // TODO: Check const auto isNZS = isBitOn( *dataW ); - const auto isNZS = (0x80000000 & *dataW) != 0; + const auto isNZS = (0x80 & *dataW) != 0; if (!isNZS) { // ZS decoding... word is bit index // load the anode data for this bit if ((unsigned) (*dataW) < frameData.size()) { - number_of_hits++; + const auto& aData = frameData[*dataW]; + + // Data 'could' be invalid, e.g. radiation-induced-upsets + // so cannot make this a hard error + if ( aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1 ) { + number_of_hits++; + } } // move to next word @@ -99,8 +104,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( auto nzsW = *(dataW + iNZS); // if word zero clear MSB as this is the NZS flag if (0 == iNZS) { - // TODO: Check this is correct setBitOff( nzsW ); - nzsW &= 0x7FFFFFFF; + nzsW &= 0x7F; } // does this word hold any active bits ? @@ -120,7 +124,13 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( // load the anode data for this bit if ((size_t)(bit) < frameData.size()) { - number_of_hits++; + const auto& aData = frameData[bit]; + + // Data 'could' be invalid, e.g. radiation-induced-upsets + // so cannot make this a hard error + if ( aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1 ) { + number_of_hits++; + } } } // bit is on @@ -230,8 +240,7 @@ __device__ void rich_decode_bank( while (iW < connSizes[iLink] && dataW != bankEnd) { // check MSB for this word - // TODO: Check const auto isNZS = isBitOn( *dataW ); - const auto isNZS = (0x80000000 & *dataW) != 0; + const auto isNZS = (0x80 & *dataW) != 0; if (!isNZS) { // ZS decoding... word is bit index @@ -241,36 +250,37 @@ __device__ void rich_decode_bank( const auto& aData = frameData[*dataW]; - // TODO: Data 'could' be invalid, e.g. radiation-induced-upsets + // Data 'could' be invalid, e.g. radiation-induced-upsets // so cannot make this a hard error - - // make a smart ID - auto hitID = Allen::RichSmartID {cData.smartID}; // sets RICH, side, module and PMT type - - // Add the PMT and pixel info - const auto nInMod = (aData.ec * (0 != ((hitID.key() >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; - hitID.setData( - cData.moduleNum, - Allen::RichSmartID::ShiftPDMod, - Allen::RichSmartID::MaskPDMod, - Allen::RichSmartID::MaskPDIsSet); - hitID.setData(nInMod, Allen::RichSmartID::ShiftPDNumInMod, Allen::RichSmartID::MaskPDNumInMod); - - const auto row = aData.anode / 8; - const auto col = 8 - 1 - (aData.anode % 8); - hitID.setData( - row, - Allen::RichSmartID::ShiftPixelRow, - Allen::RichSmartID::MaskPixelRow, - Allen::RichSmartID::MaskPixelRowIsSet); - hitID.setData( - col, - Allen::RichSmartID::ShiftPixelCol, - Allen::RichSmartID::MaskPixelCol, - Allen::RichSmartID::MaskPixelColIsSet); - - const auto insert_index = atomicAdd(event_inserted_hits, 1); - event_smart_ids[insert_index] = hitID; + if ( aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1 ) { + // make a smart ID + auto hitID = Allen::RichSmartID {cData.smartID}; // sets RICH, side, module and PMT type + + // Add the PMT and pixel info + const auto nInMod = (aData.ec * (0 != ((hitID.key() >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; + hitID.setData( + cData.moduleNum, + Allen::RichSmartID::ShiftPDMod, + Allen::RichSmartID::MaskPDMod, + Allen::RichSmartID::MaskPDIsSet); + hitID.setData(nInMod, Allen::RichSmartID::ShiftPDNumInMod, Allen::RichSmartID::MaskPDNumInMod); + + const auto row = aData.anode / 8; + const auto col = 8 - 1 - (aData.anode % 8); + hitID.setData( + row, + Allen::RichSmartID::ShiftPixelRow, + Allen::RichSmartID::MaskPixelRow, + Allen::RichSmartID::MaskPixelRowIsSet); + hitID.setData( + col, + Allen::RichSmartID::ShiftPixelCol, + Allen::RichSmartID::MaskPixelCol, + Allen::RichSmartID::MaskPixelColIsSet); + + const auto insert_index = atomicAdd(event_inserted_hits, 1); + event_smart_ids[insert_index] = hitID; + } } // move to next word @@ -294,8 +304,7 @@ __device__ void rich_decode_bank( auto nzsW = *(dataW + iNZS); // if word zero clear MSB as this is the NZS flag if (0 == iNZS) { - // TODO: Check this is correct setBitOff( nzsW ); - nzsW &= 0x7FFFFFFF; + nzsW &= 0x7F; } // does this word hold any active bits ? @@ -316,36 +325,38 @@ __device__ void rich_decode_bank( // load the anode data for this bit if ((size_t)(bit) < frameData.size()) { const auto& aData = frameData[bit]; - // TODO: Data 'could' be invalid, e.g. radiation-induced-upsets + // Data 'could' be invalid, e.g. radiation-induced-upsets // so cannot make this a hard error - - // make a smart ID - auto hitID = Allen::RichSmartID {cData.smartID}; // sets RICH, side, module and PMT type - - // Add the PMT and pixel info - const auto nInMod = (aData.ec * (0 != ((hitID.key() >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; - hitID.setData( - cData.moduleNum, - Allen::RichSmartID::ShiftPDMod, - Allen::RichSmartID::MaskPDMod, - Allen::RichSmartID::MaskPDIsSet); - hitID.setData(nInMod, Allen::RichSmartID::ShiftPDNumInMod, Allen::RichSmartID::MaskPDNumInMod); - - const auto row = aData.anode / 8; - const auto col = 8 - 1 - (aData.anode % 8); - hitID.setData( - row, - Allen::RichSmartID::ShiftPixelRow, - Allen::RichSmartID::MaskPixelRow, - Allen::RichSmartID::MaskPixelRowIsSet); - hitID.setData( - col, - Allen::RichSmartID::ShiftPixelCol, - Allen::RichSmartID::MaskPixelCol, - Allen::RichSmartID::MaskPixelColIsSet); - - const auto insert_index = atomicAdd(event_inserted_hits, 1); - event_smart_ids[insert_index] = hitID; + if ( aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1 ) { + + // make a smart ID + auto hitID = Allen::RichSmartID {cData.smartID}; // sets RICH, side, module and PMT type + + // Add the PMT and pixel info + const auto nInMod = (aData.ec * (0 != ((hitID.key() >> 27) & 0x1) ? 1 : 4)) + aData.pmtInEC; + hitID.setData( + cData.moduleNum, + Allen::RichSmartID::ShiftPDMod, + Allen::RichSmartID::MaskPDMod, + Allen::RichSmartID::MaskPDIsSet); + hitID.setData(nInMod, Allen::RichSmartID::ShiftPDNumInMod, Allen::RichSmartID::MaskPDNumInMod); + + const auto row = aData.anode / 8; + const auto col = 8 - 1 - (aData.anode % 8); + hitID.setData( + row, + Allen::RichSmartID::ShiftPixelRow, + Allen::RichSmartID::MaskPixelRow, + Allen::RichSmartID::MaskPixelRowIsSet); + hitID.setData( + col, + Allen::RichSmartID::ShiftPixelCol, + Allen::RichSmartID::MaskPixelCol, + Allen::RichSmartID::MaskPixelColIsSet); + + const auto insert_index = atomicAdd(event_inserted_hits, 1); + event_smart_ids[insert_index] = hitID; + } } } // bit is on -- GitLab From 7a8aba2309a14884140dd9354937626173a21135 Mon Sep 17 00:00:00 2001 From: Gitlab CI Date: Thu, 28 Sep 2023 14:52:54 +0000 Subject: [PATCH 53/63] Fixed formatting patch generated by https://gitlab.cern.ch/lhcb/Allen/-/jobs/32793760 --- Rec/Allen/src/TestAllenRichPixels.cpp | 18 +++++++++--------- configuration/python/AllenConf/HLT1.py | 4 ++-- .../python/AllenConf/hlt1_reconstruction.py | 4 +--- configuration/python/AllenSequences/rich.py | 4 +--- device/rich/decoding/src/RichDecoding.cu | 8 ++++---- 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/Rec/Allen/src/TestAllenRichPixels.cpp b/Rec/Allen/src/TestAllenRichPixels.cpp index 37886a57587..b1c8f990df1 100644 --- a/Rec/Allen/src/TestAllenRichPixels.cpp +++ b/Rec/Allen/src/TestAllenRichPixels.cpp @@ -12,18 +12,16 @@ #include "RichDecoding.cuh" #include "RichPDMDBDecodeMapping.cuh" -class TestAllenRichPixels final : public Gaudi::Functional::Consumer&, - const Rich::Future::DAQ::DecodedData&)> { +class TestAllenRichPixels final + : public Gaudi::Functional::Consumer< + void(const std::vector&, const Rich::Future::DAQ::DecodedData&)> { public: /// Standard constructor TestAllenRichPixels(const std::string& name, ISvcLocator* pSvcLocator); /// Algorithm execution - void operator()( - const std::vector&, - const Rich::Future::DAQ::DecodedData&) const override; + void operator()(const std::vector&, const Rich::Future::DAQ::DecodedData&) const override; }; DECLARE_COMPONENT(TestAllenRichPixels) @@ -32,8 +30,7 @@ TestAllenRichPixels::TestAllenRichPixels(const std::string& name, ISvcLocator* p Consumer( name, pSvcLocator, - {KeyValue {"rich_smart_ids", ""}, - KeyValue {"RichDecodedData", Rich::Future::DAQ::DecodedDataLocation::Default}}) + {KeyValue {"rich_smart_ids", ""}, KeyValue {"RichDecodedData", Rich::Future::DAQ::DecodedDataLocation::Default}}) {} void TestAllenRichPixels::operator()( @@ -58,7 +55,10 @@ void TestAllenRichPixels::operator()( for (const auto smart_id : recIDs) { const auto allen_smart_id = Allen::RichSmartID {smart_id.key()}; - if (smart_id.pixelDataAreValid() && std::find(allen_rich_smart_ids.begin(), allen_rich_smart_ids.end(), allen_smart_id) == allen_rich_smart_ids.end()) { + if ( + smart_id.pixelDataAreValid() && + std::find(allen_rich_smart_ids.begin(), allen_rich_smart_ids.end(), allen_smart_id) == + allen_rich_smart_ids.end()) { error() << "ID " << allen_smart_id << " not present in Allen Rich Smart ID container" << endmsg; } } diff --git a/configuration/python/AllenConf/HLT1.py b/configuration/python/AllenConf/HLT1.py index 0c72be83b62..7e77d307c0e 100644 --- a/configuration/python/AllenConf/HLT1.py +++ b/configuration/python/AllenConf/HLT1.py @@ -857,8 +857,8 @@ def setup_hlt1_node(enablePhysics=True, if with_rich: hlt1_node = CompositeNode( "AllenWithRich", [ - hlt1_node, reconstructed_objects["decoded_rich"] - ["dev_smart_ids"].producer + hlt1_node, + reconstructed_objects["decoded_rich"]["dev_smart_ids"].producer ], NodeLogic.NONLAZY_AND, force_order=True) diff --git a/configuration/python/AllenConf/hlt1_reconstruction.py b/configuration/python/AllenConf/hlt1_reconstruction.py index 50cc08adc0f..8e2c1f0af98 100644 --- a/configuration/python/AllenConf/hlt1_reconstruction.py +++ b/configuration/python/AllenConf/hlt1_reconstruction.py @@ -211,9 +211,7 @@ def hlt1_reconstruction(algorithm_name='', if with_rich: from AllenConf.rich_reconstruction import decode_rich - output.update({ - "decoded_rich": decode_rich() - }) + output.update({"decoded_rich": decode_rich()}) return output diff --git a/configuration/python/AllenSequences/rich.py b/configuration/python/AllenSequences/rich.py index 458d8a17c41..a393e3b270c 100644 --- a/configuration/python/AllenSequences/rich.py +++ b/configuration/python/AllenSequences/rich.py @@ -6,9 +6,7 @@ from AllenCore.generator import generate from PyConf.control_flow import NodeLogic, CompositeNode rich_decoding = CompositeNode( - "RichDecoding", [ - decode_rich()["dev_smart_ids"].producer - ], + "RichDecoding", [decode_rich()["dev_smart_ids"].producer], NodeLogic.NONLAZY_AND, force_order=True) diff --git a/device/rich/decoding/src/RichDecoding.cu b/device/rich/decoding/src/RichDecoding.cu index 1442073dbf4..1b7837782d2 100644 --- a/device/rich/decoding/src/RichDecoding.cu +++ b/device/rich/decoding/src/RichDecoding.cu @@ -78,7 +78,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( // Data 'could' be invalid, e.g. radiation-induced-upsets // so cannot make this a hard error - if ( aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1 ) { + if (aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1) { number_of_hits++; } } @@ -128,7 +128,7 @@ __device__ unsigned rich_calculate_number_of_hits_in_raw_bank( // Data 'could' be invalid, e.g. radiation-induced-upsets // so cannot make this a hard error - if ( aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1 ) { + if (aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1) { number_of_hits++; } } @@ -252,7 +252,7 @@ __device__ void rich_decode_bank( // Data 'could' be invalid, e.g. radiation-induced-upsets // so cannot make this a hard error - if ( aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1 ) { + if (aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1) { // make a smart ID auto hitID = Allen::RichSmartID {cData.smartID}; // sets RICH, side, module and PMT type @@ -327,7 +327,7 @@ __device__ void rich_decode_bank( const auto& aData = frameData[bit]; // Data 'could' be invalid, e.g. radiation-induced-upsets // so cannot make this a hard error - if ( aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1 ) { + if (aData.ec != -1 && aData.pmtInEC != -1 && aData.anode != -1) { // make a smart ID auto hitID = Allen::RichSmartID {cData.smartID}; // sets RICH, side, module and PMT type -- GitLab From 09e68ab52f937afc6a47eb676bf438935d3cd354 Mon Sep 17 00:00:00 2001 From: Saverio Mariani Date: Thu, 21 Dec 2023 23:17:44 +0100 Subject: [PATCH 54/63] Fix after rebase --- configuration/python/AllenConf/hlt1_reconstruction.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/python/AllenConf/hlt1_reconstruction.py b/configuration/python/AllenConf/hlt1_reconstruction.py index 8e2c1f0af98..04915d8f542 100644 --- a/configuration/python/AllenConf/hlt1_reconstruction.py +++ b/configuration/python/AllenConf/hlt1_reconstruction.py @@ -28,7 +28,7 @@ def hlt1_reconstruction(algorithm_name='', with_ut=True, with_muon=True, velo_open=False, - enableDownstream=False): + enableDownstream=False, with_rich=False): decoded_velo = decode_velo() decoded_scifi = decode_scifi() -- GitLab From 09d797c8e7293c993a8a2c8f61f342eb9c3bbe3a Mon Sep 17 00:00:00 2001 From: Saverio Mariani Date: Mon, 15 Jan 2024 12:39:22 +0100 Subject: [PATCH 55/63] Fix after rebase --- main/include/TESProvider.h | 73 ++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/main/include/TESProvider.h b/main/include/TESProvider.h index 69380768fb8..33c7e2b6769 100644 --- a/main/include/TESProvider.h +++ b/main/include/TESProvider.h @@ -9,7 +9,6 @@ #include #include #include -#include #include "SciFiRaw.cuh" @@ -66,44 +65,40 @@ public: return 1; } - for (auto allen_bank_type : it->second) { - auto allen_bank_index = to_integral(allen_bank_type); - - // Offsets to events (we only process one event) - auto& offsets = m_offsets[allen_bank_index]; - offsets[0] = 0; - offsets[1] = banks.data.size(); - - // Bank sizes - auto const n_banks = reinterpret_cast(banks.data.data())[0]; - - auto& sizes_offsets = m_sizes[allen_bank_index]; - sizes_offsets.resize(2 + n_banks / 2 + 1); - // Only 1 event, so a single offset is enough. The offset - // counts uint16_t and is a uint32_t itself. - sizes_offsets[0] = 2; - uint16_t* sizes = reinterpret_cast(&sizes_offsets[1]); - std::copy_n(banks.sizes.begin(), banks.sizes.size(), sizes); - - auto& types_offsets = m_types[allen_bank_index]; - types_offsets.resize(2 + n_banks / 4 + 1); - // Only 1 event, so a single offset offset is enough. The offset - // counts uint8_t and is a uint32_t itself. - types_offsets[0] = 4; - uint8_t* types = reinterpret_cast(&types_offsets[1]); - std::copy_n(banks.types.begin(), banks.types.size(), types); - - // bank content - auto data_size = static_cast>(banks.data.size()); - gsl::span b {banks.data.data(), data_size}; - - m_banks_and_offsets[allen_bank_index] = {{std::move(b)}, - {offsets.data(), 2u}, - static_cast(data_size), - {sizes_offsets.data(), sizes_offsets.size()}, - {types_offsets.data(), types_offsets.size()}, - banks.version}; - } + // Offsets to events (we only process one event) + auto& offsets = m_offsets[allen_bank_index]; + offsets[0] = 0; + offsets[1] = banks.data.size(); + + // Bank sizes + auto const n_banks = reinterpret_cast(banks.data.data())[0]; + + auto& sizes_offsets = m_sizes[allen_bank_index]; + sizes_offsets.resize(2 + n_banks / 2 + 1); + // Only 1 event, so a single offset is enough. The offset + // counts uint16_t and is a uint32_t itself. + sizes_offsets[0] = 2; + uint16_t* sizes = reinterpret_cast(&sizes_offsets[1]); + std::copy_n(banks.sizes.begin(), banks.sizes.size(), sizes); + + auto& types_offsets = m_types[allen_bank_index]; + types_offsets.resize(2 + n_banks / 4 + 1); + // Only 1 event, so a single offset offset is enough. The offset + // counts uint8_t and is a uint32_t itself. + types_offsets[0] = 4; + uint8_t* types = reinterpret_cast(&types_offsets[1]); + std::copy_n(banks.types.begin(), banks.types.size(), types); + + // bank content + auto data_size = static_cast>(banks.data.size()); + gsl::span b {banks.data.data(), data_size}; + + m_banks_and_offsets[allen_bank_index] = {{std::move(b)}, + {offsets.data(), 2u}, + static_cast(data_size), + {sizes_offsets.data(), sizes_offsets.size()}, + {types_offsets.data(), types_offsets.size()}, + banks.version}; } return 0; -- GitLab From 562110680c93fc84e976b65e2c050437b7aa0647 Mon Sep 17 00:00:00 2001 From: Christian Asch Date: Fri, 19 Jan 2024 11:47:21 -0600 Subject: [PATCH 56/63] Updated rich_tel40maps.bin with correct smartID size --- .../detector_configuration/rich_tel40maps.bin | Bin 314760 -> 469509 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/input/detector_configuration/rich_tel40maps.bin b/input/detector_configuration/rich_tel40maps.bin index d0a1df420e21e5ea60253d983a484688452e765c..467738102542693be65565d1726d0b849c91803f 100644 GIT binary patch literal 469509 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 Date: Tue, 23 Jan 2024 12:21:29 +0100 Subject: [PATCH 57/63] Update geometry in ci test --- scripts/ci/test_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/test_config.yaml b/scripts/ci/test_config.yaml index 4b8a0da5017..d6f8dc22d59 100644 --- a/scripts/ci/test_config.yaml +++ b/scripts/ci/test_config.yaml @@ -56,7 +56,7 @@ minimal: sequence: - hlt1_pp_rich_no_ut dataset: "Run_0000248711_HLT20840_20221011-113809-426" - geometry: "MiniBrunel_2018_MinBias_FTv4_DIGI_ecalv4_scifiv7_muonv3" + geometry: "MiniBrunel_2018_MinBias_FTv4_DIGI_ecalv4_scifiv7_muonv3_RICH" - type: "efficiency" sequence: -- GitLab From a958e4c7aba7647ee87a791de13d7808f33dc56f Mon Sep 17 00:00:00 2001 From: Saverio Mariani Date: Tue, 23 Jan 2024 13:42:59 +0100 Subject: [PATCH 58/63] Move RICH sequence thrpughput test to full ci rather than the minimal one --- scripts/ci/test_config.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/ci/test_config.yaml b/scripts/ci/test_config.yaml index d6f8dc22d59..9c7d187cb7c 100644 --- a/scripts/ci/test_config.yaml +++ b/scripts/ci/test_config.yaml @@ -52,11 +52,6 @@ minimal: - hlt1_pp_forward_then_matching dataset: "upgrade_mc_minbias_scifi_v5_retinacluster_000_v1_newLHCbID_new_UT_geometry" geometry: "geometry_dddb-20180815_sim-20180530-vc-md100_new_UT_geometry" - - type: "throughput" - sequence: - - hlt1_pp_rich_no_ut - dataset: "Run_0000248711_HLT20840_20221011-113809-426" - geometry: "MiniBrunel_2018_MinBias_FTv4_DIGI_ecalv4_scifiv7_muonv3_RICH" - type: "efficiency" sequence: @@ -216,6 +211,13 @@ full: dataset: "Beam6800GeV-expected-2024-MagDown-nu7.6" geometry: "geometry_dddb-20231017_sim-20231017-vc-md100" + #throughput test with RICH decoding -> medium/long term development + - type: "throughput" + sequence: + - hlt1_pp_rich_no_ut + dataset: "Run_0000248711_HLT20840_20221011-113809-426" + geometry: "MiniBrunel_2018_MinBias_FTv4_DIGI_ecalv4_scifiv7_muonv3_RICH" + # run physics efficiency for downstream reconstruction - type: "efficiency" sequence: -- GitLab From af943680dfc83f7a754c745e5cf229005d8f8399 Mon Sep 17 00:00:00 2001 From: Saverio Mariani Date: Wed, 24 Jan 2024 19:20:31 +0100 Subject: [PATCH 59/63] Fix rebasing mistake --- Rec/Allen/CMakeLists.txt | 4 +-- Rec/Allen/python/Allen/config.py | 47 ++++++++++++-------------------- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/Rec/Allen/CMakeLists.txt b/Rec/Allen/CMakeLists.txt index bf3adffe1c7..9cc472ea35d 100755 --- a/Rec/Allen/CMakeLists.txt +++ b/Rec/Allen/CMakeLists.txt @@ -25,7 +25,7 @@ gaudi_add_module(AllenWrapper src/ProvideRuntimeOptions.cpp src/CompareRecAllenCaloDigits.cpp src/CompareRecAllenMuonHits.cpp - src/CompareRecAllenUTHitsMCCheck.cpp + src/CompareRecAllenUTHitsMCCheck.cpp src/CompareRecAllenFTClusters.cpp src/CompareRecAllenVPHits.cpp src/TestVeloClusters.cpp @@ -62,7 +62,7 @@ gaudi_add_module(AllenWrapper LHCb::CaloDetLib LHCb::FTDetLib LHCb::MCEvent - LHCb::RecEvent + LHCb::RecEvent Rec::PrKernel) target_include_directories(AllenWrapper PRIVATE ${PROJECT_BINARY_DIR}/code_generation) diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index bb3c494e437..8dfcd9ea691 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -18,7 +18,7 @@ from PyConf.control_flow import CompositeNode, NodeLogic from PyConf.application import all_nodes_and_algs from PyConf.application import configure_input, configure from PyConf.Algorithms import ( - AllenTESProducer, DumpBeamline, DumpCaloGeometry, DumpMagneticField, + DumpBeamline, DumpCaloGeometry, DumpMagneticField, DumpVPGeometry, DumpFTGeometry, DumpUTGeometry, DumpUTLookupTables, DumpMuonGeometry, DumpMuonTable, AllenODINProducer, DumpRichPDMDBMapping, DumpRichCableMapping) @@ -110,24 +110,24 @@ def setup_allen_non_event_data_service(allen_event_loop=False, data (geometries etc.) """ converter_types = { - frozenset({'VP'}): [(DumpBeamline, 'DumpBeamline', 'beamline'), - (DumpVPGeometry, 'DumpVPGeometry', + frozenset({'VP'}): [(DumpBeamline, 'DeviceBeamline', 'beamline'), + (DumpVPGeometry, 'DeviceVPGeometry', 'velo_geometry')], - frozenset({'UT'}): [(DumpUTGeometry, 'DumpUTGeometry', 'ut_geometry'), - (DumpUTLookupTables, 'DumpUTLookupTables', + frozenset({'UT'}): [(DumpUTGeometry, 'DeviceUTGeometry', 'ut_geometry'), + (DumpUTLookupTables, 'DeviceUTLookupTables', 'ut_tables')], - frozenset({'ECal'}): [(DumpCaloGeometry, 'DumpCaloGeometry', + frozenset({'ECal'}): [(DumpCaloGeometry, 'DeviceCaloGeometry', 'ecal_geometry')], - frozenset({'Magnet'}): [(DumpMagneticField, 'DumpMagneticField', + frozenset({'Magnet'}): [(DumpMagneticField, 'DeviceMagneticField', 'polarity')], - frozenset({'FTCluster'}): [(DumpFTGeometry, 'DumpFTGeometry', + frozenset({'FTCluster'}): [(DumpFTGeometry, 'DeviceFTGeometry', 'scifi_geometry')], - frozenset({'Muon'}): [(DumpMuonGeometry, 'DumpMuonGeometry', + frozenset({'Muon'}): [(DumpMuonGeometry, 'DeviceMuonGeometry', 'muon_geometry'), - (DumpMuonTable, 'DumpMuonTable', 'muon_tables')], + (DumpMuonTable, 'DeviceMuonTable', 'muon_tables')], frozenset({'Rich1', 'Rich2'}): - [(DumpRichPDMDBMapping, 'DumpRichPDMDBMapping', 'rich_pdmdbmaps'), - (DumpRichCableMapping, 'DumpRichCableMapping', 'rich_tel40maps')], + [(DumpRichPDMDBMapping, 'DeviceRichPDMDBMapping', 'rich_pdmdbmaps'), + (DumpRichCableMapping, 'DeviceRichCableMapping', 'rich_tel40maps')], } detector_names = { @@ -180,24 +180,11 @@ def setup_allen_non_event_data_service(allen_event_loop=False, converters = {(bts, t, tn, f) for bts, convs in converter_types.items() for t, tn, f in convs if bts.intersection(bank_types)} - for bts, converter_type, converter_name, filename in converters: - converter_id = converter_type.getDefaultProperties().get('ID', None) - if converter_id is not None: - converter = converter_type() - # An algorithm that needs a TESProducer - producer = AllenTESProducer( - name='AllenTESProducer_%s' % '_'.join(bts), - Filename=filename if dump_geometry else "", - OutputDirectory=out_dir, - InputID=converter.OutputID, - InputData=converter.Converted, - ID=converter_id) - algorithm_producers.append(producer) - else: - converter = converter_type( - name=converter_name, - DumpToFile=dump_geometry, - OutputDirectory=out_dir) + for bt, converter_type, converter_name, filename in converters: + converter = converter_type( + name=converter_name, + DumpToFile=dump_geometry, + OutputDirectory=out_dir) algorithm_converters.append(converter) converters_node = CompositeNode( -- GitLab From 088c34bab69da4a66cdfe42d83db9234e33a0a01 Mon Sep 17 00:00:00 2001 From: Saverio Mariani Date: Wed, 24 Jan 2024 21:56:35 +0100 Subject: [PATCH 60/63] Undo commits on CALO decoding to be re-applied in a separate MR --- device/calo/decoding/include/CaloDecode.cuh | 1 + device/calo/decoding/src/CaloDecode.cu | 62 +++++++-------- .../event_model/calo/include/CaloRawEvent.cuh | 78 +++++++++++++++++++ 3 files changed, 109 insertions(+), 32 deletions(-) create mode 100644 device/event_model/calo/include/CaloRawEvent.cuh diff --git a/device/calo/decoding/include/CaloDecode.cuh b/device/calo/decoding/include/CaloDecode.cuh index eb1e93ab8e8..099db76c8f4 100644 --- a/device/calo/decoding/include/CaloDecode.cuh +++ b/device/calo/decoding/include/CaloDecode.cuh @@ -4,6 +4,7 @@ #pragma once +#include "CaloRawEvent.cuh" #include "CaloGeometry.cuh" #include "CaloDigit.cuh" #include "AlgorithmTypes.cuh" diff --git a/device/calo/decoding/src/CaloDecode.cu b/device/calo/decoding/src/CaloDecode.cu index ce4aa3b71c5..2c5f79b90b5 100644 --- a/device/calo/decoding/src/CaloDecode.cu +++ b/device/calo/decoding/src/CaloDecode.cu @@ -34,31 +34,30 @@ namespace { for (unsigned bank_number = threadIdx.x; bank_number < raw_event.number_of_raw_banks; bank_number += blockDim.x) { auto raw_bank = raw_event.raw_bank(bank_number); - auto raw_bank_data_u32 = reinterpret_cast(raw_bank.data); if constexpr (decoding_version < 4) { // old decoding - const auto raw_bank_end = reinterpret_cast(raw_bank.data + raw_bank.size); - while (raw_bank_data_u32 < raw_bank_end) { - uint32_t word = *raw_bank_data_u32; + + while (raw_bank.data < raw_bank.end) { + uint32_t word = *raw_bank.data; uint16_t trig_size = word & 0x7F; uint16_t code = (word >> 14) & 0x1FF; // Skip header and trigger words - raw_bank_data_u32 += 1 + (trig_size + 3) / 4; + raw_bank.data += 1 + (trig_size + 3) / 4; // pattern bits - unsigned int pattern = *raw_bank_data_u32; + unsigned int pattern = *raw_bank.data; // Loop over all cards in this front-env sub-bank. - uint32_t last_data = *(raw_bank_data_u32 + 1); - raw_bank_data_u32 += 2; + uint32_t last_data = *(raw_bank.data + 1); + raw_bank.data += 2; int16_t offset = 0; for (unsigned int bit_num = 0; 32 > bit_num; ++bit_num) { if (31 < offset) { offset -= 32; - last_data = *raw_bank_data_u32; - raw_bank_data_u32 += 1; + last_data = *raw_bank.data; + raw_bank.data += 1; } int adc; if (0 == (pattern & (1 << bit_num))) { //.. short coding @@ -71,8 +70,8 @@ namespace { if (28 == offset) adc &= 0xF; //== clean-up extra bits offset += 12; if (32 < offset) { //.. get the extra bits on next word - last_data = *raw_bank_data_u32; - raw_bank_data_u32 += 1; + last_data = *raw_bank.data; + raw_bank.data += 1; offset -= 32; int temp = (last_data << (12 - offset)) & 0xFFF; adc += temp; @@ -100,17 +99,16 @@ namespace { } auto raw_bank_fiberCheck = raw_event_fiberCheck.raw_bank(bank_number); - auto raw_bank_fiberCheck_data_u32 = reinterpret_cast(raw_bank_fiberCheck.data); - auto get_data = [](uint32_t const* raw_data_u32) { - auto d = *raw_data_u32; + auto get_data = [](uint32_t const* raw_data) { + auto d = *raw_data; if constexpr (decoding_version == 4) { // big endian d = ((d >> 24) & 0x000000FF) | ((d >> 8) & 0x0000FF00) | ((d << 8) & 0x00FF0000) | ((d << 24) & 0xFF000000); } return d; }; - uint32_t pattern = *(raw_bank_data_u32); + uint32_t pattern = *(raw_bank.data); int offset = 0; uint32_t lastData = pattern; @@ -121,10 +119,10 @@ namespace { for (int ifeb = 0; ifeb < 3; ifeb++) { // First, remove 3 LLTs if (ifeb == 0) { - raw_bank_data_u32 += 3; - raw_bank_fiberCheck_data_u32 += 3; + raw_bank.data += 3; + raw_bank_fiberCheck.data += 3; } - lastData = get_data(raw_bank_data_u32); + lastData = get_data(raw_bank.data); int nADC = 0; bool isFiberOff = false; @@ -134,12 +132,12 @@ namespace { // ... and readout data for (unsigned int bitNum = 0; 32 > bitNum; bitNum++) { if (nADC % 8 == 0) { // Check fibers pattern, 1 fiber corresponds to 8 ADC (96b) - if (offset == 32) raw_bank_fiberCheck_data_u32 += 1; - uint32_t pattern1 = get_data(raw_bank_fiberCheck_data_u32); - raw_bank_fiberCheck_data_u32 += 1; - uint32_t pattern2 = get_data(raw_bank_fiberCheck_data_u32); - raw_bank_fiberCheck_data_u32 += 1; - uint32_t pattern3 = get_data(raw_bank_fiberCheck_data_u32); + if (offset == 32) raw_bank_fiberCheck.data += 1; + uint32_t pattern1 = get_data(raw_bank_fiberCheck.data); + raw_bank_fiberCheck.data += 1; + uint32_t pattern2 = get_data(raw_bank_fiberCheck.data); + raw_bank_fiberCheck.data += 1; + uint32_t pattern3 = get_data(raw_bank_fiberCheck.data); if (pattern1 == fibMask1 && pattern2 == fibMask2 && pattern3 == fibMask3) isFiberOff = true; else @@ -147,8 +145,8 @@ namespace { } if (31 < offset) { offset -= 32; - raw_bank_data_u32 += 1; - lastData = get_data(raw_bank_data_u32); + raw_bank.data += 1; + lastData = get_data(raw_bank.data); } int adc = 0; @@ -160,16 +158,16 @@ namespace { adc = ((lastData >> (20 - offset)) & 0xfff); if (28 == offset) { //.. get the extra bits on next word - raw_bank_data_u32 += 1; - lastData = get_data(raw_bank_data_u32); + raw_bank.data += 1; + lastData = get_data(raw_bank.data); int temp = (lastData >> (offset - 4)) & 0xFF; offset -= 32; adc = (adc << 8) + temp; } if (24 == offset) { //.. get the extra bits on next word - raw_bank_data_u32 += 1; - lastData = get_data(raw_bank_data_u32); + raw_bank.data += 1; + lastData = get_data(raw_bank.data); int temp = (lastData >> (offset + 4)) & 0xF; offset -= 32; adc = (adc << 4) + temp; @@ -237,7 +235,7 @@ __global__ void calo_decode_dispatch( auto ecal_geometry = CaloGeometry(raw_ecal_geometry); auto const ecal_digits_offset = parameters.dev_ecal_digits_offsets[event_number]; - decode, decoding_version>( + decode, decoding_version>( parameters.dev_ecal_raw_input, parameters.dev_ecal_raw_input_offsets, parameters.dev_ecal_raw_input_sizes, diff --git a/device/event_model/calo/include/CaloRawEvent.cuh b/device/event_model/calo/include/CaloRawEvent.cuh new file mode 100644 index 00000000000..71f4886e0d7 --- /dev/null +++ b/device/event_model/calo/include/CaloRawEvent.cuh @@ -0,0 +1,78 @@ +/*****************************************************************************\ +* (c) Copyright 2021 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the Apache License * +* version 2 (Apache-2.0), copied verbatim in the file "LICENSE". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ +#pragma once + +#include +#include "BackendCommon.h" +#include "MEPTools.h" + +namespace Calo { + + struct RawBank { + uint32_t source_id = 0; + uint32_t const* data = nullptr; + uint32_t const* end = nullptr; + uint8_t const type; + + // For Allen format + __device__ __host__ RawBank(const char* raw_bank, const uint16_t s, const uint8_t t) : + RawBank {*reinterpret_cast(raw_bank), raw_bank + sizeof(uint32_t), s, t} + {} + + // For MEP format + __device__ __host__ RawBank(const uint32_t sid, const char* fragment, const uint16_t s, const uint8_t t) : + source_id {sid}, data {reinterpret_cast(fragment)}, + end {reinterpret_cast(fragment + s)}, type {t} + {} + }; + + template + struct RawEvent { + + uint32_t number_of_raw_banks = 0; + const char* data = nullptr; + const uint32_t* offsets = nullptr; + typename std::conditional_t* sizes = nullptr; + typename std::conditional_t* types = nullptr; + const unsigned event = 0; + + // For Allen format + __device__ __host__ + RawEvent(char const* d, uint32_t const* o, uint32_t const* s, uint32_t const* t, unsigned const event_number) : + offsets {o}, + event {event_number} + { + if constexpr (mep_layout) { + data = d; + number_of_raw_banks = MEP::number_of_banks(o); + sizes = s; + types = t; + } + else { + data = d + offsets[event]; + number_of_raw_banks = reinterpret_cast(data)[0]; + sizes = Allen::bank_sizes(s, event); + types = Allen::bank_types(t, event); + } + } + + __device__ __host__ RawBank raw_bank(unsigned const n) const + { + if constexpr (mep_layout) { + return MEP::raw_bank(data, offsets, sizes, types, event, n); + } + else { + uint32_t const* bank_offsets = reinterpret_cast(data) + 1; + return RawBank {data + (number_of_raw_banks + 2) * sizeof(uint32_t) + bank_offsets[n], sizes[n], types[n]}; + } + } + }; +} // namespace Calo -- GitLab From 06fb5505668e6c92b6c37299c7eed4db38c43b21 Mon Sep 17 00:00:00 2001 From: Gitlab CI Date: Wed, 24 Jan 2024 20:59:24 +0000 Subject: [PATCH 61/63] Fixed formatting patch generated by https://gitlab.cern.ch/lhcb/Allen/-/jobs/35516350 --- Rec/Allen/python/Allen/config.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index 8dfcd9ea691..92db909bd14 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -18,9 +18,9 @@ from PyConf.control_flow import CompositeNode, NodeLogic from PyConf.application import all_nodes_and_algs from PyConf.application import configure_input, configure from PyConf.Algorithms import ( - DumpBeamline, DumpCaloGeometry, DumpMagneticField, - DumpVPGeometry, DumpFTGeometry, DumpUTGeometry, DumpUTLookupTables, - DumpMuonGeometry, DumpMuonTable, AllenODINProducer, DumpRichPDMDBMapping, + DumpBeamline, DumpCaloGeometry, DumpMagneticField, DumpVPGeometry, + DumpFTGeometry, DumpUTGeometry, DumpUTLookupTables, DumpMuonGeometry, + DumpMuonTable, AllenODINProducer, DumpRichPDMDBMapping, DumpRichCableMapping) from DDDB.CheckDD4Hep import UseDD4Hep @@ -113,9 +113,9 @@ def setup_allen_non_event_data_service(allen_event_loop=False, frozenset({'VP'}): [(DumpBeamline, 'DeviceBeamline', 'beamline'), (DumpVPGeometry, 'DeviceVPGeometry', 'velo_geometry')], - frozenset({'UT'}): [(DumpUTGeometry, 'DeviceUTGeometry', 'ut_geometry'), - (DumpUTLookupTables, 'DeviceUTLookupTables', - 'ut_tables')], + frozenset({'UT'}): + [(DumpUTGeometry, 'DeviceUTGeometry', 'ut_geometry'), + (DumpUTLookupTables, 'DeviceUTLookupTables', 'ut_tables')], frozenset({'ECal'}): [(DumpCaloGeometry, 'DeviceCaloGeometry', 'ecal_geometry')], frozenset({'Magnet'}): [(DumpMagneticField, 'DeviceMagneticField', @@ -124,7 +124,8 @@ def setup_allen_non_event_data_service(allen_event_loop=False, 'scifi_geometry')], frozenset({'Muon'}): [(DumpMuonGeometry, 'DeviceMuonGeometry', 'muon_geometry'), - (DumpMuonTable, 'DeviceMuonTable', 'muon_tables')], + (DumpMuonTable, 'DeviceMuonTable', + 'muon_tables')], frozenset({'Rich1', 'Rich2'}): [(DumpRichPDMDBMapping, 'DeviceRichPDMDBMapping', 'rich_pdmdbmaps'), (DumpRichCableMapping, 'DeviceRichCableMapping', 'rich_tel40maps')], -- GitLab From 5843b429c8ef3c1c7ea9f3c2870e06cfd85e0610 Mon Sep 17 00:00:00 2001 From: Saverio Mariani Date: Sun, 28 Jan 2024 20:21:50 +0100 Subject: [PATCH 62/63] Fix test failing in the ci --- configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py b/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py index 61cf0b0d2f8..a5d3cdd7f30 100644 --- a/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py +++ b/configuration/python/AllenSequences/hlt1_pp_rich_no_ut.py @@ -6,4 +6,5 @@ from AllenCore.generator import generate from AllenConf.rich_reconstruction import decode_rich from PyConf.control_flow import NodeLogic, CompositeNode -generate(setup_hlt1_node(with_ut=False, with_rich=True)) +hlt1_node = setup_hlt1_node(with_ut=False, with_rich=True) +generate(hlt1_node) -- GitLab From 3f0c41b3ce25005a2693c6fed1af3f87377283f7 Mon Sep 17 00:00:00 2001 From: Saverio Mariani Date: Tue, 30 Jan 2024 17:47:53 +0100 Subject: [PATCH 63/63] Fix Moore test --- Rec/Allen/python/Allen/config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Rec/Allen/python/Allen/config.py b/Rec/Allen/python/Allen/config.py index 92db909bd14..9c14c5934b9 100755 --- a/Rec/Allen/python/Allen/config.py +++ b/Rec/Allen/python/Allen/config.py @@ -143,7 +143,9 @@ def setup_allen_non_event_data_service(allen_event_loop=False, if type(bank_types) == list: bank_types = set(bank_types) elif bank_types is None: - bank_types = set(converter_types.keys()) + bank_types = set() + for ibt in converter_types.keys(): + bank_types.update(set(ibt)) if 'VPRetinaCluster' in bank_types: bank_types.remove('VPRetinaCluster') -- GitLab