Back to home page

Project CMSSW displayed by LXR

 
 

    


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     //build the correct type of FE header object
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     //check if FE units are present in data
0026     //in Full Debug mode, use the lengths from the header
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     //in APV error mode, use the FE present byte in the FED status register
0037     // a value of '1' means a FE unit's data is missing (in old firmware versions it is always 0)
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     //set min length to 2 for ZSLite, 7 for ZS and 3 for raw
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       //if FE unit is not enabled then skip rest of FE unit adding NULL pointers
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       //if FE unit is enabled
0084       //check that channel length bytes fit into buffer
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       //get length and check that whole channel fits into buffer
0098       uint16_t channelLength = channels_.back().length();
0099 
0100       //check that the channel length is long enough to contain the header
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       //add padding if necessary and calculate offset for begining of next channel
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) {  // for the allowBadBuffer case
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             //checkClusterLengths() &&
0145             checkFEUnitLengths());
0146     //checkFEUnitAPVAddresses() );
0147   }
0148 
0149   bool FEDBuffer::checkAllChannelStatusBits() const {
0150     for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0151       //if FE unit is disabled then skip all channels on it
0152       if (!feGood(iCh / FEDCH_PER_FEUNIT)) {
0153         iCh += FEDCH_PER_FEUNIT;
0154         continue;
0155       }
0156       //channel is bad then return false
0157       if (!checkStatusBits(iCh))
0158         return false;
0159     }
0160     //if no bad channels have been found then they are all fine
0161     return true;
0162   }
0163 
0164   bool FEDBuffer::checkChannelLengths() const { return (validChannels_ == FEDCH_PER_FED); }
0165 
0166   bool FEDBuffer::checkChannelLengthsMatchBufferLength() const {
0167     //check they fit into buffer
0168     if (!checkChannelLengths())
0169       return false;
0170 
0171     //payload length from length of data buffer
0172     const uint16_t payloadLengthInWords = payloadLength_ / 8;
0173 
0174     //find channel length
0175     //find last enabled FE unit
0176     uint8_t lastEnabledFeUnit = 7;
0177     while (!(fePresent(lastEnabledFeUnit) && feEnabled(lastEnabledFeUnit)) && lastEnabledFeUnit != 0)
0178       lastEnabledFeUnit--;
0179     //last channel is last channel on last enabled FE unit
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     //channel length in words is length in bytes rounded up to nearest word
0185     uint16_t channelDataLengthInWords = channelDataLength / 8;
0186     if (channelDataLength % 8)
0187       channelDataLengthInWords++;
0188 
0189     //check lengths match
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     //if the readout mode if not one which has a packet code then this is set to zero. in this case return true
0200     if (!correctPacketCode)
0201       return true;
0202     for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
0203       //if FE unit is disabled then skip all channels on it
0204       if (!feGood(iCh / FEDCH_PER_FEUNIT)) {
0205         iCh += FEDCH_PER_FEUNIT;
0206         continue;
0207       }
0208       //only check enabled, working channels
0209       if (FEDBuffer::channelGood(iCh, true)) {
0210         //if a channel is bad then return false
0211         if (channels_[iCh].packetCode() != correctPacketCode)
0212           return false;
0213       }
0214     }
0215     //if no bad channels were found the they are all ok
0216     return true;
0217   }
0218 
0219   bool FEDBuffer::checkFEUnitAPVAddresses() const {
0220     //get golden address
0221     const uint8_t goldenAddress = apveAddress();
0222     //don't check if the address is 00 since APVe is probably not connected
0223     if (goldenAddress == 0x00)
0224       return true;
0225     //check can only be done for full debug headers
0226     const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
0227     if (!fdHeader)
0228       return true;
0229     //check all enabled FE units
0230     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
0231       if (!feGood(iFE))
0232         continue;
0233       //if address is bad then return false
0234       if (fdHeader->feUnitMajorityAddress(iFE) != goldenAddress)
0235         return false;
0236     }
0237     //if no bad addresses were found then return true
0238     return true;
0239   }
0240 
0241   bool FEDBuffer::checkFEUnitLengths() const {
0242     //check can only be done for full debug headers
0243     const FEDFullDebugHeader* fdHeader = dynamic_cast<FEDFullDebugHeader*>(feHeader_.get());
0244     if (!fdHeader)
0245       return true;
0246     //check lengths for enabled FE units
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     //if no errors were encountered then return true
0254     return true;
0255   }
0256 
0257   uint16_t FEDBuffer::calculateFEUnitLength(const uint8_t internalFEUnitNumber) const {
0258     //get length from channels
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 }  // namespace sistrip