forked from cms-sw/cmssw
/
SiStripFEDBuffer.h
444 lines (388 loc) · 16.4 KB
/
SiStripFEDBuffer.h
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
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
#ifndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
#define EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
#include "boost/cstdint.hpp"
#include <string>
#include <vector>
#include <memory>
#include <ostream>
#include <cstring>
#include <cmath>
#include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferComponents.h"
#include "FWCore/Utilities/interface/GCC11Compatibility.h"
namespace sistrip {
//
// Class definitions
//
//class representing standard (non-spy channel) FED buffers
class FEDBuffer final : public FEDBufferBase
{
public:
//construct from buffer
//if allowBadBuffer is set to true then exceptions will not be thrown if the channel lengths do not make sense or the event format is not recognized
FEDBuffer(const uint8_t* fedBuffer, const uint16_t fedBufferSize, const bool allowBadBuffer = false);
virtual ~FEDBuffer();
virtual void print(std::ostream& os) const;
const FEDFEHeader* feHeader() const;
//check that a FE unit is enabled, has a good majority address and, if in full debug mode, that it is present
bool feGood(const uint8_t internalFEUnitNum) const;
bool feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const;
//check that a FE unit is present in the data.
//The high order byte of the FEDStatus register in the tracker special header is used in APV error mode.
//The FE length from the full debug header is used in full debug mode.
bool fePresent(uint8_t internalFEUnitNum) const;
//check that a channel is present in data, found, on a good FE unit and has no errors flagged in status bits
virtual bool channelGood(const uint8_t internalFEDannelNum, const bool doAPVeCheck=true) const;
void setLegacyMode(bool legacy) { legacyUnpacker_ = legacy;}
//functions to check buffer. All return true if there is no problem.
//minimum checks to do before using buffer
virtual bool doChecks(bool doCRC=true) const;
//additional checks to check for corrupt buffers
//check channel lengths fit inside to buffer length
bool checkChannelLengths() const;
//check that channel lengths add up to buffer length (this does the previous check as well)
bool checkChannelLengthsMatchBufferLength() const;
//check channel packet codes match readout mode
bool checkChannelPacketCodes() const;
//check FE unit lengths in FULL DEBUG header match the lengths of their channels
bool checkFEUnitLengths() const;
//check FE unit APV addresses in FULL DEBUG header are equal to the APVe address if the majority was good
bool checkFEUnitAPVAddresses() const;
//do all corrupt buffer checks
virtual bool doCorruptBufferChecks() const;
//check that there are no errors in channel, APV or FEUnit status bits
//these are done by channelGood(). Channels with bad status bits may be disabled so bad status bits do not usually indicate an error
bool checkStatusBits(const uint8_t internalFEDChannelNum) const;
bool checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const;
//same but for all channels on enabled FE units
bool checkAllChannelStatusBits() const;
//check that all FE unit payloads are present
bool checkFEPayloadsPresent() const;
//print a summary of all checks
virtual std::string checkSummary() const;
private:
uint8_t nFEUnitsPresent() const;
void findChannels();
inline uint8_t getCorrectPacketCode() const { return packetCode(legacyUnpacker_); }
uint16_t calculateFEUnitLength(const uint8_t internalFEUnitNumber) const;
std::auto_ptr<FEDFEHeader> feHeader_;
const uint8_t* payloadPointer_;
uint16_t payloadLength_;
uint8_t validChannels_;
bool fePresent_[FEUNITS_PER_FED];
bool legacyUnpacker_=false;
};
//class for unpacking data from ZS FED channels
class FEDZSChannelUnpacker
{
public:
static FEDZSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel& channel);
static FEDZSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel& channel);
static FEDZSChannelUnpacker preMixRawModeUnpacker(const FEDChannel& channel);
FEDZSChannelUnpacker();
uint8_t sampleNumber() const;
uint8_t adc() const;
uint16_t adcPreMix() const;
bool hasData() const;
FEDZSChannelUnpacker& operator ++ ();
FEDZSChannelUnpacker& operator ++ (int);
private:
//pointer to beginning of FED or FE data, offset of start of channel payload in data and length of channel payload
FEDZSChannelUnpacker(const uint8_t* payload, const uint16_t channelPayloadOffset, const int16_t channelPayloadLength, const uint16_t offsetIncrement=1);
void readNewClusterInfo();
static void throwBadChannelLength(const uint16_t length);
void throwBadClusterLength();
static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster);
const uint8_t* data_;
uint16_t currentOffset_;
uint16_t offsetIncrement_;
uint8_t currentStrip_;
uint8_t valuesLeftInCluster_;
uint16_t channelPayloadOffset_;
uint16_t channelPayloadLength_;
};
//class for unpacking data from raw FED channels
class FEDRawChannelUnpacker
{
public:
static FEDRawChannelUnpacker scopeModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
static FEDRawChannelUnpacker virginRawModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
static FEDRawChannelUnpacker procRawModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
explicit FEDRawChannelUnpacker(const FEDChannel& channel);
uint8_t sampleNumber() const;
uint16_t adc() const;
bool hasData() const;
FEDRawChannelUnpacker& operator ++ ();
FEDRawChannelUnpacker& operator ++ (int);
private:
static void throwBadChannelLength(const uint16_t length);
const uint8_t* data_;
uint16_t currentOffset_;
uint8_t currentStrip_;
uint16_t valuesLeft_;
};
//class for unpacking data from any FED channels with a non-integer words bits stripping mode
class FEDBSChannelUnpacker
{
public:
static FEDBSChannelUnpacker virginRawModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
static FEDBSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
static FEDBSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel& channel, uint16_t num_bits);
FEDBSChannelUnpacker();
uint8_t sampleNumber() const;
uint16_t adc() const;
bool hasData() const;
FEDBSChannelUnpacker& operator ++ ();
FEDBSChannelUnpacker& operator ++ (int);
private:
//pointer to beginning of FED or FE data, offset of start of channel payload in data and length of channel payload
FEDBSChannelUnpacker(const uint8_t* payload, const uint16_t channelPayloadOffset, const int16_t channelPayloadLength, const uint16_t offsetIncrement, bool useZS);
void readNewClusterInfo();
static void throwBadChannelLength(const uint16_t length);
static void throwBadWordLength(const uint16_t word_length);
static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster);
const uint8_t* data_;
uint16_t oldWordOffset_;
uint16_t currentWordOffset_;
uint16_t currentBitOffset_;
uint16_t currentLocalBitOffset_;
uint16_t bitOffsetIncrement_;
uint8_t currentStrip_;
uint16_t channelPayloadOffset_;
uint16_t channelPayloadLength_;
bool useZS_;
uint8_t valuesLeftInCluster_;
};
//
// Inline function definitions
//
//FEDBuffer
inline const FEDFEHeader* FEDBuffer::feHeader() const
{
return feHeader_.get();
}
inline bool FEDBuffer::feGood(const uint8_t internalFEUnitNum) const
{
return ( !majorityAddressErrorForFEUnit(internalFEUnitNum) && !feOverflow(internalFEUnitNum) && fePresent(internalFEUnitNum) );
}
inline bool FEDBuffer::feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const
{
return ( !feOverflow(internalFEUnitNum) && fePresent(internalFEUnitNum) );
}
inline bool FEDBuffer::fePresent(uint8_t internalFEUnitNum) const
{
return fePresent_[internalFEUnitNum];
}
inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEDChannelNum) const
{
return feHeader_->checkChannelStatusBits(internalFEDChannelNum);
}
inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const
{
return checkStatusBits(internalFEDChannelNum(internalFEUnitNum,internalChannelNum));
}
//FEDBSChannelUnpacker
inline FEDBSChannelUnpacker::FEDBSChannelUnpacker()
: data_(NULL),
oldWordOffset_(0), currentWordOffset_(0),
currentBitOffset_(0), currentLocalBitOffset_(0),
bitOffsetIncrement_(10),
currentStrip_(0),
channelPayloadOffset_(0), channelPayloadLength_(0),
useZS_(false), valuesLeftInCluster_(0)
{ }
inline FEDBSChannelUnpacker::FEDBSChannelUnpacker(const uint8_t* payload, const uint16_t channelPayloadOffset, const int16_t channelPayloadLength, const uint16_t offsetIncrement, bool useZS)
: data_(payload),
oldWordOffset_(0), currentWordOffset_(channelPayloadOffset),
currentBitOffset_(0), currentLocalBitOffset_(0),
bitOffsetIncrement_(offsetIncrement),
channelPayloadOffset_(channelPayloadOffset),
channelPayloadLength_(channelPayloadLength),
useZS_(useZS), valuesLeftInCluster_(0)
{
if (bitOffsetIncrement_>16) throwBadWordLength(bitOffsetIncrement_); // more than 2 words... still to be implemented
}
inline FEDBSChannelUnpacker FEDBSChannelUnpacker::virginRawModeUnpacker(const FEDChannel& channel, uint16_t num_bits)
{
uint16_t length = channel.length();
if (length & 0xF000) throwBadChannelLength(length);
if (num_bits<=0 or num_bits>16) throwBadWordLength(num_bits);
FEDBSChannelUnpacker result(channel.data(), channel.offset()+3, length-3, num_bits, false);
return result;
}
inline FEDBSChannelUnpacker FEDBSChannelUnpacker::zeroSuppressedModeUnpacker(const FEDChannel& channel, uint16_t num_bits)
{
uint16_t length = channel.length();
if (length & 0xF000) throwBadChannelLength(length);
FEDBSChannelUnpacker result(channel.data(), channel.offset()+7, length-7, num_bits, true);
return result;
}
inline FEDBSChannelUnpacker FEDBSChannelUnpacker::zeroSuppressedLiteModeUnpacker(const FEDChannel& channel, uint16_t num_bits)
{
uint16_t length = channel.length();
if (length & 0xF000) throwBadChannelLength(length);
FEDBSChannelUnpacker result(channel.data(), channel.offset()+2, length-2, num_bits, true);
return result;
}
inline uint8_t FEDBSChannelUnpacker::sampleNumber() const
{
return currentStrip_;
}
inline uint16_t FEDBSChannelUnpacker::adc() const
{
uint16_t bits_missing = (bitOffsetIncrement_-8)+currentLocalBitOffset_;
uint16_t adc = (data_[currentWordOffset_^7]<<bits_missing);
if (currentWordOffset_>oldWordOffset_) {
adc += ( (data_[(currentWordOffset_+1)^7]>>(8-bits_missing)) );
}
return (adc&((1<<bitOffsetIncrement_)-1));
}
inline bool FEDBSChannelUnpacker::hasData() const
{
return (currentWordOffset_<channelPayloadOffset_+channelPayloadLength_);
}
inline FEDBSChannelUnpacker& FEDBSChannelUnpacker::operator ++ ()
{
oldWordOffset_ = currentWordOffset_;
currentBitOffset_ += bitOffsetIncrement_;
currentLocalBitOffset_ += bitOffsetIncrement_;
while (currentLocalBitOffset_>=8) {
currentWordOffset_++;
currentLocalBitOffset_ -= 8;
}
if (useZS_) {
if (valuesLeftInCluster_) { currentStrip_++; valuesLeftInCluster_--; }
else {
if (hasData()) {
const uint8_t oldStrip = currentStrip_;
readNewClusterInfo();
if ( !(currentStrip_ > oldStrip) ) throwUnorderedData(oldStrip,currentStrip_);
}
}
} else { currentStrip_++; }
return (*this);
}
inline FEDBSChannelUnpacker& FEDBSChannelUnpacker::operator ++ (int)
{
++(*this); return *this;
}
inline void FEDBSChannelUnpacker::readNewClusterInfo()
{
currentStrip_ = data_[(currentWordOffset_++)^7];
valuesLeftInCluster_ = data_[(currentWordOffset_++)^7]-1;
}
//FEDRawChannelUnpacker
inline FEDRawChannelUnpacker::FEDRawChannelUnpacker(const FEDChannel& channel)
: data_(channel.data()),
currentOffset_(channel.offset()+3),
currentStrip_(0),
valuesLeft_((channel.length()-3)/2)
{
if ((channel.length()-3)%2) throwBadChannelLength(channel.length());
}
inline uint8_t FEDRawChannelUnpacker::sampleNumber() const
{
return currentStrip_;
}
inline uint16_t FEDRawChannelUnpacker::adc() const
{
return ( data_[currentOffset_^7] + ((data_[(currentOffset_+1)^7]&0x03)<<8) );
}
inline bool FEDRawChannelUnpacker::hasData() const
{
return valuesLeft_;
}
inline FEDRawChannelUnpacker& FEDRawChannelUnpacker::operator ++ ()
{
currentOffset_ += 2;
currentStrip_++;
valuesLeft_--;
return (*this);
}
inline FEDRawChannelUnpacker& FEDRawChannelUnpacker::operator ++ (int)
{
++(*this); return *this;
}
//FEDZSChannelUnpacker
inline FEDZSChannelUnpacker::FEDZSChannelUnpacker()
: data_(NULL),
offsetIncrement_(1),
valuesLeftInCluster_(0),
channelPayloadOffset_(0),
channelPayloadLength_(0)
{ }
inline FEDZSChannelUnpacker::FEDZSChannelUnpacker(const uint8_t* payload, const uint16_t channelPayloadOffset, const int16_t channelPayloadLength, const uint16_t offsetIncrement)
: data_(payload),
currentOffset_(channelPayloadOffset),
offsetIncrement_(offsetIncrement),
currentStrip_(0),
valuesLeftInCluster_(0),
channelPayloadOffset_(channelPayloadOffset),
channelPayloadLength_(channelPayloadLength)
{
if (channelPayloadLength_) readNewClusterInfo();
}
inline FEDZSChannelUnpacker FEDZSChannelUnpacker::zeroSuppressedModeUnpacker(const FEDChannel& channel)
{
uint16_t length = channel.length();
if (length & 0xF000) throwBadChannelLength(length);
FEDZSChannelUnpacker result(channel.data(),channel.offset()+7,length-7);
return result;
}
inline FEDZSChannelUnpacker FEDZSChannelUnpacker::zeroSuppressedLiteModeUnpacker(const FEDChannel& channel)
{
uint16_t length = channel.length();
if (length & 0xF000) throwBadChannelLength(length);
FEDZSChannelUnpacker result(channel.data(),channel.offset()+2,length-2);
return result;
}
inline FEDZSChannelUnpacker FEDZSChannelUnpacker::preMixRawModeUnpacker(const FEDChannel& channel)
{
//CAMM - to modify more ?
uint16_t length = channel.length();
if (length & 0xF000) throwBadChannelLength(length);
FEDZSChannelUnpacker result(channel.data(),channel.offset()+7,length-7,2);
return result;
}
inline uint8_t FEDZSChannelUnpacker::sampleNumber() const
{
return currentStrip_;
}
inline uint8_t FEDZSChannelUnpacker::adc() const
{
return data_[currentOffset_^7];
}
inline uint16_t FEDZSChannelUnpacker::adcPreMix() const
{
return ( data_[currentOffset_^7] + ((data_[(currentOffset_+1)^7]&0x03)<<8) );
}
inline bool FEDZSChannelUnpacker::hasData() const
{
return (currentOffset_<channelPayloadOffset_+channelPayloadLength_);
}
inline FEDZSChannelUnpacker& FEDZSChannelUnpacker::operator ++ ()
{
if (valuesLeftInCluster_) {
currentStrip_++;
currentOffset_ += offsetIncrement_;
valuesLeftInCluster_--;
} else {
currentOffset_ += offsetIncrement_;
if (hasData()) {
const uint8_t oldStrip = currentStrip_;
readNewClusterInfo();
if ( !(currentStrip_ > oldStrip) ) throwUnorderedData(oldStrip,currentStrip_);
}
}
return (*this);
}
inline FEDZSChannelUnpacker& FEDZSChannelUnpacker::operator ++ (int)
{
++(*this); return *this;
}
inline void FEDZSChannelUnpacker::readNewClusterInfo()
{
currentStrip_ = data_[(currentOffset_++)^7];
valuesLeftInCluster_ = data_[(currentOffset_++)^7]-1;
}
}
#endif //ndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H