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
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
Header to collect LHC related constants.
Error handling of the RCU trailer.
Definition RCUTrailer.h:80
const char * what() const noexcept override
Access to the error message.
Definition RCUTrailer.h:104
@ 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
GLboolean * data
Definition glcorearb.h:298
GLuint GLuint stream
Definition glcorearb.h:1806
constexpr double LHCBunchSpacingNS
std::ostream & operator<<(std::ostream &stream, const Cell &cell)
Stream operator for EMCAL cell.
Definition Cell.cxx:355
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"