43#include <oneapi/tbb.h>
48using namespace std::string_literals;
55 uint32_t nClSector = 0;
63 for (uint32_t k = 0; k < native->
nClusters[
i][
j]; k++) {
65 float x = 0,
y = 0,
z = 0;
66 if (continuousMaxTimeBin == 0) {
67 transform->Transform(
i,
j, clin.getPad(), clin.getTime(),
x,
y,
z);
69 transform->TransformInTimeFrame(
i,
j, clin.getPad(), clin.getTime(),
x,
y,
z, continuousMaxTimeBin);
71 auto& clout =
clusters[
i].get()[nClSector];
76 clout.amp = clin.qTot;
77 clout.flags = clin.getFlags();
89 memset((
void*)&native, 0,
sizeof(native));
91 for (uint32_t
j = 0;
j < nRawClusters[
i];
j++) {
103 for (uint32_t
j = 0;
j < nRawClusters[
i];
j++) {
122 for (uint32_t k = 0; k < native.
nClusters[
i][
j]; k++) {
136 for (uint32_t k = 0; k <
digits.nTPCDigits[
i]; k++) {
152 const char* page = (
const char*)zspages.
sector[
i].
zsPtr[
j][k];
159 if (hdr2->
flags & TPCZSHDRV2::ZSFlags::nTimeBinSpanBit8) {
176#ifdef GPUCA_TPC_GEOMETRY_O2
187 int32_t curRegion = 0, outputRegion = 0;
188 uint32_t encodeBits = 0;
189 uint32_t zsVersion = 0;
190 uint32_t iSector = 0;
196 int32_t
endpoint = 0, outputEndpoint = 0;
197 int64_t hbf = -1, nexthbf = 0;
198 zsPage* page =
nullptr;
199 uint8_t* pagePtr =
nullptr;
200 int32_t bcShiftInFirstHBF = 0;
201 int32_t firstTimebinInPage = -1;
202 float encodeBitsFactor = 0;
203 bool needAnotherPage =
false;
204 uint32_t packetCounter = 0;
205 uint32_t pageCounter = 0;
206 void ZSfillEmpty(
void*
ptr, int32_t shift, uint32_t feeId, int32_t
orbit, int32_t linkid);
207 static void ZSstreamOut(uint16_t* bufIn, uint32_t& lenIn, uint8_t* bufOut, uint32_t& lenOut, uint32_t nBits);
211inline void zsEncoder::ZSfillEmpty(
void*
ptr, int32_t shift, uint32_t feeId, int32_t
orbit, int32_t linkid)
215 o2::raw::RDHUtils::setHeartBeatBC(*rdh, shift);
225inline void zsEncoder::ZSstreamOut(uint16_t* bufIn, uint32_t& lenIn, uint8_t* bufOut, uint32_t& lenOut, uint32_t nBits)
227 uint32_t
byte = 0,
bits = 0;
228 uint32_t
mask = (1 << nBits) - 1;
229 for (uint32_t
i = 0;
i < lenIn;
i++) {
233 bufOut[lenOut++] = (
uint8_t)(
byte & 0xFF);
239 bufOut[lenOut++] = byte;
248static inline auto ZSEncoderGetDigits(
const DigitArray& in, int32_t
i) {
return in[
i].data(); }
249static inline auto ZSEncoderGetNDigits(
const DigitArray& in, int32_t
i) {
return in[
i].size(); }
254struct zsEncoderRow :
public zsEncoder {
255 std::array<uint16_t, TPCZSHDR::TPC_ZS_PAGE_SIZE> streamBuffer = {};
256 std::array<uint8_t, TPCZSHDR::TPC_ZS_PAGE_SIZE> streamBuffer8 = {};
261 int32_t endpointStart = 0;
262 int32_t nRowsInTB = 0;
263 uint32_t streamSize = 0, streamSize8 = 0;
264 constexpr static int32_t RAWLNK = rdh_utils::UserLogicLinkID;
266 bool checkInput(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k);
270 uint32_t encodeSequence(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k);
273 void decodePage(std::vector<o2::tpc::Digit>& outputBuffer,
const zsPage* page, uint32_t
endpoint, uint32_t firstOrbit, uint32_t triggerBC = 0);
278 int32_t endpointa =
param->tpcGeometry.GetRegion(
a.getRow());
279 int32_t endpointb =
param->tpcGeometry.GetRegion(
b.getRow());
280 endpointa = 2 * endpointa + (
a.getRow() >=
param->tpcGeometry.GetRegionStart(endpointa) +
param->tpcGeometry.GetRegionRows(endpointa) / 2);
281 endpointb = 2 * endpointb + (
b.getRow() >=
param->tpcGeometry.GetRegionStart(endpointb) +
param->tpcGeometry.GetRegionRows(endpointb) / 2);
282 if (endpointa != endpointb) {
283 return endpointa <= endpointb;
285 if (
a.getTimeStamp() !=
b.getTimeStamp()) {
286 return a.getTimeStamp() <
b.getTimeStamp();
288 if (
a.getRow() !=
b.getRow()) {
289 return a.getRow() <
b.getRow();
291 return a.getPad() <
b.getPad();
294bool zsEncoderRow::checkInput(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k)
297 if (lastRow != tmpBuffer[k].getRow()) {
298 endpointStart =
param->tpcGeometry.GetRegionStart(curRegion);
300 if (tmpBuffer[k].getRow() >= endpointStart +
param->tpcGeometry.GetRegionRows(curRegion) / 2) {
302 endpointStart +=
param->tpcGeometry.GetRegionRows(curRegion) / 2;
305 for (uint32_t l = k + 1; l < tmpBuffer.size(); l++) {
306 if (tmpBuffer[l].getRow() == tmpBuffer[k].getRow() && tmpBuffer[l].
getTimeStamp() == tmpBuffer[k].
getTimeStamp() && tmpBuffer[l].getPad() == tmpBuffer[l - 1].getPad() + 1) {
312 if (lastEndpoint >= 0 && lastTime != -1 && (int32_t)hdr->nTimeBinSpan + tmpBuffer[k].getTimeStamp() - lastTime >= 256) {
316 uint32_t sizeChk = (uint32_t)(pagePtr -
reinterpret_cast<uint8_t*
>(page));
317 sizeChk += 2 * (nRowsInTB + (tmpBuffer[k].getRow() != lastRow && tmpBuffer[k].getTimeStamp() == lastTime));
318 sizeChk += streamSize8;
319 sizeChk += (lastTime != tmpBuffer[k].getTimeStamp()) && ((sizeChk + (streamSize * encodeBits + 7) / 8) & 1);
320 sizeChk += (tmpBuffer[k].getTimeStamp() != lastTime || tmpBuffer[k].getRow() != lastRow) ? 3 : 0;
321 sizeChk += (lastTime != -1 && tmpBuffer[k].getTimeStamp() > lastTime) ? ((tmpBuffer[k].
getTimeStamp() - lastTime - 1) * 2) : 0;
323 const uint32_t streamSizeChkBits = streamSize * encodeBits + ((lastTime != tmpBuffer[k].getTimeStamp() && (streamSize * encodeBits) % 8) ? (8 - (streamSize * encodeBits) % 8) : 0);
332 return endpoint != lastEndpoint || tmpBuffer[k].getTimeStamp() != lastTime;
335bool zsEncoderRow::writeSubPage()
337 if (pagePtr !=
reinterpret_cast<uint8_t*
>(page)) {
338 pagePtr += 2 * nRowsInTB;
339 ZSstreamOut(streamBuffer.data(), streamSize, streamBuffer8.data(), streamSize8, encodeBits);
340 pagePtr = std::copy(streamBuffer8.data(), streamBuffer8.data() + streamSize8, pagePtr);
341 if (pagePtr -
reinterpret_cast<uint8_t*
>(page) > 8192) {
342 throw std::runtime_error(
"internal error during ZS encoding");
345 for (int32_t l = 1; l < nRowsInTB; l++) {
346 curTBHdr->rowAddr1()[l - 1] += 2 * nRowsInTB;
352uint32_t zsEncoderRow::encodeSequence(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k)
355 if (lastTime != -1) {
356 hdr->nTimeBinSpan += tmpBuffer[k].getTimeStamp() - lastTime - 1;
357 pagePtr += (tmpBuffer[k].getTimeStamp() - lastTime - 1) * 2;
360 if ((pagePtr -
reinterpret_cast<uint8_t*
>(page)) & 1) {
363 curTBHdr =
reinterpret_cast<TPCZSTBHDR*
>(pagePtr);
368 if (tmpBuffer[k].getRow() != lastRow) {
369 curTBHdr->rowMask |= 1 << (tmpBuffer[k].getRow() - endpointStart);
370 ZSstreamOut(streamBuffer.data(), streamSize, streamBuffer8.data(), streamSize8, encodeBits);
372 curTBHdr->rowAddr1()[nRowsInTB - 1] = (pagePtr -
reinterpret_cast<uint8_t*
>(page)) + streamSize8;
375 nSeq = streamBuffer8.data() + streamSize8++;
379 streamBuffer8[streamSize8++] = tmpBuffer[k].getPad();
380 streamBuffer8[streamSize8++] = streamSize + seqLen;
381 for (int32_t l = 0; l < seqLen; l++) {
382 streamBuffer[streamSize++] = (uint16_t)(tmpBuffer[k + l].getChargeFloat() * encodeBitsFactor + 0.5f);
387void zsEncoderRow::decodePage(std::vector<o2::tpc::Digit>& outputBuffer,
const zsPage* decPage, uint32_t decEndpoint, uint32_t firstOrbit, uint32_t triggerBC)
389 const uint8_t* decPagePtr =
reinterpret_cast<const uint8_t*
>(decPage);
396 decPagePtr +=
sizeof(*decHDR);
398 throw std::runtime_error(
"invalid ZS version "s +
std::to_string(decHDR->
version) +
" (1 or 2 expected)"s);
400 const float decodeBitsFactor = 1.f / (1 << (encodeBits - 10));
401 uint32_t
mask = (1 << encodeBits) - 1;
402 int32_t cruid = decHDR->
cruID;
403 uint32_t sector = cruid / 10;
404 if (sector != iSector) {
405 throw std::runtime_error(
"invalid TPC sector");
407 int32_t region = cruid % 10;
408 if ((uint32_t)region != decEndpoint / 2) {
409 throw std::runtime_error(
"CRU ID / endpoint mismatch");
411 int32_t nRowsRegion =
param->tpcGeometry.GetRegionRows(region);
415 if ((decPagePtr -
reinterpret_cast<const uint8_t*
>(decPage)) & 1) {
419 bool upperRows = tbHdr->
rowMask & 0x8000;
420 if (tbHdr->
rowMask != 0 && ((upperRows) ^ ((decEndpoint & 1) != 0))) {
421 throw std::runtime_error(
"invalid endpoint");
423 const int32_t rowOffset =
param->tpcGeometry.GetRegionStart(region) + (upperRows ? (nRowsRegion / 2) : 0);
424 const int32_t
nRows = upperRows ? (nRowsRegion - nRowsRegion / 2) : (nRowsRegion / 2);
425 const int32_t nRowsUsed = __builtin_popcount((uint32_t)(tbHdr->
rowMask & 0x7FFF));
426 decPagePtr += nRowsUsed ? (2 * nRowsUsed) : 2;
428 for (int32_t
m = 0;
m <
nRows;
m++) {
429 if ((tbHdr->
rowMask & (1 <<
m)) == 0) {
432 const uint8_t* rowData = rowPos == 0 ? decPagePtr : (
reinterpret_cast<const uint8_t*
>(decPage) + tbHdr->rowAddr1()[rowPos - 1]);
433 const int32_t nSeqRead = *rowData;
434 const uint8_t* adcData = rowData + 2 * nSeqRead + 1;
435 int32_t nADC = (rowData[2 * nSeqRead] * encodeBits + 7) / 8;
436 decPagePtr += 1 + 2 * nSeqRead + nADC;
437 uint32_t
byte = 0,
bits = 0, posXbits = 0;
438 std::array<uint16_t, TPCZSHDR::TPC_ZS_PAGE_SIZE> decBuffer;
439 for (int32_t
n = 0;
n < nADC;
n++) {
440 byte |= *(adcData++) <<
bits;
442 while (
bits >= encodeBits) {
443 decBuffer[posXbits++] =
byte &
mask;
444 byte =
byte >> encodeBits;
449 for (int32_t
n = 0;
n < nSeqRead;
n++) {
450 const int32_t decSeqLen = rowData[(
n + 1) * 2] - (
n ? rowData[
n * 2] : 0);
451 for (int32_t
o = 0;
o < decSeqLen;
o++) {
463struct zsEncoderLinkBased :
public zsEncoder {
466 int32_t inverseChannelMapping[5][32];
467 int32_t nSamples = 0;
469 bool finishPage =
false;
470 std::vector<uint16_t> adcValues = {};
471 std::bitset<80> bitmask = {};
473 void createBitmask(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k);
478void zsEncoderLinkBased::init()
481 for (int32_t
i = 0;
i < 5;
i++) {
482 for (int32_t
j = 0;
j < 32;
j++) {
483 inverseChannelMapping[
i][
j] = -1;
486 for (int32_t iCRU = 0; iCRU < 2; iCRU++) {
487 for (int32_t iChannel = 0; iChannel < 80; iChannel++) {
488 int32_t sampaOnFEC = 0, channelOnSAMPA = 0;
490 if (inverseChannelMapping[sampaOnFEC][channelOnSAMPA] != -1 && inverseChannelMapping[sampaOnFEC][channelOnSAMPA] != iChannel) {
491 GPUError(
"ERROR: Channel conflict: %d %d: %d vs %d", sampaOnFEC, channelOnSAMPA, inverseChannelMapping[sampaOnFEC][channelOnSAMPA], iChannel);
492 throw std::runtime_error(
"ZS error");
494 inverseChannelMapping[sampaOnFEC][channelOnSAMPA] = iChannel;
497 for (int32_t
i = 0;
i < 5;
i++) {
498 for (int32_t
j = 0;
j < 32;
j++) {
499 if (inverseChannelMapping[
i][
j] == -1) {
500 GPUError(
"ERROR: Map missing for sampa %d channel %d",
i,
j);
501 throw std::runtime_error(
"ZS error");
507void zsEncoderLinkBased::createBitmask(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k)
514 for (l = k; l < tmpBuffer.size(); l++) {
515 const auto&
a = tmpBuffer[l];
516 int32_t cruinsector =
param->tpcGeometry.GetRegion(
a.getRow());
520 int32_t fecInPartition = fec.
getIndex() - mapper.getPartitionInfo(cru.
partition()).getSectorFECOffset();
521 int32_t tmpEndpoint = 2 * cruinsector + (fecInPartition >= (mapper.getPartitionInfo(cru.
partition()).getNumberOfFECs() + 1) / 2);
523 link = fecInPartition;
529 bitmask[channel] = 1;
530 adcValues.emplace_back((uint16_t)(
a.getChargeFloat() * encodeBitsFactor + 0.5f));
538 int32_t cruinsectora =
param->tpcGeometry.GetRegion(
a.getRow());
539 int32_t cruinsectorb =
param->tpcGeometry.GetRegion(
b.getRow());
540 if (cruinsectora != cruinsectorb) {
541 return cruinsectora < cruinsectorb;
549 int32_t fecInPartitiona = feca.
getIndex() - mapper.getPartitionInfo(cru.
partition()).getSectorFECOffset();
550 int32_t fecInPartitionb = fecb.
getIndex() - mapper.getPartitionInfo(cru.
partition()).getSectorFECOffset();
552 int32_t endpointa = 2 * cruinsectora + (fecInPartitiona >= (mapper.getPartitionInfo(cru.
partition()).getNumberOfFECs() + 1) / 2);
553 int32_t endpointb = 2 * cruinsectorb + (fecInPartitionb >= (mapper.getPartitionInfo(cru.
partition()).getNumberOfFECs() + 1) / 2);
554 if (endpointa != endpointb) {
555 return endpointa < endpointb;
557 if (
a.getTimeStamp() !=
b.getTimeStamp()) {
558 return a.getTimeStamp() <
b.getTimeStamp();
560 if (fecInPartitiona != fecInPartitionb) {
561 return fecInPartitiona < fecInPartitionb;
568struct zsEncoderImprovedLinkBased :
public zsEncoderLinkBased {
569 bool checkInput(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k);
570 uint32_t encodeSequence(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k);
571 void decodePage(std::vector<o2::tpc::Digit>& outputBuffer,
const zsPage* page, uint32_t
endpoint, uint32_t firstOrbit, uint32_t triggerBC = 0);
575 constexpr static int32_t RAWLNK = rdh_utils::ILBZSLinkID;
578bool zsEncoderImprovedLinkBased::checkInput(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k)
580 createBitmask(tmpBuffer, k);
581 finishPage =
endpoint != lastEndpoint;
582 if (firstTimebinInPage != -1 && tmpBuffer[k].
getTimeStamp() - firstTimebinInPage >= 1 << (
sizeof(hdr->nTimeBinSpan) * 8)) {
586 uint32_t sizeChk = (uint32_t)(pagePtr -
reinterpret_cast<uint8_t*
>(page));
600uint32_t zsEncoderImprovedLinkBased::encodeSequence(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k)
603 pagePtr +=
sizeof(*tbHdr);
604 tbHdr->
bunchCrossing = (tmpBuffer[k].getTimeStamp() - firstTimebinInPage) * LHCBCPERTIMEBIN;
607 tbHdr->
bitMaskLow = (bitmask & std::bitset<80>(0xFFFFFFFFFFFFFFFFlu)).to_ulong();
610 hdr->nTimeBinSpan = tmpBuffer[k].getTimeStamp() - firstTimebinInPage;
611 hdr->nTimebinHeaders++;
615 uint32_t tmpIn = nSamples;
616 ZSstreamOut(adcValues.data(), tmpIn, pagePtr, tmp, encodeBits);
619 uint64_t* payloadPtr = (uint64_t*)pagePtr;
623 for (uint32_t
i = 0;
i < nSamples;
i++) {
631bool zsEncoderImprovedLinkBased::writeSubPage()
636void zsEncoderImprovedLinkBased::initPage()
639 hdr->nTimebinHeaders = 0;
640 hdr->firstZSDataOffset = 0;
643void zsEncoderImprovedLinkBased::decodePage(std::vector<o2::tpc::Digit>& outputBuffer,
const zsPage* decPage, uint32_t decEndpoint, uint32_t firstOrbit, uint32_t triggerBC)
646 const uint8_t* decPagePtr =
reinterpret_cast<const uint8_t*
>(decPage);
653 decPagePtr +=
sizeof(*decHDR);
654 if (decHDR->
version != ZSVersion::ZSVersionLinkBasedWithMeta) {
658 throw std::runtime_error(
"Magic word missing");
660 const float decodeBitsFactor = 1.f / (1 << (encodeBits - 10));
661 uint32_t
mask = (1 << encodeBits) - 1;
662 int32_t cruid = decHDR->
cruID;
663 uint32_t sector = cruid / 10;
664 if (sector != iSector) {
665 throw std::runtime_error(
"invalid TPC sector");
667 int32_t region = cruid % 10;
673 const int32_t feeLink = tbHdr->
fecInPartition - (decEndpoint & 1) * ((mapper.getPartitionInfo(cru.
partition()).getNumberOfFECs() + 1) / 2);
674 auto fillADC = [&outputBuffer](int32_t cru, int32_t rowInSector, int32_t padInRow, int32_t timeBin,
float adcValue) {
675 outputBuffer.emplace_back(
o2::tpc::Digit{cruid, adcValue, rowInSector, padInRow, timeBin});
679 raw_processing_helpersa::processZSdata((
const char*)decPagePtr,
size, rdh_utils::getFEEID(cruid, decEndpoint & 1, feeLink), o2::raw::RDHUtils::getHeartBeatOrbit(*rdh), firstOrbit, decHDR->
timeOffset, fillADC);
682 throw std::runtime_error(
"ZS TB Hdr does not have linkZS magic word");
686 LOGP(
debug,
"zsEncoderImprovedLinkBased::decodePage skipping digits hdr->tOff {} + hdr->bc {} + (orbit {} - firstOrbit {}) * maxBunch {} - triggerBC {} = {} < 0", decHDR->
timeOffset, tbHdr->
bunchCrossing, o2::raw::RDHUtils::getHeartBeatOrbit(*rdh), firstOrbit,
o2::constants::lhc::LHCMaxBunches, triggerBC, timeBin);
689 const uint8_t* adcData = (
const uint8_t*)(decPagePtr +
sizeof(*tbHdr));
691 int32_t nADC = bitmask.count();
692 std::vector<uint16_t> decBuffer(nADC);
694 uint32_t
byte = 0,
bits = 0, posXbits = 0;
695 while (posXbits < nADC) {
696 byte |= *(adcData++) <<
bits;
698 while (
bits >= encodeBits) {
699 decBuffer[posXbits++] =
byte &
mask;
700 byte =
byte >> encodeBits;
705 const uint64_t* adcData64 = (
const uint64_t*)adcData;
706 for (int32_t
j = 0;
j < nADC;
j++) {
710 for (int32_t
j = 0, k = 0;
j < bitmask.size();
j++) {
712 int32_t sampaOnFEC = 0, channelOnSAMPA = 0;
713 mapper.getSampaAndChannelOnFEC(cruid,
j, sampaOnFEC, channelOnSAMPA);
714 const auto padSecPos = mapper.padSecPos(cruid, tbHdr->
fecInPartition, sampaOnFEC, channelOnSAMPA);
715 const auto& padPos = padSecPos.getPadPos();
726struct zsEncoderDenseLinkBased :
public zsEncoderLinkBased {
727 bool checkInput(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k);
728 uint32_t encodeSequence(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k);
729 void decodePage(std::vector<o2::tpc::Digit>& outputBuffer,
const zsPage* page, uint32_t
endpoint, uint32_t firstOrbit, uint32_t triggerBC = 0);
732 void amendPageErrorMessage(std::ostringstream& oss,
const o2::header::RAWDataHeader* rdh,
const TPCZSHDRV2* decHDR,
const uint8_t* payloadEnd,
const uint8_t* decPagePtr, uint32_t nOutput);
734 uint16_t curTimeBin = 0;
735 std::vector<uint8_t> sequenceBuffer;
736 std::vector<uint16_t> sequenceBufferADC;
738 constexpr static int32_t RAWLNK = rdh_utils::DLBZSLinkID;
739 constexpr static int32_t v2nbits = 10;
742bool zsEncoderDenseLinkBased::checkInput(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k)
744 createBitmask(tmpBuffer, k);
745 finishPage =
endpoint != lastEndpoint;
746 uint16_t newTimeBin = tmpBuffer[k].getTimeStamp() - firstTimebinInPage;
747 bool retVall = finishPage || newTimeBin != curTimeBin;
751uint32_t zsEncoderDenseLinkBased::encodeSequence(std::vector<o2::tpc::Digit>& tmpBuffer, uint32_t k)
753 if (sequenceBuffer.size() == 0) {
755 if (zsVersion == ZSVersion::ZSVersionDenseLinkBasedV2) {
758 sequenceBuffer.emplace_back(
bc << 4);
759 sequenceBuffer.emplace_back(
bc >> 4);
760 curTimeBin = tmpBuffer[k].getTimeStamp() - firstTimebinInPage;
761 hdr->nTimeBinSpan = curTimeBin & 0xFF;
762 if (curTimeBin & 0x100) {
763 hdr->flags |= TPCZSHDRV2::ZSFlags::nTimeBinSpanBit8;
765 hdr->nTimebinHeaders++;
769 sequenceBuffer.emplace_back(link);
770 uint8_t* plink = &sequenceBuffer.back();
772 std::bitset<10> bitmaskL2;
773 for (int32_t
i = 9;
i >= 0;
i--) {
774 bitmaskL2.set(
i, ((bitmask >> (
i * 8)) & std::bitset<80>(0xFF)).any());
776 if (bitmaskL2.all()) {
777 *plink |= 0b00100000;
779 *plink |= (bitmaskL2.to_ulong() >> 2) & 0b11000000;
780 sequenceBuffer.emplace_back(bitmaskL2.to_ulong() & 0xFF);
783 for (int32_t
i = 0;
i < 10;
i++) {
784 if (bitmaskL2.test(
i)) {
785 sequenceBuffer.emplace_back(((bitmask >> (
i * 8)) & std::bitset<80>(0xFF)).to_ulong());
791 sequenceBufferADC.insert(sequenceBufferADC.end(), adcValues.begin(), adcValues.end());
797bool zsEncoderDenseLinkBased::writeSubPage()
799 uint32_t
offset = sequenceBuffer.size();
800 if (sequenceBufferADC.size()) {
801 bool need12bit = zsVersion != ZSVersion::ZSVersionDenseLinkBasedV2;
802 uint32_t needNow = 0;
803 if (zsVersion == ZSVersion::ZSVersionDenseLinkBasedV2) {
804 for (uint32_t
i = 0;
i < sequenceBufferADC.size();
i++) {
805 if (sequenceBufferADC[
i] >= (1 << v2nbits)) {
811 uint32_t encodeBitsBlock = encodeBits;
813 encodeBitsBlock = v2nbits;
814 sequenceBuffer[0] |= 0x10;
816 sequenceBuffer.resize(
offset + (sequenceBufferADC.size() * encodeBitsBlock + 7) / 8);
818 uint32_t tmpIn = sequenceBufferADC.size();
819 ZSstreamOut(sequenceBufferADC.data(), tmpIn, sequenceBuffer.data() +
offset, tmp, encodeBitsBlock);
820 sequenceBufferADC.clear();
823 if (sequenceBuffer.size()) {
825 uint32_t
size = sequenceBuffer.size();
826 uint32_t fill = std::min(sizeLeft,
size);
827 memcpy(pagePtr, sequenceBuffer.data(), fill);
831 sequenceBuffer.erase(sequenceBuffer.begin(), sequenceBuffer.begin() + fill);
833 sequenceBuffer.clear();
835 finishPage = finishPage ||
size >= sizeLeft || needAnotherPage;
841void zsEncoderDenseLinkBased::initPage()
844 hdr->nTimebinHeaders = 0;
845 memcpy(pagePtr, sequenceBuffer.data(), sequenceBuffer.size());
847 pagePtr += sequenceBuffer.size();
848 sequenceBuffer.clear();
852void zsEncoderDenseLinkBased::decodePage(std::vector<o2::tpc::Digit>& outputBuffer,
const zsPage* decPage, uint32_t decEndpoint, uint32_t firstOrbit, uint32_t triggerBC)
855 const uint8_t* decPagePtr =
reinterpret_cast<const uint8_t*
>(decPage);
862 if (decHDR->
version < ZSVersion::ZSVersionDenseLinkBased || decHDR->
version > ZSVersion::ZSVersionDenseLinkBasedV2) {
866 throw std::runtime_error(
"Magic word missing");
869 const float decodeBitsFactor = 1.f / (1 << (encodeBits - 10));
870 int32_t cruid = decHDR->
cruID;
871 uint32_t sector = cruid / 10;
872 if (sector != iSector) {
873 throw std::runtime_error(
"invalid TPC sector");
875 int32_t region = cruid % 10;
877 std::vector<uint8_t> tmpBuffer;
878 bool extendFailure =
false;
879 uint32_t nOutput = 0;
880 uint32_t minTimeBin = -1, maxTimeBin = 0;
882 int32_t sizeLeftInPage = payloadEnd - decPagePtr;
883 if (sizeLeftInPage <= 0) {
884 throw std::runtime_error(
"Decoding ran beyond end of page before processing extended timebin");
888 throw std::runtime_error(
"pageExtends signaled, but current page is not full");
894 if ((uint16_t)(o2::raw::RDHUtils::getPageCounter(*rdh) + 1) != o2::raw::RDHUtils::getPageCounter(*rdhNext)) {
895 GPUError(
"Incomplete HBF: Payload extended to next page, but next page missing in stream (packet counters %d %d)", (int32_t)o2::raw::RDHUtils::getPageCounter(*rdh), (int32_t)o2::raw::RDHUtils::getPageCounter(*rdhNext));
896 extendFailure =
true;
897 decPagePtr = payloadEnd;
903 memcpy(tmpBuffer.data(), decPagePtr, sizeLeftInPage);
905 decPagePtr = tmpBuffer.data();
906 payloadEnd = decPagePtr + tmpBuffer.size();
909 uint16_t linkBC = (*((
const uint16_t*)decPagePtr) & 0xFFF0) >> 4;
910 bool v2Flag = decHDR->
version == ZSVersion::ZSVersionDenseLinkBasedV2 && *((
const uint8_t*)decPagePtr) & 0x10;
911 if (decHDR->
version == ZSVersion::ZSVersionDenseLinkBasedV2) {
914 decPagePtr +=
sizeof(uint16_t);
915 std::vector<int32_t>
links;
916 std::vector<std::bitset<80>> bitmasks;
917 uint32_t nTotalSamples = 0;
918 for (uint32_t l = 0; l < linkCount; l++) {
921 uint8_t decLink = decLinkX & 0b00011111;
922 std::bitset<10> bitmaskL2;
923 if (decLinkX & 0b00100000) {
926 bitmaskL2 = std::bitset<10>(((((uint16_t)decLinkX) & 0b11000000) << 2) | (uint16_t) * ((
const uint8_t*)decPagePtr));
930 std::bitset<80> bitmask(0);
931 for (int32_t
i = 0;
i < 10;
i++) {
932 if (bitmaskL2.test(
i)) {
933 bitmask |= std::bitset<80>(*((
const uint8_t*)decPagePtr)) <<
i * 8;
937 links.emplace_back(decLink);
938 bitmasks.emplace_back(bitmask);
939 nTotalSamples += bitmask.count();
943 int32_t encodeBitsBlock = v2Flag ? v2nbits : encodeBits;
944 decPagePtr += (nTotalSamples * encodeBitsBlock + 7) / 8;
947 int32_t timeBin = (int32_t(linkBC) + (int32_t)(o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstOrbit) *
o2::constants::lhc::LHCMaxBunches - int32_t(triggerBC)) / LHCBCPERTIMEBIN;
948 if (timeBin < 0 || nTotalSamples == 0) {
949 if (timeBin < 0 && nTotalSamples > 0) {
950 LOGP(
debug,
"zsEncoderDenseLinkBased::decodePage skipping digits (linkBC {} + orbit {} - firstOrbit {}) * maxBunch {} - triggerBC {} = {} < 0, nTotalSamples {}", linkBC, o2::raw::RDHUtils::getHeartBeatOrbit(*rdh), firstOrbit,
o2::constants::lhc::LHCMaxBunches, triggerBC, timeBin, nTotalSamples);
954 if (timeBin > maxTimeBin) {
955 maxTimeBin = timeBin;
957 if (timeBin < minTimeBin) {
958 minTimeBin = timeBin;
961 std::vector<uint16_t>
samples(nTotalSamples);
962 uint32_t
mask = (1 << encodeBitsBlock) - 1;
963 uint32_t
byte = 0,
bits = 0, posXbits = 0;
964 while (posXbits < nTotalSamples) {
965 byte |= *(adcData++) <<
bits;
967 while (
bits >= encodeBitsBlock && posXbits < nTotalSamples) {
969 byte =
byte >> encodeBitsBlock;
970 bits -= encodeBitsBlock;
973 uint32_t samplePos = 0;
975 for (uint32_t l = 0; l < linkCount; l++) {
977 const auto& bitmask = bitmasks[l];
978 int32_t nADC = bitmask.count();
980 for (int32_t
j = 0;
j < bitmask.size();
j++) {
982 int32_t sampaOnFEC = 0, channelOnSAMPA = 0;
983 mapper.getSampaAndChannelOnFEC(cruid,
j, sampaOnFEC, channelOnSAMPA);
984 const auto padSecPos = mapper.padSecPos(cruid, decLink, sampaOnFEC, channelOnSAMPA);
985 const auto& padPos = padSecPos.getPadPos();
994 if (triggerBC > 0 && hdrMinTimeBin < 0) {
998 int32_t hdrMaxTimeBin = hdrMinTimeBin + decHDR->
nTimeBinSpan + ((decHDR->
flags & TPCZSHDRV2::ZSFlags::nTimeBinSpanBit8) ? 256 : 0);
1000 if (!extendFailure && nOutput != decHDR->
nADCsamples) {
1001 std::ostringstream oss;
1002 oss <<
"Number of decoded digits " << nOutput <<
" does not match value from MetaInfo " << decHDR->
nADCsamples;
1003 amendPageErrorMessage(oss, rdh, decHDR,
nullptr,
nullptr, nOutput);
1004 throw std::runtime_error(oss.str());
1007 if (decHDR->
nADCsamples && (minTimeBin < hdrMinTimeBin || maxTimeBin > hdrMaxTimeBin)) {
1008 std::ostringstream oss;
1009 oss <<
"Incorrect time bin range in MetaInfo, header reports " << hdrMinTimeBin <<
" - " << hdrMaxTimeBin <<
"(timeOffset: " << decHDR->
timeOffset <<
" + (orbit: " << o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) <<
" - firstOrbit " << firstOrbit <<
") * LHCMaxBunches - triggerBC: " << triggerBC <<
", decoded data is " << minTimeBin <<
" - " << maxTimeBin;
1010 amendPageErrorMessage(oss, rdh, decHDR, payloadEnd, decPagePtr, nOutput);
1011 throw std::runtime_error(oss.str());
1015 std::ostringstream oss;
1016 oss <<
"Decoding ran over end of page";
1017 amendPageErrorMessage(oss, rdh, decHDR, payloadEnd, decPagePtr, nOutput);
1018 throw std::runtime_error(oss.str());
1021 std::ostringstream oss;
1022 oss <<
"Decoding didn't reach end of page";
1023 amendPageErrorMessage(oss, rdh, decHDR, payloadEnd, decPagePtr, nOutput);
1024 throw std::runtime_error(oss.str());
1028void zsEncoderDenseLinkBased::amendPageErrorMessage(std::ostringstream& oss,
const o2::header::RAWDataHeader* rdh,
const TPCZSHDRV2* decHDR,
const uint8_t* payloadEnd,
const uint8_t* decPagePtr, uint32_t nOutput)
1030 if (payloadEnd && decPagePtr) {
1031 oss <<
" (payloadEnd " << (
void*)payloadEnd <<
" - decPagePtr " << (
void*)decPagePtr <<
" - " << (payloadEnd - decPagePtr) <<
" bytes left, " << nOutput <<
" of " << decHDR->
nADCsamples <<
" digits decoded)\n";
1035 constexpr size_t bufferSize = 3 * std::max(
sizeof(*rdh),
sizeof(*decHDR)) + 1;
1037 for (
size_t i = 0;
i <
sizeof(*rdh);
i++) {
1038 snprintf(dumpBuffer + 3 *
i, 4,
"%02X ", (int32_t)((uint8_t*)rdh)[
i]);
1040 oss <<
"RDH of page: " <<
dumpBuffer <<
"\n";
1041 for (
size_t i = 0;
i <
sizeof(*decHDR);
i++) {
1042 snprintf(dumpBuffer + 3 *
i, 4,
"%02X ", (int32_t)((uint8_t*)decHDR)[
i]);
1044 oss <<
"Meta header of page: " <<
dumpBuffer <<
"\n";
1052struct zsEncoderRun :
public T {
1053 uint32_t run(std::vector<zsPage>*
buffer, std::vector<o2::tpc::Digit>& tmpBuffer,
size_t* totalSize =
nullptr);
1054 size_t compare(std::vector<zsPage>*
buffer, std::vector<o2::tpc::Digit>& tmpBuffer);
1056 using T::bcShiftInFirstHBF;
1057 using T::checkInput;
1059 using T::decodePage;
1060 using T::encodeBits;
1061 using T::encodeBitsFactor;
1062 using T::encodeSequence;
1064 using T::firstTimebinInPage;
1072 using T::lastEndpoint;
1075 using T::needAnotherPage;
1077 using T::outputEndpoint;
1078 using T::outputRegion;
1079 using T::packetCounter;
1082 using T::pageCounter;
1087 using T::writeSubPage;
1088 using T::ZSfillEmpty;
1093inline uint32_t zsEncoderRun<T>::run(std::vector<zsPage>*
buffer, std::vector<o2::tpc::Digit>& tmpBuffer,
size_t* totalSize)
1095 uint32_t totalPages = 0;
1096 zsPage singleBuffer;
1101 bcShiftInFirstHBF =
ir ?
ir->
bc : 0;
1102 int32_t orbitShift =
ir ?
ir->
orbit : 0;
1104 int32_t rawendpoint = 0;
1105 (
void)(rawcru + rawendpoint);
1106 encodeBitsFactor = (1 << (encodeBits - 10));
1109 for (uint32_t k = 0; k <= tmpBuffer.size();) {
1110 bool mustWritePage =
false, mustWriteSubPage =
false;
1111 if (needAnotherPage) {
1112 needAnotherPage =
false;
1113 mustWritePage =
true;
1115 if (k < tmpBuffer.size()) {
1119 throw std::runtime_error(
"Received digit before the defined first orbit");
1121 if (hbf != nexthbf) {
1123 mustWritePage =
true;
1126 if (lastRow != tmpBuffer[k].getRow()) {
1127 curRegion =
param->tpcGeometry.GetRegion(tmpBuffer[k].getRow());
1129 mustWriteSubPage = checkInput(tmpBuffer, k);
1132 mustWritePage =
true;
1135 if (mustWritePage || mustWriteSubPage) {
1136 mustWritePage |= writeSubPage();
1138 if (page && mustWritePage) {
1139 if constexpr (std::is_same_v<T, struct zsEncoderDenseLinkBased>) {
1143 uint8_t* triggerWord =
nullptr;
1144 if (hbf != nexthbf ||
endpoint != lastEndpoint) {
1151 needAnotherPage =
true;
1153 if (this->sequenceBuffer.size()) {
1154 needAnotherPage =
true;
1158 triggerWord = pagePtr;
1167 throw std::runtime_error(
"TPC ZS page overflow");
1169 memcpy(pagehdr, hdr,
sizeof(*hdr));
1176 *totalSize += !std::is_same_v<T, struct zsEncoderDenseLinkBased> && (lastEndpoint == -1 || hbf == nexthbf) ?
TPCZSHDR::TPC_ZS_PAGE_SIZE : (pagePtr - (
uint8_t*)page);
1179 size = CAMath::nextMultipleOf<o2::raw::RDHUtils::GBTWord128>(
size);
1183 maxhbf = std::max<int32_t>(maxhbf, hbf);
1184 minhbf = std::min<int32_t>(minhbf, hbf);
1190 o2::raw::RDHUtils::setHeartBeatBC(*rdh, bcShiftInFirstHBF);
1200 if (k >= tmpBuffer.size() && !needAnotherPage) {
1204 if (mustWritePage) {
1205 if (!needAnotherPage) {
1206 if (hbf != nexthbf) {
1209 outputRegion = curRegion;
1216 page = &singleBuffer;
1218 if (
buffer[outputEndpoint].
size() == 0 && nexthbf > orbitShift) {
1219 buffer[outputEndpoint].emplace_back();
1220 ZSfillEmpty(&
buffer[outputEndpoint].back(), bcShiftInFirstHBF, rdh_utils::getFEEID(iSector * 10 + outputEndpoint / 2, outputEndpoint & 1, this->RAWLNK), orbitShift, this->RAWLNK);
1226 buffer[outputEndpoint].emplace_back();
1227 page = &
buffer[outputEndpoint].back();
1229 pagePtr =
reinterpret_cast<uint8_t*
>(page);
1230 std::fill(page->begin(), page->end(), 0);
1232 if constexpr (std::is_same_v<T, struct zsEncoderDenseLinkBased>) {
1233 hdr = &this->hdrBuffer;
1235 hdr =
reinterpret_cast<decltype(hdr)
>(pagePtr);
1236 pagePtr +=
sizeof(*hdr);
1238 hdr->version = zsVersion;
1239 hdr->cruID = iSector * 10 + outputRegion;
1240 hdr->nTimeBinSpan = 0;
1241 hdr->nADCsamples = 0;
1242 rawcru = iSector * 10 + outputRegion;
1243 rawendpoint = outputEndpoint & 1;
1245 firstTimebinInPage = tmpBuffer[k].getTimeStamp();
1249 if (needAnotherPage) {
1252 uint32_t nEncoded = encodeSequence(tmpBuffer, k);
1253 lastTime = tmpBuffer[k].getTimeStamp();
1254 lastRow = tmpBuffer[k].getRow();
1255 hdr->nADCsamples += nEncoded;
1261 for (int32_t
i = minhbf;
i <= maxhbf;
i++) {
1270 ZSfillEmpty(&
buffer[
j].back(), bcShiftInFirstHBF, rdh_utils::getFEEID(iSector * 10 +
j / 2,
j & 1, this->RAWLNK), orbitShift, this->RAWLNK);
1279size_t zsEncoderRun<T>::compare(std::vector<zsPage>*
buffer, std::vector<o2::tpc::Digit>& tmpBuffer)
1282 std::vector<o2::tpc::Digit> compareBuffer;
1283 compareBuffer.reserve(tmpBuffer.size());
1285 uint32_t firstOrbit =
ir ?
ir->
orbit : 0;
1286 for (uint32_t k = 0; k <
buffer[
j].size(); k++) {
1287 zsPage* decPage = &
buffer[
j][k];
1288 decodePage(compareBuffer, decPage,
j, firstOrbit);
1291 if (tmpBuffer.size() != compareBuffer.size()) {
1292 nErrors += tmpBuffer.size();
1293 printf(
"Number of clusters mismatch %d %d\n", (int32_t)tmpBuffer.size(), (int32_t)compareBuffer.size());
1295 for (uint32_t
j = 0;
j < tmpBuffer.size();
j++) {
1296 const float decodeBitsFactor = (1 << (encodeBits - 10));
1297 const float c = CAMath::Round(tmpBuffer[
j].getChargeFloat() * decodeBitsFactor) / decodeBitsFactor;
1298 int32_t ok =
c == compareBuffer[
j].getChargeFloat() && (int32_t)tmpBuffer[
j].
getTimeStamp() == (int32_t)compareBuffer[
j].
getTimeStamp() && (int32_t)tmpBuffer[
j].getPad() == (int32_t)compareBuffer[
j].getPad() && (int32_t)tmpBuffer[
j].getRow() == (int32_t)compareBuffer[
j].getRow();
1303 printf(
"%4u: OK %d: Charge %3d %3d Time %4d %4d Pad %3d %3d Row %3d %3d\n",
j, ok,
1304 (int32_t)
c, (int32_t)compareBuffer[
j].getChargeFloat(), (int32_t)tmpBuffer[
j].
getTimeStamp(), (int32_t)compareBuffer[
j].
getTimeStamp(), (int32_t)tmpBuffer[
j].getPad(), (int32_t)compareBuffer[
j].getPad(), (int32_t)tmpBuffer[
j].getRow(), (int32_t)compareBuffer[
j].getRow());
1315void GPUReconstructionConvert::RunZSEncoder(
const S& in, std::unique_ptr<uint64_t[]>* outBuffer, uint32_t* outSizes,
o2::raw::RawFileWriter* raw,
const o2::InteractionRecord*
ir,
const GPUParam&
param, int32_t
version,
bool verify,
float threshold,
bool padding, std::function<
void(std::vector<o2::tpc::Digit>&)> digitsFilter)
1319 if (((outBuffer ==
nullptr) ^ (outSizes ==
nullptr)) || ((raw !=
nullptr) && (
ir ==
nullptr)) || !((outBuffer ==
nullptr) ^ (raw ==
nullptr)) || (raw && verify)) {
1320 throw std::runtime_error(
"Invalid parameters");
1322#ifdef GPUCA_TPC_GEOMETRY_O2
1324 struct tmpReductionResult {
1325 uint32_t totalPages = 0;
1326 size_t totalSize = 0;
1328 size_t digitsInput = 0;
1329 size_t digitsEncoded = 0;
1331 auto reduced = tbb::parallel_reduce(tbb::blocked_range<uint32_t>(0,
NSECTORS), tmpReductionResult(), [&](
const auto range,
auto red) {
1333 std::vector<o2::tpc::Digit> tmpBuffer;
1334 red.digitsInput += ZSEncoderGetNDigits(in,
i);
1335 tmpBuffer.resize(ZSEncoderGetNDigits(in,
i));
1336 if (threshold > 0.f && !digitsFilter) {
1337 auto it = std::copy_if(ZSEncoderGetDigits(in,
i), ZSEncoderGetDigits(in,
i) + ZSEncoderGetNDigits(in,
i), tmpBuffer.begin(), [threshold](
auto&
v) { return v.getChargeFloat() >= threshold; });
1338 tmpBuffer.resize(std::distance(tmpBuffer.begin(), it));
1340 std::copy(ZSEncoderGetDigits(in,
i), ZSEncoderGetDigits(in,
i) + ZSEncoderGetNDigits(in,
i), tmpBuffer.begin());
1344 digitsFilter(tmpBuffer);
1345 if (threshold > 0.f) {
1346 std::vector<o2::tpc::Digit> tmpBuffer2 = std::move(tmpBuffer);
1347 tmpBuffer = std::vector<o2::tpc::Digit>(tmpBuffer2.size());
1348 auto it = std::copy_if(tmpBuffer2.begin(), tmpBuffer2.end(), tmpBuffer.begin(), [threshold](
auto&
v) { return v.getChargeFloat() >= threshold; });
1349 tmpBuffer.resize(std::distance(tmpBuffer.begin(), it));
1352 red.digitsEncoded += tmpBuffer.size();
1354 auto runZS = [&](
auto& encoder) {
1357 red.totalPages += encoder.run(
buffer[
i], tmpBuffer, &red.totalSize);
1359 red.nErrors += encoder.compare(
buffer[
i], tmpBuffer);
1363 if (
version >= ZSVersion::ZSVersionRowBased10BitADC &&
version <= ZSVersion::ZSVersionRowBased12BitADC) {
1364 zsEncoderRun<zsEncoderRow> enc{{{.iSector =
i, .raw = raw, .ir =
ir, .param = &
param, .padding =
padding}}};
1366 }
else if (
version >= ZSVersion::ZSVersionLinkBasedWithMeta &&
version <= ZSVersion::ZSVersionDenseLinkBasedV2) {
1368 if (
version == ZSVersion::ZSVersionLinkBasedWithMeta) {
1369 zsEncoderRun<zsEncoderImprovedLinkBased> enc{{{{.iSector =
i, .raw = raw, .ir =
ir, .param = &
param, .padding =
padding}}}};
1371 }
else if (
version >= ZSVersion::ZSVersionDenseLinkBased &&
version <= ZSVersion::ZSVersionDenseLinkBasedV2) {
1372 zsEncoderRun<zsEncoderDenseLinkBased> enc{{{{.iSector =
i, .raw = raw, .ir =
ir, .param = &
param, .padding =
padding}}}};
1376 throw std::runtime_error(
"Link based ZS encoding not supported in standalone build");
1382 return red; }, [&](
const auto& red1,
const auto& red2) {
1384 red.totalPages += red2.totalPages;
1385 red.totalSize += red2.totalSize;
1386 red.nErrors += red2.nErrors;
1387 red.digitsInput += red2.digitsInput;
1388 red.digitsEncoded += red2.digitsEncoded;
1402 if (reduced.nErrors) {
1403 GPUError(
"ERROR: %lu INCORRECT SAMPLES DURING ZS ENCODING VERIFICATION!!!", reduced.nErrors);
1404 }
else if (verify) {
1405 GPUInfo(
"ENCODING VERIFICATION PASSED");
1407 GPUInfo(
"TOTAL ENCODED SIZE: %lu (%lu of %lu digits encoded)", reduced.totalSize, reduced.digitsEncoded, reduced.digitsInput);
1411template void GPUReconstructionConvert::RunZSEncoder<GPUTrackingInOutDigits>(
const GPUTrackingInOutDigits&, std::unique_ptr<uint64_t[]>*, uint32_t*,
o2::raw::RawFileWriter*,
const o2::InteractionRecord*,
const GPUParam&, int32_t,
bool,
float,
bool, std::function<
void(std::vector<o2::tpc::Digit>&)> digitsFilter);
1413template void GPUReconstructionConvert::RunZSEncoder<DigitArray>(
const DigitArray&, std::unique_ptr<uint64_t[]>*, uint32_t*,
o2::raw::RawFileWriter*,
const o2::InteractionRecord*,
const GPUParam&, int32_t,
bool,
float,
bool, std::function<
void(std::vector<o2::tpc::Digit>&)> digitsFilter);
1433 if (
buffers[
i].get() != ptrs[
i] || nsb != ns) {
1434 throw std::runtime_error(
"Not owning digits");
1438 const float decodeBitsFactor = (1 << (decodeBits - 10));
1439 for (uint32_t k = 0; k < ns[
i]; k++) {
1440 if (
buffers[
i][k].getChargeFloat() >= threshold) {
1445 buffers[
i][
j].setCharge(CAMath::Round(
buffers[
i][
j].getChargeFloat() * decodeBitsFactor) / decodeBitsFactor);
1462 std::shared_ptr<T> enc = std::make_shared<T>();
1463 if (
param ==
nullptr) {
1465 param = &dummyParam;
1470 return [enc](std::vector<o2::tpc::Digit>& outBuffer,
const void* page, uint32_t firstTfOrbit, uint32_t triggerBC = 0) {
1475 if (o2::raw::RDHUtils::getDetectorField(rdh) != 2) {
1479 enc->iSector = cru.sector();
1480 int32_t
endpoint = cru.region() * 2 + o2::tpc::rdh_utils::getEndPoint(rdh);
1481 enc->decodePage(outBuffer, (
const zsPage*)page,
endpoint, firstTfOrbit, triggerBC);
1489 return o2::gpu::internal::GetDecoder_internal<zsEncoderRow>(
param,
version);
1491 return o2::gpu::internal::GetDecoder_internal<zsEncoderImprovedLinkBased>(
param,
version);
1493 return o2::gpu::internal::GetDecoder_internal<zsEncoderDenseLinkBased>(
param,
version);
1495 throw std::runtime_error(
"Invalid ZS version "s +
std::to_string(
version) +
", cannot create decoder"s);
Header to collect LHC related constants.
Utility class to write detectors data to (multiple) raw data file(s) respecting CRU format.
definitions to deal with the link based zero suppression format
Definitions of TPC Zero Suppression Data Headers.
static void RunZSEncoder(const S &in, std::unique_ptr< uint64_t[]> *outBuffer, uint32_t *outSizes, o2::raw::RawFileWriter *raw, const o2::InteractionRecord *ir, const GPUParam ¶m, int32_t version, bool verify, float threshold=0.f, bool padding=false, std::function< void(std::vector< o2::tpc::Digit > &)> digitsFilter=nullptr)
static void ConvertNativeToClusterData(o2::tpc::ClusterNativeAccess *native, std::unique_ptr< GPUTPCClusterData[]> *clusters, uint32_t *nClusters, const TPCFastTransform *transform, int32_t continuousMaxTimeBin=0)
static void RunZSFilter(std::unique_ptr< o2::tpc::Digit[]> *buffers, const o2::tpc::Digit *const *ptrs, size_t *nsb, const size_t *ns, const GPUParam ¶m, bool zs12bit, float threshold)
static std::function< void(std::vector< o2::tpc::Digit > &, const void *, uint32_t, uint32_t)> GetDecoder(int32_t version, const GPUParam *param)
static int32_t GetMaxTimeBin(const o2::tpc::ClusterNativeAccess &native)
static constexpr uint32_t NSECTORS
static void RunZSEncoderCreateMeta(const uint64_t *buffer, const uint32_t *sizes, void **ptrs, GPUTrackingInOutZS *out)
static void ConvertRun2RawToNative(o2::tpc::ClusterNativeAccess &native, std::unique_ptr< o2::tpc::ClusterNative[]> &nativeBuffer, const AliHLTTPCRawCluster **rawClusters, uint32_t *nRawClusters)
void addData(uint16_t feeid, uint16_t cru, uint8_t lnk, uint8_t endpoint, const IR &ir, const gsl::span< char > data, bool preformatted=false, uint32_t trigger=0, uint32_t detField=0)
unsigned char partition() const
unsigned char getSampaChannel() const
unsigned char getIndex() const
unsigned char getSampaChip() const
static Mapper & instance(const std::string mappingDir="")
static constexpr void getSampaAndChannelOnFEC(const int cruID, const size_t rawFECChannel, int &sampaOnFEC, int &channelOnSAMPA)
static constexpr int MAXSECTOR
std::array< gsl::span< const o2::tpc::Digit >, Sector::MAXSECTOR > DigitArray
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLboolean GLboolean GLboolean b
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
uint8_t itsSharedClusterMap uint8_t
constexpr int LHCMaxBunches
const GBTLinkAttributes links[kNGBTLinks]
void dumpBuffer(gsl::span< const std::byte > buffer, std::ostream &out=std::cout, size_t maxbytes=std::numeric_limits< size_t >::max())
constexpr int LHCBCPERTIMEBIN
uint64_t getTimeStamp(o2::framework::ProcessingContext &pc)
Global TPC definitions and constants.
@ ZSVersionDenseLinkBased
@ ZSVersionLinkBasedWithMeta
@ ZSVersionDenseLinkBasedV2
@ ZSVersionRowBased10BitADC
@ ZSVersionRowBased12BitADC
unsigned short GlobalPadNumber
global pad number
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
int32_t GetCharge() const
uint16_t GetFlags() const
float GetSigmaTime2() const
int32_t GetPadRow() const
float GetSigmaPad2() const
uint16_t bc
bunch crossing ID of interaction
const o2::tpc::Digit * tpcDigits[NSECTORS]
size_t nTPCDigits[NSECTORS]
const void *const * zsPtr[NENDPOINTS]
uint32_t count[NENDPOINTS]
const uint32_t * nZSPtr[NENDPOINTS]
GPUTrackingInOutZSSector sector[NSECTORS]
static constexpr uint32_t NENDPOINTS
static void setLinkID(H &rdh, uint8_t v, NOTPTR(H))
static void setDetectorField(H &rdh, uint32_t v, NOTPTR(H))
static constexpr int GBTWord128
static void setPageCounter(H &rdh, uint16_t v, NOTPTR(H))
static void setMemorySize(H &rdh, uint16_t v, NOTPTR(H))
static void setVersion(H &rdh, uint8_t v, NOTPTR(H))
static void setPacketCounter(H &rdh, uint8_t v, NOTPTR(H))
static void setHeartBeatOrbit(RDHv4 &rdh, uint32_t v)
static void setFEEID(RDHv4 &rdh, uint16_t v)
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int nClustersTotal
const ClusterNative * clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
const ClusterNative * clustersLinear
@ payloadExtendsToNextPage
unsigned short nTimebinHeaders
unsigned short firstZSDataOffset
static constexpr bool TIGHTLY_PACKED_V3
static constexpr unsigned int TPC_ZS_NBITS_V34
static constexpr unsigned int SAMPLESPER64BIT
static constexpr unsigned int TRIGGER_WORD_SIZE
unsigned char nTimeBinSpan
unsigned short timeOffset
static constexpr unsigned int TPC_ZS_NBITS_V1
static constexpr unsigned int TPC_ZS_NBITS_V2
static constexpr size_t TPC_ZS_PAGE_SIZE
unsigned short nADCsamples
void compare(std::string_view s1, std::string_view s2)
o2::InteractionRecord ir(0, 0)
std::vector< Cluster > clusters
std::vector< Digit > digits