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
00143 {
00144 return ( (internalFEDChannelNum < validChannels_) &&
00145 feGood(internalFEDChannelNum/FEDCH_PER_FEUNIT) &&
00146 (this->readoutMode() == sistrip::READOUT_MODE_SCOPE || checkStatusBits(internalFEDChannelNum)) );
00147 }
00148
00149 bool FEDBuffer::doChecks() const
00150 {
00151
00152 if (validChannels_ != FEDCH_PER_FED) return false;
00153
00154 if (!FEDBufferBase::doChecks()) return false;
00155
00156 if (!checkCRC()) return false;
00157 return true;
00158 }
00159
00160 bool FEDBuffer::doCorruptBufferChecks() const
00161 {
00162 return ( checkCRC() &&
00163 checkChannelLengthsMatchBufferLength() &&
00164 checkChannelPacketCodes() &&
00165
00166 checkFEUnitLengths() );
00167
00168 }
00169
00170 bool FEDBuffer::checkAllChannelStatusBits() const
00171 {
00172 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00173
00174 if (!feGood(iCh/FEDCH_PER_FEUNIT)) {
00175 iCh += FEDCH_PER_FEUNIT;
00176 continue;
00177 }
00178
00179 if (!checkStatusBits(iCh)) return false;
00180 }
00181
00182 return true;
00183 }
00184
00185 bool FEDBuffer::checkChannelLengths() const
00186 {
00187 return (validChannels_ == FEDCH_PER_FED);
00188 }
00189
00190 bool FEDBuffer::checkChannelLengthsMatchBufferLength() const
00191 {
00192
00193 if (!checkChannelLengths()) return false;
00194
00195
00196 const size_t payloadLengthInWords = payloadLength_/8;
00197
00198
00199
00200 uint8_t lastEnabledFeUnit = 7;
00201 while ( !(fePresent(lastEnabledFeUnit) && feEnabled(lastEnabledFeUnit)) && lastEnabledFeUnit!=0 ) lastEnabledFeUnit--;
00202
00203 const FEDChannel& lastChannel = channels_[internalFEDChannelNum(lastEnabledFeUnit,FEDCH_PER_FEUNIT-1)];
00204 const size_t offsetLastChannel = lastChannel.offset();
00205 const size_t offsetEndOfChannelData = offsetLastChannel+lastChannel.length();
00206 const size_t channelDataLength = offsetEndOfChannelData;
00207
00208 size_t channelDataLengthInWords = channelDataLength/8;
00209 if (channelDataLength % 8) channelDataLengthInWords++;
00210
00211
00212 if (channelDataLengthInWords == payloadLengthInWords) {
00213 return true;
00214 } else {
00215 return false;
00216 }
00217 }
00218
00219 bool FEDBuffer::checkChannelPacketCodes() const
00220 {
00221 const uint8_t correctPacketCode = getCorrectPacketCode();
00222
00223 if (!correctPacketCode) return true;
00224 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00225
00226 if (!feGood(iCh/FEDCH_PER_FEUNIT)) {
00227 iCh += FEDCH_PER_FEUNIT;
00228 continue;
00229 }
00230
00231 if (channelGood(iCh)) {
00232
00233 if (channels_[iCh].packetCode() != correctPacketCode) return false;
00234 }
00235 }
00236
00237 return true;
00238 }
00239
00240 bool FEDBuffer::checkFEUnitAPVAddresses() const
00241 {
00242
00243 const uint8_t goldenAddress = apveAddress();
00244
00245 if (goldenAddress == 0x00) return true;
00246
00247 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00248 if (!fdHeader) return true;
00249
00250 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00251 if (!feGood(iFE)) continue;
00252
00253 if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) return false;
00254 }
00255
00256 return true;
00257 }
00258
00259 bool FEDBuffer::checkFEUnitLengths() const
00260 {
00261
00262 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00263 if (!fdHeader) return true;
00264
00265 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00266 if (!feGood(iFE)) continue;
00267 if (calculateFEUnitLength(iFE) != fdHeader->feUnitLength(iFE)) return false;
00268 }
00269
00270 return true;
00271 }
00272
00273 uint16_t FEDBuffer::calculateFEUnitLength(const uint8_t internalFEUnitNumber) const
00274 {
00275
00276 uint16_t lengthFromChannels = 0;
00277 for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
00278 lengthFromChannels += channels_[internalFEDChannelNum(internalFEUnitNumber,iCh)].length();
00279 }
00280 return lengthFromChannels;
00281 }
00282
00283 bool FEDBuffer::checkFEPayloadsPresent() const
00284 {
00285 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00286 if (!fePresent(iFE)) return false;
00287 }
00288 return true;
00289 }
00290
00291 std::string FEDBuffer::checkSummary() const
00292 {
00293 std::ostringstream summary;
00294 summary << FEDBufferBase::checkSummary();
00295 summary << "Check FE unit payloads are all present: " << (checkFEPayloadsPresent() ? "passed" : "FAILED" ) << std::endl;
00296 if (!checkFEPayloadsPresent()) {
00297 summary << "FE units missing payloads: ";
00298 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00299 if (!fePresent(iFE)) summary << uint16_t(iFE) << " ";
00300 }
00301 summary << std::endl;
00302 }
00303 summary << "Check channel status bits: " << ( checkAllChannelStatusBits() ? "passed" : "FAILED" ) << std::endl;
00304 if (!checkAllChannelStatusBits()) {
00305 unsigned int badChannels = 0;
00306 if (headerType() == HEADER_TYPE_FULL_DEBUG) {
00307 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00308 if (fdHeader) {
00309 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00310 if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
00311 if (!checkStatusBits(iCh)) {
00312 summary << uint16_t(iCh) << ": " << fdHeader->getChannelStatus(iCh) << std::endl;
00313 badChannels++;
00314 }
00315 }
00316 }
00317 } else {
00318 summary << "Channels with errors: ";
00319 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00320 if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
00321 if (!checkStatusBits(iCh)) {
00322 summary << uint16_t(iCh) << " ";
00323 badChannels++;
00324 }
00325 }
00326 summary << std::endl;
00327 }
00328 summary << "Number of channels with bad status bits: " << badChannels << std::endl;
00329 }
00330 summary << "Check channel lengths match buffer length: " << ( checkChannelLengthsMatchBufferLength() ? "passed" : "FAILED" ) << std::endl;
00331 summary << "Check channel packet codes: " << ( checkChannelPacketCodes() ? "passed" : "FAILED" ) << std::endl;
00332 if (!checkChannelPacketCodes()) {
00333 summary << "Channels with bad packet codes: ";
00334 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00335 if (!feGood(iCh/FEDCH_PER_FEUNIT)) continue;
00336 if (channels_[iCh].packetCode() != getCorrectPacketCode())
00337 summary << uint16_t(iCh) << " ";
00338 }
00339 }
00340 summary << "Check FE unit lengths: " << ( checkFEUnitLengths() ? "passed" : "FAILED" ) << std::endl;
00341 if (!checkFEUnitLengths()) {
00342 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00343 if (fdHeader) {
00344 summary << "Bad FE units:" << std::endl;
00345 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00346 if (!feGood(iFE)) continue;
00347 uint16_t lengthFromChannels = calculateFEUnitLength(iFE);
00348 uint16_t lengthFromHeader = fdHeader->feUnitLength(iFE);
00349 if (lengthFromHeader != lengthFromChannels) {
00350 summary << "FE unit: " << uint16_t(iFE)
00351 << " length in header: " << lengthFromHeader
00352 << " length from channel lengths: " << lengthFromChannels << std::endl;
00353 }
00354 }
00355 }
00356 }
00357 summary << "Check FE unit APV addresses match APVe: " << ( checkFEUnitAPVAddresses() ? "passed" : "FAILED" ) << std::endl;
00358 if (!checkFEUnitAPVAddresses()) {
00359 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
00360 if (fdHeader) {
00361 const uint8_t goldenAddress = apveAddress();
00362 summary << "Address from APVe:" << uint16_t(goldenAddress) << std::endl;
00363 summary << "Bad FE units:" << std::endl;
00364 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00365 if (!feGood(iFE)) continue;
00366 if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) {
00367 summary << "FE unit: " << uint16_t(iFE)
00368 << " majority address: " << uint16_t(fdHeader->feUnitMajorityAddress(iFE)) << std::endl;
00369 }
00370 }
00371 }
00372 }
00373 return summary.str();
00374 }
00375
00376 uint8_t FEDBuffer::getCorrectPacketCode() const
00377 {
00378 switch(readoutMode()) {
00379 case READOUT_MODE_SCOPE:
00380 return PACKET_CODE_SCOPE;
00381 break;
00382 case READOUT_MODE_VIRGIN_RAW:
00383 return PACKET_CODE_VIRGIN_RAW;
00384 break;
00385 case READOUT_MODE_PROC_RAW:
00386 return PACKET_CODE_PROC_RAW;
00387 break;
00388 case READOUT_MODE_ZERO_SUPPRESSED:
00389 return PACKET_CODE_ZERO_SUPPRESSED;
00390 break;
00391 case READOUT_MODE_ZERO_SUPPRESSED_LITE:
00392 case READOUT_MODE_SPY:
00393 case READOUT_MODE_INVALID:
00394 default:
00395 return 0;
00396 }
00397 }
00398
00399 uint8_t FEDBuffer::nFEUnitsPresent() const
00400 {
00401 uint8_t result = 0;
00402 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00403 if (fePresent(iFE)) result++;
00404 }
00405 return result;
00406 }
00407
00408 void FEDBuffer::print(std::ostream& os) const
00409 {
00410 FEDBufferBase::print(os);
00411 if (headerType() == HEADER_TYPE_FULL_DEBUG) {
00412 os << "FE units with data: " << uint16_t(nFEUnitsPresent()) << std::endl;
00413 os << "BE status register flags: ";
00414 dynamic_cast<const FEDFullDebugHeader*>(feHeader())->beStatusRegister().printFlags(os);
00415 os << std::endl;
00416 }
00417 }
00418
00419
00420
00421
00422 void FEDRawChannelUnpacker::throwBadChannelLength(const uint16_t length)
00423 {
00424 std::ostringstream ss;
00425 ss << "Channel length is invalid. Raw channels have 3 header bytes and 2 bytes per sample. "
00426 << "Channel length is " << uint16_t(length) << "."
00427 << std::endl;
00428 throw cms::Exception("FEDBuffer") << ss.str();
00429 }
00430
00431
00432
00433
00434 void FEDZSChannelUnpacker::throwBadChannelLength(const uint16_t length)
00435 {
00436 std::ostringstream ss;
00437 ss << "Channel length is longer than max allowed value. "
00438 << "Channel length is " << uint16_t(length) << "."
00439 << std::endl;
00440 throw cms::Exception("FEDBuffer") << ss.str();
00441 }
00442
00443 void FEDZSChannelUnpacker::throwBadClusterLength()
00444 {
00445 std::ostringstream ss;
00446 ss << "Cluster does not fit into channel. "
00447 << "Cluster length is " << uint16_t(valuesLeftInCluster_) << "."
00448 << std::endl;
00449 throw cms::Exception("FEDBuffer") << ss.str();
00450 }
00451
00452 void FEDZSChannelUnpacker::throwUnorderedData(const uint8_t currentStrip, const uint8_t firstStripOfNewCluster)
00453 {
00454 std::ostringstream ss;
00455 ss << "First strip of new cluster is not greater than last strip of previous cluster. "
00456 << "Last strip of previous cluster is " << uint16_t(currentStrip) << ". "
00457 << "First strip of new cluster is " << uint16_t(firstStripOfNewCluster) << "."
00458 << std::endl;
00459 throw cms::Exception("FEDBuffer") << ss.str();
00460 }
00461
00462 }