CMS 3D CMS Logo

SiStripFEDBuffer.cc
Go to the documentation of this file.
1 #include <iomanip>
2 #include <ostream>
3 #include <sstream>
4 #include <cstring>
5 
7 
9 
10 namespace sistrip {
11 
12  FEDBuffer::FEDBuffer(const uint8_t* fedBuffer, const uint16_t fedBufferSize, const bool allowBadBuffer)
13  : FEDBufferBase(fedBuffer, fedBufferSize, allowBadBuffer, false) {
14  channels_.reserve(FEDCH_PER_FED);
15  //build the correct type of FE header object
19  } else {
20  feHeader_ = std::unique_ptr<FEDFEHeader>();
22  if (!allowBadBuffer) {
23  std::ostringstream ss;
24  ss << "Header type is invalid. "
25  << "Header type nibble is ";
26  uint8_t headerNibble = trackerSpecialHeader().headerTypeNibble();
27  printHex(&headerNibble, 1, ss);
28  ss << ". ";
29  throw cms::Exception("FEDBuffer") << ss.str();
30  }
31  }
32  if (readoutMode() == READOUT_MODE_SPY) {
33  throw cms::Exception("FEDBuffer") << "Unpacking of spy channel data with FEDBuffer is not supported" << std::endl;
34  }
36  //check if FE units are present in data
37  //in Full Debug mode, use the lengths from the header
38  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
39  if (fdHeader) {
40  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
41  if (fdHeader->fePresent(iFE))
42  fePresent_[iFE] = true;
43  else
44  fePresent_[iFE] = false;
45  }
46  }
47  //in APV error mode, use the FE present byte in the FED status register
48  // a value of '1' means a FE unit's data is missing (in old firmware versions it is always 0)
49  else {
50  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
52  fePresent_[iFE] = false;
53  else
54  fePresent_[iFE] = true;
55  }
56  }
57  //try to find channels
58  validChannels_ = 0;
59  try {
60  findChannels();
61  } catch (const cms::Exception& e) {
62  //if there was a problem either rethrow the exception or just mark channel pointers NULL
63  if (!allowBadBuffer)
64  throw;
65  else {
66  channels_.insert(channels_.end(), uint16_t(FEDCH_PER_FED - validChannels_), FEDChannel(payloadPointer_, 0, 0));
67  }
68  }
69  }
70 
72 
74  //set min length to 2 for ZSLite, 7 for ZS and 3 for raw
75  uint16_t minLength;
76  switch (readoutMode()) {
79  minLength = 7;
80  break;
82  minLength = 2;
83  break;
92  minLength = 2;
93  break;
94  default:
95  minLength = 3;
96  break;
97  }
98  uint16_t offsetBeginningOfChannel = 0;
99  for (uint16_t i = 0; i < FEDCH_PER_FED; i++) {
100  //if FE unit is not enabled then skip rest of FE unit adding NULL pointers
101  if
103  channels_.insert(channels_.end(), uint16_t(FEDCH_PER_FEUNIT), FEDChannel(payloadPointer_, 0, 0));
104  i += FEDCH_PER_FEUNIT - 1;
106  continue;
107  }
108  //if FE unit is enabled
109  //check that channel length bytes fit into buffer
110  if
111  UNLIKELY(offsetBeginningOfChannel + 1 >= payloadLength_) {
112  std::ostringstream ss;
114  ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan()
115  << " according to external numbering scheme)"
116  << " does not fit into buffer. "
117  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
118  << "Payload length is " << uint16_t(payloadLength_) << ". ";
119  throw cms::Exception("FEDBuffer") << ss.str();
120  }
121 
122  channels_.push_back(FEDChannel(payloadPointer_, offsetBeginningOfChannel));
123  //get length and check that whole channel fits into buffer
124  uint16_t channelLength = channels_.back().length();
125 
126  //check that the channel length is long enough to contain the header
127  if
128  UNLIKELY(channelLength < minLength) {
130  std::ostringstream ss;
131  ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan()
132  << " according to external numbering scheme)"
133  << " is too short. "
134  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
135  << "Channel length is " << uint16_t(channelLength) << ". "
136  << "Min length is " << uint16_t(minLength) << ". ";
137  throw cms::Exception("FEDBuffer") << ss.str();
138  }
139  if
140  UNLIKELY(offsetBeginningOfChannel + channelLength > payloadLength_) {
142  std::ostringstream ss;
143  ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan()
144  << " according to external numbering scheme)"
145  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
146  << "Channel length is " << uint16_t(channelLength) << ". "
147  << "Payload length is " << uint16_t(payloadLength_) << ". ";
148  throw cms::Exception("FEDBuffer") << ss.str();
149  }
150 
151  validChannels_++;
152  const uint16_t offsetEndOfChannel = offsetBeginningOfChannel + channelLength;
153  //add padding if necessary and calculate offset for begining of next channel
154  if (!((i + 1) % FEDCH_PER_FEUNIT)) {
155  uint8_t numPaddingBytes = 8 - (offsetEndOfChannel % 8);
156  if (numPaddingBytes == 8)
157  numPaddingBytes = 0;
158  offsetBeginningOfChannel = offsetEndOfChannel + numPaddingBytes;
159  } else {
160  offsetBeginningOfChannel = offsetEndOfChannel;
161  }
162  }
163  }
164 
165  bool FEDBuffer::channelGood(const uint8_t internalFEDChannelNum, const bool doAPVeCheck) const {
166  return ((internalFEDChannelNum < validChannels_) &&
167  ((doAPVeCheck && feGood(internalFEDChannelNum / FEDCH_PER_FEUNIT)) ||
168  (!doAPVeCheck && feGoodWithoutAPVEmulatorCheck(internalFEDChannelNum / FEDCH_PER_FEUNIT))) &&
169  (this->readoutMode() == sistrip::READOUT_MODE_SCOPE || checkStatusBits(internalFEDChannelNum)));
170  }
171 
172  bool FEDBuffer::doChecks(bool doCRC) const {
173  //check that all channels were unpacked properly
175  return false;
176  //do checks from base class
178  return false;
179  //check CRC
180  if (doCRC && !checkCRC())
181  return false;
182  return true;
183  }
184 
187  //checkClusterLengths() &&
189  //checkFEUnitAPVAddresses() );
190  }
191 
193  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
194  //if FE unit is disabled then skip all channels on it
195  if (!feGood(iCh / FEDCH_PER_FEUNIT)) {
196  iCh += FEDCH_PER_FEUNIT;
197  continue;
198  }
199  //channel is bad then return false
200  if (!checkStatusBits(iCh))
201  return false;
202  }
203  //if no bad channels have been found then they are all fine
204  return true;
205  }
206 
208 
210  //check they fit into buffer
211  if (!checkChannelLengths())
212  return false;
213 
214  //payload length from length of data buffer
215  const uint16_t payloadLengthInWords = payloadLength_ / 8;
216 
217  //find channel length
218  //find last enabled FE unit
219  uint8_t lastEnabledFeUnit = 7;
220  while (!(fePresent(lastEnabledFeUnit) && feEnabled(lastEnabledFeUnit)) && lastEnabledFeUnit != 0)
221  lastEnabledFeUnit--;
222  //last channel is last channel on last enabled FE unit
223  const FEDChannel& lastChannel = channels_[internalFEDChannelNum(lastEnabledFeUnit, FEDCH_PER_FEUNIT - 1)];
224  const uint16_t offsetLastChannel = lastChannel.offset();
225  const uint16_t offsetEndOfChannelData = offsetLastChannel + lastChannel.length();
226  const uint16_t channelDataLength = offsetEndOfChannelData;
227  //channel length in words is length in bytes rounded up to nearest word
228  uint16_t channelDataLengthInWords = channelDataLength / 8;
229  if (channelDataLength % 8)
230  channelDataLengthInWords++;
231 
232  //check lengths match
233  if (channelDataLengthInWords == payloadLengthInWords) {
234  return true;
235  } else {
236  return false;
237  }
238  }
239 
241  const uint8_t correctPacketCode = getCorrectPacketCode();
242  //if the readout mode if not one which has a packet code then this is set to zero. in this case return true
243  if (!correctPacketCode)
244  return true;
245  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
246  //if FE unit is disabled then skip all channels on it
247  if (!feGood(iCh / FEDCH_PER_FEUNIT)) {
248  iCh += FEDCH_PER_FEUNIT;
249  continue;
250  }
251  //only check enabled, working channels
252  if (FEDBuffer::channelGood(iCh, true)) {
253  //if a channel is bad then return false
254  if (channels_[iCh].packetCode() != correctPacketCode)
255  return false;
256  }
257  }
258  //if no bad channels were found the they are all ok
259  return true;
260  }
261 
263  //get golden address
264  const uint8_t goldenAddress = apveAddress();
265  //don't check if the address is 00 since APVe is probably not connected
266  if (goldenAddress == 0x00)
267  return true;
268  //check can only be done for full debug headers
269  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
270  if (!fdHeader)
271  return true;
272  //check all enabled FE units
273  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
274  if (!feGood(iFE))
275  continue;
276  //if address is bad then return false
277  if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress)
278  return false;
279  }
280  //if no bad addresses were found then return true
281  return true;
282  }
283 
285  //check can only be done for full debug headers
286  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
287  if (!fdHeader)
288  return true;
289  //check lengths for enabled FE units
290  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
291  if (!feGood(iFE))
292  continue;
293  if (calculateFEUnitLength(iFE) != fdHeader->feUnitLength(iFE))
294  return false;
295  }
296  //if no errors were encountered then return true
297  return true;
298  }
299 
300  uint16_t FEDBuffer::calculateFEUnitLength(const uint8_t internalFEUnitNumber) const {
301  //get length from channels
302  uint16_t lengthFromChannels = 0;
303  for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
304  lengthFromChannels += channels_[internalFEDChannelNum(internalFEUnitNumber, iCh)].length();
305  }
306  return lengthFromChannels;
307  }
308 
310  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
311  if (!fePresent(iFE))
312  return false;
313  }
314  return true;
315  }
316 
318  std::ostringstream summary;
319  summary << FEDBufferBase::checkSummary();
320  summary << "Check FE unit payloads are all present: " << (checkFEPayloadsPresent() ? "passed" : "FAILED")
321  << std::endl;
322  if (!checkFEPayloadsPresent()) {
323  summary << "FE units missing payloads: ";
324  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
325  if (!fePresent(iFE))
326  summary << uint16_t(iFE) << " ";
327  }
328  summary << std::endl;
329  }
330  summary << "Check channel status bits: " << (checkAllChannelStatusBits() ? "passed" : "FAILED") << std::endl;
331  if (!checkAllChannelStatusBits()) {
332  unsigned int badChannels = 0;
334  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
335  if (fdHeader) {
336  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
337  if (!feGood(iCh / FEDCH_PER_FEUNIT))
338  continue;
339  if (!checkStatusBits(iCh)) {
340  summary << uint16_t(iCh) << ": " << fdHeader->getChannelStatus(iCh) << std::endl;
341  badChannels++;
342  }
343  }
344  }
345  } else {
346  summary << "Channels with errors: ";
347  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
348  if (!feGood(iCh / FEDCH_PER_FEUNIT))
349  continue;
350  if (!checkStatusBits(iCh)) {
351  summary << uint16_t(iCh) << " ";
352  badChannels++;
353  }
354  }
355  summary << std::endl;
356  }
357  summary << "Number of channels with bad status bits: " << badChannels << std::endl;
358  }
359  summary << "Check channel lengths match buffer length: "
360  << (checkChannelLengthsMatchBufferLength() ? "passed" : "FAILED") << std::endl;
361  summary << "Check channel packet codes: " << (checkChannelPacketCodes() ? "passed" : "FAILED") << std::endl;
362  if (!checkChannelPacketCodes()) {
363  summary << "Channels with bad packet codes: ";
364  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
365  if (!feGood(iCh / FEDCH_PER_FEUNIT))
366  continue;
367  if (channels_[iCh].packetCode() != getCorrectPacketCode())
368  summary << uint16_t(iCh) << " ";
369  }
370  }
371  summary << "Check FE unit lengths: " << (checkFEUnitLengths() ? "passed" : "FAILED") << std::endl;
372  if (!checkFEUnitLengths()) {
373  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
374  if (fdHeader) {
375  summary << "Bad FE units:" << std::endl;
376  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
377  if (!feGood(iFE))
378  continue;
379  uint16_t lengthFromChannels = calculateFEUnitLength(iFE);
380  uint16_t lengthFromHeader = fdHeader->feUnitLength(iFE);
381  if (lengthFromHeader != lengthFromChannels) {
382  summary << "FE unit: " << uint16_t(iFE) << " length in header: " << lengthFromHeader
383  << " length from channel lengths: " << lengthFromChannels << std::endl;
384  }
385  }
386  }
387  }
388  summary << "Check FE unit APV addresses match APVe: " << (checkFEUnitAPVAddresses() ? "passed" : "FAILED")
389  << std::endl;
390  if (!checkFEUnitAPVAddresses()) {
391  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
392  if (fdHeader) {
393  const uint8_t goldenAddress = apveAddress();
394  summary << "Address from APVe:" << uint16_t(goldenAddress) << std::endl;
395  summary << "Bad FE units:" << std::endl;
396  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
397  if (!feGood(iFE))
398  continue;
399  if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) {
400  summary << "FE unit: " << uint16_t(iFE)
401  << " majority address: " << uint16_t(fdHeader->feUnitMajorityAddress(iFE)) << std::endl;
402  }
403  }
404  }
405  }
406  return summary.str();
407  }
408 
409  uint8_t FEDBuffer::nFEUnitsPresent() const {
410  uint8_t result = 0;
411  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
412  if (fePresent(iFE))
413  result++;
414  }
415  return result;
416  }
417 
418  void FEDBuffer::print(std::ostream& os) const {
421  os << "FE units with data: " << uint16_t(nFEUnitsPresent()) << std::endl;
422  os << "BE status register flags: ";
423  dynamic_cast<const FEDFullDebugHeader*>(feHeader())->beStatusRegister().printFlags(os);
424  os << std::endl;
425  }
426  }
427 
428  void FEDRawChannelUnpacker::throwBadChannelLength(const uint16_t length) {
429  std::ostringstream ss;
430  ss << "Channel length is invalid. Raw channels have 3 header bytes and 2 bytes per sample. "
431  << "Channel length is " << uint16_t(length) << "." << std::endl;
432  throw cms::Exception("FEDBuffer") << ss.str();
433  }
434 
435  void FEDBSChannelUnpacker::throwBadChannelLength(const uint16_t length) {
436  std::ostringstream ss;
437  ss << "Channel length is invalid. "
438  << "Channel length is " << uint16_t(length) << "." << std::endl;
439  throw cms::Exception("FEDBuffer") << ss.str();
440  }
441 
442  void FEDBSChannelUnpacker::throwBadWordLength(const uint16_t word_length) {
443  std::ostringstream ss;
444  ss << "Word length is invalid. "
445  << "Word length is " << word_length << "." << std::endl;
446  throw cms::Exception("FEDBuffer") << ss.str();
447  }
448 
449  void FEDBSChannelUnpacker::throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster) {
450  std::ostringstream ss;
451  ss << "First strip of new cluster is not greater than last strip of previous cluster. "
452  << "Last strip of previous cluster is " << uint16_t(currentStrip) << ". "
453  << "First strip of new cluster is " << uint16_t(firstStripOfNewCluster) << "." << std::endl;
454  throw cms::Exception("FEDBuffer") << ss.str();
455  }
456 
457  void FEDZSChannelUnpacker::throwBadChannelLength(const uint16_t length) {
458  std::ostringstream ss;
459  ss << "Channel length is longer than max allowed value. "
460  << "Channel length is " << uint16_t(length) << "." << std::endl;
461  throw cms::Exception("FEDBuffer") << ss.str();
462  }
463 
465  std::ostringstream ss;
466  ss << "Cluster does not fit into channel. "
467  << "Cluster length is " << uint16_t(valuesLeftInCluster_) << "." << std::endl;
468  throw cms::Exception("FEDBuffer") << ss.str();
469  }
470 
471  void FEDZSChannelUnpacker::throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster) {
472  std::ostringstream ss;
473  ss << "First strip of new cluster is not greater than last strip of previous cluster. "
474  << "Last strip of previous cluster is " << uint16_t(currentStrip) << ". "
475  << "First strip of new cluster is " << uint16_t(firstStripOfNewCluster) << "." << std::endl;
476  throw cms::Exception("FEDBuffer") << ss.str();
477  }
478 
479 } // namespace sistrip
bool feDataMissingFlag(const uint8_t internalFEUnitNum) const
static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster)
bool checkFEUnitLengths() const
bool checkStatusBits(const uint8_t internalFEDChannelNum) const
bool fePresent(const uint8_t internalFEUnitNum) const
static void throwBadChannelLength(const uint16_t length)
virtual std::string checkSummary() const
A container class for generic run and event-related info, information required by the commissioning a...
Definition: SiStripFedKey.h:56
const uint8_t * getPointerToByteAfterEndOfPayload() const
virtual bool doCorruptBufferChecks() const
static void throwBadWordLength(const uint16_t word_length)
bool checkFEPayloadsPresent() const
static std::unique_ptr< FEDFEHeader > newFEHeader(const FEDHeaderType headerType, const uint8_t *headerBuffer)
FEDReadoutMode readoutMode() const
uint8_t internalFEDChannelNum(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum)
static void throwBadChannelLength(const uint16_t length)
const uint8_t * getPointerToDataAfterTrackerSpecialHeader() const
static void throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster)
const FEDFEHeader * feHeader() const
virtual bool channelGood(const uint8_t internalFEDannelNum, const bool doAPVeCheck=true) const
sistrip classes
bool feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const
bool fePresent_[FEUNITS_PER_FED]
const uint8_t * payloadPointer_
bool fePresent(uint8_t internalFEUnitNum) const
static const uint16_t FEUNITS_PER_FED
bool feEnabled(const uint8_t internalFEUnitNum) const
FEDHeaderType headerType() const
uint8_t packetCode(bool legacy=false, const uint8_t internalFEDChannelNum=0) const
std::vector< FEDChannel > channels_
bool checkChannelPacketCodes() const
void printHex(const void *pointer, const size_t length, std::ostream &os)
const uint16_t & feUnit() const
uint8_t nFEUnitsPresent() const
static const uint16_t FEDCH_PER_FEUNIT
std::unique_ptr< FEDFEHeader > feHeader_
bool checkFEUnitAPVAddresses() const
std::string checkSummary() const override
TrackerSpecialHeader trackerSpecialHeader() const
FEDBuffer(const uint8_t *fedBuffer, const uint16_t fedBufferSize, const bool allowBadBuffer=false)
uint8_t getCorrectPacketCode() const
uint16_t feUnitLength(const uint8_t internalFEUnitNum) const
bool checkChannelLengthsMatchBufferLength() const
uint8_t feUnitMajorityAddress(const uint8_t internalFEUnitNum) const
FEDChannelStatus getChannelStatus(const uint8_t internalFEDChannelNum) const
virtual void print(std::ostream &os) const
static const uint16_t FEDCH_PER_FED
const uint16_t & feChan() const
bool checkAllChannelStatusBits() const
static void throwBadChannelLength(const uint16_t length)
uint16_t calculateFEUnitLength(const uint8_t internalFEUnitNumber) const
bool checkChannelLengths() const
#define UNLIKELY(x)
Definition: Likely.h:21
bool feGood(const uint8_t internalFEUnitNum) const
void print(std::ostream &os) const override
FEDStatusRegister fedStatusRegister() const