Skip to content

Commit c2abd08

Browse files
committed
Added RawDataWriter helper class and its used for ITS MC->raw conversion
See Detectors/Raw/README.md for details
1 parent 318521b commit c2abd08

13 files changed

Lines changed: 1027 additions & 356 deletions

File tree

Detectors/ITSMFT/ITS/macros/test/run_digi2rawVarPage_its.C

Lines changed: 106 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <TChain.h>
44
#include <TFile.h>
55
#include <TStopwatch.h>
6-
#include <FairLogger.h>
6+
#include "Framework/Logger.h"
77
#include <vector>
88
#include <string>
99
#include <iomanip>
@@ -16,9 +16,11 @@
1616
#endif
1717

1818
// demo macro the MC->raw conversion with new (variable page size) format
19+
void setupLinks(o2::itsmft::MC2RawEncoder<o2::itsmft::ChipMappingITS>& m2r, const std::string& outPrefix);
1920

20-
void run_digi2rawVarPage_its(std::string outName = "rawits.bin", // name of the output binary file
21-
std::string inpName = "itsdigits.root", // name of the input ITS digits
21+
void run_digi2rawVarPage_its(std::string outPrefix = "rawits", // prefix of the output binary file
22+
std::string inpName = "itsdigits.root", // name of the input ITS digits
23+
int verbosity = 0,
2224
std::string digTreeName = "o2sim", // name of the digits tree
2325
std::string digBranchName = "ITSDigit", // name of the digits branch
2426
std::string rofRecName = "ITSDigitROF", // name of the ROF records branch
@@ -46,83 +48,40 @@ void run_digi2rawVarPage_its(std::string outName = "rawits.bin", // nam
4648
// ROF record entries in the digit tree
4749
ROFRVEC rofRecVec, *rofRecVecP = &rofRecVec;
4850
if (!digTree.GetBranch(rofRecName.c_str())) {
49-
LOG(FATAL) << "Failed to find the branch " << rofRecName << " in the tree " << rofRecName;
51+
LOG(FATAL) << "Failed to find the branch " << rofRecName << " in the tree " << digTreeName;
5052
}
5153
digTree.SetBranchAddress(rofRecName.c_str(), &rofRecVecP);
5254
///-------< input
5355

54-
///-------> output
55-
if (outName.empty()) {
56-
outName = "raw" + digBranchName + ".raw";
57-
LOG(INFO) << "Output file name is not provided, set to " << outName;
58-
}
59-
auto outFl = fopen(outName.c_str(), "wb");
60-
if (!outFl) {
61-
LOG(FATAL) << "failed to open raw data output file " << outName;
62-
;
63-
} else {
64-
LOG(INFO) << "opened raw data output file " << outName;
65-
}
66-
///-------< output
67-
6856
const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP);
6957

7058
o2::itsmft::MC2RawEncoder<o2::itsmft::ChipMappingITS> m2r;
71-
m2r.setVerbosity(2);
72-
m2r.setOutFile(outFl);
59+
m2r.setVerbosity(verbosity);
7360
m2r.setContinuousReadout(grp->isDetContinuousReadOut(o2::detectors::DetID::ITS)); // must be set explicitly
74-
61+
m2r.setDefaultSinkName(outPrefix + ".raw");
7562
m2r.setMinMaxRUSW(ruSWMin, ruSWMax);
7663

77-
//------------------------------------------------------------------------------->>>>
78-
// just as an example, we require here that the staves are read via 3 links, with partitioning according to lnkXB below
79-
// while OB staves use only 1 link.
80-
// Note, that if the RU container is not defined, it will be created automatically
81-
// during encoding.
82-
// If the links of the container are not defined, a single link readout will be assigned
83-
const auto& mp = m2r.getMapping();
84-
int lnkAssign[3][3] = {
85-
/* // uncomment this to have 1 link per RU
86-
{9, 0, 0}, // IB
87-
{16, 0, 0}, // MB
88-
{28, 0, 0} // OB
89-
*/
90-
{3, 3, 3}, // IB
91-
{5, 5, 6}, // MB
92-
{9, 9, 10} // OB
93-
};
94-
for (int ir = m2r.getRUSWMin(); ir <= m2r.getRUSWMax(); ir++) {
95-
96-
auto& ru = m2r.getCreateRUDecode(ir); // create RU container
97-
uint32_t lanes = mp.getCablesOnRUType(ru.ruInfo->ruType); // lanes patter of this RU
98-
int* lnkAs = lnkAssign[ru.ruInfo->ruType];
99-
int accL = 0;
100-
for (int il = 0; il < 3; il++) { // create links
101-
if (lnkAs[il]) {
102-
ru.links[il] = std::make_unique<o2::itsmft::GBTLink>();
103-
ru.links[il]->lanes = lanes & ((0x1 << lnkAs[il]) - 1) << (accL);
104-
ru.links[il]->id = il;
105-
ru.links[il]->cruID = ir;
106-
ru.links[il]->feeID = mp.RUSW2FEEId(ir, il);
107-
accL += lnkAs[il];
108-
LOG(INFO) << "RU " << std::setw(3) << ir << " on lr" << int(ru.ruInfo->layer)
109-
<< " : FEEId 0x" << std::hex << std::setfill('0') << std::setw(6) << ru.links[il]->feeID
110-
<< " reads lanes " << std::bitset<28>(ru.links[il]->lanes);
111-
}
112-
}
113-
}
64+
m2r.getWriter().setSuperPageSize(1024 * 1024); // this is default anyway
65+
m2r.getWriter().getHBFUtils().setNOrbitsPerTF(256); // this is default anyway
66+
67+
m2r.setVerbosity(0);
11468

69+
setupLinks(m2r, outPrefix);
11570
//-------------------------------------------------------------------------------<<<<
11671
int lastTreeID = -1;
11772
long offs = 0, nEntProc = 0;
11873
for (int i = 0; i < digTree.GetEntries(); i++) {
11974
digTree.GetEntry(i);
12075
for (const auto& rofRec : rofRecVec) {
12176
int nDigROF = rofRec.getNEntries();
122-
LOG(INFO) << "Processing ROF:" << rofRec.getROFrame() << " with " << nDigROF << " entries";
123-
rofRec.print();
77+
if (verbosity) {
78+
LOG(INFO) << "Processing ROF:" << rofRec.getROFrame() << " with " << nDigROF << " entries";
79+
rofRec.print();
80+
}
12481
if (!nDigROF) {
125-
LOG(INFO) << "Frame is empty"; // ??
82+
if (verbosity) {
83+
LOG(INFO) << "Frame is empty"; // ??
84+
}
12685
continue;
12786
}
12887
nEntProc++;
@@ -133,9 +92,92 @@ void run_digi2rawVarPage_its(std::string outName = "rawits.bin", // nam
13392

13493
m2r.finalize(); // finish TF and flush data
13594
//
136-
fclose(outFl);
137-
m2r.setOutFile(nullptr);
138-
//
13995
swTot.Stop();
14096
swTot.Print();
14197
}
98+
99+
void setupLinks(o2::itsmft::MC2RawEncoder<o2::itsmft::ChipMappingITS>& m2r, const std::string& outPrefix)
100+
{
101+
//------------------------------------------------------------------------------->>>>
102+
// just as an example, we require here that the staves are read via 3 links, with partitioning according to lnkXB below
103+
// while OB staves use only 1 link.
104+
// Note, that if the RU container is not defined, it will be created automatically
105+
// during encoding.
106+
// If the links of the container are not defined, a single link readout will be assigned
107+
108+
constexpr int MaxLinksPerRU = 3;
109+
constexpr int MaxLinksPerCRU = 16;
110+
const auto& mp = m2r.getMapping();
111+
int lnkAssign[3][MaxLinksPerRU] = {
112+
// requested link cabling for IB, MB and OB
113+
/* // uncomment this to have 1 link per RU
114+
{9, 0, 0}, // IB
115+
{16, 0, 0}, // MB
116+
{28, 0, 0} // OB
117+
*/
118+
{3, 3, 3}, // IB
119+
{5, 5, 6}, // MB
120+
{9, 9, 10} // OB
121+
};
122+
123+
// this is an arbitrary mapping
124+
int nCRU = 0, nRUtot = 0, nRU = 0, nLinks = 0;
125+
int linkID = 0, cruIDprev = -1, cruID = o2::detectors::DetID::ITS << 10; // this will be the lowest CRUID
126+
std::string outFileLink;
127+
128+
for (int ilr = 0; ilr < mp.NLayers; ilr++) {
129+
int nruLr = mp.getNStavesOnLr(ilr);
130+
int ruType = mp.getRUType(nRUtot); // IB, MB or OB
131+
int* lnkAs = lnkAssign[ruType];
132+
// count requested number of links per RU
133+
int nlk = 0;
134+
for (int i = 3; i--;) {
135+
nlk += lnkAs[i] ? 1 : 0;
136+
}
137+
outFileLink = outPrefix + "_lr" + std::to_string(ilr) + ".raw";
138+
for (int ir = 0; ir < nruLr; ir++) {
139+
int ruID = nRUtot++;
140+
bool accept = !(ruID < m2r.getRUSWMin() || ruID > m2r.getRUSWMax()); // ignored RUs ?
141+
if (accept) {
142+
m2r.getCreateRUDecode(ruID); // create RU container
143+
nRU++;
144+
}
145+
int accL = 0;
146+
for (int il = 0; il < MaxLinksPerRU; il++) { // create links
147+
if (accept) {
148+
nLinks++;
149+
auto& ru = *m2r.getRUDecode(ruID);
150+
uint32_t lanes = mp.getCablesOnRUType(ru.ruInfo->ruType); // lanes patter of this RU
151+
ru.links[il] = std::make_unique<o2::itsmft::GBTLink>();
152+
ru.links[il]->lanes = lanes & ((0x1 << lnkAs[il]) - 1) << (accL);
153+
ru.links[il]->id = linkID;
154+
ru.links[il]->cruID = cruID;
155+
ru.links[il]->feeID = mp.RUSW2FEEId(ir, il);
156+
ru.links[il]->endPointID = 0; // 0 or 1
157+
accL += lnkAs[il];
158+
if (m2r.getVerbosity()) {
159+
LOG(INFO) << "RU" << ruID << '(' << ir << " on lr " << ilr << ") " << ru.links[il]->describe()
160+
<< " -> " << outFileLink;
161+
}
162+
// register the link in the writer, if not done here, its data will be dumped to common default file
163+
m2r.getWriter().registerLink(ru.links[il]->feeID, ru.links[il]->cruID, ru.links[il]->id,
164+
ru.links[il]->endPointID, outFileLink);
165+
//
166+
if (cruIDprev != cruID) { // just to count used CRUs
167+
cruIDprev = cruID;
168+
nCRU++;
169+
}
170+
}
171+
if ((++linkID) >= MaxLinksPerCRU) {
172+
linkID = 0;
173+
++cruID;
174+
}
175+
}
176+
}
177+
if (linkID) {
178+
linkID = 0; // we don't want to put links of different layers on the same CRU
179+
++cruID;
180+
}
181+
}
182+
LOG(INFO) << "Distributed " << nLinks << " links on " << nRU << " RUs in " << nCRU << " CRUs";
183+
}

Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/RawPixelReader.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ struct GBTLink {
187187
uint16_t id = 0; // link ID within the CRU
188188
uint16_t cruID = 0; // CRU ID
189189
uint16_t feeID = 0; // FEE ID
190+
uint8_t endPointID = 0; // endpoint ID of the CRU
190191
PayLoadCont data; // data buffer per link
191192
int lastPageSize = 0; // size of last added page = offset from the end to get to the RDH
192193
int nTriggers = 0; // number of triggers loaded (the last one might be incomplete)
@@ -200,6 +201,15 @@ struct GBTLink {
200201
o2::header::RAWDataHeader* lastRDH = nullptr;
201202
GBTLinkDecodingStat statistics; // decoding statistics
202203

204+
std::string describe() const
205+
{
206+
std::stringstream ss;
207+
ss << "Link cruID=0x" << std::hex << std::setw(4) << std::setfill('0') << cruID << std::dec
208+
<< "/lID=" << int(id) << "/feeID=0x" << std::hex << std::setw(4) << std::setfill('0') << feeID << std::dec
209+
<< " lanes: " << std::bitset<28>(lanes).to_string();
210+
return ss.str();
211+
}
212+
203213
void clear(bool resetStat = true)
204214
{
205215
data.clear();

Detectors/ITSMFT/common/simulation/include/ITSMFTSimulation/MC2RawEncoder.h

Lines changed: 26 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "ITSMFTReconstruction/AlpideCoder.h"
2020
#include "ITSMFTReconstruction/ChipMappingITS.h"
2121
#include "ITSMFTReconstruction/ChipMappingMFT.h"
22-
#include "DetectorsRaw/HBFUtils.h"
22+
#include "DetectorsRaw/RawFileWriter.h"
2323

2424
namespace o2
2525
{
@@ -37,7 +37,11 @@ class MC2RawEncoder
3737
{
3838
mRUEntry.fill(-1);
3939
}
40-
~MC2RawEncoder() = default;
40+
41+
~MC2RawEncoder()
42+
{
43+
mWriter.close();
44+
}
4145

4246
void digits2raw(gsl::span<const Digit> digits, const o2::InteractionRecord& bcData);
4347
void finalize();
@@ -47,33 +51,12 @@ class MC2RawEncoder
4751

4852
RUDecodeData* getRUDecode(int ruSW) { return mRUEntry[ruSW] < 0 ? nullptr : &mRUDecodeVec[mRUEntry[ruSW]]; }
4953

50-
void setBCData(const o2::InteractionRecord& bcData);
51-
52-
/// number of orbits per HBF (max 255)
53-
void setNOrbitsPerHBF(uint8_t n) { mNOrbitsPerHBF = n; }
54-
int getNOrbitsPerHBF() const { return mNOrbitsPerHBF; }
55-
56-
/// nominal size of the superpage in bytes
57-
void setSuperPageSize(int n)
54+
void setVerbosity(int v)
5855
{
59-
constexpr int MinSize = 2 * MaxGBTPacketBytes;
60-
mSuperPageSize = n < MinSize ? MinSize : n;
56+
mVerbosity = v;
57+
mWriter.setVerbosity(v);
6158
}
62-
int getSuperPageSize() const { return mSuperPageSize; }
63-
64-
/// do we treat CRU pages as having max size?
65-
bool isMaxPageImposed() const { return mImposeMaxPage; }
66-
/// CRU pages are of max size of 8KB
67-
void imposeMaxPage(bool v) { mImposeMaxPage = v; }
68-
69-
/// are we starting new superpage for each TF
70-
bool isStartTFOnNewSPage(bool v) { return mStartTFOnNewSPage; }
71-
void setStartTFOnNewSPage(bool v) { mStartTFOnNewSPage = v; }
72-
73-
void setVerbosity(int v) { mVerbose = v; }
74-
int getVerbosity() const { return mVerbose; }
75-
76-
void setOutFile(FILE* outf) { mOutFile = outf; }
59+
int getVerbosity() const { return mVerbosity; }
7760

7861
Mapping& getMapping() { return mMAP; }
7962

@@ -89,44 +72,39 @@ class MC2RawEncoder
8972
void setContinuousReadout(bool v) { mROMode = v ? Continuous : Triggered; }
9073
bool isContinuousReadout() const { return mROMode == Continuous; }
9174

75+
o2::raw::RawFileWriter& getWriter() { return mWriter; }
76+
77+
std::string getDefaultSinkName() const { return mDefaultSinkName; }
78+
void setDefaultSinkName(const std::string& nm)
79+
{
80+
if (!nm.empty()) {
81+
mDefaultSinkName = nm;
82+
}
83+
}
84+
85+
int carryOverMethod(const RDH& rdh, const gsl::span<char> data, const char* ptr, int maxSize, int splitID,
86+
std::vector<char>& trailer, std::vector<char>& header) const;
87+
9288
private:
9389
void convertEmptyChips(int fromChip, int uptoChip, RUDecodeData& ru);
9490
void convertChip(ChipPixelData& chipData, RUDecodeData& ru);
9591
void fillGBTLinks(RUDecodeData& ru);
96-
void flushLinkSuperPage(GBTLink& link, FILE* outFl = nullptr);
97-
void openPageLinkHBF(GBTLink& link);
98-
void addPageLinkHBF(GBTLink& link, bool stop = false);
99-
void closePageLinkHBF(GBTLink& link) { addPageLinkHBF(link, true); }
100-
void openHBF();
101-
void closeHBF();
102-
void flushAllLinks();
10392

104-
private:
10593
enum RoMode_t { NotSet,
10694
Continuous,
10795
Triggered };
108-
o2::raw::HBFUtils mHBFUtils;
109-
std::vector<o2::InteractionRecord> mHBIRVec; // workspace for HB IR generation
110-
o2::InteractionRecord mLastIR; // last IR processed (or 1st in TF if none)
11196
o2::InteractionRecord mCurrIR; // currently processed int record
112-
FILE* mOutFile = nullptr;
97+
o2::raw::RawFileWriter mWriter;
98+
std::string mDefaultSinkName = "dataSink.raw";
11399
Mapping mMAP;
114100
Coder mCoder;
115-
RDH mRDH; // current RDH
116-
int mSuperPageSize = 1024 * 1024; // super page size
117-
int mHBFCounter = -1;
118-
int mVerbose = 0; //! verbosity level
119-
uint8_t mNOrbitsPerHBF = 0xff; ///< number of orbitd per HB frame
101+
int mVerbosity = 0; //! verbosity level
120102
uint8_t mRUSWMin = 0; ///< min RU (SW) to convert
121103
uint8_t mRUSWMax = 0xff; ///< max RU (SW) to convert
122104
int mNRUs = 0; /// total number of RUs seen
123105
int mNLinks = 0; /// total number of GBT links seen
124106
std::array<RUDecodeData, Mapping::getNRUs()> mRUDecodeVec; /// decoding buffers for all active RUs
125107
std::array<int, Mapping::getNRUs()> mRUEntry; /// entry of the RU with given SW ID in the mRUDecodeVec
126-
int mCurRUDecodeID = -1;
127-
bool mImposeMaxPage = true; /// force (pad) all CRU pages to be 8KB
128-
bool mStartTFOnNewSPage = true; /// user muse set explicitly RO mode
129-
bool mImposeROModeFlag = true; /// Propagate SOT or SOC to RDH.triggerType when true
130108
RoMode_t mROMode = NotSet;
131109

132110
ClassDefNV(MC2RawEncoder, 1);

0 commit comments

Comments
 (0)