Project
Loading...
Searching...
No Matches
RCUTrailer.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#include <cfloat>
12#include <cmath>
13#include <iostream>
14#include <fmt/format.h>
17#include <fairlogger/Logger.h>
18
19using namespace o2::emcal;
20
22{
23 mRCUId = -1;
24 mFirmwareVersion = 0;
25 mTrailerSize = 0;
26 mPayloadSize = 0;
27 mFECERRA = 0;
28 mFECERRB = 0;
29 mErrorCounter.mErrorRegister2 = 0;
30 mErrorCounter.mErrorRegister3 = 0;
31 mActiveFECsA = 0;
32 mActiveFECsB = 0;
33 mAltroConfig.mWord1 = 0;
34 mAltroConfig.mWord2 = 0;
35 mIsInitialized = false;
36}
37
38bool RCUTrailer::checkLastTrailerWord(uint32_t trailerword)
39{
40 const int MIN_FWVERSION = 2;
41 const int MAX_FWVERSION = 2;
42 if ((trailerword >> 30) != 3) {
43 return false;
44 }
45 auto firmwarevesion = (trailerword >> 16) & 0xFF;
46 auto trailerSize = (trailerword & 0x7F);
47 if (firmwarevesion < MIN_FWVERSION || firmwarevesion > MAX_FWVERSION) {
48 return false;
49 }
50 if (trailerSize < 2) {
51 return false;
52 }
53 if (firmwarevesion == 2) {
54 if (trailerSize < 9) {
55 return false;
56 }
57 }
58 return true;
59}
60
61void RCUTrailer::constructFromRawPayload(const gsl::span<const uint32_t> payloadwords)
62{
63 reset();
64 int index = payloadwords.size();
65 auto word = payloadwords[--index];
66 if ((word >> 30) != 3) {
67 throw Error(Error::ErrorType_t::DECODING_INVALID, "Last RCU trailer word not found!");
68 }
69 mFirmwareVersion = (word >> 16) & 0xFF;
70
71 mRCUId = (int)((word >> 7) & 0x1FF);
72 int trailerSize = (word & 0x7F);
73
74 if (trailerSize < 2) {
75 throw Error(Error::ErrorType_t::SIZE_INVALID, fmt::format("Invalid trailer size found (%d bytes) !", trailerSize * 4).data());
76 }
77 mTrailerSize = trailerSize;
78
79 trailerSize -= 2; // Cut first and last trailer words as they are handled separately
80 int foundTrailerWords = 0;
81 for (; trailerSize > 0; trailerSize--) {
82 word = payloadwords[--index];
83 if ((word >> 30) != 2) {
84 continue;
85 }
86 foundTrailerWords++;
87 int parCode = (word >> 26) & 0xF;
88 int parData = word & 0x3FFFFFF;
89 // std::cout << "Found trailer word 0x" << std::hex << word << "(Par code: " << std::dec << parCode << ", Par data: 0x" << std::hex << parData << std::dec << ")" << std::endl;
90 switch (parCode) {
91 case 1:
92 // ERR_REG1
93 mFECERRA = ((parData >> 13) & 0x1FFF) << 7;
94 mFECERRB = ((parData & 0x1FFF)) << 7;
95 break;
96 case 2:
97 // ERR_REG2
98 mErrorCounter.mErrorRegister2 = parData & 0x1FF;
99 break;
100 case 3:
101 // ERR_REG3
102 mErrorCounter.mErrorRegister3 = parData & 0x1FFFFFF;
103 break;
104 case 4:
105 // FEC_RO_A
106 mActiveFECsA = parData & 0xFFFF;
107 break;
108 case 5:
109 // FEC_RO_B
110 mActiveFECsB = parData & 0xFFFF;
111 break;
112 case 6:
113 // RDO_CFG1
114 mAltroConfig.mWord1 = parData & 0xFFFFF;
115 break;
116 case 7:
117 // RDO_CFG2
118 mAltroConfig.mWord2 = parData & 0x1FFFFFF;
119 break;
120 default:
121 LOG(warning) << "RCU trailer: Undefined parameter code " << parCode << " in word " << index << " (0x" << std::hex << word << std::dec << "), ignoring word";
122 mWordCorruptions++;
123 break;
124 }
125 }
126 auto lastword = payloadwords[--index];
127 if (lastword >> 30 == 2) {
128 mPayloadSize = lastword & 0x3FFFFFF;
129 foundTrailerWords++;
130 }
131 if (foundTrailerWords + 1 < mTrailerSize) { // Must account for the first word which was chopped
132 throw Error(Error::ErrorType_t::DECODING_INVALID, fmt::format("Corrupted trailer words: {:d} word(s) not having trailer marker", mTrailerSize - foundTrailerWords).data());
133 }
134 mIsInitialized = true;
135}
136
138{
139 uint8_t fq = mAltroConfig.mSampleTime;
140 double tSample;
141 switch (fq) {
142 case 0:
143 // 20 MHz
144 tSample = 2.0;
145 break;
146 case 1:
147 // 10 Mhz
148 tSample = 4.0;
149 break;
150 case 2:
151 // 5 MHz
152 tSample = 8.;
153 break;
154 default:
155 throw Error(Error::ErrorType_t::SAMPLINGFREQ_INVALID, fmt::format("Invalid sampling frequency value {:d} !", int(fq)).data());
156 }
157
158 return tSample * o2::constants::lhc::LHCBunchSpacingNS;
159}
160
161void RCUTrailer::setTimeSamplePhaseNS(uint64_t triggertime, uint64_t timesample)
162{
163 int sample = 0;
164 switch (timesample) {
165 case 50:
166 sample = 0;
167 break;
168 case 100:
169 sample = 1;
170 break;
171 case 200:
172 sample = 2;
173 break;
174 default:
175 throw Error(Error::ErrorType_t::SAMPLINGFREQ_INVALID, fmt::format(fmt::runtime("invalid time sample: {:f}"), timesample).data());
176 };
177 mAltroConfig.mSampleTime = sample;
178 // calculate L1 phase
179 mAltroConfig.mL1Phase = (triggertime % timesample) / 25;
180}
181
183{
184 double tSample = getTimeSampleNS(),
185 phase = static_cast<double>(mAltroConfig.mL1Phase) * o2::constants::lhc::LHCBunchSpacingNS;
186 if (phase >= tSample) {
187 throw Error(Error::ErrorType_t::L1PHASE_INVALID, fmt::format("Invalid L1 trigger phase ({:e} ns (phase) >= {:e} ns (sampling time)) !", phase, tSample).data());
188 }
189 return phase;
190}
191
192std::vector<uint32_t> RCUTrailer::encode() const
193{
194 std::vector<uint32_t> encoded;
195 encoded.emplace_back(mPayloadSize | 2 << 30);
196 encoded.emplace_back(mFECERRB >> 7 | (mFECERRA >> 7) << 13 | 1 << 26 | 2 << 30);
197 encoded.emplace_back(mErrorCounter.mErrorRegister2 | 2 << 26 | 2 << 30);
198 encoded.emplace_back(mErrorCounter.mErrorRegister3 | 3 << 26 | 2 << 30);
199 encoded.emplace_back(mActiveFECsA | 4 << 26 | 2 << 30);
200 encoded.emplace_back(mActiveFECsB | 5 << 26 | 2 << 30);
201 encoded.emplace_back(mAltroConfig.mWord1 | 6 << 26 | 2 << 30);
202 encoded.emplace_back(mAltroConfig.mWord2 | 7 << 26 | 2 << 30);
203
204 uint32_t lasttrailerword = 3 << 30 | mFirmwareVersion << 16 | mRCUId << 7 | (encoded.size() + 1);
205 encoded.emplace_back(lasttrailerword);
206
207 return encoded;
208}
209
210void RCUTrailer::printStream(std::ostream& stream) const
211{
212 std::vector<std::string> errors;
213 double timesample = -1., l1phase = -1.;
214 try {
215 timesample = getTimeSampleNS();
216 } catch (Error& e) {
217 errors.push_back(e.what());
218 }
219 try {
220 l1phase = getL1PhaseNS();
221 } catch (Error& e) {
222 errors.push_back(e.what());
223 }
224
225 stream << "RCU trailer (Format version 2):\n"
226 << "==================================================\n"
227 << "RCU ID: " << mRCUId << "\n"
228 << "Firmware version: " << int(mFirmwareVersion) << "\n"
229 << "Trailer size: " << mTrailerSize << "\n"
230 << "Payload size: " << mPayloadSize << "\n"
231 << "FECERRA: 0x" << std::hex << mFECERRA << "\n"
232 << "FECERRB: 0x" << std::hex << mFECERRB << "\n"
233 << "ERRREG2: 0x" << std::hex << mErrorCounter.mErrorRegister2 << "\n"
234 << "ERRREG3: 0x" << std::hex << mErrorCounter.mErrorRegister3 << "\n"
235 << "#channels skipped due to address mismatch: " << std::dec << getNumberOfChannelAddressMismatch() << "\n"
236 << "#channels skipped due to bad block length: " << std::dec << getNumberOfChannelLengthMismatch() << "\n"
237 << "Active FECs (branch A): 0x" << std::hex << mActiveFECsA << "\n"
238 << "Active FECs (branch B): 0x" << std::hex << mActiveFECsB << "\n"
239 << "Baseline corr: " << std::hex << getBaselineCorrection() << "\n"
240 << "Polarity: " << (getPolarity() ? "yes" : "no") << "\n"
241 << "Number of presamples: " << std::dec << getNumberOfPresamples() << "\n"
242 << "Number of postsamples: " << std::dec << getNumberOfPostsamples() << "\n"
243 << "Second baseline corr: " << (hasSecondBaselineCorr() ? "yes" : "no") << "\n"
244 << "Glitch filter: " << std::dec << getGlitchFilter() << "\n"
245 << "Number of non-ZS postsamples: " << std::dec << getNumberOfNonZeroSuppressedPostsamples() << "\n"
246 << "Number of non-ZS presamples: " << std::dec << getNumberOfNonZeroSuppressedPresamples() << "\n"
247 << "Zero suppression: " << (hasZeroSuppression() ? "yes" : "no") << "\n"
248 << "Number of ALTRO buffers: " << std::dec << getNumberOfAltroBuffers() << "\n"
249 << "Number of pretrigger samples: " << std::dec << getNumberOfPretriggerSamples() << "\n"
250 << "Number of samples per channel: " << std::dec << getNumberOfSamplesPerChannel() << "\n"
251 << "Sparse readout: " << (isSparseReadout() ? "yes" : "no") << "\n"
252 << "AltroCFG1: 0x" << std::hex << mAltroConfig.mWord1 << "\n"
253 << "AltroCFG2: 0x" << std::hex << mAltroConfig.mWord2 << "\n"
254 << "Sampling time: " << std::dec << timesample << " ns\n"
255 << "L1 Phase: " << std::dec << l1phase << " ns (" << mAltroConfig.mL1Phase << ")\n"
256 << std::dec << std::fixed;
257 if (errors.size()) {
258 stream << "Errors: \n"
259 << "-------------------------------------------------\n";
260 for (const auto& e : errors) {
261 stream << e << "\n";
262 }
263 }
264 stream << "==================================================\n";
265}
266
267RCUTrailer RCUTrailer::constructFromPayloadWords(const gsl::span<const uint32_t> payloadwords)
268{
270 result.constructFromRawPayload(payloadwords);
271 return result;
272}
273
274std::ostream& o2::emcal::operator<<(std::ostream& stream, const o2::emcal::RCUTrailer& trailer)
275{
276 trailer.printStream(stream);
277 return stream;
278}
uint64_t phase
Definition RawEventData.h:7
unsigned char uint8_t
unsigned int uint32_t
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
Header to collect LHC related constants.
Error handling of the RCU trailer.
Definition RCUTrailer.h:80
@ SAMPLINGFREQ_INVALID
Invalid sampling frequency.
@ DECODING_INVALID
Invalid words during decoding.
Information stored in the RCU trailer.
Definition RCUTrailer.h:75
void reset()
Reset the RCU trailer.
uint16_t getNumberOfChannelAddressMismatch() const
Get the number of channels with address mismatch.
Definition RCUTrailer.h:199
bool hasZeroSuppression() const
Check whether zero suppression has been applied.
Definition RCUTrailer.h:260
void setTimeSamplePhaseNS(uint64_t triggertime, uint64_t timesample)
Set the time sample length and L1 phase based on the trigger time.
static RCUTrailer constructFromPayloadWords(const gsl::span< const uint32_t > payloadwords)
Decode RCU trailer from payload.
uint16_t getNumberOfPostsamples() const
Get the number of postsamples (after zero suppression)
Definition RCUTrailer.h:240
uint16_t getBaselineCorrection() const
Get baseline correction method.
Definition RCUTrailer.h:228
uint16_t getNumberOfSamplesPerChannel() const
Get the number of samples per channel.
Definition RCUTrailer.h:268
void printStream(std::ostream &stream) const
Prints the contents of the RCU trailer data.
bool hasSecondBaselineCorr() const
Check if second baseline correction is applied.
Definition RCUTrailer.h:244
uint16_t getNumberOfPretriggerSamples() const
Get the number of pretrigger samples.
Definition RCUTrailer.h:264
uint16_t getGlitchFilter() const
Get the glitch filter.
Definition RCUTrailer.h:248
static bool checkLastTrailerWord(uint32_t trailerword)
Check whether the word is a valid last trailer word.
void constructFromRawPayload(const gsl::span< const uint32_t > payloadwords)
Decode RCU trailer from the 32-bit words in the raw buffer.
uint16_t getNumberOfNonZeroSuppressedPresamples() const
Get the number of presamples before zero suppression.
Definition RCUTrailer.h:256
double getL1PhaseNS() const
Access to the L1 phase.
bool isSparseReadout() const
Check whether readout is in sparse mode.
Definition RCUTrailer.h:276
uint16_t getNumberOfAltroBuffers() const
Get the number of ALTRO buffers.
Definition RCUTrailer.h:272
double getTimeSampleNS() const
Access to the sampling time.
std::vector< uint32_t > encode() const
Encode RCU trailer as array of DDL (32-bit) words.
bool getPolarity() const
Check polarity setting.
Definition RCUTrailer.h:232
uint16_t getNumberOfNonZeroSuppressedPostsamples() const
Get the number of postsamples before zero suppression.
Definition RCUTrailer.h:252
uint16_t getNumberOfPresamples() const
Get the number of presamples (after zero suppression)
Definition RCUTrailer.h:236
uint16_t getNumberOfChannelLengthMismatch() const
Get the number of channels with length mismatch.
Definition RCUTrailer.h:203
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint index
Definition glcorearb.h:781
GLuint GLuint stream
Definition glcorearb.h:1806
std::ostream & operator<<(std::ostream &stream, const Cell &cell)
Stream operator for EMCAL cell.
Definition Cell.cxx:366
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"