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