CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 size_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()) {
77  minLength = 7;
78  break;
81  minLength = 2;
82  break;
83  default:
84  minLength = 3;
85  break;
86  }
87  size_t offsetBeginningOfChannel = 0;
88  for (size_t i = 0; i < FEDCH_PER_FED; i++) {
89  //if FE unit is not enabled then skip rest of FE unit adding NULL pointers
92  i += FEDCH_PER_FEUNIT-1;
94  continue;
95  }
96  //if FE unit is enabled
97  //check that channel length bytes fit into buffer
98  if unlikely(offsetBeginningOfChannel+1 >= payloadLength_) {
99  std::ostringstream ss;
101  ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan() << " according to external numbering scheme)"
102  << " does not fit into buffer. "
103  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
104  << "Payload length is " << uint16_t(payloadLength_) << ". ";
105  throw cms::Exception("FEDBuffer") << ss.str();
106  }
107 
108  channels_.push_back(FEDChannel(payloadPointer_,offsetBeginningOfChannel));
109  //get length and check that whole channel fits into buffer
110  uint16_t channelLength = channels_.back().length();
111 
112  //check that the channel length is long enough to contain the header
113  if unlikely(channelLength < minLength) {
115  std::ostringstream ss;
116  ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan() << " according to external numbering scheme)"
117  << " is too short. "
118  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
119  << "Channel length is " << uint16_t(channelLength) << ". "
120  << "Min length is " << uint16_t(minLength) << ". ";
121  throw cms::Exception("FEDBuffer") << ss.str();
122  }
123  if unlikely(offsetBeginningOfChannel+channelLength > payloadLength_) {
125  std::ostringstream ss;
126  ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan() << " according to external numbering scheme)"
127  << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
128  << "Channel length is " << uint16_t(channelLength) << ". "
129  << "Payload length is " << uint16_t(payloadLength_) << ". ";
130  throw cms::Exception("FEDBuffer") << ss.str();
131  }
132 
133  validChannels_++;
134  const size_t offsetEndOfChannel = offsetBeginningOfChannel+channelLength;
135  //add padding if necessary and calculate offset for begining of next channel
136  if (!( (i+1) % FEDCH_PER_FEUNIT )) {
137  uint8_t numPaddingBytes = 8 - (offsetEndOfChannel % 8);
138  if (numPaddingBytes == 8) numPaddingBytes = 0;
139  offsetBeginningOfChannel = offsetEndOfChannel + numPaddingBytes;
140  } else {
141  offsetBeginningOfChannel = offsetEndOfChannel;
142  }
143  }
144  }
145 
146  bool FEDBuffer::channelGood(const uint8_t internalFEDChannelNum, const bool doAPVeCheck) const
147  {
148  return ( (internalFEDChannelNum < validChannels_) &&
149  ( (doAPVeCheck && feGood(internalFEDChannelNum/FEDCH_PER_FEUNIT)) ||
150  (!doAPVeCheck && feGoodWithoutAPVEmulatorCheck(internalFEDChannelNum/FEDCH_PER_FEUNIT))
151  ) &&
152  (this->readoutMode() == sistrip::READOUT_MODE_SCOPE || checkStatusBits(internalFEDChannelNum)) );
153  }
154 
155  bool FEDBuffer::doChecks(bool doCRC) const
156  {
157  //check that all channels were unpacked properly
158  if (validChannels_ != FEDCH_PER_FED) return false;
159  //do checks from base class
160  if (!FEDBufferBase::doChecks()) return false;
161  //check CRC
162  if (doCRC && !checkCRC()) return false;
163  return true;
164  }
165 
167  {
168  return ( checkCRC() &&
171  //checkClusterLengths() &&
172  checkFEUnitLengths() );
173  //checkFEUnitAPVAddresses() );
174  }
175 
177  {
178  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
179  //if FE unit is disabled then skip all channels on it
180  if (!feGood(iCh/FEDCH_PER_FEUNIT)) {
181  iCh += FEDCH_PER_FEUNIT;
182  continue;
183  }
184  //channel is bad then return false
185  if (!checkStatusBits(iCh)) return false;
186  }
187  //if no bad channels have been found then they are all fine
188  return true;
189  }
190 
192  {
193  return (validChannels_ == FEDCH_PER_FED);
194  }
195 
197  {
198  //check they fit into buffer
199  if (!checkChannelLengths()) return false;
200 
201  //payload length from length of data buffer
202  const size_t payloadLengthInWords = payloadLength_/8;
203 
204  //find channel length
205  //find last enabled FE unit
206  uint8_t lastEnabledFeUnit = 7;
207  while ( !(fePresent(lastEnabledFeUnit) && feEnabled(lastEnabledFeUnit)) && lastEnabledFeUnit!=0 ) lastEnabledFeUnit--;
208  //last channel is last channel on last enabled FE unit
209  const FEDChannel& lastChannel = channels_[internalFEDChannelNum(lastEnabledFeUnit,FEDCH_PER_FEUNIT-1)];
210  const size_t offsetLastChannel = lastChannel.offset();
211  const size_t offsetEndOfChannelData = offsetLastChannel+lastChannel.length();
212  const size_t channelDataLength = offsetEndOfChannelData;
213  //channel length in words is length in bytes rounded up to nearest word
214  size_t channelDataLengthInWords = channelDataLength/8;
215  if (channelDataLength % 8) channelDataLengthInWords++;
216 
217  //check lengths match
218  if (channelDataLengthInWords == payloadLengthInWords) {
219  return true;
220  } else {
221  return false;
222  }
223  }
224 
226  {
227  const uint8_t correctPacketCode = getCorrectPacketCode();
228  //if the readout mode if not one which has a packet code then this is set to zero. in this case return true
229  if (!correctPacketCode) return true;
230  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
231  //if FE unit is disabled then skip all channels on it
232  if (!feGood(iCh/FEDCH_PER_FEUNIT)) {
233  iCh += FEDCH_PER_FEUNIT;
234  continue;
235  }
236  //only check enabled, working channels
237  if (channelGood(iCh)) {
238  //if a channel is bad then return false
239  if (channels_[iCh].packetCode() != correctPacketCode) return false;
240  }
241  }
242  //if no bad channels were found the they are all ok
243  return true;
244  }
245 
247  {
248  //get golden address
249  const uint8_t goldenAddress = apveAddress();
250  //don't check if the address is 00 since APVe is probably not connected
251  if (goldenAddress == 0x00) return true;
252  //check can only be done for full debug headers
253  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
254  if (!fdHeader) return true;
255  //check all enabled FE units
256  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
257  if (!feGood(iFE)) continue;
258  //if address is bad then return false
259  if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) return false;
260  }
261  //if no bad addresses were found then return true
262  return true;
263  }
264 
266  {
267  //check can only be done for full debug headers
268  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
269  if (!fdHeader) return true;
270  //check lengths for enabled FE units
271  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
272  if (!feGood(iFE)) continue;
273  if (calculateFEUnitLength(iFE) != fdHeader->feUnitLength(iFE)) return false;
274  }
275  //if no errors were encountered then return true
276  return true;
277  }
278 
279  uint16_t FEDBuffer::calculateFEUnitLength(const uint8_t internalFEUnitNumber) const
280  {
281  //get length from channels
282  uint16_t lengthFromChannels = 0;
283  for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
284  lengthFromChannels += channels_[internalFEDChannelNum(internalFEUnitNumber,iCh)].length();
285  }
286  return lengthFromChannels;
287  }
288 
290  {
291  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
292  if (!fePresent(iFE)) return false;
293  }
294  return true;
295  }
296 
298  {
299  std::ostringstream summary;
300  summary << FEDBufferBase::checkSummary();
301  summary << "Check FE unit payloads are all present: " << (checkFEPayloadsPresent() ? "passed" : "FAILED" ) << std::endl;
302  if (!checkFEPayloadsPresent()) {
303  summary << "FE units missing payloads: ";
304  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
305  if (!fePresent(iFE)) summary << uint16_t(iFE) << " ";
306  }
307  summary << std::endl;
308  }
309  summary << "Check channel status bits: " << ( checkAllChannelStatusBits() ? "passed" : "FAILED" ) << std::endl;
310  if (!checkAllChannelStatusBits()) {
311  unsigned int badChannels = 0;
313  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
314  if (fdHeader) {
315  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
316  if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
317  if (!checkStatusBits(iCh)) {
318  summary << uint16_t(iCh) << ": " << fdHeader->getChannelStatus(iCh) << std::endl;
319  badChannels++;
320  }
321  }
322  }
323  } else {
324  summary << "Channels with errors: ";
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) << " ";
329  badChannels++;
330  }
331  }
332  summary << std::endl;
333  }
334  summary << "Number of channels with bad status bits: " << badChannels << std::endl;
335  }
336  summary << "Check channel lengths match buffer length: " << ( checkChannelLengthsMatchBufferLength() ? "passed" : "FAILED" ) << std::endl;
337  summary << "Check channel packet codes: " << ( checkChannelPacketCodes() ? "passed" : "FAILED" ) << std::endl;
338  if (!checkChannelPacketCodes()) {
339  summary << "Channels with bad packet codes: ";
340  for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
341  if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
342  if (channels_[iCh].packetCode() != getCorrectPacketCode())
343  summary << uint16_t(iCh) << " ";
344  }
345  }
346  summary << "Check FE unit lengths: " << ( checkFEUnitLengths() ? "passed" : "FAILED" ) << std::endl;
347  if (!checkFEUnitLengths()) {
348  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
349  if (fdHeader) {
350  summary << "Bad FE units:" << std::endl;
351  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
352  if (!feGood(iFE)) continue;
353  uint16_t lengthFromChannels = calculateFEUnitLength(iFE);
354  uint16_t lengthFromHeader = fdHeader->feUnitLength(iFE);
355  if (lengthFromHeader != lengthFromChannels) {
356  summary << "FE unit: " << uint16_t(iFE)
357  << " length in header: " << lengthFromHeader
358  << " length from channel lengths: " << lengthFromChannels << std::endl;
359  }
360  }
361  }
362  }
363  summary << "Check FE unit APV addresses match APVe: " << ( checkFEUnitAPVAddresses() ? "passed" : "FAILED" ) << std::endl;
364  if (!checkFEUnitAPVAddresses()) {
365  const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
366  if (fdHeader) {
367  const uint8_t goldenAddress = apveAddress();
368  summary << "Address from APVe:" << uint16_t(goldenAddress) << std::endl;
369  summary << "Bad FE units:" << std::endl;
370  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
371  if (!feGood(iFE)) continue;
372  if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) {
373  summary << "FE unit: " << uint16_t(iFE)
374  << " majority address: " << uint16_t(fdHeader->feUnitMajorityAddress(iFE)) << std::endl;
375  }
376  }
377  }
378  }
379  return summary.str();
380  }
381 
383  {
384  switch(readoutMode()) {
385  case READOUT_MODE_SCOPE:
386  return PACKET_CODE_SCOPE;
387  break;
389  return PACKET_CODE_VIRGIN_RAW;
390  break;
392  return PACKET_CODE_PROC_RAW;
393  break;
396  break;
399  case READOUT_MODE_SPY:
401  default:
402  return 0;
403  }
404  }
405 
407  {
408  uint8_t result = 0;
409  for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
410  if (fePresent(iFE)) result++;
411  }
412  return result;
413  }
414 
415  void FEDBuffer::print(std::ostream& os) const
416  {
419  os << "FE units with data: " << uint16_t(nFEUnitsPresent()) << std::endl;
420  os << "BE status register flags: ";
421  dynamic_cast<const FEDFullDebugHeader*>(feHeader())->beStatusRegister().printFlags(os);
422  os << std::endl;
423  }
424  }
425 
426 
427 
428 
430  {
431  std::ostringstream ss;
432  ss << "Channel length is invalid. Raw channels have 3 header bytes and 2 bytes per sample. "
433  << "Channel length is " << uint16_t(length) << "."
434  << std::endl;
435  throw cms::Exception("FEDBuffer") << ss.str();
436  }
437 
438 
439 
440 
442  {
443  std::ostringstream ss;
444  ss << "Channel length is longer than max allowed value. "
445  << "Channel length is " << uint16_t(length) << "."
446  << std::endl;
447  throw cms::Exception("FEDBuffer") << ss.str();
448  }
449 
451  {
452  std::ostringstream ss;
453  ss << "Cluster does not fit into channel. "
454  << "Cluster length is " << uint16_t(valuesLeftInCluster_) << "."
455  << std::endl;
456  throw cms::Exception("FEDBuffer") << ss.str();
457  }
458 
459  void FEDZSChannelUnpacker::throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster)
460  {
461  std::ostringstream ss;
462  ss << "First strip of new cluster is not greater than last strip of previous cluster. "
463  << "Last strip of previous cluster is " << uint16_t(currentStrip) << ". "
464  << "First strip of new cluster is " << uint16_t(firstStripOfNewCluster) << "."
465  << std::endl;
466  throw cms::Exception("FEDBuffer") << ss.str();
467  }
468 
469 }
std::auto_ptr< FEDFEHeader > feHeader_
bool feDataMissingFlag(const uint8_t internalFEUnitNum) const
int i
Definition: DBlmapReader.cc:9
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
FEDBuffer(const uint8_t *fedBuffer, const size_t fedBufferSize, const bool allowBadBuffer=false)
const uint8_t * getPointerToByteAfterEndOfPayload() const
virtual bool doCorruptBufferChecks() const
static const uint8_t PACKET_CODE_SCOPE
virtual void print(std::ostream &os) const
bool checkFEPayloadsPresent() const
FEDReadoutMode readoutMode() const
uint8_t internalFEDChannelNum(const uint8_t internalFEUnitNum, const uint8_t internalFEUnitChannelNum)
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
bool feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const
bool fePresent_[FEUNITS_PER_FED]
#define unlikely(x)
const uint8_t * payloadPointer_
static const uint8_t PACKET_CODE_ZERO_SUPPRESSED
bool fePresent(uint8_t internalFEUnitNum) const
static const uint16_t FEUNITS_PER_FED
tuple result
Definition: query.py:137
bool feEnabled(const uint8_t internalFEUnitNum) const
FEDHeaderType headerType() const
virtual std::string checkSummary() const
std::vector< FEDChannel > channels_
bool checkChannelPacketCodes() const
static const uint8_t PACKET_CODE_PROC_RAW
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
TrackerSpecialHeader trackerSpecialHeader() const
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)
volatile std::atomic< bool > shutdown_flag false
bool feGood(const uint8_t internalFEUnitNum) const
static const uint8_t PACKET_CODE_VIRGIN_RAW
FEDStatusRegister fedStatusRegister() const