Skip to content

Commit dd95d89

Browse files
aphecetchektf
authored andcommitted
✨ [MRRTF-99] Add support for MCH UserLogic Raw Data Format V1
1 parent 4c74266 commit dd95d89

17 files changed

Lines changed: 327 additions & 200 deletions

Detectors/MUON/MCH/Raw/Common/include/MCHRawCommon/DataFormats.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,54 @@ using uint10_t = uint16_t;
3434
using uint20_t = uint32_t;
3535
using uint50_t = uint64_t;
3636

37+
// Format of 64 bits-words of the UserLogicFormat
38+
template <int VERSION>
39+
struct ULHeaderWord;
40+
41+
// initial UL format (2020)
42+
template <>
43+
struct ULHeaderWord<0> {
44+
union {
45+
uint64_t word;
46+
struct {
47+
uint64_t data : 50;
48+
uint64_t error : 2;
49+
uint64_t incomplete : 1;
50+
uint64_t dsID : 6;
51+
uint64_t linkID : 5;
52+
};
53+
};
54+
};
55+
56+
// version 1 of UL format (2021)
57+
// = as initial version with 1 bit less for linkID and 1 bit more for error
58+
template <>
59+
struct ULHeaderWord<1> {
60+
union {
61+
uint64_t word;
62+
struct {
63+
uint64_t data : 50;
64+
uint64_t error : 3;
65+
uint64_t incomplete : 1;
66+
uint64_t dsID : 6;
67+
uint64_t linkID : 4;
68+
};
69+
};
70+
};
71+
72+
// structure of the FEEID field (16 bits) in the MCH Raw Data RDH
73+
struct FEEID {
74+
union {
75+
uint16_t word;
76+
struct {
77+
uint16_t id : 8;
78+
uint16_t chargeSum : 1;
79+
uint16_t reserved : 3;
80+
uint16_t ulFormatVersion : 4;
81+
};
82+
};
83+
};
84+
3785
}; // namespace o2::mch::raw
3886

3987
#endif

Detectors/MUON/MCH/Raw/Decoder/README.md

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,16 @@ called a (CRU) page. How the loop on the raw pages is done is *not* the decoder
1616

1717
## createPageDecoder
1818

19-
On the reading/consumer/decoding end, the choice of the internal decoder to use is made
20-
using the data itself. You must give (at least) a part of a raw data buffer that contains
21-
a (valid) RawDataHeader. That RDH is used to deduce which implementation is picked.
19+
On the reading/consumer/decoding end, the choice of the internal decoder to use
20+
is made using the data itself. You must give (at least) a part of a raw data
21+
buffer that contains a (valid) RawDataHeader. That RDH is used to deduce which
22+
implementation is picked.
2223

2324
gsl::span<const std::byte> rawbuffer = ... ;
2425
auto pageDecoder = o2::mch::raw::createPageDecoder(rawbuffer,channelHandler);
2526

2627
The `pageDecoder` that is returned is a function that you have to call on each
27-
data page that you want to decode :
28+
data page that you want to decode :
2829

2930
while(some_data_is_available) {
3031
// get some memory buffer from somewhere ...
@@ -34,20 +35,22 @@ data page that you want to decode :
3435
pageDecode(buffer);
3536
}
3637

37-
Internally the implementation is using templatized implementation, `PageDecoderImpl<FORMAT,CHARGESUM>`.
38-
Currently the following template parameters combinations have been tested :
38+
Internally the implementation is using templatized implementation, `PageDecoderImpl<FORMAT,CHARGESUM,VERSION>`.
39+
Currently the following template parameters combinations have been tested :
3940

40-
| FORMAT | CHARGESUM |
41-
| :-------------: | :-----------: |
42-
| BareFormat | ChargeSumMode |
43-
| BareFormat | SampleMode |
44-
| UserLogicFormat | ChargeSumMode |
45-
| UserLogicFormat | SampleMode |
41+
| FORMAT | CHARGESUM | VERSION |
42+
| :-------------: | :-----------: | :-----: |
43+
| BareFormat | ChargeSumMode | 0 |
44+
| BareFormat | SampleMode | 0 |
45+
| UserLogicFormat | ChargeSumMode | 0 |
46+
| UserLogicFormat | SampleMode | 0 |
47+
| UserLogicFormat | ChargeSumMode | 1 |
48+
| UserLogicFormat | SampleMode | 1 |
4649

47-
The `createPageDecoder` function requires two parameters : a raw memory buffer
48-
(in the form of a `gsl::span<const std::byte>` (note that the span is on constant bytes,
49-
i.e. the input buffer is read-only)
50-
and a `SampaChannelHandler`.
50+
The `createPageDecoder` function requires two parameters : a raw memory buffer
51+
(in the form of a `gsl::span<const std::byte>` (note that the span is on
52+
constant bytes, i.e. the input buffer is read-only) and a
53+
`SampaChannelHandler`.
5154

5255
## SampaChannelHandler
5356

@@ -57,7 +60,7 @@ identifier within that dual sampa, a `SampaCluster` and returns nothing, i.e. :
5760

5861
> A word of caution here about the naming. A `SampaCluster` is a group of raw
5962
> data samples of *one* dual sampa channel, and has nothing to do with a
60-
> cluster of pads or something alike.
63+
> cluster of pads or something alike.
6164
6265
```.cpp
6366
using SampaChannelHandler = std::function<void(DsElecId dsId,
@@ -67,7 +70,7 @@ using SampaChannelHandler = std::function<void(DsElecId dsId,
6770

6871
That function is called by the raw data decoder for each `SampaCluster` that it
6972
finds in the data.
70-
A very simple example would be a function to dump the SampaClusters :
73+
A very simple example would be a function to dump the SampaClusters :
7174

7275
```.cpp
7376
SampaChannelHandler handlePacket(DsElecId dsId, uint8_t channel, SampaCluster sc) {
@@ -78,5 +81,5 @@ SampaChannelHandler handlePacket(DsElecId dsId, uint8_t channel, SampaCluster sc
7881
7982
## Example of decoding raw data
8083
81-
A (not particularly clean) example of how to decode raw data can be found in the source of the `o2-mchraw-dump`
82-
executable [rawdump](../Tools/rawdump.cxx)
84+
A (not particularly clean) example of how to decode raw data can be found in
85+
the source of the `o2-mchraw-dump` executable [rawdump](../Tools/rawdump.cxx)

Detectors/MUON/MCH/Raw/Decoder/src/DataDecoder.cxx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,13 @@ static void patchPage(gsl::span<const std::byte> rdhBuffer, bool verbose)
7474
auto cruId = o2::raw::RDHUtils::getCRUID(rdhAny) & 0xFF;
7575
auto flags = o2::raw::RDHUtils::getCRUID(rdhAny) & 0xFF00;
7676
auto endpoint = o2::raw::RDHUtils::getEndPointID(rdhAny);
77-
uint32_t feeId = cruId * 2 + endpoint + flags;
78-
o2::raw::RDHUtils::setFEEID(rdhAny, feeId);
77+
auto existingFeeId = o2::raw::RDHUtils::getFEEID(rdhAny);
78+
if (existingFeeId == 0) {
79+
// early versions of raw data did not set the feeId
80+
// which we need to select the right decoder
81+
uint32_t feeId = cruId * 2 + endpoint + flags;
82+
o2::raw::RDHUtils::setFEEID(rdhAny, feeId);
83+
}
7984

8085
if (verbose) {
8186
std::cout << mNrdhs << "--\n";

Detectors/MUON/MCH/Raw/Decoder/src/PageDecoder.cxx

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ namespace o2::mch::raw
2020
{
2121
namespace impl
2222
{
23-
uint16_t CRUID_MASK = 0xFF;
24-
uint16_t CHARGESUM_MASK = 0x100;
2523

26-
template <typename FORMAT, typename CHARGESUM>
24+
template <typename FORMAT, typename CHARGESUM, int VERSION = 0>
2725
struct PayloadDecoderImpl {
2826

2927
using type = struct PayloadDecoderImplReturnType {
@@ -33,18 +31,18 @@ struct PayloadDecoderImpl {
3331
type operator()(const FeeLinkId& feeLinkId, DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar);
3432
};
3533

36-
template <typename CHARGESUM>
37-
struct PayloadDecoderImpl<UserLogicFormat, CHARGESUM> {
38-
using type = UserLogicEndpointDecoder<CHARGESUM>;
34+
template <typename CHARGESUM, int VERSION>
35+
struct PayloadDecoderImpl<UserLogicFormat, CHARGESUM, VERSION> {
36+
using type = UserLogicEndpointDecoder<CHARGESUM, VERSION>;
3937

4038
type operator()(const FeeLinkId& feeLinkId, DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar)
4139
{
42-
return std::move(UserLogicEndpointDecoder<CHARGESUM>(feeLinkId.feeId(), fee2solar, decodedDataHandlers));
40+
return std::move(UserLogicEndpointDecoder<CHARGESUM, VERSION>(feeLinkId.feeId(), fee2solar, decodedDataHandlers));
4341
}
4442
};
4543

4644
template <typename CHARGESUM>
47-
struct PayloadDecoderImpl<BareFormat, CHARGESUM> {
45+
struct PayloadDecoderImpl<BareFormat, CHARGESUM, 0> {
4846
using type = BareGBTDecoder<CHARGESUM>;
4947

5048
type operator()(const FeeLinkId& feeLinkId, DecodedDataHandlers decodedDataHandlers, FeeLink2SolarMapper fee2solar)
@@ -57,7 +55,7 @@ struct PayloadDecoderImpl<BareFormat, CHARGESUM> {
5755
}
5856
};
5957

60-
template <typename FORMAT, typename CHARGESUM>
58+
template <typename FORMAT, typename CHARGESUM, int VERSION = 0>
6159
class PageDecoderImpl
6260
{
6361
public:
@@ -75,11 +73,12 @@ class PageDecoderImpl
7573

7674
auto feeId = o2::raw::RDHUtils::getFEEID(rdhP);
7775
auto linkId = o2::raw::RDHUtils::getLinkID(rdhP);
78-
FeeLinkId feeLinkId(feeId & CRUID_MASK, linkId);
76+
FEEID f{feeId};
77+
FeeLinkId feeLinkId(f.id, linkId);
7978

8079
auto p = mPayloadDecoders.find(feeLinkId);
8180
if (p == mPayloadDecoders.end()) {
82-
mPayloadDecoders.emplace(feeLinkId, PayloadDecoderImpl<FORMAT, CHARGESUM>()(feeLinkId, mDecodedDataHandlers, mFee2SolarMapper));
81+
mPayloadDecoders.emplace(feeLinkId, PayloadDecoderImpl<FORMAT, CHARGESUM, VERSION>()(feeLinkId, mDecodedDataHandlers, mFee2SolarMapper));
8382
p = mPayloadDecoders.find(feeLinkId);
8483
}
8584

@@ -95,7 +94,7 @@ class PageDecoderImpl
9594
private:
9695
DecodedDataHandlers mDecodedDataHandlers;
9796
FeeLink2SolarMapper mFee2SolarMapper;
98-
std::map<FeeLinkId, typename PayloadDecoderImpl<FORMAT, CHARGESUM>::type> mPayloadDecoders;
97+
std::map<FeeLinkId, typename PayloadDecoderImpl<FORMAT, CHARGESUM, VERSION>::type> mPayloadDecoders;
9998
};
10099

101100
} // namespace impl
@@ -109,19 +108,32 @@ PageDecoder createPageDecoder(RawBuffer rdhBuffer, DecodedDataHandlers decodedDa
109108
}
110109
auto linkId = o2::raw::RDHUtils::getLinkID(rdhP);
111110
auto feeId = o2::raw::RDHUtils::getFEEID(rdhP);
111+
FEEID f{feeId};
112112
if (linkId == 15) {
113-
if (feeId & impl::CHARGESUM_MASK) {
114-
return impl::PageDecoderImpl<UserLogicFormat, ChargeSumMode>(decodedDataHandlers, fee2solar);
113+
if (f.ulFormatVersion != 0 && f.ulFormatVersion != 1) {
114+
throw std::logic_error(fmt::format("ulFormatVersion {} is unknown", static_cast<int>(f.ulFormatVersion)));
115+
}
116+
if (f.chargeSum) {
117+
if (f.ulFormatVersion == 0) {
118+
return impl::PageDecoderImpl<UserLogicFormat, ChargeSumMode, 0>(decodedDataHandlers, fee2solar);
119+
} else if (f.ulFormatVersion == 1) {
120+
return impl::PageDecoderImpl<UserLogicFormat, ChargeSumMode, 1>(decodedDataHandlers, fee2solar);
121+
}
115122
} else {
116-
return impl::PageDecoderImpl<UserLogicFormat, SampleMode>(decodedDataHandlers, fee2solar);
123+
if (f.ulFormatVersion == 0) {
124+
return impl::PageDecoderImpl<UserLogicFormat, SampleMode, 0>(decodedDataHandlers, fee2solar);
125+
} else if (f.ulFormatVersion == 1) {
126+
return impl::PageDecoderImpl<UserLogicFormat, SampleMode, 1>(decodedDataHandlers, fee2solar);
127+
}
117128
}
118129
} else {
119-
if (feeId & impl::CHARGESUM_MASK) {
130+
if (f.chargeSum) {
120131
return impl::PageDecoderImpl<BareFormat, ChargeSumMode>(decodedDataHandlers, fee2solar);
121132
} else {
122133
return impl::PageDecoderImpl<BareFormat, SampleMode>(decodedDataHandlers, fee2solar);
123134
}
124135
}
136+
return nullptr;
125137
}
126138

127139
PageDecoder createPageDecoder(RawBuffer rdhBuffer, DecodedDataHandlers decodedDataHandlers)

Detectors/MUON/MCH/Raw/Decoder/src/UserLogicElinkDecoder.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class UserLogicElinkDecoder
3636
UserLogicElinkDecoder(DsElecId dsId, DecodedDataHandlers decodedDataHandlers);
3737

3838
/// Append 50 bits-worth of data
39-
void append(uint64_t data50, uint8_t error);
39+
void append(uint64_t data50, uint8_t error, bool incomplete);
4040

4141
/// Reset our internal state
4242
/// i.e. assume the sync has to be found again
@@ -99,11 +99,6 @@ constexpr bool isSync(uint64_t data)
9999
return data == sampaSyncWord;
100100
};
101101

102-
constexpr bool isIncomplete(uint8_t error)
103-
{
104-
return (error & 0x4) > 0;
105-
}
106-
107102
template <typename CHARGESUM>
108103
UserLogicElinkDecoder<CHARGESUM>::UserLogicElinkDecoder(DsElecId dsId,
109104
DecodedDataHandlers decodedDataHandlers)
@@ -112,10 +107,10 @@ UserLogicElinkDecoder<CHARGESUM>::UserLogicElinkDecoder(DsElecId dsId,
112107
}
113108

114109
template <typename CHARGESUM>
115-
void UserLogicElinkDecoder<CHARGESUM>::append(uint64_t data50, uint8_t error)
110+
void UserLogicElinkDecoder<CHARGESUM>::append(uint64_t data50, uint8_t error, bool incomplete)
116111
{
117112
#ifdef ULDEBUG
118-
debugHeader() << (*this) << fmt::format(" --> append50 {:013x} error {} incomplete {} data10={:d} {:d} {:d} {:d} {:d}\n", data50, error, (int)isIncomplete(error), static_cast<uint10_t>(data50 & 0x3FF), static_cast<uint10_t>((data50 & 0xFFC00) >> 10), static_cast<uint10_t>((data50 & 0x3FF00000) >> 20), static_cast<uint10_t>((data50 & 0xFFC0000000) >> 30), static_cast<uint10_t>((data50 & 0x3FF0000000000) >> 40));
113+
debugHeader() << (*this) << fmt::format(" --> append50 {:013x} error {} incomplete {} data10={:d} {:d} {:d} {:d} {:d}\n", data50, error, incomplete, static_cast<uint10_t>(data50 & 0x3FF), static_cast<uint10_t>((data50 & 0xFFC00) >> 10), static_cast<uint10_t>((data50 & 0x3FF00000) >> 20), static_cast<uint10_t>((data50 & 0xFFC0000000) >> 30), static_cast<uint10_t>((data50 & 0x3FF0000000000) >> 40));
119114
#endif
120115

121116
if (isSync(data50)) {
@@ -134,8 +129,8 @@ void UserLogicElinkDecoder<CHARGESUM>::append(uint64_t data50, uint8_t error)
134129
bool packetEnd = append10(static_cast<uint10_t>(data & 0x3FF));
135130
data >>= 10;
136131
#ifdef ULDEBUG
137-
if (isIncomplete(error)) {
138-
debugHeader() << (*this) << fmt::format(" --> incomplete {} packetEnd @i={}\n", (int)isIncomplete(error), packetEnd, i);
132+
if (incomplete) {
133+
debugHeader() << (*this) << fmt::format(" --> incomplete {} packetEnd @i={}\n", incomplete, packetEnd, i);
139134
}
140135
#endif
141136
if (hasError()) {
@@ -145,15 +140,15 @@ void UserLogicElinkDecoder<CHARGESUM>::append(uint64_t data50, uint8_t error)
145140
reset();
146141
break;
147142
}
148-
if (isIncomplete(error) && packetEnd) {
143+
if (incomplete && packetEnd) {
149144
#ifdef ULDEBUG
150145
debugHeader() << (*this) << " stop due to isIncomplete\n";
151146
#endif
152147
break;
153148
}
154149
}
155150

156-
if (isIncomplete(error) && (i == 5) && (mState != State::WaitingSync)) {
151+
if (incomplete && (i == 5) && (mState != State::WaitingSync)) {
157152
#ifdef ULDEBUG
158153
debugHeader() << (*this) << " data packet end not found when isIncomplete --> resetting\n";
159154
#endif

0 commit comments

Comments
 (0)