00001 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBuffer.h"
00002 #include "FWCore/Utilities/interface/CRC16.h"
00003 #include "FWCore/Utilities/interface/Exception.h"
00004 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
00005 #include <iomanip>
00006 #include <ostream>
00007 #include <sstream>
00008
00009 namespace sistrip {
00010
00011 FEDBuffer::FEDBuffer(const uint8_t* fedBuffer, size_t fedBufferSize, bool allowBadBuffer)
00012 : FEDBufferBase(fedBuffer,fedBufferSize,allowBadBuffer)
00013 {
00014 channels_.reserve(FEDCH_PER_FED);
00015
00016 if (headerType() != HEADER_TYPE_INVALID) {
00017 feHeader_ = FEDFEHeader::newFEHeader(headerType(),getPointerToDataAfterTrackerSpecialHeader());
00018 payloadPointer_ = getPointerToDataAfterTrackerSpecialHeader()+feHeader_->lengthInBytes();
00019 } else {
00020 feHeader_ = std::auto_ptr<FEDFEHeader>();
00021 payloadPointer_ = getPointerToDataAfterTrackerSpecialHeader();
00022 if (!allowBadBuffer) {
00023 std::ostringstream ss;
00024 ss << "Header type is invalid. "
00025 << "Header type nibble is ";
00026 uint8_t headerNibble = trackerSpecialHeader().headerTypeNibble();
00027 printHex(&headerNibble,1,ss);
00028 ss << ". ";
00029 throw cms::Exception("FEDBuffer") << ss;
00030 }
00031 }
00032 payloadLength_ = getPointerToByteAfterEndOfPayload()-payloadPointer_;
00033
00034
00035 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00036 if (fdHeader) {
00037 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00038 if (fdHeader->fePresent(iFE)) fePresent_[iFE] = true;
00039 else fePresent_[iFE] = false;
00040 }
00041 } else {
00042 memset(fePresent_,true,FEUNITS_PER_FED);
00043 }
00044
00045 lastValidChannel_ = 0;
00046 try {
00047 findChannels();
00048 } catch (const cms::Exception& e) {
00049
00050 if (!allowBadBuffer) throw;
00051 else {
00052 channels_.insert(channels_.end(),size_t(FEDCH_PER_FED-lastValidChannel_),FEDChannel(payloadPointer_,0));
00053 }
00054 }
00055 }
00056
00057 FEDBuffer::~FEDBuffer()
00058 {
00059 }
00060
00061 void FEDBuffer::findChannels()
00062 {
00063 size_t offsetBeginningOfChannel = 0;
00064 for (size_t i = 0; i < FEDCH_PER_FED; i++) {
00065
00066 if (!feGood(i/FEDCH_PER_FEUNIT)) {
00067 channels_.insert(channels_.end(),size_t(FEDCH_PER_FEUNIT),FEDChannel(payloadPointer_,0));
00068 i += FEDCH_PER_FEUNIT-1;
00069 lastValidChannel_ += FEDCH_PER_FEUNIT;
00070 continue;
00071 }
00072
00073
00074 if (offsetBeginningOfChannel+2 >= payloadLength_) {
00075 throw cms::Exception("FEDBuffer") << "Channel " << uint16_t(i) << " does not fit into buffer. "
00076 << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
00077 << "Payload length is " << uint16_t(payloadLength_) << ". ";
00078 }
00079 channels_.push_back(FEDChannel(payloadPointer_,offsetBeginningOfChannel));
00080
00081 uint16_t channelLength = channels_.back().length();
00082 if (offsetBeginningOfChannel+channelLength > payloadLength_) {
00083 throw cms::Exception("FEDBuffer") << "Channel " << uint16_t(i) << " does not fit into buffer. "
00084 << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
00085 << "Channel length is " << uint16_t(channelLength) << ". "
00086 << "Payload length is " << uint16_t(payloadLength_) << ". ";
00087 }
00088 lastValidChannel_++;
00089 const size_t offsetEndOfChannel = offsetBeginningOfChannel+channelLength;
00090
00091 if (!( (i+1) % FEDCH_PER_FEUNIT )) {
00092 uint8_t numPaddingBytes = 8 - (offsetEndOfChannel % 8);
00093 if (numPaddingBytes == 8) numPaddingBytes = 0;
00094 offsetBeginningOfChannel = offsetEndOfChannel + numPaddingBytes;
00095 } else {
00096 offsetBeginningOfChannel = offsetEndOfChannel;
00097 }
00098 }
00099 }
00100
00101 bool FEDBuffer::doChecks() const
00102 {
00103
00104 if (lastValidChannel_ != FEDCH_PER_FED) return false;
00105
00106 if (!FEDBufferBase::doChecks()) return false;
00107 return true;
00108 }
00109
00110 bool FEDBuffer::doCorruptBufferChecks() const
00111 {
00112 return ( checkCRC() &&
00113 checkChannelLengthsMatchBufferLength() &&
00114 checkChannelPacketCodes() &&
00115
00116 checkFEUnitLengths() );
00117
00118 }
00119
00120 bool FEDBuffer::checkAllChannelStatusBits() const
00121 {
00122 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00123
00124 if (!feGood(iCh/FEDCH_PER_FEUNIT)) {
00125 iCh += FEDCH_PER_FEUNIT;
00126 continue;
00127 }
00128
00129 if (!checkStatusBits(iCh)) return false;
00130 }
00131
00132 return true;
00133 }
00134
00135 bool FEDBuffer::checkChannelLengths() const
00136 {
00137 return (lastValidChannel_ == FEDCH_PER_FED);
00138 }
00139
00140 bool FEDBuffer::checkChannelLengthsMatchBufferLength() const
00141 {
00142
00143 if (!checkChannelLengths()) return false;
00144
00145
00146 const size_t payloadLengthInWords = payloadLength_/8;
00147
00148
00149
00150 uint8_t lastEnabledFeUnit = 7;
00151 while (!feGood(lastEnabledFeUnit)) lastEnabledFeUnit--;
00152
00153 const FEDChannel& lastChannel = channels_[internalFEDChannelNum(lastEnabledFeUnit,FEDCH_PER_FEUNIT-1)];
00154 const size_t offsetLastChannel = lastChannel.offset();
00155 const size_t offsetEndOfChannelData = offsetLastChannel+lastChannel.length();
00156 const size_t channelDataLength = offsetEndOfChannelData;
00157
00158 size_t channelDataLengthInWords = channelDataLength/8;
00159 if (channelDataLength % 8) channelDataLengthInWords++;
00160
00161
00162 if (channelDataLengthInWords == payloadLengthInWords) {
00163 return true;
00164 } else {
00165 return false;
00166 }
00167 }
00168
00169 bool FEDBuffer::checkChannelPacketCodes() const
00170 {
00171 uint8_t correctPacketCode = getCorrectPacketCode();
00172
00173 if (!correctPacketCode) return true;
00174 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00175
00176 if (!feGood(iCh/FEDCH_PER_FEUNIT)) {
00177 iCh += FEDCH_PER_FEUNIT;
00178 continue;
00179 }
00180
00181 if (channelGood(iCh)) {
00182
00183 if (channels_[iCh].packetCode() != correctPacketCode) return false;
00184 }
00185 }
00186
00187 return true;
00188 }
00189
00190 bool FEDBuffer::checkFEUnitAPVAddresses() const
00191 {
00192
00193 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00194 if (!fdHeader) return true;
00195
00196 const uint8_t goldenAddress = apveAddress();
00197
00198 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00199 if (!feGood(iFE)) continue;
00200
00201 if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) return false;
00202 }
00203
00204 return true;
00205 }
00206
00207 bool FEDBuffer::checkFEUnitLengths() const
00208 {
00209
00210 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00211 if (!fdHeader) return true;
00212
00213 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00214 if (!feGood(iFE)) continue;
00215 if (calculateFEUnitLength(iFE) != fdHeader->feUnitLength(iFE)) return false;
00216 }
00217
00218 return true;
00219 }
00220
00221 uint16_t FEDBuffer::calculateFEUnitLength(uint8_t internalFEUnitNumber) const
00222 {
00223
00224 uint16_t lengthFromChannels = 0;
00225 for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
00226 lengthFromChannels += channels_[internalFEDChannelNum(internalFEUnitNumber,iCh)].length();
00227 }
00228 return lengthFromChannels;
00229 }
00230
00231 std::string FEDBuffer::checkSummary() const
00232 {
00233 std::stringstream summary;
00234 summary << FEDBufferBase::checkSummary();
00235 summary << "Check channel status bits: " << ( checkAllChannelStatusBits() ? "passed" : "FAILED" ) << std::endl;
00236 if (!checkAllChannelStatusBits()) {
00237 summary << "Channels with errors: ";
00238 unsigned int badChannels = 0;
00239 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00240 if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
00241 if (!checkStatusBits(iCh)) {
00242 summary << uint16_t(iCh) << " ";
00243 badChannels++;
00244 }
00245 }
00246 summary << std::endl;
00247 summary << "Number of channels with bad status bits: " << badChannels << std::endl;
00248 }
00249 summary << "Check channel lengths match buffer length: " << ( checkChannelLengthsMatchBufferLength() ? "passed" : "FAILED" ) << std::endl;
00250 summary << "Check channel packet codes: " << ( checkChannelPacketCodes() ? "passed" : "FAILED" ) << std::endl;
00251 if (!checkChannelPacketCodes()) {
00252 summary << "Channels with bad packet codes: ";
00253 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00254 if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
00255 if (channels_[iCh].packetCode() != getCorrectPacketCode())
00256 summary << uint16_t(iCh) << " ";
00257 }
00258 }
00259 summary << "Check FE unit lengths: " << ( checkFEUnitLengths() ? "passed" : "FAILED" ) << std::endl;
00260 if (!checkFEUnitLengths()) {
00261 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00262 if (fdHeader) {
00263 summary << "Bad FE units:" << std::endl;
00264 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00265 if (!feGood(iFE)) continue;
00266 uint16_t lengthFromChannels = calculateFEUnitLength(iFE);
00267 uint16_t lengthFromHeader = fdHeader->feUnitLength(iFE);
00268 if (lengthFromHeader != lengthFromChannels) {
00269 summary << "FE unit: " << uint16_t(iFE)
00270 << " length in header: " << lengthFromHeader
00271 << " length from channel lengths: " << lengthFromChannels << std::endl;
00272 }
00273 }
00274 }
00275 }
00276 summary << "Check FE unit APV addresses match APVe: " << ( checkFEUnitAPVAddresses() ? "passed" : "FAILED" ) << std::endl;
00277 if (!checkFEUnitAPVAddresses()) {
00278 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00279 if (fdHeader) {
00280 const uint8_t goldenAddress = apveAddress();
00281 summary << "Address from APVe:" << uint16_t(goldenAddress) << std::endl;
00282 summary << "Bad FE units:" << std::endl;
00283 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00284 if (!feGood(iFE)) continue;
00285 if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) {
00286 summary << "FE unit: " << uint16_t(iFE)
00287 << " majority address: " << uint16_t(fdHeader->feUnitMajorityAddress(iFE)) << std::endl;
00288 }
00289 }
00290 }
00291 }
00292 return summary.str();
00293 }
00294
00295 uint8_t FEDBuffer::getCorrectPacketCode() const
00296 {
00297 switch(readoutMode()) {
00298 case READOUT_MODE_SCOPE:
00299 return PACKET_CODE_SCOPE;
00300 break;
00301 case READOUT_MODE_VIRGIN_RAW:
00302 return PACKET_CODE_VIRGIN_RAW;
00303 break;
00304 case READOUT_MODE_PROC_RAW:
00305 return PACKET_CODE_PROC_RAW;
00306 break;
00307 case READOUT_MODE_ZERO_SUPPRESSED:
00308 return PACKET_CODE_ZERO_SUPPRESSED;
00309 break;
00310 case READOUT_MODE_ZERO_SUPPRESSED_LITE:
00311 case READOUT_MODE_INVALID:
00312 default:
00313 return 0;
00314 }
00315 }
00316
00317 uint8_t FEDBuffer::nFEUnitsPresent() const
00318 {
00319 uint8_t result = 0;
00320 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00321 if (fePresent(iFE)) result++;
00322 }
00323 return result;
00324 }
00325
00326 void FEDBuffer::print(std::ostream& os) const
00327 {
00328 FEDBufferBase::print(os);
00329 if (headerType() == HEADER_TYPE_FULL_DEBUG) os << "FE units with data: " << uint16_t(nFEUnitsPresent()) << std::endl;
00330 }
00331
00332
00333
00334
00335 FEDBufferBase::FEDBufferBase(const uint8_t* fedBuffer, size_t fedBufferSize, bool allowUnrecognizedFormat)
00336 : originalBuffer_(fedBuffer),
00337 bufferSize_(fedBufferSize)
00338 {
00339
00340 static const size_t MIN_BUFFER_SIZE = 8+8+8;
00341
00342 if (!originalBuffer_) throw cms::Exception("FEDBuffer") << "Buffer pointer is NULL. ";
00343 if (bufferSize_ < MIN_BUFFER_SIZE)
00344 throw cms::Exception("FEDBuffer") << "Buffer is too small. "
00345 << "Min size is " << MIN_BUFFER_SIZE << ". "
00346 << "Buffer size is " << bufferSize_ << ". ";
00347
00348
00349 specialHeader_ = TrackerSpecialHeader(originalBuffer_+8);
00350
00351
00352 const FEDBufferFormat bufferFormat = specialHeader_.bufferFormat();
00353 if (bufferFormat == BUFFER_FORMAT_INVALID && !allowUnrecognizedFormat) {
00354 cms::Exception e("FEDBuffer");
00355 e << "Buffer format not recognized. "
00356 << "Tracker special header: " << specialHeader_;
00357 throw e;
00358 }
00359
00360 if ( (bufferFormat == BUFFER_FORMAT_OLD_VME) || (bufferFormat == BUFFER_FORMAT_NEW) ) {
00361 uint8_t* newBuffer = new uint8_t[bufferSize_];
00362 const uint32_t* originalU32 = reinterpret_cast<const uint32_t*>(originalBuffer_);
00363 const size_t sizeU32 = bufferSize_/4;
00364 uint32_t* newU32 = reinterpret_cast<uint32_t*>(newBuffer);
00365 if (bufferFormat == BUFFER_FORMAT_OLD_VME) {
00366
00367 for (size_t i = 0; i < sizeU32; i+=2) {
00368 newU32[i] = originalU32[i+1];
00369 newU32[i+1] = originalU32[i];
00370 }
00371 }
00372 if (bufferFormat == BUFFER_FORMAT_NEW) {
00373
00374 memcpy(newU32,originalU32,8);
00375
00376 memcpy(newU32+sizeU32-2,originalU32+sizeU32-2,8);
00377
00378 for (size_t i = 2; i < sizeU32-2; i+=2) {
00379 newU32[i] = originalU32[i+1];
00380 newU32[i+1] = originalU32[i];
00381 }
00382 }
00383 orderedBuffer_ = newBuffer;
00384 }
00385 else {
00386 orderedBuffer_ = originalBuffer_;
00387 }
00388
00389
00390 daqHeader_ = FEDDAQHeader(orderedBuffer_);
00391
00392 daqTrailer_ = FEDDAQTrailer(orderedBuffer_+bufferSize_-8);
00393 }
00394
00395 FEDBufferBase::~FEDBufferBase()
00396 {
00397
00398 if (orderedBuffer_ != originalBuffer_) delete[] orderedBuffer_;
00399 }
00400
00401 uint16_t FEDBufferBase::calcCRC() const
00402 {
00403 uint16_t crc = 0xFFFF;
00404 for (size_t i = 0; i < bufferSize_-8; i++) {
00405 crc = evf::compute_crc_8bit(crc,orderedBuffer_[i^7]);
00406 }
00407 for (size_t i=bufferSize_-8; i<bufferSize_; i++) {
00408 uint8_t byte;
00409
00410 if (i==bufferSize_-4 || i==bufferSize_-3)
00411 byte = 0x00;
00412 else
00413 byte = orderedBuffer_[i^7];
00414 crc = evf::compute_crc_8bit(crc,byte);
00415 }
00416 return crc;
00417 }
00418
00419 void FEDBufferBase::print(std::ostream& os) const
00420 {
00421 os << "buffer format: " << bufferFormat() << std::endl;
00422 os << "Buffer size: " << bufferSize() << " bytes" << std::endl;
00423 os << "Event length from DAQ trailer: " << daqEventLengthInBytes() << " bytes" << std::endl;
00424 os << "Source ID: " << daqSourceID() << std::endl;
00425 os << "Header type: " << headerType() << std::endl;
00426 os << "Readout mode: " << readoutMode() << std::endl;
00427 os << "Data type: " << dataType() << std::endl;
00428 os << "DAQ event type: " << daqEventType() << std::endl;
00429 os << "TTS state: " << daqTTSState() << std::endl;
00430 os << "L1 ID: " << daqLvl1ID() << std::endl;
00431 os << "BX ID: " << daqBXID() << std::endl;
00432 os << "FED status register flags: "; fedStatusRegister().printFlags(os); os << std::endl;
00433 os << "APVe Address: " << uint16_t(apveAddress()) << std::endl;
00434 os << "Enabled FE units: " << uint16_t(nFEUnitsEnabled()) << std::endl;
00435 }
00436
00437 uint8_t FEDBufferBase::nFEUnitsEnabled() const
00438 {
00439 uint8_t result = 0;
00440 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00441 if (feEnabled(iFE)) result++;
00442 }
00443 return result;
00444 }
00445
00446 bool FEDBufferBase::checkSourceIDs() const
00447 {
00448 return ( (daqSourceID() >= FEDNumbering::getSiStripFEDIds().first) &&
00449 (daqSourceID() <= FEDNumbering::getSiStripFEDIds().second) );
00450 }
00451
00452 bool FEDBufferBase::checkMajorityAddresses() const
00453 {
00454 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00455 if (!feEnabled(iFE)) continue;
00456 if (majorityAddressErrorForFEUnit(iFE)) return false;
00457 }
00458 return true;
00459 }
00460
00461 bool FEDBufferBase::doChecks() const
00462 {
00463 return (doTrackerSpecialHeaderChecks() && doDAQHeaderAndTrailerChecks());
00464 }
00465
00466 std::string FEDBufferBase::checkSummary() const
00467 {
00468 std::stringstream summary;
00469 summary << "Check buffer type valid: " << ( checkBufferFormat() ? "passed" : "FAILED" ) << std::endl;
00470 summary << "Check header format valid: " << ( checkHeaderType() ? "passed" : "FAILED" ) << std::endl;
00471 summary << "Check readout mode valid: " << ( checkReadoutMode() ? "passed" : "FAILED" ) << std::endl;
00472 summary << "Check APVe address valid: " << ( checkAPVEAddressValid() ? "passed" : "FAILED" ) << std::endl;
00473 summary << "Check FE unit majority addresses: " << ( checkMajorityAddresses() ? "passed" : "FAILED" ) << std::endl;
00474 if (!checkMajorityAddresses()) {
00475 summary << "FEs with majority address error: ";
00476 unsigned int badFEs = 0;
00477 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00478 if (!feEnabled(iFE)) continue;
00479 if (majorityAddressErrorForFEUnit(iFE)) {
00480 summary << uint16_t(iFE) << " ";
00481 badFEs++;
00482 }
00483 }
00484 summary << std::endl;
00485 summary << "Number of FE Units with bad addresses: " << badFEs << std::endl;
00486 }
00487 summary << "Check for FE unit buffer overflows: " << ( checkNoFEOverflows() ? "passed" : "FAILED" ) << std::endl;
00488 if (!checkNoFEOverflows()) {
00489 summary << "FEs which overflowed: ";
00490 unsigned int badFEs = 0;
00491 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00492 if (feOverflow(iFE)) {
00493 summary << uint16_t(iFE) << " ";
00494 badFEs++;
00495 }
00496 }
00497 summary << std::endl;
00498 summary << "Number of FE Units which overflowed: " << badFEs << std::endl;
00499 }
00500 summary << "Check for S-Link CRC errors: " << ( checkNoSlinkCRCError() ? "passed" : "FAILED" ) << std::endl;
00501 summary << "Check for S-Link transmission error: " << ( checkNoSLinkTransmissionError() ? "passed" : "FAILED" ) << std::endl;
00502 summary << "Check CRC: " << ( checkCRC() ? "passed" : "FAILED" ) << std::endl;
00503 summary << "Check source ID is FED ID: " << ( checkSourceIDs() ? "passed" : "FAILED" ) << std::endl;
00504 summary << "Check for unexpected source ID at FRL: " << ( checkNoUnexpectedSourceID() ? "passed" : "FAILED" ) << std::endl;
00505 summary << "Check there are no extra headers or trailers: " << ( checkNoExtraHeadersOrTrailers() ? "passed" : "FAILED" ) << std::endl;
00506 summary << "Check length from trailer: " << ( checkLengthFromTrailer() ? "passed" : "FAILED" ) << std::endl;
00507 return summary.str();
00508 }
00509
00510
00511
00512
00513 void FEDRawChannelUnpacker::throwBadChannelLength(uint16_t length)
00514 {
00515 std::stringstream ss;
00516 ss << "Channel length is invalid. Raw channels have 3 header bytes and 2 bytes per sample. "
00517 << "Channel length is " << uint16_t(length) << "."
00518 << std::endl;
00519 throw cms::Exception("FEDBuffer") << ss.str();
00520 }
00521
00522
00523
00524
00525 void FEDZSChannelUnpacker::throwBadChannelLength(uint16_t length)
00526 {
00527 std::stringstream ss;
00528 ss << "Channel length is longer than max allowed value. "
00529 << "Channel length is " << uint16_t(length) << "."
00530 << std::endl;
00531 throw cms::Exception("FEDBuffer") << ss.str();
00532 }
00533
00534 void FEDZSChannelUnpacker::throwBadClusterLength()
00535 {
00536 std::stringstream ss;
00537 ss << "Cluster does not fit into channel. "
00538 << "Cluster length is " << uint16_t(valuesLeftInCluster_) << "."
00539 << std::endl;
00540 throw cms::Exception("FEDBuffer") << ss.str();
00541 }
00542
00543 }