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