CMS 3D CMS Logo

SiStripFEDBuffer.cc
Go to the documentation of this file.
1 #include <iomanip>
2 #include <ostream>
3 #include <cstring>
5 
7 
10 
11 namespace sistrip {
12 
13  FEDBuffer::FEDBuffer(const FEDRawData& fedBuffer, const bool allowBadBuffer) : FEDBufferBase(fedBuffer, false) {
14  validChannels_ = 0;
15  channels_.reserve(FEDCH_PER_FED);
16  //build the correct type of FE header object
20  } else {
21  feHeader_ = std::unique_ptr<FEDFEHeader>();
23  }
25  //check if FE units are present in data
26  //in Full Debug mode, use the lengths from the header
27  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
28  if (fdHeader) {
29  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
30  if (fdHeader->fePresent(iFE))
31  fePresent_[iFE] = true;
32  else
33  fePresent_[iFE] = false;
34  }
35  }
36  //in APV error mode, use the FE present byte in the FED status register
37  // a value of '1' means a FE unit's data is missing (in old firmware versions it is always 0)
38  else {
39  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
41  fePresent_[iFE] = false;
42  else
43  fePresent_[iFE] = true;
44  }
45  }
46  }
47 
50  //set min length to 2 for ZSLite, 7 for ZS and 3 for raw
51  uint16_t minLength;
52  switch (readoutMode()) {
55  minLength = 7;
56  break;
58  minLength = 2;
59  break;
68  minLength = 2;
69  break;
70  default:
71  minLength = 3;
72  break;
73  }
74  uint16_t offsetBeginningOfChannel = 0;
75  for (uint16_t i = 0; i < FEDCH_PER_FED; i++) {
76  //if FE unit is not enabled then skip rest of FE unit adding NULL pointers
78  channels_.insert(channels_.end(), uint16_t(FEDCH_PER_FEUNIT), FEDChannel(payloadPointer_, 0, 0));
79  i += FEDCH_PER_FEUNIT - 1;
81  continue;
82  }
83  //if FE unit is enabled
84  //check that channel length bytes fit into buffer
85  if UNLIKELY (offsetBeginningOfChannel + 1 >= payloadLength_) {
87  LogDebug("FEDBuffer") << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel "
88  << key.feChan() << " according to external numbering scheme) "
89  << "does not fit into buffer. "
90  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
91  << "Payload length is " << uint16_t(payloadLength_) << ". ";
93  break;
94  }
95 
96  channels_.emplace_back(payloadPointer_, offsetBeginningOfChannel);
97  //get length and check that whole channel fits into buffer
98  uint16_t channelLength = channels_.back().length();
99 
100  //check that the channel length is long enough to contain the header
101  if UNLIKELY (channelLength < minLength) {
103  LogDebug("FEDBuffer") << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel "
104  << key.feChan() << " according to external numbering scheme)"
105  << " is too short. "
106  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
107  << "Channel length is " << uint16_t(channelLength) << ". "
108  << "Min length is " << uint16_t(minLength) << ". ";
110  break;
111  }
112  if UNLIKELY (offsetBeginningOfChannel + channelLength > payloadLength_) {
114  LogDebug("FEDBuffer") << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel "
115  << key.feChan() << " according to external numbering scheme)"
116  << "does not fit into buffer. "
117  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
118  << "Channel length is " << uint16_t(channelLength) << ". "
119  << "Payload length is " << uint16_t(payloadLength_) << ". ";
121  break;
122  }
123 
124  validChannels_++;
125  const uint16_t offsetEndOfChannel = offsetBeginningOfChannel + channelLength;
126  //add padding if necessary and calculate offset for begining of next channel
127  if (!((i + 1) % FEDCH_PER_FEUNIT)) {
128  uint8_t numPaddingBytes = 8 - (offsetEndOfChannel % 8);
129  if (numPaddingBytes == 8)
130  numPaddingBytes = 0;
131  offsetBeginningOfChannel = offsetEndOfChannel + numPaddingBytes;
132  } else {
133  offsetBeginningOfChannel = offsetEndOfChannel;
134  }
135  }
136  if UNLIKELY (FEDBufferStatusCode::SUCCESS != st) { // for the allowBadBuffer case
137  channels_.insert(channels_.end(), uint16_t(FEDCH_PER_FED - validChannels_), FEDChannel(payloadPointer_, 0, 0));
138  }
139  return st;
140  }
141 
144  //checkClusterLengths() &&
146  //checkFEUnitAPVAddresses() );
147  }
148 
150  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
151  //if FE unit is disabled then skip all channels on it
152  if (!feGood(iCh / FEDCH_PER_FEUNIT)) {
153  iCh += FEDCH_PER_FEUNIT;
154  continue;
155  }
156  //channel is bad then return false
157  if (!checkStatusBits(iCh))
158  return false;
159  }
160  //if no bad channels have been found then they are all fine
161  return true;
162  }
163 
165 
167  //check they fit into buffer
168  if (!checkChannelLengths())
169  return false;
170 
171  //payload length from length of data buffer
172  const uint16_t payloadLengthInWords = payloadLength_ / 8;
173 
174  //find channel length
175  //find last enabled FE unit
176  uint8_t lastEnabledFeUnit = 7;
177  while (!(fePresent(lastEnabledFeUnit) && feEnabled(lastEnabledFeUnit)) && lastEnabledFeUnit != 0)
178  lastEnabledFeUnit--;
179  //last channel is last channel on last enabled FE unit
180  const FEDChannel& lastChannel = channels_[internalFEDChannelNum(lastEnabledFeUnit, FEDCH_PER_FEUNIT - 1)];
181  const uint16_t offsetLastChannel = lastChannel.offset();
182  const uint16_t offsetEndOfChannelData = offsetLastChannel + lastChannel.length();
183  const uint16_t channelDataLength = offsetEndOfChannelData;
184  //channel length in words is length in bytes rounded up to nearest word
185  uint16_t channelDataLengthInWords = channelDataLength / 8;
186  if (channelDataLength % 8)
187  channelDataLengthInWords++;
188 
189  //check lengths match
190  if (channelDataLengthInWords == payloadLengthInWords) {
191  return true;
192  } else {
193  return false;
194  }
195  }
196 
198  const uint8_t correctPacketCode = getCorrectPacketCode();
199  //if the readout mode if not one which has a packet code then this is set to zero. in this case return true
200  if (!correctPacketCode)
201  return true;
202  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
203  //if FE unit is disabled then skip all channels on it
204  if (!feGood(iCh / FEDCH_PER_FEUNIT)) {
205  iCh += FEDCH_PER_FEUNIT;
206  continue;
207  }
208  //only check enabled, working channels
209  if (FEDBuffer::channelGood(iCh, true)) {
210  //if a channel is bad then return false
211  if (channels_[iCh].packetCode() != correctPacketCode)
212  return false;
213  }
214  }
215  //if no bad channels were found the they are all ok
216  return true;
217  }
218 
220  //get golden address
221  const uint8_t goldenAddress = apveAddress();
222  //don't check if the address is 00 since APVe is probably not connected
223  if (goldenAddress == 0x00)
224  return true;
225  //check can only be done for full debug headers
226  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
227  if (!fdHeader)
228  return true;
229  //check all enabled FE units
230  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
231  if (!feGood(iFE))
232  continue;
233  //if address is bad then return false
234  if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress)
235  return false;
236  }
237  //if no bad addresses were found then return true
238  return true;
239  }
240 
242  //check can only be done for full debug headers
243  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
244  if (!fdHeader)
245  return true;
246  //check lengths for enabled FE units
247  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
248  if (!feGood(iFE))
249  continue;
250  if (calculateFEUnitLength(iFE) != fdHeader->feUnitLength(iFE))
251  return false;
252  }
253  //if no errors were encountered then return true
254  return true;
255  }
256 
257  uint16_t FEDBuffer::calculateFEUnitLength(const uint8_t internalFEUnitNumber) const {
258  //get length from channels
259  uint16_t lengthFromChannels = 0;
260  for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
261  lengthFromChannels += channels_[internalFEDChannelNum(internalFEUnitNumber, iCh)].length();
262  }
263  return lengthFromChannels;
264  }
265 
267  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
268  if (!fePresent(iFE))
269  return false;
270  }
271  return true;
272  }
273 
275  std::ostringstream summary;
277  summary << "Check FE unit payloads are all present: " << (checkFEPayloadsPresent() ? "passed" : "FAILED")
278  << std::endl;
279  if (!checkFEPayloadsPresent()) {
280  summary << "FE units missing payloads: ";
281  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
282  if (!fePresent(iFE))
283  summary << uint16_t(iFE) << " ";
284  }
285  summary << std::endl;
286  }
287  summary << "Check channel status bits: " << (checkAllChannelStatusBits() ? "passed" : "FAILED") << std::endl;
288  if (!checkAllChannelStatusBits()) {
289  unsigned int badChannels = 0;
291  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
292  if (fdHeader) {
293  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
294  if (!feGood(iCh / FEDCH_PER_FEUNIT))
295  continue;
296  if (!checkStatusBits(iCh)) {
297  summary << uint16_t(iCh) << ": " << fdHeader->getChannelStatus(iCh) << std::endl;
298  badChannels++;
299  }
300  }
301  }
302  } else {
303  summary << "Channels with errors: ";
304  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
305  if (!feGood(iCh / FEDCH_PER_FEUNIT))
306  continue;
307  if (!checkStatusBits(iCh)) {
308  summary << uint16_t(iCh) << " ";
309  badChannels++;
310  }
311  }
312  summary << std::endl;
313  }
314  summary << "Number of channels with bad status bits: " << badChannels << std::endl;
315  }
316  summary << "Check channel lengths match buffer length: "
317  << (checkChannelLengthsMatchBufferLength() ? "passed" : "FAILED") << std::endl;
318  summary << "Check channel packet codes: " << (checkChannelPacketCodes() ? "passed" : "FAILED") << std::endl;
319  if (!checkChannelPacketCodes()) {
320  summary << "Channels with bad packet codes: ";
321  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
322  if (!feGood(iCh / FEDCH_PER_FEUNIT))
323  continue;
324  if (channels_[iCh].packetCode() != getCorrectPacketCode())
325  summary << uint16_t(iCh) << " ";
326  }
327  }
328  summary << "Check FE unit lengths: " << (checkFEUnitLengths() ? "passed" : "FAILED") << std::endl;
329  if (!checkFEUnitLengths()) {
330  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
331  if (fdHeader) {
332  summary << "Bad FE units:" << std::endl;
333  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
334  if (!feGood(iFE))
335  continue;
336  uint16_t lengthFromChannels = calculateFEUnitLength(iFE);
337  uint16_t lengthFromHeader = fdHeader->feUnitLength(iFE);
338  if (lengthFromHeader != lengthFromChannels) {
339  summary << "FE unit: " << uint16_t(iFE) << " length in header: " << lengthFromHeader
340  << " length from channel lengths: " << lengthFromChannels << std::endl;
341  }
342  }
343  }
344  }
345  summary << "Check FE unit APV addresses match APVe: " << (checkFEUnitAPVAddresses() ? "passed" : "FAILED")
346  << std::endl;
347  if (!checkFEUnitAPVAddresses()) {
348  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
349  if (fdHeader) {
350  const uint8_t goldenAddress = apveAddress();
351  summary << "Address from APVe:" << uint16_t(goldenAddress) << std::endl;
352  summary << "Bad FE units:" << std::endl;
353  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
354  if (!feGood(iFE))
355  continue;
356  if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) {
357  summary << "FE unit: " << uint16_t(iFE)
358  << " majority address: " << uint16_t(fdHeader->feUnitMajorityAddress(iFE)) << std::endl;
359  }
360  }
361  }
362  }
363  return summary.str();
364  }
365 
366  uint8_t FEDBuffer::nFEUnitsPresent() const {
367  uint8_t result = 0;
368  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
369  if (fePresent(iFE))
370  result++;
371  }
372  return result;
373  }
374 
375  void FEDBuffer::print(std::ostream& os) const {
378  os << "FE units with data: " << uint16_t(nFEUnitsPresent()) << std::endl;
379  os << "BE status register flags: ";
380  dynamic_cast<const FEDFullDebugHeader*>(feHeader())->beStatusRegister().printFlags(os);
381  os << std::endl;
382  }
383  }
384 
386  using namespace sistrip::fedchannelunpacker;
387  switch (status) {
388  case StatusCode::SUCCESS:
389  return "SUCCESS";
391  return "Channel length is invalid.";
393  return "First strip of new cluster is not greater than last strip of previous cluster.";
395  return "Invalid packet code.";
397  return "Invalid packet code 0 for zero-suppressed data.";
398  }
399  return "";
400  }
401 } // namespace sistrip
FEDReadoutMode readoutMode() const
bool checkChannelLengthsMatchBufferLength() const
std::string checkSummary() const override
A container class for generic run and event-related info, information required by the commissioning a...
Definition: SiStripFedKey.h:56
static std::unique_ptr< FEDFEHeader > newFEHeader(const FEDHeaderType headerType, const uint8_t *headerBuffer)
const FEDFEHeader * feHeader() const
FEDBuffer(const FEDRawData &fedBuffer, const bool allowBadBuffer=false)
uint8_t internalFEDChannelNum(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum)
bool fePresent(const uint8_t internalFEUnitNum) const
bool checkFEUnitAPVAddresses() const
uint16_t calculateFEUnitLength(const uint8_t internalFEUnitNumber) const
FEDBufferStatusCode findChannels()
uint8_t nFEUnitsPresent() const
const uint8_t * getPointerToDataAfterTrackerSpecialHeader() const
virtual std::string checkSummary() const
bool checkFEUnitLengths() const
std::string toString(fedchannelunpacker::StatusCode status)
sistrip classes
const uint8_t * getPointerToByteAfterEndOfPayload() const
bool feEnabled(const uint8_t internalFEUnitNum) const
bool feDataMissingFlag(const uint8_t internalFEUnitNum) const
virtual bool doCorruptBufferChecks() const
bool fePresent_[FEUNITS_PER_FED]
bool checkChannelPacketCodes() const
const uint8_t * payloadPointer_
static const uint16_t FEUNITS_PER_FED
bool checkFEPayloadsPresent() const
bool checkAllChannelStatusBits() const
std::vector< FEDChannel > channels_
uint16_t feUnitLength(const uint8_t internalFEUnitNum) const
uint8_t getCorrectPacketCode() const
bool channelGood(const uint8_t internalFEDannelNum, const bool doAPVeCheck) const
static const uint16_t FEDCH_PER_FEUNIT
bool checkStatusBits(const uint8_t internalFEDChannelNum) const
bool checkChannelLengths() const
std::unique_ptr< FEDFEHeader > feHeader_
static const uint16_t FEDCH_PER_FED
FEDStatusRegister fedStatusRegister() const
bool feGood(const uint8_t internalFEUnitNum) const
uint8_t feUnitMajorityAddress(const uint8_t internalFEUnitNum) const
void print(std::ostream &os) const override
#define UNLIKELY(x)
Definition: Likely.h:21
FEDChannelStatus getChannelStatus(const uint8_t internalFEDChannelNum) const
bool fePresent(uint8_t internalFEUnitNum) const
#define LogDebug(id)
uint8_t packetCode(bool legacy=false, const uint8_t internalFEDChannelNum=0) const
virtual void print(std::ostream &os) const