Skip to content

Commit 0ac4575

Browse files
committed
Updated CMV header and fixed payload size comparison
1 parent 9808d50 commit 0ac4575

File tree

3 files changed

+78
-47
lines changed

3 files changed

+78
-47
lines changed

DataFormats/Detectors/TPC/include/DataFormatsTPC/CMV.h

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
/// @author Tuba Gündem, tuba.gundem@cern.ch
1414
/// @brief Common mode values data format definition
1515

16-
/// The data is sent by the CRU as 96 bit words. The CMV data layout is as follows:
17-
/// - 80-bit Header: [version:8][packetID:8][errorCode:8][magicWord:8][heartbeatOrbit:32][heartbeatBC:16]
16+
/// The data is sent by the CRU as 256+16 bit words. The CMV data layout is as follows:
17+
/// - 256-bit Header: [version:8][packetID:8][errorCode:8][magicWord:8][heartbeatOrbit:32][heartbeatBC:16][padding:176]
1818
/// - 16-bit CMV value: [CMV:16]
1919

2020
#ifndef ALICEO2_DATAFORMATSTPC_CMV_H
@@ -25,56 +25,81 @@
2525
namespace o2::tpc::cmv
2626
{
2727

28-
static constexpr uint32_t NTimeBins = 3564; ///< number of time bins (spans 8 orbits)
29-
static constexpr uint32_t SignificantBits = 2; ///< number of bits used for floating point precision
30-
static constexpr float FloatConversion = 1.f / float(1 << SignificantBits); ///< conversion factor from integer representation to float
28+
static constexpr uint32_t NTimeBins = 3564; ///< number of time bins (spans 8 orbits)
29+
static constexpr uint32_t SignificantBits = 2; ///< number of bits used for floating point precision
30+
static constexpr float FloatConversion = 1.f / float(1 << SignificantBits); ///< conversion factor from integer representation to float
3131

3232
/// Header definition of the CMVs
3333
struct Header {
3434
static constexpr uint8_t MagicWord = 0xDC;
3535
union {
36-
uint32_t word0 = 0; ///< bits 0 - 31
36+
uint32_t word0 = 0; ///< bits 0 - 31
3737
struct {
38-
uint8_t version : 8; ///< version
39-
uint8_t packetID : 8; ///< packet id
40-
uint8_t errorCode : 8; ///< errors
41-
uint8_t magicWord : 8; ///< magic word
38+
uint8_t version : 8; ///< version
39+
uint8_t packetID : 8; ///< packet id
40+
uint8_t errorCode : 8; ///< errors
41+
uint8_t magicWord : 8; ///< magic word
4242
};
4343
};
4444
union {
45-
uint32_t word1 = 0; ///< bits 32 - 63
45+
uint32_t word1 = 0; ///< bits 32 - 63
4646
struct {
47-
uint32_t heartbeatOrbit : 32; ///< first heart beat timing of the package
47+
uint32_t heartbeatOrbit : 32; ///< first heart beat timing of the package
4848
};
4949
};
5050
union {
51-
uint16_t word2 = 0; ///< bits 64 - 79
51+
uint16_t word2 = 0; ///< bits 64 - 79
5252
struct {
53-
uint16_t heartbeatBC : 16; ///< first BC id of the package
53+
uint16_t heartbeatBC : 16; ///< first BC id of the package
54+
};
55+
};
56+
union {
57+
uint16_t word3 = 0; ///< bits 80 - 95
58+
struct {
59+
uint16_t unused1 : 16; ///< reserved
60+
};
61+
};
62+
union {
63+
uint32_t word4 = 0; ///< bits 96 - 127
64+
struct {
65+
uint32_t unused2 : 32; ///< reserved
66+
};
67+
};
68+
union {
69+
uint64_t word5 = 0; ///< bits 128 - 191
70+
struct {
71+
uint64_t unused3 : 64; ///< reserved
72+
};
73+
};
74+
union {
75+
uint64_t word6 = 0; ///< bits 192 - 255
76+
struct {
77+
uint64_t unused4 : 64; ///< reserved
5478
};
5579
};
5680
};
5781

5882
/// CMV single data container
5983
struct Data {
60-
uint16_t CMV{0}; ///< 16bit ADC value
61-
84+
uint16_t CMV{0}; ///< 16bit ADC value
85+
6286
// Raw integer accessors
6387
uint16_t getCMV() const { return CMV; }
6488
void setCMV(uint16_t value) { CMV = value; }
65-
89+
6690
// Float helpers using SignificantBits for fixed-point conversion
6791
float getCMVFloat() const { return static_cast<float>(CMV) * FloatConversion; }
68-
void setCMVFloat(float value) {
92+
void setCMVFloat(float value)
93+
{
6994
// round to nearest representable fixed-point value
7095
setCMV(uint32_t((value + 0.5f * FloatConversion) / FloatConversion));
7196
}
7297
};
7398

7499
/// CMV full data container: one packet carries NTimeBins time bins
75100
struct Container {
76-
Header header; ///< CMV data header
77-
Data data[NTimeBins]; ///< data values for given number of time bins
101+
Header header; ///< CMV data header
102+
Data data[NTimeBins]; ///< data values for given number of time bins
78103

79104
// Header and data accessors
80105
const Header& getHeader() const { return header; }
@@ -89,8 +114,8 @@ struct Container {
89114

90115
float getCMVFloat(uint32_t timeBin) const { return data[timeBin].getCMVFloat(); }
91116
void setCMVFloat(uint32_t timeBin, float value) { data[timeBin].setCMVFloat(value); }
92-
93117
};
118+
94119
} // namespace o2::tpc::cmv
95120

96-
#endif
121+
#endif

Detectors/TPC/workflow/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,6 @@ o2_add_executable(pressure-temperature
289289
SOURCES src/tpc-pressure-temperature.cxx
290290
PUBLIC_LINK_LIBRARIES O2::TPCWorkflow)
291291

292-
add_subdirectory(readers)
293-
294292
o2_add_executable(cmv-to-vector
295293
COMPONENT_NAME tpc
296294
SOURCES src/tpc-cmv-to-vector.cxx
@@ -309,4 +307,6 @@ o2_add_executable(cmv-to-vector
309307
# o2_add_executable(cmv-producer
310308
# COMPONENT_NAME tpc
311309
# SOURCES src/tpc-cmv-producer.cxx
312-
# PUBLIC_LINK_LIBRARIES O2::TPCWorkflow)
310+
# PUBLIC_LINK_LIBRARIES O2::TPCWorkflow)
311+
312+
add_subdirectory(readers)

Detectors/TPC/workflow/src/CMVToVectorSpec.cxx

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class CMVToVectorDevice : public o2::framework::Task
9393
// open files if necessary
9494
if ((mWriteDebug || mWriteDebugOnError) && !mDebugStream) {
9595
const auto debugFileName = fmt::format(fmt::runtime(mDebugStreamFileName), fmt::arg("run", runNumber));
96-
LOGP(info, "creating debug stream {}", debugFileName);
96+
LOGP(info, "Creating debug stream {}", debugFileName);
9797
mDebugStream = std::make_unique<o2::utils::TreeStreamRedirector>(debugFileName.data(), "recreate");
9898
}
9999

@@ -103,7 +103,7 @@ class CMVToVectorDevice : public o2::framework::Task
103103
rawType = "cmv.raw";
104104
}
105105
const auto rawFileName = fmt::format(fmt::runtime(mRawOutputFileName), fmt::arg("run", runNumber), fmt::arg("raw_type", rawType));
106-
LOGP(info, "creating raw debug file {}", rawFileName);
106+
LOGP(info, "Creating raw debug file {}", rawFileName);
107107
mRawOutputFile.open(rawFileName, std::ios::binary);
108108
}
109109

@@ -118,6 +118,7 @@ class CMVToVectorDevice : public o2::framework::Task
118118
tfCounter = dh->tfCounter;
119119
const auto subSpecification = dh->subSpecification;
120120
auto payloadSize = DataRefUtils::getPayloadSize(ref);
121+
// LOGP(info, "Processing TF {}, subSpecification {}, payloadSize {}", tfCounter, subSpecification, payloadSize);
121122

122123
// ---| data loop |---
123124
const gsl::span<const char> raw = pc.inputs().get<gsl::span<char>>(ref);
@@ -150,10 +151,14 @@ class CMVToVectorDevice : public o2::framework::Task
150151
const uint32_t cruID = rdh_utils::getCRU(feeId);
151152
const auto detField = RDHUtils::getDetectorField(*rdhPtr);
152153

154+
// LOGP(info, "Detected CMV packet: CRU {}, link {}, feeId {}", cruID, link, feeId);
155+
153156
if ((detField != (decltype(detField))RawDataType::CMV) || (link != rdh_utils::CMVLinkID)) {
157+
// LOGP(debug, "Skipping packet: detField {}, (expected RawDataType {}), link {}, (expected CMVLinkID {})", detField, (decltype(detField))RawDataType::CMV, link, rdh_utils::CMVLinkID);
154158
continue;
155159
}
156-
LOGP(debug, "CMV Processing firstTForbit {:9}, tfCounter {:5}, run {:6}, feeId {:6} ({:3}/-/{:2})", dh->firstTForbit, dh->tfCounter, dh->runNumber, feeId, cruID, link);
160+
161+
LOGP(debug, "Processing firstTForbit {:9}, tfCounter {:5}, run {:6}, feeId {:6}, cruID {:3}, link {:2}", dh->firstTForbit, dh->tfCounter, dh->runNumber, feeId, cruID, link);
157162

158163
if (std::find(mCRUs.begin(), mCRUs.end(), cruID) == mCRUs.end()) {
159164
LOGP(error, "CMV CRU {:3} not configured in CRUs, skipping", cruID);
@@ -163,7 +168,10 @@ class CMVToVectorDevice : public o2::framework::Task
163168
auto& cmvVec = mCMVvectors[cruID];
164169
auto& infoVec = mCMVInfos[cruID];
165170

166-
assert(size == sizeof(cmv::Container));
171+
if (size != sizeof(cmv::Container)) {
172+
LOGP(error, "CMV packet size mismatch: got {} bytes, expected {} bytes (sizeof cmv::Container). Skipping package.", size, sizeof(cmv::Container));
173+
return;
174+
}
167175
auto data = it.data();
168176
auto& cmvs = *((cmv::Container*)(data));
169177
const uint32_t orbit = cmvs.header.heartbeatOrbit;
@@ -174,6 +182,7 @@ class CMVToVectorDevice : public o2::framework::Task
174182
cmvVec.reserve(cmvVec.size() + cmv::NTimeBins);
175183
for (uint32_t tb = 0; tb < cmv::NTimeBins; ++tb) {
176184
cmvVec.push_back(cmvs.getCMVFloat(tb));
185+
// LOGP(info, "Appended CMV {} for timebin {}, CRU {}, orbit {}, bc {}", cmvs.getCMVFloat(tb), tb, cruID, orbit, bc);
177186
}
178187
}
179188
} catch (const std::exception& e) {
@@ -263,23 +272,21 @@ class CMVToVectorDevice : public o2::framework::Task
263272
bool matches(uint32_t orbit, int16_t bc) const { return ((heartbeatOrbit == orbit) && (heartbeatBC == bc)); }
264273
};
265274

266-
int mRawDataType{0}; ///< type of raw data to dump in case of errors
267-
bool mWriteDebug{false}; ///< write a debug output
268-
bool mWriteDebugOnError{false}; ///< write a debug output in case of errors
269-
bool mWriteRawDataOnError{false}; ///< write raw data in case of errors
270-
std::vector<uint32_t> mCRUs; ///< CRUs expected for this device
271-
std::unordered_map<uint32_t, std::vector<float>> mCMVvectors; ///< decoded CMVs per cru over all CMV packets in the TF
272-
std::unordered_map<uint32_t, std::vector<CMVInfo>> mCMVInfos; ///< CMV packet information within the TF
273-
std::string mDebugStreamFileName; ///< name of the debug stream output file
274-
std::unique_ptr<o2::utils::TreeStreamRedirector> mDebugStream; ///< debug output streamer
275-
std::ofstream mRawOutputFile; ///< raw output file
276-
std::string mRawOutputFileName; ///< name of the raw output file
275+
int mRawDataType{0}; ///< type of raw data to dump in case of errors
276+
bool mWriteDebug{false}; ///< write a debug output
277+
bool mWriteDebugOnError{false}; ///< write a debug output in case of errors
278+
bool mWriteRawDataOnError{false}; ///< write raw data in case of errors
279+
std::vector<uint32_t> mCRUs; ///< CRUs expected for this device
280+
std::unordered_map<uint32_t, std::vector<float>> mCMVvectors; ///< decoded CMVs per cru over all CMV packets in the TF
281+
std::unordered_map<uint32_t, std::vector<CMVInfo>> mCMVInfos; ///< CMV packet information within the TF
282+
std::string mDebugStreamFileName; ///< name of the debug stream output file
283+
std::unique_ptr<o2::utils::TreeStreamRedirector> mDebugStream; ///< debug output streamer
284+
std::ofstream mRawOutputFile; ///< raw output file
285+
std::string mRawOutputFileName; ///< name of the raw output file
277286

278287
//____________________________________________________________________________
279288
bool snapshotCMVs(DataAllocator& output, uint32_t tfCounter)
280289
{
281-
LOGP(debug, "snapshotCMVs");
282-
283290
bool hasErrors = false;
284291

285292
// send data per CRU with its own orbit/BC vector
@@ -288,11 +295,11 @@ class CMVToVectorDevice : public o2::framework::Task
288295
const auto& infVec = mCMVInfos[cru];
289296

290297
if (infVec.size() != 4) {
291-
LOGP(warning, "CMV CRU {:3}: expected 4 packets per TF, got {}", cru, infVec.size());
298+
LOGP(warning, "CRU {:3}: expected 4 packets per TF, got {}", cru, infVec.size());
292299
hasErrors = true;
293300
}
294301
if (cmvVec.size() != cmv::NTimeBins * infVec.size()) {
295-
LOGP(warning, "CMV CRU {:3}: vector size {} does not match expected {}", cru, cmvVec.size(), cmv::NTimeBins * infVec.size());
302+
LOGP(warning, "CRU {:3}: vector size {} does not match expected {}", cru, cmvVec.size(), cmv::NTimeBins * infVec.size());
296303
hasErrors = true;
297304
}
298305

@@ -336,17 +343,16 @@ class CMVToVectorDevice : public o2::framework::Task
336343
if (mCMVInfos.find(cru) == mCMVInfos.end()) {
337344
continue;
338345
}
339-
346+
340347
auto& infos = mCMVInfos[cru];
341348
auto& cmvVec = mCMVvectors[cru];
342-
349+
343350
stream << "cru=" << cru
344351
<< "tfCounter=" << tfCounter
345352
<< "nCMVs=" << cmvVec.size()
346353
<< "cmvs=" << cmvVec
347354
<< "\n";
348355
}
349-
350356
}
351357

352358
void writeRawData(InputRecord& inputs)

0 commit comments

Comments
 (0)