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