Project
Loading...
Searching...
No Matches
Encoder.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14#include <iostream>
15#include <chrono>
16#include <algorithm>
19#include "TString.h"
20#include <fairlogger/Logger.h>
24
25#include <array>
26#define VERBOSE
27
28namespace o2
29{
30namespace tof
31{
32namespace raw
33{
35
37{
38 // intialize 72 buffers (one per crate)
39 for (int i = 0; i < 72; i++) {
40 mBuffer[i] = nullptr;
41 mUnion[i] = nullptr;
42 mStart[i] = nullptr;
43 mCrateOn[i] = true;
44 }
45}
46
47void Encoder::nextWord(int icrate)
48{
49 if (mOldFormat && mNextWordStatus[icrate]) {
50 mUnion[icrate]++;
51 mUnion[icrate]->data = 0;
52 mUnion[icrate]++;
53 mUnion[icrate]->data = 0;
54 }
55 mUnion[icrate]++;
56 //nextWordNoEmpty(icrate);
57 mNextWordStatus[icrate] = !mNextWordStatus[icrate];
58}
59
60bool Encoder::open(const std::string& name, const std::string& path, const std::string& fileFor)
61{
62 bool status = false;
63 static const uint8_t nopadding = 1;
64 static const uint8_t padding = 0;
65 uint8_t dataformat = mOldFormat ? padding : nopadding;
66
67 // register links
69 mFileWriter.useRDHVersion(RDHUtils::getVersion<o2::header::RAWDataHeader>());
70 if (o2::raw::RDHUtils::getVersion(&rdh) > 6) {
71 mFileWriter.useRDHDataFormat(dataformat);
72 } else {
74 }
75 for (int crateid = 0; crateid < 72; crateid++) {
76 // cru=0 --> FLP 1, ... defined in Geo
77 // cru=1 --> FLP 1, ... defined in Geo
78 // cru=2 --> FLP 0, ... defined in Geo
79 // cru=3 --> FLP 0, ... defined in Geo
80 RDHUtils::setFEEID(rdh, Geo::getFEEid(crateid));
81 RDHUtils::setCRUID(rdh, Geo::getCRUid(crateid));
84 const int served = 3;
85 const int received = 3;
86 uint32_t detField = (served << 24) + (received << 16);
87 RDHUtils::setDetectorField(rdh, detField);
88 // currently storing each CRU in a separate file
89 std::string outFileLink;
90 if (mCrateOn[crateid]) {
91 if (fileFor == "all") { // single file for all links
92 outFileLink = o2::utils::Str::concat_string(path, "/TOF.raw");
93 } else if (fileFor == "cruendpoint") {
94 outFileLink = o2::utils::Str::concat_string(path, "/", "TOF_alio2-cr1-flp", std::to_string(Geo::getFLPid(crateid)), "_cru", std::to_string(Geo::getCRUid(crateid)), "_", std::to_string(Geo::getCRUendpoint(crateid)), ".raw");
95 } else if (fileFor == "link") {
96 outFileLink = o2::utils::Str::concat_string(path, "/", "TOF_alio2-cr1-flp", std::to_string(Geo::getFLPid(crateid)), "_cru", std::to_string(Geo::getCRUid(crateid)), "_", std::to_string(Geo::getCRUendpoint(crateid)), "_link", std::to_string(RDHUtils::getLinkID(rdh)), ".raw");
97 } else {
98 throw std::runtime_error("invalid option provided for file grouping");
99 }
100 mFileWriter.registerLink(rdh, outFileLink);
101 }
102 }
103
104 std::string inputGRP = o2::base::NameConf::getGRPFileName();
105 const auto grp = o2::parameters::GRPObject::loadFrom(inputGRP);
106 mFileWriter.setContinuousReadout(grp->isDetContinuousReadOut(o2::detectors::DetID::TOF)); // must be set explicitly
107
108 return status;
109}
110
111bool Encoder::flush(int icrate)
112{
113 int nbyte = getSize(mStart[icrate], mUnion[icrate]);
114 if (nbyte) {
115 if (mCrateOn[icrate]) {
116 //printf("flush crate %d -- byte = %d -- orbit = %d, bc = %d\n",icrate, nbyte, mIR.orbit, mIR.bc);
117 mFileWriter.addData(Geo::getFEEid(icrate), Geo::getCRUid(icrate), Geo::getCRUlink(icrate), Geo::getCRUendpoint(icrate), mIR, gsl::span(mBuffer[icrate], nbyte));
118 }
119 mIntegratedAllBytes += nbyte;
120 }
121 mUnion[icrate] = mStart[icrate];
122 return false;
123}
124
126{
128 return false;
129}
130
132{
133 if (size < 500000) {
134 size = 500000;
135 }
136
137 mSize = size;
138
139 mBufferLocal.resize(size * 72);
140
141 mBuffer[0] = mBufferLocal.data();
142 memset(mBuffer[0], 0, mSize * 72);
143 mStart[0] = reinterpret_cast<Union_t*>(mBuffer[0]);
144 mUnion[0] = mStart[0]; // rewind
145
146 for (int i = 1; i < 72; i++) {
147 mBuffer[i] = mBuffer[i - 1] + size;
148 mStart[i] = reinterpret_cast<Union_t*>(mBuffer[i]);
149 mUnion[i] = mStart[i]; // rewind
150 }
151 return false;
152}
153
154void Encoder::encodeTRM(const std::vector<Digit>& summary, Int_t icrate, Int_t itrm, int& istart) // encode one TRM assuming digit vector sorted by electronic index
155// return next TRM index (-1 if not in the same crate)
156// start to convert digiti from istart --> then update istart to the starting position of the new TRM
157{
158
159 static unsigned long bc_shift = uint64_t(o2::raw::HBFUtils::Instance().orbitFirstSampled) * Geo::BC_IN_ORBIT;
160
161 if (mVerbose) {
162 printf("Crate %d: encode TRM %d \n", icrate, itrm);
163 }
164
165 // TRM HEADER
166 Union_t* trmheader = mUnion[icrate];
167 mUnion[icrate]->trmDataHeader.slotId = itrm;
168 mUnion[icrate]->trmDataHeader.eventWords = 0; // to be filled at the end
169 mUnion[icrate]->trmDataHeader.eventCnt = mEventCounter;
170 mUnion[icrate]->trmDataHeader.emptyBit = 0;
171 mUnion[icrate]->trmDataHeader.dataId = 4;
172 nextWord(icrate);
173
174 // LOOP OVER CHAINS
175 for (int ichain = 0; ichain < 2; ichain++) {
176 // CHAIN HEADER
177 mUnion[icrate]->trmChainHeader.slotId = itrm;
178 mUnion[icrate]->trmChainHeader.bunchCnt = mIR.bc;
179 mUnion[icrate]->trmChainHeader.mbz = 0;
180 mUnion[icrate]->trmChainHeader.dataId = 2 * ichain;
181 nextWord(icrate);
182
183 while (istart < summary.size()) { // fill hits
185 int whatChain = summary[istart].getElChainIndex();
186 if (whatChain != ichain) {
187 break;
188 }
189 int whatTRM = summary[istart].getElTRMIndex();
190 if (whatTRM != itrm) {
191 break;
192 }
193 int whatCrate = summary[istart].getElCrateIndex();
194 if (whatCrate != icrate) {
195 break;
196 }
197
198 int hittimeTDC = (summary[istart].getBC() - bc_shift - mEventCounter * Geo::BC_IN_WINDOW) * 1024 + summary[istart].getTDC(); // time in TDC bin within the TOF WINDOW
199
200 if (hittimeTDC < 0) {
201 LOG(error) << "Negative hit encoded " << hittimeTDC << ", something went wrong in filling readout window";
202 printf("%llu %d %d\n", (unsigned long long)summary[istart].getBC() - bc_shift, mEventCounter * Geo::BC_IN_WINDOW, summary[istart].getTDC());
203 }
204 // leading time
205 mUnion[icrate]->trmDataHit.time = hittimeTDC;
206 mUnion[icrate]->trmDataHit.chanId = summary[istart].getElChIndex();
207 mUnion[icrate]->trmDataHit.tdcId = summary[istart].getElTDCIndex();
208 mUnion[icrate]->trmDataHit.dataId = 0xa;
209 nextWord(icrate);
210
211 // trailing time
212 mUnion[icrate]->trmDataHit.time = hittimeTDC + summary[istart].getTOT() * Geo::RATIO_TOT_TDC_BIN;
213 mUnion[icrate]->trmDataHit.chanId = summary[istart].getElChIndex();
214 mUnion[icrate]->trmDataHit.tdcId = summary[istart].getElTDCIndex();
215 mUnion[icrate]->trmDataHit.dataId = 0xc;
216 nextWord(icrate);
217
218 istart++;
219 }
220
221 // CHAIN TRAILER
222 mUnion[icrate]->trmChainTrailer.status = 0;
223 mUnion[icrate]->trmChainTrailer.mbz = 0;
224 mUnion[icrate]->trmChainTrailer.eventCnt = mEventCounter;
225 mUnion[icrate]->trmChainTrailer.dataId = 1 + 2 * ichain;
226 nextWord(icrate);
227 }
228
229 // set TRM data size
230 int neventwords = getSize(trmheader, mUnion[icrate]) / 4 + 1;
231 if (mOldFormat) {
232 neventwords -= neventwords / 4 * 2;
233 }
234 trmheader->trmDataHeader.eventWords = neventwords;
235
236 // TRM TRAILER
237 mUnion[icrate]->trmDataTrailer.trailerMark = 3;
238 mUnion[icrate]->trmDataTrailer.eventCRC = 0; // to be implemented
239 mUnion[icrate]->trmDataTrailer.tempValue = 0;
240 mUnion[icrate]->trmDataTrailer.tempAddress = 0;
241 mUnion[icrate]->trmDataTrailer.tempChain = 0;
242 mUnion[icrate]->trmDataTrailer.tempAck = 0;
243 mUnion[icrate]->trmDataTrailer.lutErrorBit = 0;
244 mUnion[icrate]->trmDataTrailer.dataId = 5;
245 nextWord(icrate);
246}
247
248bool Encoder::encode(std::vector<std::vector<o2::tof::Digit>> digitWindow, int tofwindow) // pass a vector of digits in a TOF readout window, tof window is the entry in the vector-of-vector of digits needed to extract bunch id and orbit
249{
250 if (digitWindow.size() != Geo::NWINDOW_IN_ORBIT) {
251 printf("Something went wrong in encoding: digitWindow=%lu different from %d\n", digitWindow.size(), Geo::NWINDOW_IN_ORBIT);
252 return 999;
253 }
254
255 for (int iwin = 0; iwin < Geo::NWINDOW_IN_ORBIT; iwin++) {
256 std::vector<o2::tof::Digit>& summary = digitWindow.at(iwin);
257 // caching electronic indexes in digit array
258 for (auto dig = summary.begin(); dig != summary.end(); dig++) {
259 int digitchannel = dig->getChannel();
260 dig->setElectronicIndex(Geo::getECHFromCH(digitchannel));
261 }
262
263 // sorting by electroni indexes
264 std::sort(summary.begin(), summary.end(),
265 [](Digit a, Digit b) { return a.getElectronicIndex() < b.getElectronicIndex(); });
266 }
267
268#ifdef VERBOSE
269 if (mVerbose) {
270 std::cout << "-------- START ENCODE EVENT ----------------------------------------" << std::endl;
271 }
272#endif
273 auto start = std::chrono::high_resolution_clock::now();
274
275 mEventCounter = tofwindow; // tof window index
277
278 for (int i = 0; i < 72; i++) {
279 mNextWordStatus[i] = false;
280 }
281
282 int bcFirstWin;
283
284 // encode all windows
285 for (int iwin = 0; iwin < Geo::NWINDOW_IN_ORBIT; iwin++) {
286 mEventCounter = tofwindow + iwin; // tof window index
287
288 std::vector<o2::tof::Digit>& summary = digitWindow.at(iwin);
289
290 mIR.bc = ((mEventCounter % Geo::NWINDOW_IN_ORBIT) * Geo::BC_IN_ORBIT) / Geo::NWINDOW_IN_ORBIT + mFirstBC; // bunch crossing in the current orbit at the beginning of the window.
291
292 if (iwin == 0) {
293 bcFirstWin = mIR.bc;
294 }
295
296 int icurrentdigit = 0;
297 // TOF data header
298 for (int i = 0; i < 72; i++) {
299 mTOFDataHeader[i] = reinterpret_cast<TOFDataHeader_t*>(mUnion[i]);
300 mTOFDataHeader[i]->bytePayload = 0; // event length in byte (to be filled later)
301 mTOFDataHeader[i]->mbz = 0;
302 mTOFDataHeader[i]->dataId = 4;
303 nextWord(i);
304
305 mUnion[i]->tofOrbit.orbit = mIR.orbit;
306 nextWord(i);
307
308 mDRMDataHeader[i] = reinterpret_cast<DRMDataHeader_t*>(mUnion[i]);
309 mDRMDataHeader[i]->slotId = 1;
310 mDRMDataHeader[i]->eventWords = 0; // event length in word (to be filled later) --> word = byte/4
311 mDRMDataHeader[i]->drmId = i;
312 mDRMDataHeader[i]->dataId = 4;
313 nextWord(i);
314
315 mUnion[i]->drmHeadW1.slotId = 1;
316 mUnion[i]->drmHeadW1.partSlotMask = (i % 2 == 0 ? 0x7fc : 0x7fe);
317 mUnion[i]->drmHeadW1.clockStatus = 2;
318 mUnion[i]->drmHeadW1.drmhVersion = 0x12;
319 mUnion[i]->drmHeadW1.drmHSize = 5;
320 mUnion[i]->drmHeadW1.mbza = 0;
321 mUnion[i]->drmHeadW1.mbzb = 0;
322 mUnion[i]->drmHeadW1.dataId = 4;
323 nextWord(i);
324
325 mUnion[i]->drmHeadW2.slotId = 1;
326 mUnion[i]->drmHeadW2.enaSlotMask = (i % 2 == 0 ? 0x7fc : 0x7fe);
327 mUnion[i]->drmHeadW2.mbz = 0;
328 mUnion[i]->drmHeadW2.faultSlotMask = 0;
329 mUnion[i]->drmHeadW2.readoutTimeOut = 0;
330 mUnion[i]->drmHeadW2.dataId = 4;
331 nextWord(i);
332
333 mUnion[i]->drmHeadW3.slotId = 1;
334 mUnion[i]->drmHeadW3.gbtBunchCnt = mIR.bc;
335 mUnion[i]->drmHeadW3.locBunchCnt = 0;
336 mUnion[i]->drmHeadW3.dataId = 4;
337 nextWord(i);
338
339 mUnion[i]->drmHeadW4.slotId = 1;
340 mUnion[i]->drmHeadW4.tempValue = 0;
341 mUnion[i]->drmHeadW4.mbza = 0;
342 mUnion[i]->drmHeadW4.tempAddress = 0;
343 mUnion[i]->drmHeadW4.mbzb = 0;
344 mUnion[i]->drmHeadW4.dataId = 4;
345 nextWord(i);
346
347 mUnion[i]->drmHeadW5.slotId = 1;
348 mUnion[i]->drmHeadW5.eventCRC = 0;
349 mUnion[i]->drmHeadW5.irq = 0;
350 mUnion[i]->drmHeadW5.mbz = 0;
351 mUnion[i]->drmHeadW5.dataId = 4;
352 nextWord(i);
353
354 int trm0 = 4 - (i % 2);
355 for (int itrm = trm0; itrm < 13; itrm++) {
356 encodeTRM(summary, i, itrm, icurrentdigit);
357 }
358
359 mUnion[i]->drmDataTrailer.slotId = 1;
360 mUnion[i]->drmDataTrailer.locEvCnt = mEventCounter;
361 mUnion[i]->drmDataTrailer.mbz = 0;
362 mUnion[i]->drmDataTrailer.dataId = 5;
363 int neventwords = getSize(mDRMDataHeader[i], mUnion[i]) / 4 + 1;
364 if (mOldFormat) {
365 neventwords -= neventwords / 4 * 2;
366 }
367 neventwords -= 6;
368 mDRMDataHeader[i]->eventWords = neventwords;
369 nextWord(i);
370 mUnion[i]->data = 0x70000000;
371 nextWord(i);
372
373 // check if the numer of paylod words is divisible by 4 (16 bytes), otherwise fill with two words
374 int nbytes = getSize(mTOFDataHeader[i], mUnion[i]);
375 if (nbytes % 4) {
376 LOG(error) << "Nbytes not divisible by 4? Something went wrong with the word (32 bits) length";
377 } else if (nbytes % 8) {
378 LOG(error) << "Odd number of nwords in TOF payload, this should not happen";
379 } else if (nbytes % 16) {
380 // LOG(info) << "Nwords not divisible by 4, let's fill with 2 more words";
381 mUnion[i]->data = 0x70000000;
382 nextWord(i);
383 mUnion[i]->data = 0x70000000;
384 nextWord(i);
385 }
386
387 mTOFDataHeader[i]->bytePayload = getSize(mTOFDataHeader[i], mUnion[i]);
388 }
389
390 // check that all digits were used
391 if (icurrentdigit < summary.size()) {
392 LOG(error) << "Not all digits are been used : only " << icurrentdigit << " of " << summary.size();
393 }
394 }
395
396 mIR.bc = bcFirstWin;
397
398 for (int i = 0; i < 72; i++) {
399 flush(i);
400 }
401
402 mStartRun = false;
403
404 auto finish = std::chrono::high_resolution_clock::now();
405 std::chrono::duration<double> elapsed = finish - start;
406 mIntegratedTime = elapsed.count();
407
408 return false;
409}
410
411int Encoder::getSize(void* first, void* last)
412{
413 char* in = reinterpret_cast<char*>(first);
414 char* out = reinterpret_cast<char*>(last);
415
416 return int(out - in);
417}
418
419} // namespace compressed
420} // namespace tof
421} // namespace o2
Definition of the 32 Central Trigger System (CTS) Trigger Types defined in https://twiki....
uint16_t padding
Definition of the TOF encoder.
Definition of the TOF encoder.
uint16_t getBC() const
int32_t i
Header of the General Run Parameters object.
Header to collect LHC related constants.
Definition of the Names Generator class.
static std::string getGRPFileName(const std::string_view prefix=STANDARDSIMPREFIX)
Definition NameConf.cxx:58
static constexpr ID TOF
Definition DetID.h:66
static GRPObject * loadFrom(const std::string &grpFileName="")
void useRDHDataFormat(unsigned char v)
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)
LinkData & registerLink(uint16_t fee, uint16_t cru, uint8_t link, uint8_t endpoint, std::string_view outFileName)
TOF digit implementation.
Definition Digit.h:31
static constexpr Int_t RATIO_TOT_TDC_BIN
Definition Geo.h:152
static Int_t getCRUid(int link)
Definition Geo.h:44
static Int_t getFEEid(int link)
Definition Geo.h:53
static constexpr int BC_IN_WINDOW
Definition Geo.h:165
static Int_t getFLPid(int link)
Definition Geo.h:49
static constexpr int BC_IN_ORBIT
Definition Geo.h:105
static Int_t getCRUendpoint(int link)
Definition Geo.h:39
static Int_t getECHFromCH(int chan)
Definition Geo.h:351
static Int_t getCRUlink(int link)
Definition Geo.h:35
static constexpr int NWINDOW_IN_ORBIT
Definition Geo.h:163
Union_t * mStart[72]
Definition Encoder.h:82
bool encode(std::vector< std::vector< o2::tof::Digit > > digitWindow, int tofwindow=0)
Definition Encoder.cxx:248
o2::InteractionRecord mIR
Definition Encoder.h:102
bool mNextWordStatus[72]
Definition Encoder.h:85
int getSize(void *first, void *last)
Definition Encoder.cxx:411
TOFDataHeader_t * mTOFDataHeader[72]
Definition Encoder.h:83
double mIntegratedAllBytes
Definition Encoder.h:70
bool alloc(long size)
Definition Encoder.cxx:131
char * mBuffer[72]
Definition Encoder.h:78
std::vector< char > mBufferLocal
Definition Encoder.h:79
void encodeTRM(const std::vector< Digit > &summary, Int_t icrate, Int_t itrm, int &istart)
Definition Encoder.cxx:154
void nextWord(int icrate)
Definition Encoder.cxx:47
o2::raw::RawFileWriter mFileWriter
Definition Encoder.h:91
Union_t * mUnion[72]
Definition Encoder.h:81
DRMDataHeader_t * mDRMDataHeader[72]
Definition Encoder.h:84
bool open(const std::string &name, const std::string &path=".", const std::string &fileFor="cruendpoint")
Definition Encoder.cxx:60
bool flush(int icrate)
Definition Encoder.cxx:111
GLsizeiptr size
Definition glcorearb.h:659
GLuint const GLchar * name
Definition glcorearb.h:781
GLint first
Definition glcorearb.h:399
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLuint start
Definition glcorearb.h:469
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
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)
Definition common.h:52
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
IR getFirstSampledTFIR() const
get TF and HB (abs) for this IR
Definition HBFUtils.h:74
static void setLinkID(H &rdh, uint8_t v, NOTPTR(H))
Definition RDHUtils.h:256
static void setDetectorField(H &rdh, uint32_t v, NOTPTR(H))
Definition RDHUtils.h:582
static void setEndPointID(H &rdh, uint8_t v, NOTPTR(H))
Definition RDHUtils.h:304
static void setFEEID(RDHv4 &rdh, uint16_t v)
Definition RDHUtils.h:146
static constexpr int getVersion()
get numeric version of the RDH
Definition RDHUtils.h:58
static void setCRUID(H &rdh, uint16_t v, NOTPTR(H))
Definition RDHUtils.h:288
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"