Skip to content

Commit d938894

Browse files
committed
Introduce RDHv7 and related changes for rec/sim
For the discussion of RDHv7 see https://alice.its.cern.ch/jira/browse/O2-3525
1 parent bc3724b commit d938894

File tree

13 files changed

+270
-56
lines changed

13 files changed

+270
-56
lines changed

DataFormats/Headers/include/Headers/RAWDataHeader.h

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,102 @@ namespace header
4242
/// assume that this is the only type the software has to support (based on
4343
/// experience with previous systems)
4444
///
45+
/// RAWDataHeaderV7
46+
/// V7 introduces a detector source ID field
47+
/// Description of the fields can be found here
48+
/// https://gitlab.cern.ch/AliceO2Group/wp6-doc/-/blob/master/rdh/RDHv7.md
49+
//
50+
///
51+
/// 63 56 48 40 32 24 16 8 0
52+
/// |---------------|---------------|---------------|---------------|
53+
///
54+
/// | reserved | priori| | header |
55+
/// 0 | reserve zero |Source | ty bit| FEE id | size |version|
56+
///
57+
/// 1 |ep | cru id |pcount|link id | memory size |offset nxt pack|
58+
///
59+
/// 2 | orbit | reserved |bunch cross |
60+
/// | data
61+
/// 3 | reserved | format|
62+
///
63+
/// 4 | zero | stop | page count | trigger type |
64+
///
65+
/// 5 | reserved |
66+
///
67+
/// 6 | zero | detector par | detector field |
68+
///
69+
/// 5 | reserved |
70+
///
71+
struct RAWDataHeaderV7 {
72+
union {
73+
// default value
74+
uint64_t word0 = 0x00000000ffff4007;
75+
// | | | version 67
76+
// | | | 8x64 bit words = 64 (0x40) byte
77+
// | | invalid FEE id
78+
// | priority bit 0
79+
struct {
80+
uint64_t version : 8; /// bit 0 to 7: header version
81+
uint64_t headerSize : 8; /// bit 8 to 15: header size
82+
uint64_t feeId : 16; /// bit 16 to 31: FEE identifier
83+
uint64_t priority : 8; /// bit 32 to 39: priority bit
84+
uint64_t sourceID : 8; /// bit 40 to 47: source ID
85+
uint64_t zero0 : 16; /// bit 48 to 63: zeroed
86+
}; ///
87+
}; ///
88+
union { ///
89+
uint64_t word1 = 0x0; /// data written by the CRU
90+
struct { ///
91+
uint32_t offsetToNext : 16; /// bit 64 to 79: offset to next packet in memory
92+
uint32_t memorySize : 16; /// bit 80 to 95: memory size
93+
uint32_t linkID : 8; /// bit 96 to 103: link id
94+
uint32_t packetCounter : 8; /// bit 104 to 111: packet counter
95+
uint16_t cruID : 12; /// bit 112 to 123: CRU ID
96+
uint32_t endPointID : 4; /// bit 124 to 127: DATAPATH WRAPPER ID: number used to
97+
}; /// identify one of the 2 End Points [0/1]
98+
}; ///
99+
union { ///
100+
uint64_t word2 = 0x0; ///
101+
struct { ///
102+
uint32_t bunchCrossing : 12; /// bit 0 to 11: bunch crossing counter
103+
uint32_t reserved2 : 20; /// bit 12 to 31: reserved
104+
uint32_t orbit; /// bit 32 to 63: orbit
105+
}; ///
106+
}; ///
107+
union { ///
108+
uint64_t word3 = 0x0; ///
109+
struct { ///
110+
uint32_t dataFormat : 8; /// bit 0 to 7: data format: 0: padded (48 bit of padding + 80 bit of data)
111+
/// 1: no padding, TOF LIKE (word#1 64 bit + word#0 64 bit = 128 bit)
112+
/// 2: no padding, ITS/MFT like (appending words of 80 bit to build 128 bit)
113+
uint64_t zero3 : 56; /// bit 8 to 63 zeroed
114+
}; ///
115+
}; ///
116+
union { ///
117+
uint64_t word4 = 0x0; ///
118+
struct { ///
119+
uint64_t triggerType : 32; /// bit 0 to 31: trigger type
120+
uint64_t pageCnt : 16; /// bit 32 to 47: pages counter
121+
uint64_t stop : 8; /// bit 48 to 53: stop code
122+
uint64_t zero4 : 8; /// bit 54 to 63: zeroed
123+
}; ///
124+
}; ///
125+
union { ///
126+
uint64_t word5 = 0x0; /// bit 0 to 63: zeroed
127+
}; ///
128+
union { ///
129+
uint64_t word6 = 0x0; ///
130+
struct { ///
131+
uint64_t detectorField : 32; /// bit 0 to 31: detector field
132+
uint64_t detectorPAR : 16; /// bit 32 to 47: detector PAR (Pause and Reset)
133+
uint64_t zero6 : 16; /// bit 48 to 63: zeroed
134+
}; ///
135+
}; ///
136+
union { ///
137+
uint64_t word7 = 0x0; /// bit 0 to 63: zeroed
138+
};
139+
};
140+
45141
/// RAWDataHeaderV6
46142
/// V6 introduces a detector source ID field
47143
/// Description of the fields can be found here
@@ -66,7 +162,7 @@ namespace header
66162
///
67163
/// 6 | zero | detector par | detector field |
68164
///
69-
/// 5 | reserved |
165+
/// 7 | reserved |
70166
struct RAWDataHeaderV6 {
71167
union {
72168
// default value
@@ -159,7 +255,7 @@ struct RAWDataHeaderV6 {
159255
///
160256
/// 6 | zero | detector par | detector field |
161257
///
162-
/// 5 | reserved |
258+
/// 7 | reserved |
163259
struct RAWDataHeaderV5 {
164260
union {
165261
// default value
@@ -254,7 +350,7 @@ struct RAWDataHeaderV5 {
254350
///
255351
/// 6 |res| page count | stop | detector par |detector field |
256352
///
257-
/// 5 | reserved |
353+
/// 7 | reserved |
258354
///
259355
/// Field 1,3,5,7 are reserved fields and added to extend each word to 128 bit, marked
260356
/// grey in the documentation to indicate that those fields are added by the CRU
@@ -427,7 +523,7 @@ struct RAWDataHeaderV2 {
427523

428524
using RAWDataHeader = RAWDataHeaderV6; // default version
429525
using RDHLowest = RAWDataHeaderV4; // link this to lowest version
430-
using RDHHighest = RAWDataHeaderV6; // link this to highest version
526+
using RDHHighest = RAWDataHeaderV7; // link this to highest version
431527

432528
} // namespace header
433529
} // namespace o2

DataFormats/Headers/include/Headers/RDHAny.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,16 @@ struct RDHAny {
4747
//------------------ service methods
4848
using RDHv4 = o2::header::RAWDataHeaderV4; // V3 == V4
4949
using RDHv5 = o2::header::RAWDataHeaderV5;
50-
using RDHv6 = o2::header::RAWDataHeaderV6; // update this for every new version
50+
using RDHv6 = o2::header::RAWDataHeaderV6;
51+
using RDHv7 = o2::header::RAWDataHeaderV7; // update this for every new version
5152

5253
/// make sure we RDH is a legitimate RAWDataHeader
5354
template <typename RDH>
5455
GPUhdi() static constexpr void sanityCheckStrict()
5556
{
5657
#ifndef GPUCA_GPUCODE_DEVICE
5758
static_assert(std::is_same<RDH, RDHv4>::value || std::is_same<RDH, RDHv5>::value ||
58-
std::is_same<RDH, RDHv6>::value,
59+
std::is_same<RDH, RDHv6>::value || std::is_same<RDH, RDHv7>::value,
5960
"not an RDH");
6061
#endif
6162
}
@@ -66,7 +67,7 @@ struct RDHAny {
6667
{
6768
#ifndef GPUCA_GPUCODE_DEVICE
6869
static_assert(std::is_same<RDH, RDHv4>::value || std::is_same<RDH, RDHv5>::value ||
69-
std::is_same<RDH, RDHv6>::value || std::is_same<RDHAny, RDH>::value,
70+
std::is_same<RDH, RDHv6>::value || std::is_same<RDH, RDHv7>::value || std::is_same<RDHAny, RDH>::value,
7071
"not an RDH or RDHAny");
7172
#endif
7273
}

Detectors/CPV/simulation/src/RawWriter.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ void RawWriter::digitsToRaw(gsl::span<o2::cpv::Digit> digitsbranch, gsl::span<o2
125125
// prepare preformatted data for one orbit and send it to RawFileWriter
126126
bool RawWriter::processOrbit(const gsl::span<o2::cpv::Digit> digitsbranch, const gsl::span<o2::cpv::TriggerRecord> trgs)
127127
{
128-
static int nMaxGbtWordsPerPage = o2::raw::RDHUtils::MAXCRUPage / o2::raw::RDHUtils::GBTWord - 4; // 512*16/16 - 4 = 508;
129-
// 4 gbt words are reserved for RDH
128+
static int nMaxGbtWordsPerPage = o2::raw::RDHUtils::MAXCRUPage / o2::raw::RDHUtils::GBTWord128 - 4; // 512*16/16 - 4 = 508;
129+
// 4 gbt words are reserved for RDH
130130

131131
// clear payloads of all links
132132
for (auto& payload : mPayload) {

Detectors/CTP/simulation/src/Digits2Raw.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ std::vector<char> Digits2Raw::digits2HBTPayload(const gsl::span<gbtword80_t> dig
190190
toAdd.push_back(c);
191191
}
192192
// Pad zeros up to 128 bits
193-
uint32_t NZeros = (o2::raw::RDHUtils::GBTWord * 8 - NGBT) / 8;
193+
uint32_t NZeros = (o2::raw::RDHUtils::GBTWord128 * 8 - NGBT) / 8;
194194
for (uint32_t i = 0; i < NZeros; i++) {
195195
char c = 0;
196196
toAdd.push_back(c);
@@ -213,7 +213,7 @@ std::vector<char> Digits2Raw::digits2HBTPayload(const gsl::span<gbtword80_t> dig
213213
toAdd.push_back(c);
214214
}
215215
// Pad zeros up to 128 bits
216-
uint32_t NZeros = (o2::raw::RDHUtils::GBTWord * 8 - NGBT) / 8;
216+
uint32_t NZeros = (o2::raw::RDHUtils::GBTWord128 * 8 - NGBT) / 8;
217217
for (uint32_t i = 0; i < NZeros; i++) {
218218
char c = 0;
219219
toAdd.push_back(c);

Detectors/MUON/MID/Raw/src/Encoder.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void Encoder::completeWord(std::vector<char>& buffer)
101101
{
102102
/// Completes the buffer with zeros to reach the expected CRU word size
103103
size_t dataSize = buffer.size();
104-
size_t cruWord = 2 * o2::raw::RDHUtils::GBTWord;
104+
size_t cruWord = 2 * o2::raw::RDHUtils::GBTWord128;
105105
size_t modulo = dataSize % cruWord;
106106
if (modulo) {
107107
dataSize += cruWord - modulo;

Detectors/Raw/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ the SOX in the RDH will be set only if this TF coincides with the 1st TF of the
201201
With HBFUtils.obligatorySOR==true old behaviour will be preserved: the raw data will start from TF with HBFUtils.orbitFirst with SOX always set and for CRU detectors all HBFs/TFs between HBFUtils.orbitFirst and 1st non-empty HBF will be
202202
filled by dummy RDHs.
203203

204+
With the introduction of `RDHv7` some detectors write their payload w/o padding their GBT words to 16 bytes. Usually such detectors are required to align their CRU page size to certain size (see [discussion](https://alice.its.cern.ch/jira/browse/O2-3525)).
205+
To delegate this padding for alignment reason to the RawFileWriter one should use methods:
206+
207+
204208
## RawFileReader
205209

206210
A class for parsing raw data file(s) with "variable-size" CRU format.

Detectors/Raw/include/DetectorsRaw/RDHUtils.h

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ struct RDHUtils {
4646
using RDHAny = o2::header::RDHAny;
4747
using RDHv4 = o2::header::RAWDataHeaderV4; // V3 == V4
4848
using RDHv5 = o2::header::RAWDataHeaderV5;
49-
using RDHv6 = o2::header::RAWDataHeaderV6; // update this for every new version
49+
using RDHv6 = o2::header::RAWDataHeaderV6;
50+
using RDHv7 = o2::header::RAWDataHeaderV7; // update this for every new version
5051

51-
static constexpr int GBTWord = 16; // length of GBT word
52-
static constexpr int MAXCRUPage = 512 * GBTWord;
52+
static constexpr int GBTWord128 = 16; // length of GBT word
53+
static constexpr int MAXCRUPage = 512 * GBTWord128;
5354
/// get numeric version of the RDH
5455

5556
///_______________________________
@@ -58,6 +59,9 @@ struct RDHUtils {
5859
{
5960
#ifndef GPUCA_GPUCODE_DEVICE
6061
RDHAny::sanityCheckStrict<H>();
62+
if (std::is_same<H, RDHv7>::value) {
63+
return 7;
64+
}
6165
if (std::is_same<H, RDHv6>::value) {
6266
return 6;
6367
}
@@ -182,6 +186,7 @@ struct RDHUtils {
182186
processError(getVersion(rdh), "sourceID");
183187
return 0xff;
184188
}
189+
GPUhdi() static uint8_t getSourceID(const RDHv7& rdh) { return rdh.sourceID; }
185190
GPUhdi() static uint8_t getSourceID(const RDHv6& rdh) { return rdh.sourceID; }
186191
GPUhdi() static uint8_t getSourceID(const RDHAny& rdh) { return getSourceID(rdh.voidify()); }
187192
GPUhdi() static uint8_t getSourceID(const void* rdhP)
@@ -194,6 +199,7 @@ struct RDHUtils {
194199
return 0xff;
195200
}
196201
}
202+
static void setSourceID(RDHv7& rdh, uint8_t s) { rdh.sourceID = s; }
197203
static void setSourceID(RDHv6& rdh, uint8_t s) { rdh.sourceID = s; }
198204
static void setSourceID(RDHAny& rdh, uint8_t s) { setSourceID(rdh.voidify(), s); }
199205
static void setSourceID(void* rdhP, uint8_t s)
@@ -475,6 +481,27 @@ struct RDHUtils {
475481
}
476482
}
477483

484+
///_______________________________
485+
template <typename H>
486+
GPUhdi() static uint8_t getDataFormat(const H& rdh, NOTPTR(H))
487+
{ // does not exist before V7 (Jan. 2023), but <V7 headers are backward compatible to DataFormat=0 (padding)
488+
return 0xff;
489+
}
490+
GPUhdi() static uint8_t getDataFormat(const RDHv7& rdh) { return rdh.dataFormat; }
491+
GPUhdi() static uint8_t getDataFormat(const RDHAny& rdh) { return getDataFormat(rdh.voidify()); }
492+
GPUhdi() static uint8_t getDataFormat(const void* rdhP) { return (getVersion(rdhP) > 6) ? getDataFormat(TOCREF(RDHv7, rdhP)) : 0; }
493+
static void setDataFormat(RDHv7& rdh, uint8_t s) { rdh.dataFormat = s; }
494+
static void setDataFormat(RDHAny& rdh, uint8_t s) { setDataFormat(rdh.voidify(), s); }
495+
static void setDataFormat(void* rdhP, uint8_t s)
496+
{
497+
int version = getVersion(rdhP);
498+
if (version > 6) {
499+
setDataFormat(TOREF(RDHv7, rdhP), s);
500+
} else {
501+
processError(version, "dataFormat");
502+
}
503+
}
504+
478505
///_______________________________
479506
template <typename H>
480507
GPUhdi() static uint32_t getTriggerType(const H& rdh, NOTPTR(H))
@@ -633,6 +660,7 @@ struct RDHUtils {
633660
static void printRDH(const RDHv4& rdh);
634661
static void printRDH(const RDHv5& rdh);
635662
static void printRDH(const RDHv6& rdh);
663+
static void printRDH(const RDHv7& rdh);
636664
static void printRDH(const RDHAny& rdh) { printRDH(rdh.voidify()); }
637665
static void printRDH(const void* rdhP);
638666

@@ -648,6 +676,7 @@ struct RDHUtils {
648676
static bool checkRDH(const RDHv4& rdh, bool verbose = true);
649677
static bool checkRDH(const RDHv5& rdh, bool verbose = true);
650678
static bool checkRDH(const RDHv6& rdh, bool verbose = true);
679+
static bool checkRDH(const RDHv7& rdh, bool verbose = true);
651680
static bool checkRDH(const RDHAny rdh, bool verbose = true) { return checkRDH(rdh.voidify(), verbose); }
652681
static bool checkRDH(const void* rdhP, bool verbose = true);
653682

@@ -674,10 +703,9 @@ struct RDHUtils {
674703
{
675704
return getSubSpec(rdh.cruID, rdh.linkID, rdh.endPointID, rdh.feeId, o2::header::DAQID::INVALID);
676705
}
677-
GPUhdi() static LinkSubSpec_t getSubSpec(const RDHv6& rdh)
678-
{
679-
return getFEEID(rdh);
680-
} // starting from V6 use FEEID only
706+
707+
GPUhdi() static LinkSubSpec_t getSubSpec(const RDHv7& rdh) { return getFEEID(rdh); }
708+
GPUhdi() static LinkSubSpec_t getSubSpec(const RDHv6& rdh) { return getFEEID(rdh); }
681709
GPUhdi() static LinkSubSpec_t getSubSpec(const RDHAny& rdh) { return getSubSpec(rdh.voidify()); }
682710
GPUhdi() static LinkSubSpec_t getSubSpec(const void* rdhP)
683711
{

Detectors/Raw/include/DetectorsRaw/RawFileWriter.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,14 @@ class RawFileWriter
356356
mUseRDHVersion = v;
357357
}
358358

359+
unsigned char getUsedRDHDataFormat() const { return mUseRDHDataFormat; }
360+
unsigned char getAlignmentSize() const { return mAlignmentSize; }
361+
unsigned char getAlignmentPaddingFiller() const { return mAlignmentPaddingFiller; }
362+
363+
void useRDHDataFormat(unsigned char v) { mUseRDHDataFormat = v; }
364+
void setAlignmentSize(unsigned char v) { mAlignmentSize = v; }
365+
void setAlignmentPaddingFiller(unsigned char v) { mAlignmentPaddingFiller = v; }
366+
359367
bool getDontFillEmptyHBF() const { return mDontFillEmptyHBF; }
360368
void setDontFillEmptyHBF(bool v) { mDontFillEmptyHBF = v; }
361369

@@ -402,6 +410,9 @@ class RawFileWriter
402410
int mVerbosity = 0;
403411
o2::header::DataOrigin mOrigin = o2::header::gDataOriginInvalid;
404412
int mUseRDHVersion = RDHUtils::getVersion<o2::header::RAWDataHeader>(); // by default, use default version
413+
unsigned char mUseRDHDataFormat = 0; // by default use padding
414+
unsigned char mAlignmentSize = 0; // apply alignment to the CRU page size
415+
unsigned char mAlignmentPaddingFiller = 0xff; // using this filler
405416
int mSuperPageSize = 1024 * 1024; // super page size
406417
bool mStartTFOnNewSPage = true; // every TF must start on a new SPage
407418
bool mDontFillEmptyHBF = false; // skipp adding empty HBFs (uness it must have TF flag)

0 commit comments

Comments
 (0)