File indexing completed on 2024-04-06 12:11:03
0001 #include <iomanip>
0002 #include <ostream>
0003 #include <cstring>
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005
0006 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBuffer.h"
0007
0008 #include "DataFormats/SiStripCommon/interface/SiStripFedKey.h"
0009 #include "FWCore/Utilities/interface/Likely.h"
0010
0011 namespace sistrip {
0012
0013 FEDBuffer::FEDBuffer(const FEDRawData& fedBuffer, const bool allowBadBuffer) : FEDBufferBase(fedBuffer, false) {
0014 validChannels_ = 0;
0015 channels_.reserve(FEDCH_PER_FED);
0016
0017 if ((headerType() != HEADER_TYPE_INVALID) && (headerType() != HEADER_TYPE_NONE)) {
0018 feHeader_ = FEDFEHeader::newFEHeader(headerType(), getPointerToDataAfterTrackerSpecialHeader());
0019 payloadPointer_ = getPointerToDataAfterTrackerSpecialHeader() + feHeader_->lengthInBytes();
0020 } else {
0021 feHeader_ = std::unique_ptr<FEDFEHeader>();
0022 payloadPointer_ = getPointerToDataAfterTrackerSpecialHeader();
0023 }
0024 payloadLength_ = getPointerToByteAfterEndOfPayload() - payloadPointer_;
0025
0026
0027 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
0028 if (fdHeader) {
0029 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0030 if (fdHeader->fePresent(iFE))
0031 fePresent_[iFE] = true;
0032 else
0033 fePresent_[iFE] = false;
0034 }
0035 }
0036
0037
0038 else {
0039 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0040 if (fedStatusRegister().feDataMissingFlag(iFE))
0041 fePresent_[iFE] = false;
0042 else
0043 fePresent_[iFE] = true;
0044 }
0045 }
0046 }
0047
0048 FEDBufferStatusCode FEDBuffer::findChannels() {
0049 auto st = FEDBufferStatusCode::SUCCESS;
0050
0051 uint16_t minLength;
0052 switch (readoutMode()) {
0053 case READOUT_MODE_ZERO_SUPPRESSED:
0054 case READOUT_MODE_ZERO_SUPPRESSED_FAKE:
0055 minLength = 7;
0056 break;
0057 case READOUT_MODE_PREMIX_RAW:
0058 minLength = 2;
0059 break;
0060 case READOUT_MODE_ZERO_SUPPRESSED_LITE10:
0061 case READOUT_MODE_ZERO_SUPPRESSED_LITE10_CMOVERRIDE:
0062 case READOUT_MODE_ZERO_SUPPRESSED_LITE8:
0063 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_CMOVERRIDE:
0064 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT:
0065 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT_CMOVERRIDE:
0066 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT:
0067 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT_CMOVERRIDE:
0068 minLength = 2;
0069 break;
0070 default:
0071 minLength = 3;
0072 break;
0073 }
0074 uint16_t offsetBeginningOfChannel = 0;
0075 for (uint16_t i = 0; i < FEDCH_PER_FED; i++) {
0076
0077 if UNLIKELY (!(fePresent(i / FEDCH_PER_FEUNIT) && feEnabled(i / FEDCH_PER_FEUNIT))) {
0078 channels_.insert(channels_.end(), uint16_t(FEDCH_PER_FEUNIT), FEDChannel(payloadPointer_, 0, 0));
0079 i += FEDCH_PER_FEUNIT - 1;
0080 validChannels_ += FEDCH_PER_FEUNIT;
0081 continue;
0082 }
0083
0084
0085 if UNLIKELY (offsetBeginningOfChannel + 1 >= payloadLength_) {
0086 const SiStripFedKey key(0, i / FEDCH_PER_FEUNIT, i % FEDCH_PER_FEUNIT);
0087 LogDebug("FEDBuffer") << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel "
0088 << key.feChan() << " according to external numbering scheme) "
0089 << "does not fit into buffer. "
0090 << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
0091 << "Payload length is " << uint16_t(payloadLength_) << ". ";
0092 st = FEDBufferStatusCode::CHANNEL_BEGIN_BEYOND_PAYLOAD;
0093 break;
0094 }
0095
0096 channels_.emplace_back(payloadPointer_, offsetBeginningOfChannel);
0097
0098 uint16_t channelLength = channels_.back().length();
0099
0100
0101 if UNLIKELY (channelLength < minLength) {
0102 const SiStripFedKey key(0, i / FEDCH_PER_FEUNIT, i % FEDCH_PER_FEUNIT);
0103 LogDebug("FEDBuffer") << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel "
0104 << key.feChan() << " according to external numbering scheme)"
0105 << " is too short. "
0106 << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
0107 << "Channel length is " << uint16_t(channelLength) << ". "
0108 << "Min length is " << uint16_t(minLength) << ". ";
0109 st = FEDBufferStatusCode::CHANNEL_TOO_SHORT;
0110 break;
0111 }
0112 if UNLIKELY (offsetBeginningOfChannel + channelLength > payloadLength_) {
0113 const SiStripFedKey key(0, i / FEDCH_PER_FEUNIT, i % FEDCH_PER_FEUNIT);
0114 LogDebug("FEDBuffer") << "Channel " << uint16_t(i) << " (FE unit " << key.feUnit() << " channel "
0115 << key.feChan() << " according to external numbering scheme)"
0116 << "does not fit into buffer. "
0117 << "Channel starts at " << uint16_t(offsetBeginningOfChannel) << " in payload. "
0118 << "Channel length is " << uint16_t(channelLength) << ". "
0119 << "Payload length is " << uint16_t(payloadLength_) << ". ";
0120 st = FEDBufferStatusCode::CHANNEL_END_BEYOND_PAYLOAD;
0121 break;
0122 }
0123
0124 validChannels_++;
0125 const uint16_t offsetEndOfChannel = offsetBeginningOfChannel + channelLength;
0126
0127 if (!((i + 1) % FEDCH_PER_FEUNIT)) {
0128 uint8_t numPaddingBytes = 8 - (offsetEndOfChannel % 8);
0129 if (numPaddingBytes == 8)
0130 numPaddingBytes = 0;
0131 offsetBeginningOfChannel = offsetEndOfChannel + numPaddingBytes;
0132 } else {
0133 offsetBeginningOfChannel = offsetEndOfChannel;
0134 }
0135 }
0136 if UNLIKELY (FEDBufferStatusCode::SUCCESS != st) {
0137 channels_.insert(channels_.end(), uint16_t(FEDCH_PER_FED - validChannels_), FEDChannel(payloadPointer_, 0, 0));
0138 }
0139 return st;
0140 }
0141
0142 bool FEDBuffer::doCorruptBufferChecks() const {
0143 return (checkCRC() && checkChannelLengthsMatchBufferLength() && checkChannelPacketCodes() &&
0144
0145 checkFEUnitLengths());
0146
0147 }
0148
0149 bool FEDBuffer::checkAllChannelStatusBits() const {
0150 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0151
0152 if (!feGood(iCh / FEDCH_PER_FEUNIT)) {
0153 iCh += FEDCH_PER_FEUNIT;
0154 continue;
0155 }
0156
0157 if (!checkStatusBits(iCh))
0158 return false;
0159 }
0160
0161 return true;
0162 }
0163
0164 bool FEDBuffer::checkChannelLengths() const { return (validChannels_ == FEDCH_PER_FED); }
0165
0166 bool FEDBuffer::checkChannelLengthsMatchBufferLength() const {
0167
0168 if (!checkChannelLengths())
0169 return false;
0170
0171
0172 const uint16_t payloadLengthInWords = payloadLength_ / 8;
0173
0174
0175
0176 uint8_t lastEnabledFeUnit = 7;
0177 while (!(fePresent(lastEnabledFeUnit) && feEnabled(lastEnabledFeUnit)) && lastEnabledFeUnit != 0)
0178 lastEnabledFeUnit--;
0179
0180 const FEDChannel& lastChannel = channels_[internalFEDChannelNum(lastEnabledFeUnit, FEDCH_PER_FEUNIT - 1)];
0181 const uint16_t offsetLastChannel = lastChannel.offset();
0182 const uint16_t offsetEndOfChannelData = offsetLastChannel + lastChannel.length();
0183 const uint16_t channelDataLength = offsetEndOfChannelData;
0184
0185 uint16_t channelDataLengthInWords = channelDataLength / 8;
0186 if (channelDataLength % 8)
0187 channelDataLengthInWords++;
0188
0189
0190 if (channelDataLengthInWords == payloadLengthInWords) {
0191 return true;
0192 } else {
0193 return false;
0194 }
0195 }
0196
0197 bool FEDBuffer::checkChannelPacketCodes() const {
0198 const uint8_t correctPacketCode = getCorrectPacketCode();
0199
0200 if (!correctPacketCode)
0201 return true;
0202 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0203
0204 if (!feGood(iCh / FEDCH_PER_FEUNIT)) {
0205 iCh += FEDCH_PER_FEUNIT;
0206 continue;
0207 }
0208
0209 if (FEDBuffer::channelGood(iCh, true)) {
0210
0211 if (channels_[iCh].packetCode() != correctPacketCode)
0212 return false;
0213 }
0214 }
0215
0216 return true;
0217 }
0218
0219 bool FEDBuffer::checkFEUnitAPVAddresses() const {
0220
0221 const uint8_t goldenAddress = apveAddress();
0222
0223 if (goldenAddress == 0x00)
0224 return true;
0225
0226 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
0227 if (!fdHeader)
0228 return true;
0229
0230 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0231 if (!feGood(iFE))
0232 continue;
0233
0234 if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress)
0235 return false;
0236 }
0237
0238 return true;
0239 }
0240
0241 bool FEDBuffer::checkFEUnitLengths() const {
0242
0243 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
0244 if (!fdHeader)
0245 return true;
0246
0247 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0248 if (!feGood(iFE))
0249 continue;
0250 if (calculateFEUnitLength(iFE) != fdHeader->feUnitLength(iFE))
0251 return false;
0252 }
0253
0254 return true;
0255 }
0256
0257 uint16_t FEDBuffer::calculateFEUnitLength(const uint8_t internalFEUnitNumber) const {
0258
0259 uint16_t lengthFromChannels = 0;
0260 for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
0261 lengthFromChannels += channels_[internalFEDChannelNum(internalFEUnitNumber, iCh)].length();
0262 }
0263 return lengthFromChannels;
0264 }
0265
0266 bool FEDBuffer::checkFEPayloadsPresent() const {
0267 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0268 if (!fePresent(iFE))
0269 return false;
0270 }
0271 return true;
0272 }
0273
0274 std::string FEDBuffer::checkSummary() const {
0275 std::ostringstream summary;
0276 summary << FEDBufferBase::checkSummary();
0277 summary << "Check FE unit payloads are all present: " << (checkFEPayloadsPresent() ? "passed" : "FAILED")
0278 << std::endl;
0279 if (!checkFEPayloadsPresent()) {
0280 summary << "FE units missing payloads: ";
0281 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0282 if (!fePresent(iFE))
0283 summary << uint16_t(iFE) << " ";
0284 }
0285 summary << std::endl;
0286 }
0287 summary << "Check channel status bits: " << (checkAllChannelStatusBits() ? "passed" : "FAILED") << std::endl;
0288 if (!checkAllChannelStatusBits()) {
0289 unsigned int badChannels = 0;
0290 if (headerType() == HEADER_TYPE_FULL_DEBUG) {
0291 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
0292 if (fdHeader) {
0293 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0294 if (!feGood(iCh / FEDCH_PER_FEUNIT))
0295 continue;
0296 if (!checkStatusBits(iCh)) {
0297 summary << uint16_t(iCh) << ": " << fdHeader->getChannelStatus(iCh) << std::endl;
0298 badChannels++;
0299 }
0300 }
0301 }
0302 } else {
0303 summary << "Channels with errors: ";
0304 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0305 if (!feGood(iCh / FEDCH_PER_FEUNIT))
0306 continue;
0307 if (!checkStatusBits(iCh)) {
0308 summary << uint16_t(iCh) << " ";
0309 badChannels++;
0310 }
0311 }
0312 summary << std::endl;
0313 }
0314 summary << "Number of channels with bad status bits: " << badChannels << std::endl;
0315 }
0316 summary << "Check channel lengths match buffer length: "
0317 << (checkChannelLengthsMatchBufferLength() ? "passed" : "FAILED") << std::endl;
0318 summary << "Check channel packet codes: " << (checkChannelPacketCodes() ? "passed" : "FAILED") << std::endl;
0319 if (!checkChannelPacketCodes()) {
0320 summary << "Channels with bad packet codes: ";
0321 for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0322 if (!feGood(iCh / FEDCH_PER_FEUNIT))
0323 continue;
0324 if (channels_[iCh].packetCode() != getCorrectPacketCode())
0325 summary << uint16_t(iCh) << " ";
0326 }
0327 }
0328 summary << "Check FE unit lengths: " << (checkFEUnitLengths() ? "passed" : "FAILED") << std::endl;
0329 if (!checkFEUnitLengths()) {
0330 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
0331 if (fdHeader) {
0332 summary << "Bad FE units:" << std::endl;
0333 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0334 if (!feGood(iFE))
0335 continue;
0336 uint16_t lengthFromChannels = calculateFEUnitLength(iFE);
0337 uint16_t lengthFromHeader = fdHeader->feUnitLength(iFE);
0338 if (lengthFromHeader != lengthFromChannels) {
0339 summary << "FE unit: " << uint16_t(iFE) << " length in header: " << lengthFromHeader
0340 << " length from channel lengths: " << lengthFromChannels << std::endl;
0341 }
0342 }
0343 }
0344 }
0345 summary << "Check FE unit APV addresses match APVe: " << (checkFEUnitAPVAddresses() ? "passed" : "FAILED")
0346 << std::endl;
0347 if (!checkFEUnitAPVAddresses()) {
0348 const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
0349 if (fdHeader) {
0350 const uint8_t goldenAddress = apveAddress();
0351 summary << "Address from APVe:" << uint16_t(goldenAddress) << std::endl;
0352 summary << "Bad FE units:" << std::endl;
0353 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0354 if (!feGood(iFE))
0355 continue;
0356 if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress) {
0357 summary << "FE unit: " << uint16_t(iFE)
0358 << " majority address: " << uint16_t(fdHeader->feUnitMajorityAddress(iFE)) << std::endl;
0359 }
0360 }
0361 }
0362 }
0363 return summary.str();
0364 }
0365
0366 uint8_t FEDBuffer::nFEUnitsPresent() const {
0367 uint8_t result = 0;
0368 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0369 if (fePresent(iFE))
0370 result++;
0371 }
0372 return result;
0373 }
0374
0375 void FEDBuffer::print(std::ostream& os) const {
0376 FEDBufferBase::print(os);
0377 if (headerType() == HEADER_TYPE_FULL_DEBUG) {
0378 os << "FE units with data: " << uint16_t(nFEUnitsPresent()) << std::endl;
0379 os << "BE status register flags: ";
0380 dynamic_cast<const FEDFullDebugHeader*>(feHeader())->beStatusRegister().printFlags(os);
0381 os << std::endl;
0382 }
0383 }
0384
0385 std::string toString(fedchannelunpacker::StatusCode status) {
0386 using namespace sistrip::fedchannelunpacker;
0387 switch (status) {
0388 case StatusCode::SUCCESS:
0389 return "SUCCESS";
0390 case StatusCode::BAD_CHANNEL_LENGTH:
0391 return "Channel length is invalid.";
0392 case StatusCode::UNORDERED_DATA:
0393 return "First strip of new cluster is not greater than last strip of previous cluster.";
0394 case StatusCode::BAD_PACKET_CODE:
0395 return "Invalid packet code.";
0396 case StatusCode::ZERO_PACKET_CODE:
0397 return "Invalid packet code 0 for zero-suppressed data.";
0398 }
0399 return "";
0400 }
0401 }