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
|
#ifndef EventFilter_SiStripRawToDigi_SiStripFEDBufferGenerator_H
#define EventFilter_SiStripRawToDigi_SiStripFEDBufferGenerator_H
#include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferComponents.h"
#include "DataFormats/FEDRawData/interface/FEDRawData.h"
#include <vector>
#include <list>
#include <utility>
#include <memory>
#include <cstdint>
namespace sistrip {
//
// Class definitions
//
class FEDStripData {
public:
//class used to represent channel data
class ChannelData {
public:
ChannelData(bool dataIsAlreadyConvertedTo8Bit,
const size_t numberOfSamples,
const std::pair<uint16_t, uint16_t> medians = std::make_pair<uint16_t>(0, 0));
//number of samples
size_t size() const;
//get common mode medians for first and second APV
std::pair<uint16_t, uint16_t> getMedians() const;
//set common mode medians for first and second APV
void setMedians(const std::pair<uint16_t, uint16_t> values);
//get the 10bit value to be used for raw modes
uint16_t getSample(const uint16_t sampleNumber) const;
//get the 8 bit value to be used for ZS modes, converting it as the FED does if specified in constructor
uint8_t get8BitSample(const uint16_t sampleNumber, uint16_t nBotBitsToDrop) const;
uint16_t get10BitSample(const uint16_t sampleNumber) const;
void setSample(const uint16_t sampleNumber, const uint16_t adcValue);
//setting value directly is equivalent to get and set Sample but without length check
uint16_t& operator[](const size_t sampleNumber);
const uint16_t& operator[](const size_t sampleNumber) const;
private:
std::pair<uint16_t, uint16_t> medians_;
std::vector<uint16_t> data_;
bool dataIs8Bit_;
};
FEDStripData(const std::vector<ChannelData>& data);
//specify whether the data is already in the 8bit ZS format (only affects what is returned by ChannelData::get8BitSample() if the value if >253)
//if the data is for scope mode then specify the scope length
FEDStripData(bool dataIsAlreadyConvertedTo8Bit = true, const size_t samplesPerChannel = STRIPS_PER_FEDCH);
//access to elements
ChannelData& operator[](const uint8_t internalFEDChannelNum);
const ChannelData& operator[](const uint8_t internalFEDChannelNum) const;
ChannelData& channel(const uint8_t internalFEDChannelNum);
const ChannelData& channel(const uint8_t internalFEDChannelNum) const;
private:
std::vector<ChannelData> data_;
};
class FEDBufferPayload {
public:
FEDBufferPayload(const std::vector<std::vector<uint8_t> >& channelBuffers);
//size of payload in bytes
size_t lengthInBytes() const;
//returns NULL if payload size is 0, otherwise return a pointer to the payload buffer
const uint8_t* data() const;
//size of FE unit payload
uint16_t getFELength(const uint8_t internalFEUnitNum) const;
private:
void appendToBuffer(size_t* pIndexInBuffer, const uint8_t value);
void appendToBuffer(size_t* pIndexInBuffer,
std::vector<uint8_t>::const_iterator start,
std::vector<uint8_t>::const_iterator finish);
std::vector<uint8_t> data_;
std::vector<uint16_t> feLengths_;
};
class FEDBufferPayloadCreator {
public:
//specify which FE units and channels should have data generated for them
//If an FE unit is disabled then the channel is as well. The whole FE payload will be missing.
//If a channel is disabled then it is considered to have all zeros in the data but will be present in the data
FEDBufferPayloadCreator(const std::vector<bool>& enabledFEUnits, const std::vector<bool>& enabledChannels);
//create the payload for a particular mode
FEDBufferPayload createPayload(FEDReadoutMode mode, uint8_t packetCode, const FEDStripData& data) const;
FEDBufferPayload operator()(FEDReadoutMode mode, uint8_t packetCode, const FEDStripData& data) const;
private:
//fill vector with channel data
void fillChannelBuffer(std::vector<uint8_t>* channelBuffer,
FEDReadoutMode mode,
uint8_t packetCode,
const FEDStripData::ChannelData& data,
const bool channelEnabled) const;
//fill the vector with channel data for raw mode
void fillRawChannelBuffer(std::vector<uint8_t>* channelBuffer,
const uint8_t packetCode,
const FEDStripData::ChannelData& data,
const bool channelEnabled,
const bool reorderData) const;
//fill the vector with channel data for zero suppressed modes
void fillZeroSuppressedChannelBuffer(std::vector<uint8_t>* channelBuffer,
const uint8_t packetCode,
const FEDStripData::ChannelData& data,
const bool channelEnabled) const;
void fillZeroSuppressedLiteChannelBuffer(std::vector<uint8_t>* channelBuffer,
const FEDStripData::ChannelData& data,
const bool channelEnabled,
const FEDReadoutMode mode) const;
void fillPreMixRawChannelBuffer(std::vector<uint8_t>* channelBuffer,
const FEDStripData::ChannelData& data,
const bool channelEnabled) const;
//add the ZS cluster data for the channel to the end of the vector
void fillClusterData(std::vector<uint8_t>* channelBuffer,
uint8_t packetCode,
const FEDStripData::ChannelData& data,
const FEDReadoutMode mode) const;
void fillClusterDataPreMixMode(std::vector<uint8_t>* channelBuffer, const FEDStripData::ChannelData& data) const;
std::vector<bool> feUnitsEnabled_;
std::vector<bool> channelsEnabled_;
};
class FEDBufferGenerator {
public:
//constructor in which you can specify the defaults for some parameters
FEDBufferGenerator(const uint32_t l1ID = 0,
const uint16_t bxID = 0,
const std::vector<bool>& feUnitsEnabled = std::vector<bool>(FEUNITS_PER_FED, true),
const std::vector<bool>& channelsEnabled = std::vector<bool>(FEDCH_PER_FED, true),
const FEDReadoutMode readoutMode = READOUT_MODE_ZERO_SUPPRESSED,
const FEDHeaderType headerType = HEADER_TYPE_FULL_DEBUG,
const FEDBufferFormat bufferFormat = BUFFER_FORMAT_OLD_SLINK,
const FEDDAQEventType evtType = DAQ_EVENT_TYPE_PHYSICS);
//methods to get and set the defaults
uint32_t getL1ID() const;
uint16_t getBXID() const;
FEDReadoutMode getReadoutMode() const;
FEDHeaderType getHeaderType() const;
FEDBufferFormat getBufferFormat() const;
FEDDAQEventType getDAQEventType() const;
FEDBufferGenerator& setL1ID(const uint32_t newL1ID);
FEDBufferGenerator& setBXID(const uint16_t newBXID);
FEDBufferGenerator& setReadoutMode(const FEDReadoutMode newReadoutMode);
FEDBufferGenerator& setHeaderType(const FEDHeaderType newHeaderType);
FEDBufferGenerator& setBufferFormat(const FEDBufferFormat newBufferFormat);
FEDBufferGenerator& setDAQEventType(const FEDDAQEventType newDAQEventType);
//disabled FE units produce no data at all
//disabled channels have headers but data is all zeros (raw modes) or have no clusters (ZS)
bool getFEUnitEnabled(const uint8_t internalFEUnitNumber) const;
bool getChannelEnabled(const uint8_t internalFEDChannelNumber) const;
FEDBufferGenerator& setFEUnitEnable(const uint8_t internalFEUnitNumber, const bool enabled);
FEDBufferGenerator& setChannelEnable(const uint8_t internalFEDChannelNumber, const bool enabled);
FEDBufferGenerator& setFEUnitEnables(const std::vector<bool>& feUnitsEnabled);
FEDBufferGenerator& setChannelEnables(const std::vector<bool>& channelsEnabled);
//make finer changes to defaults for parts of buffer
//setting source ID in DAQ header and length and CRC in DAQ trailer has no effect since they are set when buffer is built
FEDDAQHeader& daqHeader();
FEDDAQTrailer& daqTrailer();
TrackerSpecialHeader& trackerSpecialHeader();
FEDFEHeader& feHeader();
//method to generate buffer
//unspecified parameters use defaults set by constructor or setters
//FEDRawData object will be resized to fit buffer and filled
void generateBuffer(FEDRawData* rawDataObject,
const FEDStripData& data,
uint16_t sourceID,
uint8_t packetCode) const;
private:
//method to fill buffer at pointer from pre generated components (only the length and CRC will be changed)
//at least bufferSizeInBytes(feHeader,payload) must have already been allocated
static void fillBuffer(uint8_t* pointerToStartOfBuffer,
const FEDDAQHeader& daqHeader,
const FEDDAQTrailer& daqTrailer,
const TrackerSpecialHeader& tkSpecialHeader,
const FEDFEHeader& feHeader,
const FEDBufferPayload& payload);
//returns required size of buffer from given components
static size_t bufferSizeInBytes(const FEDFEHeader& feHeader, const FEDBufferPayload& payload);
//used to store default values
FEDDAQHeader defaultDAQHeader_;
FEDDAQTrailer defaultDAQTrailer_;
TrackerSpecialHeader defaultTrackerSpecialHeader_;
std::unique_ptr<FEDFEHeader> defaultFEHeader_;
std::vector<bool> feUnitsEnabled_;
std::vector<bool> channelsEnabled_;
};
//
// Inline function definitions
//
//FEDStripData
inline FEDStripData::FEDStripData(const std::vector<ChannelData>& data) : data_(data) {}
//re-use const method
inline FEDStripData::ChannelData& FEDStripData::channel(const uint8_t internalFEDChannelNum) {
return const_cast<FEDStripData::ChannelData&>(std::as_const(*this).channel(internalFEDChannelNum));
}
inline FEDStripData::ChannelData& FEDStripData::operator[](const uint8_t internalFEDChannelNum) {
return channel(internalFEDChannelNum);
}
inline const FEDStripData::ChannelData& FEDStripData::operator[](const uint8_t internalFEDChannelNum) const {
return channel(internalFEDChannelNum);
}
inline FEDStripData::ChannelData::ChannelData(bool dataIsAlreadyConvertedTo8Bit,
const size_t numberOfSamples,
const std::pair<uint16_t, uint16_t> medians)
: medians_(medians), data_(numberOfSamples, 0), dataIs8Bit_(dataIsAlreadyConvertedTo8Bit) {}
inline size_t FEDStripData::ChannelData::size() const { return data_.size(); }
inline const uint16_t& FEDStripData::ChannelData::operator[](const size_t sampleNumber) const {
return data_[sampleNumber];
}
//re-use const method
inline uint16_t& FEDStripData::ChannelData::operator[](const size_t sampleNumber) {
return const_cast<uint16_t&>(std::as_const(*this)[sampleNumber]);
}
inline uint16_t FEDStripData::ChannelData::getSample(const uint16_t sampleNumber) const {
//try {
// return data_.at(sampleNumber);
//} catch (const std::out_of_range&) {
// std::ostringstream ss;
// ss << "Sample index out of range. "
// << "Requesting sample " << sampleNumber
// << " when channel has only " << data_.size() << " samples.";
// throw cms::Exception("FEDBufferGenerator") << ss.str();
//}
return data_[sampleNumber];
}
inline uint8_t FEDStripData::ChannelData::get8BitSample(const uint16_t sampleNumber, uint16_t nBotBitsToDrop) const {
uint16_t sample = getSample(sampleNumber) >> nBotBitsToDrop;
if (dataIs8Bit_) {
return (0xFF & sample);
} else {
if (sample < 0xFE)
return sample;
else if (sample == 0x3FF)
return 0xFF;
else
return 0xFE;
}
}
inline uint16_t FEDStripData::ChannelData::get10BitSample(const uint16_t sampleNumber) const {
if (dataIs8Bit_) {
return (0xFF & getSample(sampleNumber));
} else {
const uint16_t sample = getSample(sampleNumber);
if (sample < 0x3FF)
return sample;
else
return 0x3FF;
}
}
inline std::pair<uint16_t, uint16_t> FEDStripData::ChannelData::getMedians() const { return medians_; }
inline void FEDStripData::ChannelData::setMedians(const std::pair<uint16_t, uint16_t> values) { medians_ = values; }
//FEDBufferPayload
inline size_t FEDBufferPayload::lengthInBytes() const { return data_.size(); }
inline void FEDBufferPayload::appendToBuffer(size_t* pIndexInBuffer, const uint8_t value) {
data_[((*pIndexInBuffer)++) ^ 7] = value;
}
inline void FEDBufferPayload::appendToBuffer(size_t* pIndexInBuffer,
std::vector<uint8_t>::const_iterator start,
std::vector<uint8_t>::const_iterator finish) {
for (std::vector<uint8_t>::const_iterator iVal = start; iVal != finish; iVal++) {
appendToBuffer(pIndexInBuffer, *iVal);
}
}
//FEDBufferPayloadCreator
inline FEDBufferPayloadCreator::FEDBufferPayloadCreator(const std::vector<bool>& feUnitsEnabled,
const std::vector<bool>& channelsEnabled)
: feUnitsEnabled_(feUnitsEnabled), channelsEnabled_(channelsEnabled) {}
inline FEDBufferPayload FEDBufferPayloadCreator::operator()(FEDReadoutMode mode,
uint8_t packetCode,
const FEDStripData& data) const {
return createPayload(mode, packetCode, data);
}
//FEDBufferGenerator
inline uint32_t FEDBufferGenerator::getL1ID() const { return defaultDAQHeader_.l1ID(); }
inline uint16_t FEDBufferGenerator::getBXID() const { return defaultDAQHeader_.bxID(); }
inline FEDReadoutMode FEDBufferGenerator::getReadoutMode() const {
return defaultTrackerSpecialHeader_.readoutMode();
}
inline FEDHeaderType FEDBufferGenerator::getHeaderType() const { return defaultTrackerSpecialHeader_.headerType(); }
inline FEDBufferFormat FEDBufferGenerator::getBufferFormat() const {
return defaultTrackerSpecialHeader_.bufferFormat();
}
inline FEDDAQEventType FEDBufferGenerator::getDAQEventType() const { return defaultDAQHeader_.eventType(); }
inline FEDBufferGenerator& FEDBufferGenerator::setL1ID(const uint32_t newL1ID) {
defaultDAQHeader_.setL1ID(newL1ID);
return *this;
}
inline FEDBufferGenerator& FEDBufferGenerator::setBXID(const uint16_t newBXID) {
defaultDAQHeader_.setBXID(newBXID);
return *this;
}
inline FEDBufferGenerator& FEDBufferGenerator::setReadoutMode(const FEDReadoutMode newReadoutMode) {
defaultTrackerSpecialHeader_.setReadoutMode(newReadoutMode);
return *this;
}
inline FEDBufferGenerator& FEDBufferGenerator::setHeaderType(const FEDHeaderType newHeaderType) {
defaultTrackerSpecialHeader_.setHeaderType(newHeaderType);
return *this;
}
inline FEDBufferGenerator& FEDBufferGenerator::setBufferFormat(const FEDBufferFormat newBufferFormat) {
defaultTrackerSpecialHeader_.setBufferFormat(newBufferFormat);
return *this;
}
inline FEDBufferGenerator& FEDBufferGenerator::setDAQEventType(const FEDDAQEventType newDAQEventType) {
defaultDAQHeader_.setEventType(newDAQEventType);
return *this;
}
inline FEDDAQHeader& FEDBufferGenerator::daqHeader() { return defaultDAQHeader_; }
inline FEDDAQTrailer& FEDBufferGenerator::daqTrailer() { return defaultDAQTrailer_; }
inline TrackerSpecialHeader& FEDBufferGenerator::trackerSpecialHeader() { return defaultTrackerSpecialHeader_; }
inline FEDFEHeader& FEDBufferGenerator::feHeader() { return *defaultFEHeader_; }
inline size_t FEDBufferGenerator::bufferSizeInBytes(const FEDFEHeader& feHeader, const FEDBufferPayload& payload) {
//FE header + payload + tracker special header + daq header + daq trailer
return feHeader.lengthInBytes() + payload.lengthInBytes() + 8 + 8 + 8;
}
} // namespace sistrip
#endif //ndef EventFilter_SiStripRawToDigi_FEDBufferGenerator_H
|