Go to the documentation of this file.00001 #include <iomanip>
00002 #include <ostream>
00003 #include <sstream>
00004 #include <cstring>
00005
00006 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBuffer.h"
00007
00008 #include "DataFormats/SiStripCommon/interface/SiStripFedKey.h"
00009
00010 namespace sistrip {
00011
00012 FEDBuffer::FEDBuffer(const uint8_t* fedBuffer, const size_t fedBufferSize, const bool allowBadBuffer)
00013 : FEDBufferBase(fedBuffer,fedBufferSize,allowBadBuffer,false)
00014 {
00015 channels_.reserve(FEDCH_PER_FED);
00016
00017 if ( (headerType() != HEADER_TYPE_INVALID) && (headerType() != HEADER_TYPE_NONE) ) {
00018 feHeader_ = FEDFEHeader::newFEHeader(headerType(),getPointerToDataAfterTrackerSpecialHeader());
00019 payloadPointer_ = getPointerToDataAfterTrackerSpecialHeader()+feHeader_->lengthInBytes();
00020 } else {
00021 feHeader_ = std::auto_ptr<FEDFEHeader>();
00022 payloadPointer_ = getPointerToDataAfterTrackerSpecialHeader();
00023 if (!allowBadBuffer) {
00024 std::ostringstream ss;
00025 ss << "Header type is invalid. "
00026 << "Header type nibble is ";
00027 uint8_t headerNibble = trackerSpecialHeader().headerTypeNibble();
00028 printHex(&headerNibble,1,ss);
00029 ss << ". ";
00030 throw cms::Exception("FEDBuffer") << ss.str();
00031 }
00032 }
00033 if (readoutMode() == READOUT_MODE_SPY) {
00034 throw cms::Exception("FEDBuffer") << "Unpacking of spy channel data with FEDBuffer is not supported" << std::endl;
00035 }
00036 payloadLength_ = getPointerToByteAfterEndOfPayload()-payloadPointer_;
00037
00038
00039 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00040 if (fdHeader) {
00041 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00042 if (fdHeader->fePresent(iFE)) fePresent_[iFE] = true;
00043 else fePresent_[iFE] = false;
00044 }
00045 }
00046
00047
00048 else {
00049 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00050 if (fedStatusRegister().feDataMissingFlag(iFE)) fePresent_[iFE] = false;
00051 else fePresent_[iFE] = true;
00052 }
00053 }
00054
00055 validChannels_ = 0;
00056 try {
00057 findChannels();
00058 } catch (const cms::Exception& e) {
00059
00060 if (!allowBadBuffer) throw;
00061 else {
00062 channels_.insert(channels_.end(),size_t(FEDCH_PER_FED-validChannels_),FEDChannel(payloadPointer_,0,0));
00063 }
00064 }
00065 }
00066
00067 FEDBuffer::~FEDBuffer()
00068 {
00069 }
00070
00071 void FEDBuffer::findChannels()
00072 {
00073
00074 uint16_t minLength;
00075 switch (readoutMode()) {
00076 case READOUT_MODE_ZERO_SUPPRESSED:
00077 minLength = 7;
00078 break;
00079 case READOUT_MODE_ZERO_SUPPRESSED_LITE:
00080 minLength = 2;
00081 break;
00082 default:
00083 minLength = 3;
00084 break;
00085 }
00086 size_t offsetBeginningOfChannel = 0;
00087 for (size_t i = 0; i < FEDCH_PER_FED; i++) {
00088
00089 if ( !(fePresent(i/FEDCH_PER_FEUNIT) && feEnabled(i/FEDCH_PER_FEUNIT)) ) {
00090 channels_.insert(channels_.end(),size_t(FEDCH_PER_FEUNIT),FEDChannel(payloadPointer_,0,0));
00091 i += FEDCH_PER_FEUNIT-1;
00092 validChannels_ += FEDCH_PER_FEUNIT;
00093 continue;
00094 }
00095
00096
00097 if (offsetBeginningOfChannel+1 >= payloadLength_) {
00098 std::ostringstream ss;
00099 SiStripFedKey key(0,i/FEDCH_PER_FEUNIT,i%FEDCH_PER_FEUNIT);
00100 ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan() << " according to external numbering scheme)"
00101 << " does not fit into buffer. "
00102 << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
00103 << "Payload length is " << uint16_t(payloadLength_) << ". ";
00104 throw cms::Exception("FEDBuffer") << ss.str();
00105 }
00106 channels_.push_back(FEDChannel(payloadPointer_,offsetBeginningOfChannel));
00107
00108 uint16_t channelLength = channels_.back().length();
00109
00110 if (channelLength < minLength) {
00111 SiStripFedKey key(0,i/FEDCH_PER_FEUNIT,i%FEDCH_PER_FEUNIT);
00112 std::ostringstream ss;
00113 ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan() << " according to external numbering scheme)"
00114 << " is too short. "
00115 << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
00116 << "Channel length is " << uint16_t(channelLength) << ". "
00117 << "Min length is " << uint16_t(minLength) << ". ";
00118 throw cms::Exception("FEDBuffer") << ss.str();
00119 }
00120 if (offsetBeginningOfChannel+channelLength > payloadLength_) {
00121 SiStripFedKey key(0,i/FEDCH_PER_FEUNIT,i%FEDCH_PER_FEUNIT);
00122 std::ostringstream ss;
00123 ss << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel " << key.feChan() << " according to external numbering scheme)"
00124 << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
00125 << "Channel length is " << uint16_t(channelLength) << ". "
00126 << "Payload length is " << uint16_t(payloadLength_) << ". ";
00127 throw cms::Exception("FEDBuffer") << ss.str();
00128 }
00129 validChannels_++;
00130 const size_t offsetEndOfChannel = offsetBeginningOfChannel+channelLength;
00131
00132 if (!( (i+1) % FEDCH_PER_FEUNIT )) {
00133 uint8_t numPaddingBytes = 8 - (offsetEndOfChannel % 8);
00134 if (numPaddingBytes == 8) numPaddingBytes = 0;
00135 offsetBeginningOfChannel = offsetEndOfChannel + numPaddingBytes;
00136 } else {
00137 offsetBeginningOfChannel = offsetEndOfChannel;
00138 }
00139 }
00140 }
00141
00142 bool FEDBuffer::channelGood(const uint8_t internalFEDChannelNum, const bool doAPVeCheck) const
00143 {
00144 return ( (internalFEDChannelNum < validChannels_) &&
00145 ( (doAPVeCheck && feGood(internalFEDChannelNum/FEDCH_PER_FEUNIT)) ||
00146 (!doAPVeCheck && feGoodWithoutAPVEmulatorCheck(internalFEDChannelNum/FEDCH_PER_FEUNIT))
00147 ) &&
00148 (this->readoutMode() == sistrip::READOUT_MODE_SCOPE || checkStatusBits(internalFEDChannelNum)) );
00149 }
00150
00151 bool FEDBuffer::doChecks() const
00152 {
00153
00154 if (validChannels_ != FEDCH_PER_FED) return false;
00155
00156 if (!FEDBufferBase::doChecks()) return false;
00157
00158 if (!checkCRC()) return false;
00159 return true;
00160 }
00161
00162 bool FEDBuffer::doCorruptBufferChecks() const
00163 {
00164 return ( checkCRC() &&
00165 checkChannelLengthsMatchBufferLength() &&
00166 checkChannelPacketCodes() &&
00167
00168 checkFEUnitLengths() );
00169
00170 }
00171
00172 bool FEDBuffer::checkAllChannelStatusBits() const
00173 {
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 (!checkStatusBits(iCh)) return false;
00182 }
00183
00184 return true;
00185 }
00186
00187 bool FEDBuffer::checkChannelLengths() const
00188 {
00189 return (validChannels_ == FEDCH_PER_FED);
00190 }
00191
00192 bool FEDBuffer::checkChannelLengthsMatchBufferLength() const
00193 {
00194
00195 if (!checkChannelLengths()) return false;
00196
00197
00198 const size_t payloadLengthInWords = payloadLength_/8;
00199
00200
00201
00202 uint8_t lastEnabledFeUnit = 7;
00203 while ( !(fePresent(lastEnabledFeUnit) && feEnabled(lastEnabledFeUnit)) && lastEnabledFeUnit!=0 ) lastEnabledFeUnit--;
00204
00205 const FEDChannel& lastChannel = channels_[internalFEDChannelNum(lastEnabledFeUnit,FEDCH_PER_FEUNIT-1)];
00206 const size_t offsetLastChannel = lastChannel.offset();
00207 const size_t offsetEndOfChannelData = offsetLastChannel+lastChannel.length();
00208 const size_t channelDataLength = offsetEndOfChannelData;
00209
00210 size_t channelDataLengthInWords = channelDataLength/8;
00211 if (channelDataLength % 8) channelDataLengthInWords++;
00212
00213
00214 if (channelDataLengthInWords == payloadLengthInWords) {
00215 return true;
00216 } else {
00217 return false;
00218 }
00219 }
00220
00221 bool FEDBuffer::checkChannelPacketCodes() const
00222 {
00223 const uint8_t correctPacketCode = getCorrectPacketCode();
00224
00225 if (!correctPacketCode) return true;
00226 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00227
00228 if (!feGood(iCh/FEDCH_PER_FEUNIT)) {
00229 iCh += FEDCH_PER_FEUNIT;
00230 continue;
00231 }
00232
00233 if (channelGood(iCh)) {
00234
00235 if (channels_[iCh].packetCode() != correctPacketCode) return false;
00236 }
00237 }
00238
00239 return true;
00240 }
00241
00242 bool FEDBuffer::checkFEUnitAPVAddresses() const
00243 {
00244
00245 const uint8_t goldenAddress = apveAddress();
00246
00247 if (goldenAddress == 0x00) return true;
00248
00249 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00250 if (!fdHeader) return true;
00251
00252 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00253 if (!feGood(iFE)) continue;
00254
00255 if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) return false;
00256 }
00257
00258 return true;
00259 }
00260
00261 bool FEDBuffer::checkFEUnitLengths() const
00262 {
00263
00264 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00265 if (!fdHeader) return true;
00266
00267 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00268 if (!feGood(iFE)) continue;
00269 if (calculateFEUnitLength(iFE) != fdHeader->feUnitLength(iFE)) return false;
00270 }
00271
00272 return true;
00273 }
00274
00275 uint16_t FEDBuffer::calculateFEUnitLength(const uint8_t internalFEUnitNumber) const
00276 {
00277
00278 uint16_t lengthFromChannels = 0;
00279 for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
00280 lengthFromChannels += channels_[internalFEDChannelNum(internalFEUnitNumber,iCh)].length();
00281 }
00282 return lengthFromChannels;
00283 }
00284
00285 bool FEDBuffer::checkFEPayloadsPresent() const
00286 {
00287 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00288 if (!fePresent(iFE)) return false;
00289 }
00290 return true;
00291 }
00292
00293 std::string FEDBuffer::checkSummary() const
00294 {
00295 std::ostringstream summary;
00296 summary << FEDBufferBase::checkSummary();
00297 summary << "Check FE unit payloads are all present: " << (checkFEPayloadsPresent() ? "passed" : "FAILED" ) << std::endl;
00298 if (!checkFEPayloadsPresent()) {
00299 summary << "FE units missing payloads: ";
00300 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00301 if (!fePresent(iFE)) summary << uint16_t(iFE) << " ";
00302 }
00303 summary << std::endl;
00304 }
00305 summary << "Check channel status bits: " << ( checkAllChannelStatusBits() ? "passed" : "FAILED" ) << std::endl;
00306 if (!checkAllChannelStatusBits()) {
00307 unsigned int badChannels = 0;
00308 if (headerType() == HEADER_TYPE_FULL_DEBUG) {
00309 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00310 if (fdHeader) {
00311 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00312 if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
00313 if (!checkStatusBits(iCh)) {
00314 summary << uint16_t(iCh) << ": " << fdHeader->getChannelStatus(iCh) << std::endl;
00315 badChannels++;
00316 }
00317 }
00318 }
00319 } else {
00320 summary << "Channels with errors: ";
00321 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00322 if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
00323 if (!checkStatusBits(iCh)) {
00324 summary << uint16_t(iCh) << " ";
00325 badChannels++;
00326 }
00327 }
00328 summary << std::endl;
00329 }
00330 summary << "Number of channels with bad status bits: " << badChannels << std::endl;
00331 }
00332 summary << "Check channel lengths match buffer length: " << ( checkChannelLengthsMatchBufferLength() ? "passed" : "FAILED" ) << std::endl;
00333 summary << "Check channel packet codes: " << ( checkChannelPacketCodes() ? "passed" : "FAILED" ) << std::endl;
00334 if (!checkChannelPacketCodes()) {
00335 summary << "Channels with bad packet codes: ";
00336 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00337 if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
00338 if (channels_[iCh].packetCode() != getCorrectPacketCode())
00339 summary << uint16_t(iCh) << " ";
00340 }
00341 }
00342 summary << "Check FE unit lengths: " << ( checkFEUnitLengths() ? "passed" : "FAILED" ) << std::endl;
00343 if (!checkFEUnitLengths()) {
00344 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00345 if (fdHeader) {
00346 summary << "Bad FE units:" << std::endl;
00347 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00348 if (!feGood(iFE)) continue;
00349 uint16_t lengthFromChannels = calculateFEUnitLength(iFE);
00350 uint16_t lengthFromHeader = fdHeader->feUnitLength(iFE);
00351 if (lengthFromHeader != lengthFromChannels) {
00352 summary << "FE unit: " << uint16_t(iFE)
00353 << " length in header: " << lengthFromHeader
00354 << " length from channel lengths: " << lengthFromChannels << std::endl;
00355 }
00356 }
00357 }
00358 }
00359 summary << "Check FE unit APV addresses match APVe: " << ( checkFEUnitAPVAddresses() ? "passed" : "FAILED" ) << std::endl;
00360 if (!checkFEUnitAPVAddresses()) {
00361 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00362 if (fdHeader) {
00363 const uint8_t goldenAddress = apveAddress();
00364 summary << "Address from APVe:" << uint16_t(goldenAddress) << std::endl;
00365 summary << "Bad FE units:" << std::endl;
00366 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00367 if (!feGood(iFE)) continue;
00368 if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) {
00369 summary << "FE unit: " << uint16_t(iFE)
00370 << " majority address: " << uint16_t(fdHeader->feUnitMajorityAddress(iFE)) << std::endl;
00371 }
00372 }
00373 }
00374 }
00375 return summary.str();
00376 }
00377
00378 uint8_t FEDBuffer::getCorrectPacketCode() const
00379 {
00380 switch(readoutMode()) {
00381 case READOUT_MODE_SCOPE:
00382 return PACKET_CODE_SCOPE;
00383 break;
00384 case READOUT_MODE_VIRGIN_RAW:
00385 return PACKET_CODE_VIRGIN_RAW;
00386 break;
00387 case READOUT_MODE_PROC_RAW:
00388 return PACKET_CODE_PROC_RAW;
00389 break;
00390 case READOUT_MODE_ZERO_SUPPRESSED:
00391 return PACKET_CODE_ZERO_SUPPRESSED;
00392 break;
00393 case READOUT_MODE_ZERO_SUPPRESSED_LITE:
00394 case READOUT_MODE_SPY:
00395 case READOUT_MODE_INVALID:
00396 default:
00397 return 0;
00398 }
00399 }
00400
00401 uint8_t FEDBuffer::nFEUnitsPresent() const
00402 {
00403 uint8_t result = 0;
00404 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00405 if (fePresent(iFE)) result++;
00406 }
00407 return result;
00408 }
00409
00410 void FEDBuffer::print(std::ostream& os) const
00411 {
00412 FEDBufferBase::print(os);
00413 if (headerType() == HEADER_TYPE_FULL_DEBUG) {
00414 os << "FE units with data: " << uint16_t(nFEUnitsPresent()) << std::endl;
00415 os << "BE status register flags: ";
00416 dynamic_cast<const FEDFullDebugHeader*>(feHeader())->beStatusRegister().printFlags(os);
00417 os << std::endl;
00418 }
00419 }
00420
00421
00422
00423
00424 void FEDRawChannelUnpacker::throwBadChannelLength(const uint16_t length)
00425 {
00426 std::ostringstream ss;
00427 ss << "Channel length is invalid. Raw channels have 3 header bytes and 2 bytes per sample. "
00428 << "Channel length is " << uint16_t(length) << "."
00429 << std::endl;
00430 throw cms::Exception("FEDBuffer") << ss.str();
00431 }
00432
00433
00434
00435
00436 void FEDZSChannelUnpacker::throwBadChannelLength(const uint16_t length)
00437 {
00438 std::ostringstream ss;
00439 ss << "Channel length is longer than max allowed value. "
00440 << "Channel length is " << uint16_t(length) << "."
00441 << std::endl;
00442 throw cms::Exception("FEDBuffer") << ss.str();
00443 }
00444
00445 void FEDZSChannelUnpacker::throwBadClusterLength()
00446 {
00447 std::ostringstream ss;
00448 ss << "Cluster does not fit into channel. "
00449 << "Cluster length is " << uint16_t(valuesLeftInCluster_) << "."
00450 << std::endl;
00451 throw cms::Exception("FEDBuffer") << ss.str();
00452 }
00453
00454 void FEDZSChannelUnpacker::throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster)
00455 {
00456 std::ostringstream ss;
00457 ss << "First strip of new cluster is not greater than last strip of previous cluster. "
00458 << "Last strip of previous cluster is " << uint16_t(currentStrip) << ". "
00459 << "First strip of new cluster is " << uint16_t(firstStripOfNewCluster) << "."
00460 << std::endl;
00461 throw cms::Exception("FEDBuffer") << ss.str();
00462 }
00463
00464 }