Skip to content

Commit 82626ae

Browse files
committed
TPC: Add standalone interface for ZS decoding
1 parent 18726a3 commit 82626ae

4 files changed

Lines changed: 95 additions & 33 deletions

File tree

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ struct TPCZSHDR {
5151
};
5252
struct TPCZSHDRV2 : public TPCZSHDR {
5353
static constexpr unsigned int TPC_ZS_NBITS_V3 = 12;
54-
static constexpr unsigned int TPC_ZS_NBITS_V4 = 12;
5554
static constexpr bool TIGHTLY_PACKED_V3 = false;
5655
static constexpr unsigned int SAMPLESPER64BIT = 64 / TPC_ZS_NBITS_V3; // 5 12-bit samples with 4 bit padding per 64 bit word for non-TIGHTLY_PACKED data
5756

GPU/GPUTracking/Base/GPUReconstructionConvert.cxx

Lines changed: 81 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "CommonConstants/LHCConstants.h"
3838
#include "DataFormatsTPC/Digit.h"
3939
#include "TPCBase/RDHUtils.h"
40+
#include "TPCBase/CRU.h"
4041
#include "DetectorsRaw/RDHUtils.h"
4142
#endif
4243

@@ -191,11 +192,11 @@ struct zsEncoder {
191192
int curRegion = 0;
192193
unsigned int encodeBits = 0;
193194
unsigned int zsVersion = 0;
194-
unsigned int iSector;
195-
o2::raw::RawFileWriter* raw;
196-
const o2::InteractionRecord* ir;
197-
const GPUParam& param;
198-
bool padding;
195+
unsigned int iSector = 0;
196+
o2::raw::RawFileWriter* raw = nullptr;
197+
const o2::InteractionRecord* ir = nullptr;
198+
const GPUParam* param = nullptr;
199+
bool padding = false;
199200
int lastEndpoint = -2, lastTime = -1, lastRow = GPUCA_ROW_COUNT;
200201
int endpoint = 0;
201202
long hbf = -1, nexthbf = 0;
@@ -261,7 +262,7 @@ struct zsEncoderRow : public zsEncoder {
261262

262263
bool checkInput(std::vector<o2::tpc::Digit>& tmpBuffer, unsigned int k);
263264
bool writeSubPage();
264-
void init() {}
265+
void init() { encodeBits = zsVersion == 2 ? TPCZSHDR::TPC_ZS_NBITS_V2 : TPCZSHDR::TPC_ZS_NBITS_V1; }
265266
void initPage() {}
266267
unsigned int encodeSequence(std::vector<o2::tpc::Digit>& tmpBuffer, unsigned int k);
267268

@@ -271,10 +272,10 @@ struct zsEncoderRow : public zsEncoder {
271272

272273
inline bool zsEncoderRow::sort(const o2::tpc::Digit a, const o2::tpc::Digit b)
273274
{
274-
int endpointa = param.tpcGeometry.GetRegion(a.getRow());
275-
int endpointb = param.tpcGeometry.GetRegion(b.getRow());
276-
endpointa = 2 * endpointa + (a.getRow() >= param.tpcGeometry.GetRegionStart(endpointa) + param.tpcGeometry.GetRegionRows(endpointa) / 2);
277-
endpointb = 2 * endpointb + (b.getRow() >= param.tpcGeometry.GetRegionStart(endpointb) + param.tpcGeometry.GetRegionRows(endpointb) / 2);
275+
int endpointa = param->tpcGeometry.GetRegion(a.getRow());
276+
int endpointb = param->tpcGeometry.GetRegion(b.getRow());
277+
endpointa = 2 * endpointa + (a.getRow() >= param->tpcGeometry.GetRegionStart(endpointa) + param->tpcGeometry.GetRegionRows(endpointa) / 2);
278+
endpointb = 2 * endpointb + (b.getRow() >= param->tpcGeometry.GetRegionStart(endpointb) + param->tpcGeometry.GetRegionRows(endpointb) / 2);
278279
if (endpointa != endpointb) {
279280
return endpointa <= endpointb;
280281
}
@@ -291,11 +292,11 @@ bool zsEncoderRow::checkInput(std::vector<o2::tpc::Digit>& tmpBuffer, unsigned i
291292
{
292293
seqLen = 1;
293294
if (lastRow != tmpBuffer[k].getRow()) {
294-
endpointStart = param.tpcGeometry.GetRegionStart(curRegion);
295+
endpointStart = param->tpcGeometry.GetRegionStart(curRegion);
295296
endpoint = curRegion * 2;
296-
if (tmpBuffer[k].getRow() >= endpointStart + param.tpcGeometry.GetRegionRows(curRegion) / 2) {
297+
if (tmpBuffer[k].getRow() >= endpointStart + param->tpcGeometry.GetRegionRows(curRegion) / 2) {
297298
endpoint++;
298-
endpointStart += param.tpcGeometry.GetRegionRows(curRegion) / 2;
299+
endpointStart += param->tpcGeometry.GetRegionRows(curRegion) / 2;
299300
}
300301
}
301302
for (unsigned int l = k + 1; l < tmpBuffer.size(); l++) {
@@ -404,7 +405,7 @@ void zsEncoderRow::decodePage(std::vector<o2::tpc::Digit>& outputBuffer, const z
404405
if ((unsigned int)region != decEndpoint / 2) {
405406
throw std::runtime_error("CRU ID / endpoint mismatch");
406407
}
407-
int nRowsRegion = param.tpcGeometry.GetRegionRows(region);
408+
int nRowsRegion = param->tpcGeometry.GetRegionRows(region);
408409

409410
int timeBin = (decHDR->timeOffset + (unsigned long)(o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstOrbit) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN;
410411
for (int l = 0; l < decHDR->nTimeBins; l++) {
@@ -416,7 +417,7 @@ void zsEncoderRow::decodePage(std::vector<o2::tpc::Digit>& outputBuffer, const z
416417
if (tbHdr->rowMask != 0 && ((upperRows) ^ ((decEndpoint & 1) != 0))) {
417418
throw std::runtime_error("invalid endpoint");
418419
}
419-
const int rowOffset = param.tpcGeometry.GetRegionStart(region) + (upperRows ? (nRowsRegion / 2) : 0);
420+
const int rowOffset = param->tpcGeometry.GetRegionStart(region) + (upperRows ? (nRowsRegion / 2) : 0);
420421
const int nRows = upperRows ? (nRowsRegion - nRowsRegion / 2) : (nRowsRegion / 2);
421422
const int nRowsUsed = __builtin_popcount((unsigned int)(tbHdr->rowMask & 0x7FFF));
422423
decPagePtr += nRowsUsed ? (2 * nRowsUsed) : 2;
@@ -474,6 +475,7 @@ struct zsEncoderLinkBased : public zsEncoder {
474475

475476
void zsEncoderLinkBased::init()
476477
{
478+
encodeBits = TPCZSHDRV2::TPC_ZS_NBITS_V3;
477479
for (int i = 0; i < 5; i++) {
478480
for (int j = 0; j < 32; j++) {
479481
inverseChannelMapping[i][j] = -1;
@@ -516,7 +518,7 @@ void zsEncoderLinkBased::createBitmask(std::vector<o2::tpc::Digit>& tmpBuffer, u
516518
unsigned int l;
517519
for (l = k; l < tmpBuffer.size(); l++) {
518520
const auto& a = tmpBuffer[l];
519-
int cruinsector = param.tpcGeometry.GetRegion(a.getRow());
521+
int cruinsector = param->tpcGeometry.GetRegion(a.getRow());
520522
o2::tpc::GlobalPadNumber pad = mapper.globalPadNumber(o2::tpc::PadPos(a.getRow(), a.getPad()));
521523
o2::tpc::FECInfo fec = mapper.fecInfo(pad);
522524
o2::tpc::CRU cru = cruinsector;
@@ -547,8 +549,8 @@ bool zsEncoderLinkBased::writeSubPage()
547549
bool zsEncoderLinkBased::sort(const o2::tpc::Digit a, const o2::tpc::Digit b)
548550
{
549551
// Fixme: this is blasphemy... one shoult precompute all values and sort an index array
550-
int cruinsectora = param.tpcGeometry.GetRegion(a.getRow());
551-
int cruinsectorb = param.tpcGeometry.GetRegion(b.getRow());
552+
int cruinsectora = param->tpcGeometry.GetRegion(a.getRow());
553+
int cruinsectorb = param->tpcGeometry.GetRegion(b.getRow());
552554
if (cruinsectora != cruinsectorb) {
553555
return cruinsectora < cruinsectorb;
554556
}
@@ -727,7 +729,7 @@ bool zsEncoderDenseLinkBased::checkInput(std::vector<o2::tpc::Digit>& tmpBuffer,
727729
unsigned int sizeChk = (unsigned int)(pagePtr - reinterpret_cast<unsigned char*>(page));
728730
sizeChk += 3 * sizeof(char); // timebin + linkID + linkCounter
729731
sizeChk += 80 / 8; // bitmask
730-
sizeChk += (nSamples * TPCZSHDRV2::TPC_ZS_NBITS_V4 + 7) / 8;
732+
sizeChk += (nSamples * encodeBits + 7) / 8;
731733
if (sizeChk > TPCZSHDR::TPC_ZS_PAGE_SIZE) {
732734
finishPage = true;
733735
}
@@ -777,7 +779,7 @@ unsigned int zsEncoderDenseLinkBased::encodeSequence(std::vector<o2::tpc::Digit>
777779
}
778780
}
779781

780-
static_assert(TPCZSHDRV2::TPC_ZS_NBITS_V4 == 12);
782+
static_assert(TPCZSHDRV2::TPC_ZS_NBITS_V3 == 12);
781783
unsigned int nStreaming = nSamples;
782784
if (free4bitPointer) {
783785
nStreaming--;
@@ -858,7 +860,7 @@ void zsEncoderDenseLinkBased::decodePage(std::vector<o2::tpc::Digit>& outputBuff
858860
decPagePtr += sizeof(unsigned char);
859861
}
860862
const unsigned char* adcData = (const unsigned char*)(decPagePtr);
861-
decPagePtr += (nADC * TPCZSHDRV2::TPC_ZS_NBITS_V4 + 7) / 8;
863+
decPagePtr += (nADC * encodeBits + 7) / 8;
862864
unsigned int byte = 0, bits = 0, posXbits = 0;
863865
while (posXbits < nADC) {
864866
byte |= *(adcData++) << bits;
@@ -941,7 +943,6 @@ inline unsigned int zsEncoderRun<T>::run(std::vector<zsPage>* buffer, std::vecto
941943
int rawendpoint = 0;
942944
(void)(rawcru + rawendpoint); // avoid compiler warning
943945
encodeBitsFactor = (1 << (encodeBits - 10));
944-
init();
945946

946947
std::sort(tmpBuffer.begin(), tmpBuffer.end(), [this](const o2::tpc::Digit a, const o2::tpc::Digit b) { return sort(a, b); });
947948
for (unsigned int k = 0; k <= tmpBuffer.size(); k++) {
@@ -958,7 +959,7 @@ inline unsigned int zsEncoderRun<T>::run(std::vector<zsPage>* buffer, std::vecto
958959
}
959960
}
960961
if (lastRow != tmpBuffer[k].getRow()) {
961-
curRegion = param.tpcGeometry.GetRegion(tmpBuffer[k].getRow());
962+
curRegion = param->tpcGeometry.GetRegion(tmpBuffer[k].getRow());
962963
}
963964
mustWriteSubPage = checkInput(tmpBuffer, k);
964965
} else {
@@ -1110,26 +1111,23 @@ void GPUReconstructionConvert::RunZSEncoder(const S& in, std::unique_ptr<unsigne
11101111

11111112
auto runZS = [&](auto& encoder) {
11121113
encoder.zsVersion = version;
1114+
encoder.init();
11131115
totalPages += encoder.run(buffer[i], tmpBuffer);
11141116
if (verify) {
11151117
nErrors += encoder.compare(buffer[i], tmpBuffer); // Verification
11161118
}
11171119
};
11181120

11191121
if (version >= 1 && version <= 2) {
1120-
bool zs12bit = version == 2;
1121-
zsEncoderRun<zsEncoderRow> enc{{{.iSector = i, .raw = raw, .ir = ir, .param = param, .padding = padding}}};
1122-
enc.encodeBits = zs12bit ? TPCZSHDR::TPC_ZS_NBITS_V2 : TPCZSHDR::TPC_ZS_NBITS_V1;
1122+
zsEncoderRun<zsEncoderRow> enc{{{.iSector = i, .raw = raw, .ir = ir, .param = &param, .padding = padding}}};
11231123
runZS(enc);
11241124
} else if (version >= 3 || version <= 4) {
11251125
#ifdef GPUCA_O2_LIB
11261126
if (version == 3) {
1127-
zsEncoderRun<zsEncoderImprovedLinkBased> enc{{{{.iSector = i, .raw = raw, .ir = ir, .param = param, .padding = padding}}}};
1128-
enc.encodeBits = TPCZSHDRV2::TPC_ZS_NBITS_V3;
1127+
zsEncoderRun<zsEncoderImprovedLinkBased> enc{{{{.iSector = i, .raw = raw, .ir = ir, .param = &param, .padding = padding}}}};
11291128
runZS(enc);
11301129
} else if (version == 4) {
1131-
zsEncoderRun<zsEncoderDenseLinkBased> enc{{{{.iSector = i, .raw = raw, .ir = ir, .param = param, .padding = padding}}}};
1132-
enc.encodeBits = TPCZSHDRV2::TPC_ZS_NBITS_V4;
1130+
zsEncoderRun<zsEncoderDenseLinkBased> enc{{{{.iSector = i, .raw = raw, .ir = ir, .param = &param, .padding = padding}}}};
11331131
runZS(enc);
11341132
}
11351133
#else
@@ -1205,3 +1203,56 @@ void GPUReconstructionConvert::RunZSFilter(std::unique_ptr<o2::tpc::Digit[]>* bu
12051203
}
12061204
#endif
12071205
}
1206+
1207+
#ifdef GPUCA_O2_LIB
1208+
template <class T>
1209+
static inline auto GetDecoder_internal(const GPUParam& param, int version)
1210+
{
1211+
std::shared_ptr<T> enc = std::make_shared<T>();
1212+
enc->param = &param;
1213+
enc->zsVersion = version;
1214+
enc->init();
1215+
return [enc](std::vector<o2::tpc::Digit>& outBuffer, const void* page, unsigned int firstTfOrbit) {
1216+
const o2::header::RAWDataHeader& rdh = *(const o2::header::RAWDataHeader*)page;
1217+
if (o2::raw::RDHUtils::getMemorySize(rdh) == sizeof(o2::header::RAWDataHeader)) {
1218+
return;
1219+
}
1220+
if (o2::raw::RDHUtils::getDetectorField(rdh) != 2) {
1221+
return;
1222+
}
1223+
o2::tpc::CRU cru(o2::tpc::rdh_utils::getCRU(rdh));
1224+
enc->iSector = cru.sector();
1225+
int endpoint = cru.region() * 2 + o2::tpc::rdh_utils::getEndPoint(rdh);
1226+
enc->decodePage(outBuffer, (const zsPage*)page, endpoint, firstTfOrbit);
1227+
};
1228+
}
1229+
1230+
std::function<void(std::vector<o2::tpc::Digit>&, const void*, unsigned int)> GPUReconstructionConvert::GetDecoder(int version, const GPUParam& param)
1231+
{
1232+
if (version >= 1 && version <= 2) {
1233+
return GetDecoder_internal<zsEncoderRow>(param, version);
1234+
} else if (version == 3) {
1235+
return GetDecoder_internal<zsEncoderImprovedLinkBased>(param, version);
1236+
} else if (version == 4) {
1237+
return GetDecoder_internal<zsEncoderDenseLinkBased>(param, version);
1238+
} else {
1239+
throw std::runtime_error("Invalid ZS version");
1240+
}
1241+
}
1242+
1243+
void GPUReconstructionZSDecoder::DecodePage(std::vector<o2::tpc::Digit>& outputBuffer, const void* page, unsigned int tfFirstOrbit, const GPUParam& param)
1244+
{
1245+
const o2::header::RAWDataHeader* rdh = (const o2::header::RAWDataHeader*)page;
1246+
if (o2::raw::RDHUtils::getMemorySize(*rdh) == sizeof(o2::header::RAWDataHeader)) {
1247+
return;
1248+
}
1249+
const TPCZSHDR* const hdr = (const TPCZSHDR*)((const char*)page + sizeof(o2::header::RAWDataHeader));
1250+
if (mDecoders.size() < hdr->version + 1) {
1251+
mDecoders.resize(hdr->version + 1);
1252+
}
1253+
if (mDecoders[hdr->version] == nullptr) {
1254+
mDecoders[hdr->version] = GPUReconstructionConvert::GetDecoder(hdr->version, param);
1255+
}
1256+
mDecoders[hdr->version](outputBuffer, page, tfFirstOrbit);
1257+
}
1258+
#endif

GPU/GPUTracking/Base/GPUReconstructionConvert.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#define GPURECONSTRUCTIONCONVERT_H
1717

1818
#include <memory>
19+
#include <functional>
20+
#include <vector>
1921
#include "GPUDef.h"
2022

2123
namespace o2
@@ -58,7 +60,18 @@ class GPUReconstructionConvert
5860
static int GetMaxTimeBin(const o2::tpc::ClusterNativeAccess& native);
5961
static int GetMaxTimeBin(const GPUTrackingInOutDigits& digits);
6062
static int GetMaxTimeBin(const GPUTrackingInOutZS& zspages);
63+
static std::function<void(std::vector<o2::tpc::Digit>&, const void*, unsigned int)> GetDecoder(int version, const GPUParam& param);
6164
};
65+
66+
class GPUReconstructionZSDecoder
67+
{
68+
public:
69+
void DecodePage(std::vector<o2::tpc::Digit>& outputBuffer, const void* page, unsigned int tfFirstOrbit, const GPUParam& param);
70+
71+
private:
72+
std::vector<std::function<void(std::vector<o2::tpc::Digit>&, const void*, unsigned int)>> mDecoders;
73+
};
74+
6275
} // namespace gpu
6376
} // namespace GPUCA_NAMESPACE
6477

GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ std::pair<unsigned int, unsigned int> GPUChainTracking::TPCClusterizerDecodeZSCo
9191
unsigned int nDigits = 0;
9292
unsigned int nPages = 0;
9393
bool doGPU = mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCClusterFinding;
94-
int firstHBF = (mIOPtrs.settingsTF && mIOPtrs.settingsTF->hasTfStartOrbit) ? mIOPtrs.settingsTF->tfStartOrbit : (mIOPtrs.tpcZS->slice[iSlice].count[0] && mIOPtrs.tpcZS->slice[iSlice].nZSPtr[0][0]) ? o2::raw::RDHUtils::getHeartBeatOrbit(*(const o2::header::RAWDataHeader*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[0][0])
95-
: 0;
94+
int firstHBF = (mIOPtrs.settingsTF && mIOPtrs.settingsTF->hasTfStartOrbit) ? mIOPtrs.settingsTF->tfStartOrbit : (mIOPtrs.tpcZS->slice[iSlice].count[0] && mIOPtrs.tpcZS->slice[iSlice].nZSPtr[0][0]) ? o2::raw::RDHUtils::getHeartBeatOrbit(*(const o2::header::RAWDataHeader*)mIOPtrs.tpcZS->slice[iSlice].zsPtr[0][0]) : 0;
9695

9796
for (unsigned short j = 0; j < GPUTrackingInOutZS::NENDPOINTS; j++) {
9897
#ifndef GPUCA_NO_VC

0 commit comments

Comments
 (0)