12#ifndef TRACKINGITSU_INCLUDE_ROFOVERLAPTABLE_H_
13#define TRACKINGITSU_INCLUDE_ROFOVERLAPTABLE_H_
51 assert(rofId < mNROFsTF && rofId >= 0);
90 const BCType bc = (ts.getTimeStamp() < ts.getTimeStampError()) ?
BCType(0) :
static_cast<BCType>(o2::gpu::CAMath::Floor(ts.getTimeStamp() - ts.getTimeStampError()));
107 GPUhdi() bool intersectROF(
BCType rof,
float lower,
float upper) const noexcept
109 const auto rofTS = getROFTimeBounds(rof,
true);
110 return static_cast<float>(rofTS.upper()) > lower && upper >
static_cast<float>(rofTS.lower());
116 const float lower = ts.getTimeStamp() - ts.getTimeStampError();
117 const float upper = ts.getTimeStamp() + ts.getTimeStampError();
118 return getROFRange(lower, upper);
123 return getROFRange(
static_cast<float>(ts.lower()),
static_cast<float>(ts.upper()));
126 GPUhdi()
BCRange getROFRange(
float lower,
float upper) const noexcept
132 if (
first <= last && !intersectROF(
first, lower, upper)) {
135 if (last >=
first && !intersectROF(last, lower, upper)) {
138 return {
first, first <= last ? static_cast<BCType>(last -
first + 1) :
BCType{0}};
155template <
int32_t NLayers>
168 mLayers[
layer] = {nROFsTF, rofLength, rofDelay, rofBias, rofTE};
174 mLayers[
layer] = timing;
180 return mLayers[
layer];
183 GPUhdi() constexpr int32_t getEntries() noexcept {
return NLayers; }
188 LOGP(info,
"Imposed time structure:");
189 for (int32_t iL{0}; iL < NLayers; ++iL) {
190 LOGP(info,
"\tLayer:{} {}", iL, mLayers[iL].
asString());
197template <
int32_t NLayers,
typename TableEntry,
typename TableIndex>
199 const TableEntry* mFlatTable{
nullptr};
200 const TableIndex* mIndices{
nullptr};
206 return mLayers[
layer];
209 GPUh() int32_t getClock() const noexcept
213 uint32_t maxNROFs{0};
214 for (int32_t iL{0}; iL < NLayers; ++iL) {
215 const auto&
layer = getLayer(iL);
219 if (
layer.mNROFsTF > maxNROFs) {
221 maxNROFs =
layer.mNROFsTF;
229 return mLayers[getClock()];
232 GPUhdi() const TableEntry& getOverlap(int32_t from, int32_t to,
size_t rofIdx) const noexcept
234 assert(from < NLayers && to < NLayers);
235 const size_t linearIdx = (from * NLayers) + to;
236 const auto& idx = mIndices[linearIdx];
238 return mFlatTable[idx.getFirstEntry() + rofIdx];
241 GPUhdi() bool doROFsOverlap(int32_t layer0,
size_t rof0, int32_t layer1,
size_t rof1) const noexcept
243 if (layer0 == layer1) {
247 assert(layer0 < NLayers && layer1 < NLayers);
248 const size_t linearIdx = (layer0 * NLayers) + layer1;
249 const auto& idx = mIndices[linearIdx];
251 if (rof0 >= idx.getEntries()) {
255 const auto& overlap = mFlatTable[idx.getFirstEntry() + rof0];
257 if (overlap.getEntries() == 0) {
261 const size_t firstCompatible = overlap.getFirstEntry();
262 const size_t lastCompatible = firstCompatible + overlap.getEntries() - 1;
263 return rof1 >= firstCompatible && rof1 <= lastCompatible;
266 GPUhdi()
TimeEstBC getTimeStamp(int32_t layer0,
size_t rof0, int32_t layer1,
size_t rof1) const noexcept
268 assert(layer0 < NLayers && layer1 < NLayers);
269 assert(doROFsOverlap(layer0, rof0, layer1, rof1));
275 const auto t0 = mLayers[layer0].getROFTimeBounds(rof0,
true);
276 const auto t1 = mLayers[layer1].getROFTimeBounds(rof1,
true);
284 for (int32_t
i = 0;
i < NLayers; ++
i) {
285 for (int32_t
j = 0;
j < NLayers; ++
j) {
294 GPUh()
void printMapping(int32_t from, int32_t to)
const
297 LOGP(error,
"No self-lookup supported");
301 constexpr int w_index = 10;
302 constexpr int w_first = 12;
303 constexpr int w_last = 12;
304 constexpr int w_count = 10;
306 LOGF(info,
"Overlap mapping: Layer %d -> Layer %d", from, to);
309 LOGF(info,
"%*s | %*s | %*s | %*s", w_index,
"ROF.index", w_first,
"First.ROF", w_last,
"Last.ROF", w_count,
"Count");
310 LOGF(info,
"%.*s-+-%.*s-+-%.*s-+-%.*s", w_index,
"----------", w_first,
"------------", w_last,
"------------", w_count,
"----------");
312 const size_t linearIdx = (from * NLayers) + to;
313 const auto& idx = mIndices[linearIdx];
314 for (int32_t
i = 0;
i < idx.getEntries(); ++
i) {
315 const auto& overlap = getOverlap(from, to,
i);
316 LOGF(info,
"%*d | %*d | %*d | %*d", w_index,
i, w_first, overlap.getFirstEntry(), w_last, overlap.getEntriesBound() - 1, w_count, overlap.getEntries());
322 uint32_t totalEntries{0};
323 size_t flatTableSize{0};
325 for (int32_t
i = 0;
i < NLayers; ++
i) {
326 for (int32_t
j = 0;
j < NLayers; ++
j) {
328 const size_t linearIdx = (
i * NLayers) +
j;
329 const auto& idx = mIndices[linearIdx];
330 totalEntries += idx.getEntries();
331 flatTableSize += idx.getEntries();
336 for (int32_t
i = 0;
i < NLayers; ++
i) {
340 const uint32_t totalBytes = (flatTableSize *
sizeof(TableEntry)) + (
static_cast<unsigned long>(NLayers * NLayers) *
sizeof(TableIndex));
341 LOGF(info,
"------------------------------------------------------------");
342 LOGF(info,
"Total overlap table size: %u entries", totalEntries);
343 LOGF(info,
"Flat table size: %zu entries", flatTableSize);
344 LOGF(info,
"Total view size: %u bytes", totalBytes);
345 LOGF(info,
"------------------------------------------------------------");
351template <
int32_t NLayers>
364 std::vector<TableEntry> table[NLayers][NLayers];
365 for (int32_t
i{0};
i < NLayers; ++
i) {
366 for (int32_t
j{0};
j < NLayers; ++
j) {
368 buildMapping(
i,
j, table[
i][
j]);
393 GPUh() size_t getFlatTableSize() const noexcept {
return mFlatTable.size(); }
394 static GPUh() constexpr
size_t getIndicesSize() {
return static_cast<size_t>(NLayers * NLayers); }
397 GPUh()
void buildMapping(int32_t from, int32_t to,
std::vector<TableEntry>& table)
399 const auto& layerFrom = this->mLayers[from];
400 const auto& layerTo = this->mLayers[to];
401 table.resize(layerFrom.mNROFsTF);
403 for (int32_t iROF{0}; iROF < layerFrom.mNROFsTF; ++iROF) {
405 int64_t fromEnd = (
int64_t)layerFrom.getROFEndInBC(iROF) + layerFrom.mROFAddTimeErr;
407 int32_t firstROFTo = o2::gpu::CAMath::Max(0, (int32_t)((fromStart - (
int64_t)layerTo.mROFAddTimeErr - (
int64_t)layerTo.mROFDelay - (
int64_t)layerTo.mROFBias) / (
int64_t)layerTo.mROFLength));
408 auto lastROFTo = (int32_t)((fromEnd + (
int64_t)layerTo.mROFAddTimeErr - (
int64_t)layerTo.mROFDelay - (
int64_t)layerTo.mROFBias - 1) / (
int64_t)layerTo.mROFLength);
409 firstROFTo = o2::gpu::CAMath::Max(0, firstROFTo);
410 lastROFTo = o2::gpu::CAMath::Min((int32_t)layerTo.mNROFsTF - 1, lastROFTo);
412 while (firstROFTo <= lastROFTo) {
414 int64_t toEnd = (
int64_t)layerTo.getROFEndInBC(firstROFTo) + layerTo.mROFAddTimeErr;
415 if (toEnd > fromStart && toStart < fromEnd) {
420 while (lastROFTo >= firstROFTo) {
422 int64_t toEnd = (
int64_t)layerTo.getROFEndInBC(lastROFTo) + layerTo.mROFAddTimeErr;
423 if (toEnd > fromStart && toStart < fromEnd) {
428 int32_t
count = (firstROFTo <= lastROFTo) ? (lastROFTo - firstROFTo + 1) : 0;
429 table[iROF] = {
static_cast<T>(firstROFTo),
static_cast<T>(
count)};
436 for (int32_t
i{0};
i < NLayers; ++
i) {
437 for (int32_t
j{0};
j < NLayers; ++
j) {
439 total += table[
i][
j].size();
444 mFlatTable.reserve(total);
446 for (int32_t
i{0};
i < NLayers; ++
i) {
447 for (int32_t
j{0};
j < NLayers; ++
j) {
448 size_t idx = (
i * NLayers) +
j;
450 mIndices[
idx].setFirstEntry(
static_cast<T>(mFlatTable.size()));
451 mIndices[
idx].setEntries(
static_cast<T>(table[
i][
j].
size()));
452 mFlatTable.insert(mFlatTable.end(), table[
i][
j].begin(), table[
i][
j].end());
454 mIndices[
idx] = {0, 0};
460 TableIndex mIndices[NLayers * NLayers];
461 std::vector<TableEntry> mFlatTable;
465template <
int32_t NLayers,
typename TableEntry,
typename TableIndex>
467 const TableEntry* mFlatTable{
nullptr};
468 const TableIndex* mIndices{
nullptr};
474 return mLayers[
layer];
477 GPUhdi() const TableEntry& getVertices(int32_t
layer,
size_t rofIdx) const noexcept
479 assert(
layer < NLayers);
482 return mFlatTable[idx.getFirstEntry() + rofIdx];
485 GPUh() int32_t getMaxVerticesPerROF() const noexcept
489 const auto& idx = mIndices[
layer];
490 for (int32_t
i = 0;
i < idx.getEntries(); ++
i) {
491 const auto&
entry = mFlatTable[idx.getFirstEntry() +
i];
501 assert(
layer < NLayers);
502 const auto& layerDef = mLayers[
layer];
504 int64_t rofUpper = (
int64_t)layerDef.getROFEndInBC(rofIdx) + layerDef.mROFAddTimeErr;
507 return vUpper >= rofLower && vLower < rofUpper;
513 for (int32_t
i = 0;
i < NLayers; ++
i) {
521 constexpr int w_rof = 10;
522 constexpr int w_first = 12;
523 constexpr int w_last = 12;
524 constexpr int w_count = 10;
526 LOGF(info,
"Vertex lookup: Layer %d",
layer);
527 LOGF(info,
"%*s | %*s | %*s | %*s", w_rof,
"ROF.index", w_first,
"First.Vtx", w_last,
"Last.Vtx", w_count,
"Count");
528 LOGF(info,
"%.*s-+-%.*s-+-%.*s-+-%.*s", w_rof,
"----------", w_first,
"------------", w_last,
"------------", w_count,
"----------");
530 const auto& idx = mIndices[
layer];
531 for (int32_t
i = 0;
i < idx.getEntries(); ++
i) {
532 const auto&
entry = mFlatTable[idx.getFirstEntry() +
i];
536 LOGF(info,
"%*d | %*d | %*d | %*d", w_rof,
i, w_first,
first, w_last, last, w_count,
count);
542 uint32_t totalROFs{0};
543 uint32_t totalVertexRefs{0};
545 for (int32_t
i = 0;
i < NLayers; ++
i) {
546 const auto& idx = mIndices[
i];
547 totalROFs += idx.getEntries();
549 for (int32_t
j = 0;
j < idx.getEntries(); ++
j) {
550 const auto&
entry = mFlatTable[idx.getFirstEntry() +
j];
551 totalVertexRefs +=
entry.getEntries();
555 const uint32_t totalBytes = (totalROFs *
sizeof(TableEntry)) + (NLayers *
sizeof(TableIndex));
556 LOGF(info,
"------------------------------------------------------------");
557 LOGF(info,
"Total ROFs in table: %u", totalROFs);
558 LOGF(info,
"Total vertex references: %u", totalVertexRefs);
559 LOGF(info,
"Total view size: %u bytes", totalBytes);
560 LOGF(info,
"------------------------------------------------------------");
570template <
int32_t NLayers>
582 GPUh() size_t getFlatTableSize() const noexcept {
return mFlatTable.size(); }
583 static GPUh() constexpr
size_t getIndicesSize() {
return NLayers; }
589 if (nVertices > std::numeric_limits<T>::max()) {
590 LOGF(fatal,
"too many vertices %zu, max supported is %u", nVertices, std::numeric_limits<T>::max());
593 std::vector<TableEntry> table[NLayers];
595 buildMapping(
layer, vertices, nVertices, table[
layer]);
605 total += this->mLayers[
layer].mNROFsTF;
607 mFlatTable.resize(total, {0, 0});
610 size_t nROFs = this->mLayers[
layer].mNROFsTF;
612 mIndices[
layer].setEntries(
static_cast<T>(nROFs));
622 const auto& idx = mIndices[
layer];
623 size_t nROFs = idx.getEntries();
624 for (
size_t iROF = 0; iROF < nROFs; ++iROF) {
625 updateROFMapping(
layer, iROF, vertices, nVertices,
offset + iROF);
651 GPUh()
void buildMapping(int32_t
layer, const
Vertex* vertices,
size_t nVertices,
std::vector<TableEntry>& table)
653 const auto& layerDef = this->mLayers[
layer];
654 table.resize(layerDef.mNROFsTF);
655 size_t vertexSearchStart = 0;
656 for (int32_t iROF{0}; iROF < layerDef.mNROFsTF; ++iROF) {
658 int64_t rofUpper = (
int64_t)layerDef.getROFEndInBC(iROF) + layerDef.mROFAddTimeErr;
659 size_t lastVertex = binarySearchFirst(vertices, nVertices, vertexSearchStart, rofUpper);
660 size_t firstVertex = vertexSearchStart;
661 while (firstVertex < lastVertex) {
662 auto vUpper = (
int64_t)vertices[firstVertex].getTimeStamp().upper();
663 if (vUpper > rofLower) {
668 size_t count = (lastVertex > firstVertex) ? (lastVertex - firstVertex) : 0;
669 table[iROF] = {
static_cast<T>(firstVertex),
static_cast<T>(
count)};
670 vertexSearchStart = firstVertex;
675 GPUh()
void updateROFMapping(int32_t
layer,
size_t iROF, const Vertex* vertices,
size_t nVertices,
size_t flatTableIdx)
677 const auto& layerDef = this->mLayers[
layer];
679 int64_t rofUpper = (
int64_t)layerDef.getROFEndInBC(iROF) + layerDef.mROFAddTimeErr;
680 size_t lastVertex = binarySearchFirst(vertices, nVertices, 0, rofUpper);
681 size_t firstVertex = 0;
682 while (firstVertex < lastVertex) {
685 if (vUpper > rofLower) {
690 size_t count = (lastVertex > firstVertex) ? (lastVertex - firstVertex) : 0;
691 mFlatTable[flatTableIdx].setFirstEntry(
static_cast<T>(firstVertex));
692 mFlatTable[flatTableIdx].setEntries(
static_cast<T>(
count));
696 GPUh() size_t binarySearchFirst(const Vertex* vertices,
size_t nVertices,
size_t searchStart, BCType targetBC)
const
698 size_t left = searchStart;
699 size_t right = nVertices;
703 if (lower < targetBC) {
717 for (int32_t
i{0};
i < NLayers; ++
i) {
718 total += table[
i].size();
721 mFlatTable.reserve(total);
724 for (int32_t
i{0};
i < NLayers; ++
i) {
725 mIndices[
i].setFirstEntry(
static_cast<T>(mFlatTable.size()));
726 mIndices[
i].setEntries(
static_cast<T>(table[
i].
size()));
727 mFlatTable.insert(mFlatTable.end(), table[
i].begin(), table[
i].end());
731 TableIndex mIndices[NLayers];
732 std::vector<TableEntry> mFlatTable;
736template <
int32_t NLayers,
typename TableEntry,
typename TableIndex>
738 const TableEntry* mFlatMask{
nullptr};
739 const TableIndex* mLayerROFOffsets{
nullptr};
741 GPUhdi() bool isROFEnabled(int32_t
layer, int32_t rofId) const noexcept
744 return mFlatMask[mLayerROFOffsets[
layer] + rofId] != 0u;
750 for (int32_t
i = 0;
i < NLayers; ++
i) {
757 constexpr int w_rof = 10;
758 constexpr int w_active = 10;
759 int32_t nROFs = mLayerROFOffsets[
layer + 1] - mLayerROFOffsets[
layer];
760 LOGF(info,
"Mask table: Layer %d",
layer);
761 LOGF(info,
"%*s | %*s", w_rof,
"ROF", w_active,
"Enabled");
762 LOGF(info,
"%.*s-+-%.*s", w_rof,
"----------", w_active,
"----------");
763 for (int32_t
i = 0;
i < nROFs; ++
i) {
764 LOGF(info,
"%*d | %*d", w_rof,
i, w_active, (
int)isROFEnabled(
layer,
i));
770 int32_t nROFs = mLayerROFOffsets[
layer + 1] - mLayerROFOffsets[
layer];
771 int32_t enabledROFs = 0;
772 for (int32_t
j = 0;
j < nROFs; ++
j) {
773 if (isROFEnabled(
layer,
j)) {
777 return std::format(
"ROFMask on Layer {} ROFs enabled: {}/{}",
layer, enabledROFs, nROFs);
788template <
int32_t NLayers>
803 int32_t totalROFs = 0;
805 mLayerROFOffsets[
layer] = totalROFs;
806 totalROFs += this->getLayer(
layer).mNROFsTF;
808 mLayerROFOffsets[NLayers] = totalROFs;
809 mFlatMask.resize(totalROFs, 0u);
812 GPUh() size_t getFlatMaskSize() const noexcept {
return mFlatMask.size(); }
817 assert(rofId >= 0 && rofId < mLayerROFOffsets[
layer + 1] - mLayerROFOffsets[
layer]);
818 mFlatMask[mLayerROFOffsets[
layer] + rofId] =
state;
821 GPUh()
void setROFsEnabled(int32_t
layer, int32_t firstRof, int32_t nRofs, uint8_t
state = 1) noexcept
824 assert(firstRof >= 0);
825 assert(firstRof + nRofs <= mLayerROFOffsets[
layer + 1] - mLayerROFOffsets[
layer]);
826 std::memset(mFlatMask.data() + mLayerROFOffsets[
layer] + firstRof,
state, nRofs);
830 GPUh()
void selectROF(const BCRange& t)
832 const int32_t bcStart = t.getFirstEntry();
833 const int32_t bcEnd = t.getEntriesBound();
835 const auto& lay = this->getLayer(
layer);
837 for (int32_t rofId{0}; rofId < lay.mNROFsTF; ++rofId) {
838 if (
static_cast<int32_t
>(lay.getROFStartInBC(rofId)) < bcEnd &&
839 static_cast<int32_t
>(lay.getROFEndInBC(rofId)) > bcStart) {
840 mFlatMask[
offset + rofId] = 1u;
847 GPUh()
void selectROFs(const
std::vector<BCRange>& ts)
850 for (
const auto& t : ts) {
855 GPUh()
void resetMask(uint8_t s = 0u)
857 std::memset(mFlatMask.data(), s, mFlatMask.size());
862 std::ranges::transform(mFlatMask, mFlatMask.begin(), [](uint8_t
x) { return 1 - x; });
867 std::swap(mFlatMask,
other.mFlatMask);
868 std::swap(mLayerROFOffsets,
other.mLayerROFOffsets);
871 GPUh() View getView()
const
874 view.mFlatMask = mFlatMask.data();
875 view.mLayerROFOffsets = mLayerROFOffsets;
879 GPUh() View getDeviceView(const TableEntry* deviceFlatMaskPtr, const TableIndex* deviceOffsetPtr)
const
882 view.mFlatMask = deviceFlatMaskPtr;
883 view.mLayerROFOffsets = deviceOffsetPtr;
888 TableIndex mLayerROFOffsets[NLayers + 1] = {0};
std::string asString(TDataMember const &dm, char *pointer)
Header to collect LHC related constants.
Class to refer to the 1st entry and N elements of some group in the continuous container.
GPUhdi() const LayerTiming &getLayer(int32_t layer) const
GPUh() void defineLayer(int32_t layer
GPUhdi() const expr int32_t getEntries() noexcept
LayerTimingBase()=default
GPUh() void print() const
GPUh() explicit ROFMaskTable(const LayerTimingBase< NLayers > &timingBase)
GPUh() size_t getFlatMaskSize() const noexcept
GPUh() void setROFEnabled(int32_t layer
LayerTimingBase< NLayers >::T T
std::vector< TableEntry > mFlatMask
LayerTimingBase< NLayers >::T T
GPUh() View getView() const
static GPUh() const expr size_t getIndicesSize()
ROFOverlapTable()=default
GPUh() size_t getFlatTableSize() const noexcept
LayerTiming::BCType BCType
GPUh() View getView() const
ROFVertexLookupTable()=default
GPUh() void update(const Vertex *vertices
static GPUh() const expr size_t getIndicesSize()
GPUh() size_t getFlatTableSize() const noexcept
GPUh() void init(const Vertex *vertices
LayerTimingBase< NLayers >::T T
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLenum GLuint GLint GLint layer
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
constexpr int LHCMaxBunches
uint16_t TimeStampErrorType
uint64_t getTimeStamp(o2::framework::ProcessingContext &pc)
GPUhdi() BCType getROFStartInBC(BCType rofId) const noexcept
GPUhdi() TimeEstBC getROFTimeBounds(BCType rofId
GPUhdi() BCType getROFEndInBC(BCType rofId) const noexcept
dataformats::RangeReference< BCType, BCType > BCRange
GPUhdi() bool isROFEnabled(int32_t layer
GPUh() void printLayer(int32_t layer) const
GPUh() void printAll() const
LOGP(info, "From: {}", mLayers[from].asString())
LOGF(info, "%*s | %*s | %*s | %*s", w_index, "ROF.index", w_first, "First.ROF", w_last, "Last.ROF", w_count, "Count")
GPUhdi() const LayerTiming &getLayer(int32_t layer) const noexcept
const LayerTiming * mLayers
const TableIndex * mIndices
GPUhdi() bool doROFsOverlap(int32_t layer0
assert(rofIdx< idx.getEntries())
GPUh() void printSummary() const
LOGF(info, "Overlap mapping: Layer %d -> Layer %d", from, to)
GPUh() const LayerTiming &getClockLayer() const noexcept
GPUh() void printAll() const
Print functions.
GPUh() int32_t getClock() const noexcept
GPUhdi() const TableEntry &getOverlap(int32_t from
GPUhdi() TimeEstBC getTimeStamp(int32_t layer0
LOGP(info, "To : {}", mLayers[to].asString())
LOGF(info, "%.*s-+-%.*s-+-%.*s-+-%.*s", w_index, "----------", w_first, "------------", w_last, "------------", w_count, "----------")
assert(doROFsOverlap(layer0, rof0, layer1, rof1))
const TableEntry * mFlatTable
assert(rofIdx< idx.getEntries())
GPUh() void printLayer(int32_t layer) const
GPUhdi() const LayerTiming &getLayer(int32_t layer) const noexcept
const TableEntry * mFlatTable
const LayerTiming * mLayers
const TableIndex * mIndices
GPUh() void printAll() const
GPUh() int32_t getMaxVerticesPerROF() const noexcept
GPUh() void printSummary() const
GPUhdi() const TableEntry &getVertices(int32_t layer
GPUhdi() bool isVertexCompatible(int32_t layer
VectorOfTObjectPtrs other
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"