forked from AliceO2Group/AliceO2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRawPixelDecoder.h
More file actions
311 lines (271 loc) · 13 KB
/
RawPixelDecoder.h
File metadata and controls
311 lines (271 loc) · 13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
/// \file RawPixelDecoder.h
/// \brief Definition of the Alpide pixel reader for raw data processing
#ifndef ALICEO2_ITSMFT_RAWPIXELDECODER_H_
#define ALICEO2_ITSMFT_RAWPIXELDECODER_H_
#include <unordered_map>
#include <array>
#include <TStopwatch.h>
#include "Framework/Logger.h"
#include "Framework/InputSpec.h"
#include "ITSMFTReconstruction/ChipMappingITS.h"
#include "ITSMFTReconstruction/ChipMappingMFT.h"
#include "DetectorsRaw/HBFUtils.h"
#include "Headers/RAWDataHeader.h"
#include "Headers/DataHeader.h"
#include "CommonDataFormat/InteractionRecord.h"
#include "ITSMFTReconstruction/GBTLink.h"
#include "ITSMFTReconstruction/RUDecodeData.h"
#include "ITSMFTReconstruction/PixelReader.h"
#include "DataFormatsITSMFT/ROFRecord.h"
#include "ITSMFTReconstruction/PixelData.h"
#include "ITSMFTReconstruction/GBTWord.h"
namespace o2
{
namespace framework
{
class InputRecord;
class TimingInfo;
} // namespace framework
namespace itsmft
{
class ChipPixelData;
template <class Mapping>
class RawPixelDecoder final : public PixelReader
{
using RDH = o2::header::RAWDataHeader;
public:
RawPixelDecoder();
~RawPixelDecoder() final = default;
void setFormat(GBTLink::Format f) {}
void init() final {}
bool getNextChipData(ChipPixelData& chipData) final;
ChipPixelData* getNextChipData(std::vector<ChipPixelData>& chipDataVec) final;
void ensureChipOrdering() {}
void startNewTF(o2::framework::InputRecord& inputs);
void collectROFCableData(int iru);
int decodeNextTrigger() final;
template <class DigitContainer, class ROFContainer>
int fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs);
template <class STATVEC>
void fillChipsStatus(STATVEC& chipStatus);
template <class CalibContainer>
void fillCalibData(CalibContainer& calib);
template <class LinkErrors, class DecErrors, class ErrMsgs>
void collectDecodingErrors(LinkErrors& linkErrors, DecErrors& decErrors, ErrMsgs& errInfos);
const RUDecodeData* getRUDecode(int ruSW) const { return mRUEntry[ruSW] < 0 ? nullptr : &mRUDecodeVec[mRUEntry[ruSW]]; }
const GBTLink* getGBTLink(int i) const { return i < 0 ? nullptr : &mGBTLinks[i]; }
int getNLinks() const { return mGBTLinks.size(); }
auto getUserDataOrigin() const { return mUserDataOrigin; }
void setUserDataOrigin(header::DataOrigin orig) { mUserDataOrigin = orig; }
auto getUserDataDescription() const { return mUserDataDescription; }
void setUserDataDescription(header::DataDescription desc) { mUserDataDescription = desc; }
void setNThreads(int n);
int getNThreads() const { return mNThreads; }
void setFillCalibData(bool v) { mFillCalibData = v; }
bool getFillCalibData() const { return mFillCalibData; }
void setVerbosity(int v);
int getVerbosity() const { return mVerbosity; }
void setInputFilter(std::vector<o2::framework::InputSpec> filter) { mInputFilter = std::move(filter); }
const auto& getInputFilter() const noexcept { return mInputFilter; }
void setAlwaysParseTrigger(bool v) { mAlwaysParseTrigger = v; }
bool getAlwaysParseTrigger() const { return mAlwaysParseTrigger; }
void printReport(bool decstat = true, bool skipNoErr = true) const;
size_t produceRawDataDumps(int dump, const o2::framework::TimingInfo& tinfo);
void clearStat(bool resetRaw = false);
TStopwatch& getTimerTFStart() { return mTimerTFStart; }
TStopwatch& getTimerDecode() { return mTimerDecode; }
TStopwatch& getTimerExtract() { return mTimerFetchData; }
uint32_t getNChipsFiredROF() const { return mNChipsFiredROF; }
uint32_t getNPixelsFiredROF() const { return mNPixelsFiredROF; }
size_t getNChipsFired() const { return mNChipsFired; }
size_t getNPixelsFired() const { return mNPixelsFired; }
void setAllowEmptyROFs(bool v) { mAlloEmptyROFs = v; }
bool getAllowEmptyROFs() const { return mAlloEmptyROFs; }
void setVerifyDecoder(bool v) { mVerifyDecoder = v; }
bool getVerifyDecoder() const { return mVerifyDecoder; }
void setInstanceID(size_t i) { mInstanceID = i; }
void setNInstances(size_t n) { mNInstances = n; }
auto getInstanceID() const { return mInstanceID; }
auto getNInstances() const { return mNInstances; }
void setRawDumpDirectory(const std::string& s) { mRawDumpDirectory = s; }
auto getRawDumpDirectory() const { return mRawDumpDirectory; }
std::vector<PhysTrigger>& getExternalTriggers() { return mExtTriggers; }
const std::vector<PhysTrigger>& getExternalTriggers() const { return mExtTriggers; }
void setSkipRampUpData(bool v = true) { mSkipRampUpData = v; }
bool getSkipRampUpData() const { return mSkipRampUpData; }
auto getNROFsProcessed() const { return mROFCounter; }
struct LinkEntry {
int entry = -1;
};
uint16_t getSquashingDepth() { return 0; }
bool doIRMajorityPoll();
bool isRampUpStage() const { return mROFRampUpStage; }
void reset();
private:
void setupLinks(o2::framework::InputRecord& inputsm);
int getRUEntrySW(int ruSW) const { return mRUEntry[ruSW]; }
RUDecodeData* getRUDecode(int ruSW) { return &mRUDecodeVec[mRUEntry[ruSW]]; }
GBTLink* getGBTLink(int i) { return i < 0 ? nullptr : &mGBTLinks[i]; }
RUDecodeData& getCreateRUDecode(int ruSW);
static constexpr uint16_t NORUDECODED = 0xffff; // this must be > than max N RUs
std::vector<o2::framework::InputSpec> mInputFilter; // input spec filter
std::vector<GBTLink> mGBTLinks; // active links pool
std::unordered_map<uint32_t, LinkEntry> mSubsSpec2LinkID; // link subspec to link entry in the pool mapping
std::vector<RUDecodeData> mRUDecodeVec; // set of active RUs
std::array<short, Mapping::getNRUs()> mRUEntry; // entry of the RU with given SW ID in the mRUDecodeVec
std::vector<ChipPixelData*> mOrderedChipsPtr; // special ordering helper used for the MFT (its chipID is not contiguous in RU)
std::vector<PhysTrigger> mExtTriggers; // external triggers
GBTLink* mLinkForTriggers = nullptr; // link assigned to collect the triggers
std::string mSelfName{}; // self name
std::string mRawDumpDirectory; // destination directory for dumps
header::DataOrigin mUserDataOrigin = o2::header::gDataOriginInvalid; // alternative user-provided data origin to pick
header::DataDescription mUserDataDescription = o2::header::gDataDescriptionInvalid; // alternative user-provided description to pick
uint16_t mCurRUDecodeID = NORUDECODED; // index of currently processed RUDecode container
int mLastReadChipID = -1; // chip ID returned by previous getNextChipData call, used for ordering checks
int mNLinksInTF = 0; // number of links seen in the TF
Mapping mMAP; // chip mapping
std::unordered_map<o2::InteractionRecord, int> mIRPoll; // poll for links IR used for synchronization
bool mFillCalibData = false; // request to fill calib data from GBT
bool mAlloEmptyROFs = false; // do not skip empty ROFs
bool mROFRampUpStage = false; // are we still in the ROF ramp up stage?
bool mSkipRampUpData = false;
bool mVerifyDecoder = false;
bool mAlwaysParseTrigger = false;
int mVerbosity = 0;
int mNThreads = 1; // number of decoding threads
// statistics
o2::itsmft::ROFRecord::ROFtype mROFCounter = 0; // RSTODO is this needed? eliminate from ROFRecord ?
uint32_t mNChipsFiredROF = 0; // counter within the ROF
uint32_t mNPixelsFiredROF = 0; // counter within the ROF
uint32_t mNLinksDone = 0; // number of links reached end of data
size_t mNChipsFired = 0; // global counter
size_t mNPixelsFired = 0; // global counter
size_t mNExtTriggers = 0; // global counter
size_t mInstanceID = 0; // pipeline instance
size_t mNInstances = 1; // total number of pipelines
TStopwatch mTimerTFStart;
TStopwatch mTimerDecode;
TStopwatch mTimerFetchData;
};
///______________________________________________________________
/// Fill decoded digits to global vector
template <class Mapping>
template <class DigitContainer, class ROFContainer>
int RawPixelDecoder<Mapping>::fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs)
{
if (mInteractionRecord.isDummy()) {
return 0; // nothing was decoded
}
mTimerFetchData.Start(false);
int ref = digits.size();
for (unsigned int iru = 0; iru < mRUDecodeVec.size(); iru++) {
for (int ic = 0; ic < mRUDecodeVec[iru].nChipsFired; ic++) {
const auto& chip = mRUDecodeVec[iru].chipsData[ic];
for (const auto& hit : mRUDecodeVec[iru].chipsData[ic].getData()) {
digits.emplace_back(chip.getChipID(), hit.getRow(), hit.getCol());
}
}
}
int nFilled = digits.size() - ref;
rofs.emplace_back(mInteractionRecord, mROFCounter, ref, nFilled);
mTimerFetchData.Stop();
return nFilled;
}
///______________________________________________________________
/// Fill decoded digits to global vector
template <>
template <class DigitContainer, class ROFContainer>
int RawPixelDecoder<ChipMappingMFT>::fillDecodedDigits(DigitContainer& digits, ROFContainer& rofs)
{
if (mInteractionRecord.isDummy()) {
return 0; // nothing was decoded
}
mTimerFetchData.Start(false);
int ref = digits.size();
for (auto chipData = mOrderedChipsPtr.rbegin(); chipData != mOrderedChipsPtr.rend(); ++chipData) {
assert(mLastReadChipID < (*chipData)->getChipID());
mLastReadChipID = (*chipData)->getChipID();
for (const auto& hit : (*chipData)->getData()) {
digits.emplace_back(mLastReadChipID, hit.getRow(), hit.getCol());
}
}
int nFilled = digits.size() - ref;
rofs.emplace_back(mInteractionRecord, mROFCounter, ref, nFilled);
mTimerFetchData.Stop();
return nFilled;
}
///______________________________________________________________
/// update status for every active chip
template <class Mapping>
template <class STATVEC>
void RawPixelDecoder<Mapping>::fillChipsStatus(STATVEC& chipStatus)
{
if (mInteractionRecord.isDummy() || mROFRampUpStage) {
return; // nothing was decoded
}
for (unsigned int iru = 0; iru < mRUDecodeVec.size(); iru++) {
for (auto chID : mRUDecodeVec[iru].seenChipIDs) {
chipStatus[chID] = 1;
}
}
}
///______________________________________________________________
/// Fill decoded digits to global vector
template <class Mapping>
template <class CalibContainer>
void RawPixelDecoder<Mapping>::fillCalibData(CalibContainer& calib)
{
if (!mInteractionRecord.isDummy()) {
auto curSize = calib.size();
calib.resize(curSize + Mapping::getNRUs());
for (unsigned int iru = 0; iru < mRUDecodeVec.size(); iru++) {
calib[curSize + mRUDecodeVec[iru].ruSWID] = mRUDecodeVec[iru].calibData;
}
}
}
///______________________________________________________________________
template <class Mapping>
template <class LinkErrors, class DecErrors, class ErrMsgs>
void RawPixelDecoder<Mapping>::collectDecodingErrors(LinkErrors& linkErrors, DecErrors& decErrors, ErrMsgs& errInfos)
{
for (auto& lnk : mGBTLinks) {
if (lnk.gbtErrStatUpadated) {
linkErrors.push_back(lnk.statistics);
lnk.gbtErrStatUpadated = false;
}
}
size_t nerr = 0, nerrMsg = 0;
for (auto& ru : mRUDecodeVec) {
nerr += ru.chipErrorsTF.size();
nerrMsg += ru.errMsgVecTF.size();
}
if (nerr || nerrMsg) {
decErrors.reserve(nerr);
errInfos.reserve(nerrMsg);
for (auto& ru : mRUDecodeVec) {
for (const auto& err : ru.chipErrorsTF) {
decErrors.emplace_back(ChipError{err.first, err.second.first, err.second.second}); // id, nerrors, errorFlags
}
for (auto& err : ru.errMsgVecTF) {
errInfos.push_back(err);
}
ru.chipErrorsTF.clear();
ru.errMsgVecTF.clear();
}
}
}
using RawDecoderITS = RawPixelDecoder<ChipMappingITS>;
using RawDecoderMFT = RawPixelDecoder<ChipMappingMFT>;
} // namespace itsmft
} // namespace o2
#endif /* ALICEO2_ITSMFT_RAWPIXELDECODER_H */