diff --git a/core/data/DataLinkDef.h b/core/data/DataLinkDef.h index ac3e3775a2239c7ec904e276dea320cfcc8a1181..75ecb0560e8e03cac23ae9c9bcfffacda7a7011c 100644 --- a/core/data/DataLinkDef.h +++ b/core/data/DataLinkDef.h @@ -131,9 +131,18 @@ #pragma link C++ class CbmDigiVector < CbmPsdDsp> + ; #pragma link C++ class vector < CbmEventStore> + ; -#pragma read sourceClass = "CbmTofDigi" version = "[1-2]" targetClass = "CbmTofDigi" source = \ - "UInt_t fuAddress" target = "fuAddress" include = "Logger.h" code = \ - "{ UInt_t system = (onfile.fuAddress >> 0) & ((1 << 4) - 1); \ +#pragma read sourceClass="CbmStsDigi" version="[7]" targetClass="CbmStsDigi" \ + source="Long64_t fTime; Int_t fAddress; UShort_t fChannel; UShort_t fCharge" \ + target="" \ + include="Logger.h" \ + code="{ newObj->SetAddressAndTime(onfile.fAddress, onfile.fTime); \ + newObj->SetChannelAndCharge(onfile.fChannel, onfile.fCharge); \ + }" + +#pragma read sourceClass="CbmTofDigi" version="[1-2]" targetClass="CbmTofDigi" \ + source="UInt_t fuAddress" target="fuAddress" \ + include="Logger.h" \ + code="{ UInt_t system = (onfile.fuAddress >> 0) & ((1 << 4) - 1); \ UInt_t smId = (onfile.fuAddress >> 4) & ((1 << 8) - 1); \ UInt_t smType = (onfile.fuAddress >> 12) & ((1 << 4) - 1); \ UInt_t rpcId = (onfile.fuAddress >> 16) & ((1 << 7) - 1); \ diff --git a/core/data/sts/CbmStsAddress.cxx b/core/data/sts/CbmStsAddress.cxx index 81fb9c7959790c8937fc625f72bad6cd735765a1..d6d8331b8e6728e2b222b9cb587186708df88c87 100644 --- a/core/data/sts/CbmStsAddress.cxx +++ b/core/data/sts/CbmStsAddress.cxx @@ -19,6 +19,7 @@ namespace CbmStsAddress { + // clang-format off // ----- Definition of address bit field ------------------------------ const uint16_t kBits[kCurrentVersion + 1][kStsNofLevels] = { @@ -66,7 +67,7 @@ namespace CbmStsAddress {(1 << kBits[1][0]) - 1, (1 << kBits[1][1]) - 1, (1 << kBits[1][2]) - 1, (1 << kBits[1][3]) - 1, (1 << kBits[1][4]) - 1, (1 << kBits[1][5]) - 1, (1 << kBits[1][6]) - 1}}; // ------------------------------------------------------------------------- - + // clang-format on } // Namespace CbmStsAddress diff --git a/core/data/sts/CbmStsAddress.h b/core/data/sts/CbmStsAddress.h index e62a00feb13b4fed2b36a6a5cc3d10a807bb623a..c232c6df28af1e2cc95dfef77b4a155e28a359cc 100644 --- a/core/data/sts/CbmStsAddress.h +++ b/core/data/sts/CbmStsAddress.h @@ -108,8 +108,8 @@ namespace CbmStsAddress ** @param address Unique element address ** @value Version number ** - ** The version is encoded in the last 6 bits (58 to 63). - ** The maximal number of versions is 64. + ** The version is encoded in the last 4 bits (28 to 31). + ** The maximal number of versions is 16. **/ uint32_t GetVersion(int32_t address); @@ -138,6 +138,20 @@ namespace CbmStsAddress int32_t UnpackDigiAddress(int32_t digiAddress); + /** @brief Strip address to contain only unit, (half)ladder and module. + ** @param address Full address + ** @return 17 bit address that can be stored in a Digi + **/ + int32_t PackDigiAddress(int32_t address); + + + /** @brief Add version and system to compressed address that's stored in a digi + ** @param digiAddress Compressed address from digi + ** @return Full address + **/ + int32_t UnpackDigiAddress(int32_t digiAddress); + + /** @brief String output ** @param address Unique element address **/ diff --git a/core/data/sts/CbmStsDigi.cxx b/core/data/sts/CbmStsDigi.cxx index 73b9162ac39749ed068e368bd4388ddd383c4716..733544a0e8d23c1a3fceadfd9ff66e42de20b825 100644 --- a/core/data/sts/CbmStsDigi.cxx +++ b/core/data/sts/CbmStsDigi.cxx @@ -4,12 +4,17 @@ /** CbmStsDigi.cxx ** @author V.Friese <v.friese@gsi.de> + ** @author Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de> ** @since 28.08.2006 ** @version 4.0 **/ #include "CbmStsDigi.h" +#include "CbmStsAddress.h" + +#include <algorithm> +#include <cstdlib> #include <sstream> // for operator<<, basic_ostream, char_traits using std::string; @@ -19,10 +24,29 @@ using std::stringstream; string CbmStsDigi::ToString() const { stringstream ss; - ss << "StsDigi: address " << fAddress << " | channel " << fChannel << " | charge " << fCharge << " | time " << fTime; + ss << "StsDigi: address " << UnpackAddress() << " | channel " << UnpackChannel() << " | charge " << UnpackCharge() + << " | time " << UnpackTime(); return ss.str(); } +void CbmStsDigi::PackAddressAndTime(int32_t newAddress, uint32_t newTime) +{ + int32_t packedAddr = CbmStsAddress::PackDigiAddress(newAddress); + + uint32_t highestBitAddr = packedAddr >> kNumLowerAddrBits; + uint32_t lowerAddr = packedAddr & ((1 << kNumLowerAddrBits) - 1); + + fAddress = lowerAddr; + fTime = (highestBitAddr << kNumTimestampBits) | newTime; +} + +int32_t CbmStsDigi::UnpackAddress() const +{ + int32_t highestBitAddr = fTime >> kNumTimestampBits; + int32_t packedAddress = (highestBitAddr << kNumLowerAddrBits) | int32_t(fAddress); + return CbmStsAddress::UnpackDigiAddress(packedAddress); +} + #ifndef NO_ROOT ClassImp(CbmStsDigi) #endif diff --git a/core/data/sts/CbmStsDigi.h b/core/data/sts/CbmStsDigi.h index 2e7fe4a919f7cef6690aba660a2b509bd4d617c1..94594b483e007cdad3f155a76f71e45aab5613a0 100644 --- a/core/data/sts/CbmStsDigi.h +++ b/core/data/sts/CbmStsDigi.h @@ -4,6 +4,7 @@ /** @file CbmStsDigi.h ** @author V.Friese <v.friese@gsi.de> + ** @author Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de> ** @since 28.08.2006 ** @version 6 **/ @@ -13,6 +14,7 @@ #define CBMSTSDIGI_H 1 #include "CbmDefs.h" // for ECbmModuleId::kSts +#include "CbmStsAddress.h" #ifndef NO_ROOT #include <Rtypes.h> // for ClassDef @@ -45,23 +47,20 @@ public: ** @param time Measurement time [ns] ** @param charge Charge [ADC units] **/ - CbmStsDigi(int32_t address, int32_t channel, uint64_t time, uint16_t charge) - : fTime(time) - , fAddress(address) - , fChannel(channel) - , fCharge(charge) + CbmStsDigi(int32_t address, int32_t channel, uint32_t time, uint16_t charge) { + PackAddressAndTime(address, time); + PackChannelAndCharge(channel, charge); } /** Destructor **/ ~CbmStsDigi() {}; - /** Unique detector element address (see CbmStsAddress) ** @value Unique address of readout channel **/ - int32_t GetAddress() const { return fAddress; } + int32_t GetAddress() const { return UnpackAddress(); } /** @brief Get the desired name of the branch for this obj in the cbm output tree (static) @@ -73,7 +72,7 @@ public: /** @brief Channel number in module ** @value Channel number **/ - uint16_t GetChannel() const { return fChannel; } + uint16_t GetChannel() const { return UnpackChannel(); } /** @brief Class name (static) @@ -85,7 +84,7 @@ public: /** Charge ** @value Charge [ADC units] **/ - double GetCharge() const { return double(fCharge); } + double GetCharge() const { return static_cast<double>(UnpackCharge()); } /** System ID (static) @@ -97,16 +96,15 @@ public: /** Time of measurement ** @value Time [ns] **/ - double GetTime() const { return double(fTime); } + double GetTime() const { return static_cast<double>(UnpackTime()); } template<class Archive> void serialize(Archive& ar, const unsigned int /*version*/) { ar& fTime; + ar& fChannelAndCharge; ar& fAddress; - ar& fChannel; - ar& fCharge; } @@ -115,11 +113,30 @@ public: **/ void SetTime(double dNewTime) { - // Future versions of StsDigi won't be able to store negative timestamps. - assert(dNewTime >= 0); - fTime = dNewTime; + // StsDigi is not able to store negative timestamps. + assert(dNewTime >= 0 && dNewTime <= kMaxTimestamp); + PackTime(dNewTime); } + void SetChannel(uint16_t channel) { PackChannelAndCharge(channel, UnpackCharge()); } + + void SetCharge(uint16_t charge) { PackChannelAndCharge(UnpackChannel(), charge); } + + void SetAddress(int32_t address) { PackAddressAndTime(address, UnpackTime()); } + + + /** Set new channel and charge. + ** + ** Slightly more efficient than calling both individual setters. + **/ + void SetChannelAndCharge(uint16_t channel, uint16_t charge) { PackChannelAndCharge(channel, charge); } + + /** Set new address and time at once. + ** + ** Slightly more efficient than calling both individual setters. + **/ + void SetAddressAndTime(int32_t address, uint32_t time) { PackAddressAndTime(address, time); } + /** String output **/ std::string ToString() const; @@ -128,14 +145,37 @@ public: private: friend class boost::serialization::access; - int64_t fTime = 0.; ///< Time [ns] - int32_t fAddress = 0; ///< Unique element address - uint16_t fChannel = 0; ///< Channel number - uint16_t fCharge = 0; ///< Charge [ADC units] + static constexpr int kNumAdcBits = 5; + static constexpr uint32_t kAdcMask = (1u << kNumAdcBits) - 1u; + static constexpr int kNumLowerAddrBits = 16; + static constexpr int kNumTimestampBits = 31; + static constexpr uint32_t kTimestampMask = (1u << kNumTimestampBits) - 1u; + static constexpr uint32_t kMaxTimestamp = kTimestampMask; + static constexpr uint32_t kTimeAddressBitMask = ~kTimestampMask; + + uint32_t fTime = 0; ///< Time [ns] in lower 31 bits, highest bit is the 17th address bit. + uint16_t fChannelAndCharge = 0; ///< Channel number (lower 11 bits) and charge [ADC Units] in upper 5 bits. + uint16_t fAddress = 0; ///< Unique element address (lower 16 bits of 17) + + + void PackTime(uint32_t newTime) { fTime = (fTime & kTimeAddressBitMask) | (newTime & kTimestampMask); } + uint32_t UnpackTime() const { return fTime & kTimestampMask; } + + + void PackChannelAndCharge(uint16_t channel, uint16_t charge) + { + fChannelAndCharge = (channel << kNumAdcBits) | charge; + } + uint16_t UnpackChannel() const { return fChannelAndCharge >> kNumAdcBits; } + uint16_t UnpackCharge() const { return fChannelAndCharge & kAdcMask; } + + + void PackAddressAndTime(int32_t address, uint32_t time); + int32_t UnpackAddress() const; #ifndef NO_ROOT - ClassDefNV(CbmStsDigi, 7); + ClassDefNV(CbmStsDigi, 8); #endif }; diff --git a/core/data/test/sts/_GTestCbmStsDigi.cxx b/core/data/test/sts/_GTestCbmStsDigi.cxx index e906ba158da78d74d0005b09170fabd7f8023af7..5912fd2928b13954e0d32c5c84310a824ef4d669 100644 --- a/core/data/test/sts/_GTestCbmStsDigi.cxx +++ b/core/data/test/sts/_GTestCbmStsDigi.cxx @@ -2,61 +2,66 @@ SPDX-License-Identifier: GPL-3.0-only Authors: Florian Uhlig [committer] */ +#include "CbmStsAddress.h" #include "CbmStsDigi.h" #include "compareStsDigi.h" #include "gtest/gtest-spi.h" #include "gtest/gtest.h" +static const Int_t kTestAddress = CbmStsAddress::GetAddress(5, 6, 1, 8, 0, 0, 1); + TEST(_GTestCbmStsDigi, CheckDefaultConstructor) { // Create object CbmStsDigi test; - compareStsDigiDataMembers(test, 0, 0, 0, ECbmModuleId::kSts, 0); + const Int_t defaultAddr = CbmStsAddress::GetAddress(0, 0, 0, 0, 0, 0, 1); + + compareStsDigiDataMembers(test, defaultAddr, 0, 0, ECbmModuleId::kSts, 0); CbmStsDigi* test1 = new CbmStsDigi(); - compareStsDigiDataMembers(*test1, 0, 0, 0, ECbmModuleId::kSts, 0); + compareStsDigiDataMembers(*test1, defaultAddr, 0, 0, ECbmModuleId::kSts, 0); } TEST(_GTestCbmStsDigi, CheckStandardConstructor) { // Create object - CbmStsDigi test(111, 42, 987654321, 23); + CbmStsDigi test(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); - CbmStsDigi* test1 = new CbmStsDigi(111, 42, 897654321, 23); + CbmStsDigi* test1 = new CbmStsDigi(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(*test1, 111, 23, 42, ECbmModuleId::kSts, 897654321); + compareStsDigiDataMembers(*test1, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); } TEST(_GTestCbmStsDigi, CheckCopyConstructor) { // Create object - CbmStsDigi test(111, 42, 987654321, 23); + CbmStsDigi test(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); // Create object by copy constructing // test should be equal to test2 and // test should not be changed CbmStsDigi test2 {test}; - compareStsDigiDataMembers(test2, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test2, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); // Test if the original object wasn't changed - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); } TEST(_GTestCbmStsDigi, CheckAssignmentOperator) { // Create object - CbmStsDigi test(111, 42, 987654321, 23); + CbmStsDigi test(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); // Create object by copy assignment // test should be equal to test2 and @@ -64,73 +69,77 @@ TEST(_GTestCbmStsDigi, CheckAssignmentOperator) CbmStsDigi test2; test2 = test; - compareStsDigiDataMembers(test2, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test2, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); // Test if the original object wasn't changed - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); } TEST(_GTestCbmStsDigi, CheckMoveConstructor) { // Create object - CbmStsDigi test(111, 42, 987654321, 23); + CbmStsDigi test(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); // Create object by move constructing CbmStsDigi test2 {std::move(test)}; - compareStsDigiDataMembers(test2, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test2, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); // For objects with simple types move fall back to copy so // the original object is kept unchanged - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); } TEST(_GTestCbmStsDigi, CheckAssignmentMoveConstructor) { // Create object - CbmStsDigi test(111, 42, 987654321, 23); + CbmStsDigi test(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); // Create object by move constructing CbmStsDigi test2 {}; test2 = std::move(test); - compareStsDigiDataMembers(test2, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test2, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); // For objects with simple types move fall back to copy so // the original object is kept unchanged - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); } TEST(_GTestCbmStsDigi, CheckSetTime) { // Create object - CbmStsDigi test(111, 42, 987654321, 23); + CbmStsDigi test(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); test.SetTime(897654321.0); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 897654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 897654321); } TEST(_GTestCbmStsDigi, CheckToString) { - CbmStsDigi test(111, 42, 987654321, 23); + CbmStsDigi test(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); - EXPECT_STREQ("StsDigi: address 111 | channel 42 | charge 23 | time 987654321", test.ToString().c_str()); + std::string expected = + "StsDigi: address " + std::to_string(kTestAddress) + " | channel 42 | charge 23 | time 987654321"; + + EXPECT_STREQ(expected.c_str(), test.ToString().c_str()); } + TEST(_GTestCbmStsDigi, CheckGetClassName) { - CbmStsDigi test(111, 42, 987654321, 23); + CbmStsDigi test(kTestAddress, 42, 987654321, 23); - compareStsDigiDataMembers(test, 111, 23, 42, ECbmModuleId::kSts, 987654321); + compareStsDigiDataMembers(test, kTestAddress, 23, 42, ECbmModuleId::kSts, 987654321); EXPECT_STREQ("CbmStsDigi", test.GetClassName()); }