File indexing completed on 2024-04-06 12:11:01
0001 #ifndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
0002 #define EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
0003
0004 #include <string>
0005 #include <vector>
0006 #include <memory>
0007 #include <ostream>
0008 #include <cstring>
0009 #include <cmath>
0010 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferComponents.h"
0011 #include "DataFormats/SiStripDigi/interface/SiStripRawDigi.h"
0012 #include "DataFormats/SiStripDigi/interface/SiStripDigi.h"
0013
0014 #include <cstdint>
0015
0016 namespace sistrip {
0017 constexpr uint16_t BITS_PER_BYTE = 8;
0018
0019
0020
0021
0022
0023
0024 class FEDBuffer final : public FEDBufferBase {
0025 public:
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 explicit FEDBuffer(const FEDRawData& fedBuffer, const bool allowBadBuffer = false);
0042 ~FEDBuffer() override {}
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 FEDBufferStatusCode findChannels();
0055
0056 void print(std::ostream& os) const override;
0057 const FEDFEHeader* feHeader() const;
0058
0059 bool feGood(const uint8_t internalFEUnitNum) const;
0060 bool feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const;
0061
0062
0063
0064 bool fePresent(uint8_t internalFEUnitNum) const;
0065
0066 using sistrip::FEDBufferBase::channelGood;
0067 bool channelGood(const uint8_t internalFEDannelNum, const bool doAPVeCheck) const;
0068 void setLegacyMode(bool legacy) { legacyUnpacker_ = legacy; }
0069
0070
0071
0072 using sistrip::FEDBufferBase::doChecks;
0073 bool doChecks(bool doCRC) const;
0074
0075
0076
0077 bool checkChannelLengths() const;
0078
0079 bool checkChannelLengthsMatchBufferLength() const;
0080
0081 bool checkChannelPacketCodes() const;
0082
0083 bool checkFEUnitLengths() const;
0084
0085 bool checkFEUnitAPVAddresses() const;
0086
0087 virtual bool doCorruptBufferChecks() const;
0088
0089
0090
0091 bool checkStatusBits(const uint8_t internalFEDChannelNum) const;
0092 bool checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const;
0093
0094 bool checkAllChannelStatusBits() const;
0095
0096
0097 bool checkFEPayloadsPresent() const;
0098
0099
0100 std::string checkSummary() const override;
0101
0102 private:
0103 uint8_t nFEUnitsPresent() const;
0104 inline uint8_t getCorrectPacketCode() const { return packetCode(legacyUnpacker_); }
0105 uint16_t calculateFEUnitLength(const uint8_t internalFEUnitNumber) const;
0106 std::unique_ptr<FEDFEHeader> feHeader_;
0107 const uint8_t* payloadPointer_;
0108 uint16_t payloadLength_;
0109 uint8_t validChannels_;
0110 bool fePresent_[FEUNITS_PER_FED];
0111 bool legacyUnpacker_ = false;
0112 };
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 inline FEDBufferStatusCode preconstructCheckFEDBuffer(const FEDRawData& fedBuffer, bool allowBadBuffer = false) {
0132 const auto st_base = preconstructCheckFEDBufferBase(fedBuffer, !allowBadBuffer);
0133 if (FEDBufferStatusCode::SUCCESS != st_base)
0134 return st_base;
0135 const TrackerSpecialHeader hdr{fedBuffer.data() + 8};
0136 const auto hdr_type = hdr.headerType();
0137 if ((!allowBadBuffer) && ((hdr_type == sistrip::HEADER_TYPE_INVALID) || (hdr_type == sistrip::HEADER_TYPE_NONE))) {
0138 #ifdef EDM_ML_DEBUG
0139 std::ostringstream msg;
0140 msg << "Header type is invalid. Header type nibble is ";
0141 const auto headerTypeNibble = hdr.headerTypeNibble();
0142 printHex(&headerTypeNibble, 1, msg);
0143 LogDebug("FEDBuffer") << msg.str();
0144 #endif
0145 return FEDBufferStatusCode::WRONG_HEADERTYPE;
0146 }
0147 if (READOUT_MODE_SPY == hdr.readoutMode())
0148 return FEDBufferStatusCode::EXPECT_NOT_SPY;
0149 return FEDBufferStatusCode::SUCCESS;
0150 }
0151
0152
0153
0154 inline const FEDFEHeader* FEDBuffer::feHeader() const { return feHeader_.get(); }
0155
0156 inline bool FEDBuffer::channelGood(const uint8_t internalFEDChannelNum, const bool doAPVeCheck) const {
0157 return ((internalFEDChannelNum < validChannels_) &&
0158 ((doAPVeCheck && feGood(internalFEDChannelNum / FEDCH_PER_FEUNIT)) ||
0159 (!doAPVeCheck && feGoodWithoutAPVEmulatorCheck(internalFEDChannelNum / FEDCH_PER_FEUNIT))) &&
0160 (this->readoutMode() == sistrip::READOUT_MODE_SCOPE || checkStatusBits(internalFEDChannelNum)));
0161 }
0162
0163 inline bool FEDBuffer::feGood(const uint8_t internalFEUnitNum) const {
0164 return (!majorityAddressErrorForFEUnit(internalFEUnitNum) && !feOverflow(internalFEUnitNum) &&
0165 fePresent(internalFEUnitNum));
0166 }
0167
0168 inline bool FEDBuffer::feGoodWithoutAPVEmulatorCheck(const uint8_t internalFEUnitNum) const {
0169 return (!feOverflow(internalFEUnitNum) && fePresent(internalFEUnitNum));
0170 }
0171
0172 inline bool FEDBuffer::fePresent(uint8_t internalFEUnitNum) const { return fePresent_[internalFEUnitNum]; }
0173
0174 inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEDChannelNum) const {
0175 return feHeader_->checkChannelStatusBits(internalFEDChannelNum);
0176 }
0177
0178 inline bool FEDBuffer::checkStatusBits(const uint8_t internalFEUnitNum, const uint8_t internalChannelNum) const {
0179 return checkStatusBits(internalFEDChannelNum(internalFEUnitNum, internalChannelNum));
0180 }
0181
0182 inline bool FEDBuffer::doChecks(bool doCRC) const {
0183
0184 return (validChannels_ == FEDCH_PER_FED) &&
0185
0186 (FEDBufferBase::doChecks()) &&
0187
0188 (!doCRC || checkCRC());
0189 }
0190
0191 namespace fedchannelunpacker {
0192 enum class StatusCode { SUCCESS = 0, BAD_CHANNEL_LENGTH, UNORDERED_DATA, BAD_PACKET_CODE, ZERO_PACKET_CODE };
0193
0194 namespace detail {
0195
0196 template <uint8_t num_words>
0197 uint16_t getADC_W(const uint8_t* data, uint_fast16_t offset, uint8_t bits_shift) {
0198
0199 return (data[offset ^ 7] + (num_words == 2 ? ((data[(offset + 1) ^ 7] & 0x03) << 8) : 0)) << bits_shift;
0200 }
0201
0202 template <uint16_t mask>
0203 uint16_t getADC_B2(const uint8_t* data, uint_fast16_t wOffset, uint_fast8_t bOffset) {
0204
0205 return (((data[wOffset ^ 7]) << bOffset) + (data[(wOffset + 1) ^ 7] >> (BITS_PER_BYTE - bOffset))) & mask;
0206 }
0207 template <uint16_t mask>
0208 uint16_t getADC_B1(const uint8_t* data, uint_fast16_t wOffset, uint_fast8_t bOffset) {
0209
0210 return (data[wOffset ^ 7] >> (BITS_PER_BYTE - bOffset)) & mask;
0211 }
0212
0213
0214 template <uint8_t num_bits, typename OUT>
0215 StatusCode unpackRawW(const FEDChannel& channel, OUT&& out, uint8_t bits_shift = 0) {
0216 constexpr auto num_words = num_bits / 8;
0217 static_assert(((num_bits % 8) == 0) && (num_words > 0) && (num_words < 3));
0218 if ((num_words > 1) && ((channel.length() - 3) % num_words)) {
0219 LogDebug("FEDBuffer") << "Channel length is invalid. Raw channels have 3 header bytes and " << num_words
0220 << " bytes per sample. "
0221 << "Channel length is " << uint16_t(channel.length()) << ".";
0222 return StatusCode::BAD_CHANNEL_LENGTH;
0223 }
0224 const uint8_t* const data = channel.data();
0225 const uint_fast16_t end = channel.offset() + channel.length();
0226 for (uint_fast16_t offset = channel.offset() + 3; offset != end; offset += num_words) {
0227 *out++ = SiStripRawDigi(getADC_W<num_words>(data, offset, bits_shift));
0228 }
0229 return StatusCode::SUCCESS;
0230 }
0231
0232
0233 template <uint_fast8_t num_bits, typename OUT>
0234 StatusCode unpackRawB(const FEDChannel& channel, OUT&& out) {
0235 static_assert(num_bits <= 16, "Word length must be between 0 and 16.");
0236 if (channel.length() & 0xF000) {
0237 LogDebug("FEDBuffer") << "Channel length is invalid. Channel length is " << uint16_t(channel.length()) << ".";
0238 return StatusCode::BAD_CHANNEL_LENGTH;
0239 }
0240 constexpr uint16_t mask = (1 << num_bits) - 1;
0241 const uint8_t* const data = channel.data();
0242 const uint_fast16_t chEnd = channel.offset() + channel.length();
0243 uint_fast16_t wOffset = channel.offset() + 3;
0244 uint_fast8_t bOffset = 0;
0245 while (((wOffset + 1) < chEnd) || ((chEnd - wOffset) * BITS_PER_BYTE - bOffset >= num_bits)) {
0246 bOffset += num_bits;
0247 if ((num_bits > BITS_PER_BYTE) || (bOffset > BITS_PER_BYTE)) {
0248 bOffset -= BITS_PER_BYTE;
0249 **out++ = SiStripRawDigi(getADC_B2<mask>(data, wOffset, bOffset));
0250 ++wOffset;
0251 } else {
0252 **out++ = SiStripRawDigi(getADC_B1<mask>(data, wOffset, bOffset));
0253 }
0254 if (bOffset == BITS_PER_BYTE) {
0255 bOffset = 0;
0256 ++wOffset;
0257 }
0258 }
0259 return StatusCode::SUCCESS;
0260 }
0261
0262 template <uint8_t num_bits, typename OUT>
0263 StatusCode unpackZSW(
0264 const FEDChannel& channel, OUT&& out, uint8_t headerLength, uint16_t stripStart, uint8_t bits_shift = 0) {
0265 constexpr auto num_words = num_bits / 8;
0266 static_assert(((num_bits % 8) == 0) && (num_words > 0) && (num_words < 3));
0267 if (channel.length() & 0xF000) {
0268 LogDebug("FEDBuffer") << "Channel length is invalid. Channel length is " << uint16_t(channel.length()) << ".";
0269 return StatusCode::BAD_CHANNEL_LENGTH;
0270 }
0271 const uint8_t* const data = channel.data();
0272 uint_fast16_t offset = channel.offset() + headerLength;
0273 uint_fast8_t firstStrip{0}, nInCluster{0}, inCluster{0};
0274 const uint_fast16_t end = channel.offset() + channel.length();
0275 while (offset != end) {
0276 if (inCluster == nInCluster) {
0277 if (offset + 2 >= end) {
0278
0279 break;
0280 }
0281 const uint_fast8_t newFirstStrip = data[(offset++) ^ 7];
0282 if (newFirstStrip < (firstStrip + inCluster)) {
0283 LogDebug("FEDBuffer") << "First strip of new cluster is not greater than last strip of previous cluster. "
0284 << "Last strip of previous cluster is " << uint16_t(firstStrip + inCluster) << ". "
0285 << "First strip of new cluster is " << uint16_t(newFirstStrip) << ".";
0286 return StatusCode::UNORDERED_DATA;
0287 }
0288 firstStrip = newFirstStrip;
0289 nInCluster = data[(offset++) ^ 7];
0290 inCluster = 0;
0291 }
0292 *out++ = SiStripDigi(stripStart + firstStrip + inCluster, getADC_W<num_words>(data, offset, bits_shift));
0293 offset += num_words;
0294 ++inCluster;
0295 }
0296 return StatusCode::SUCCESS;
0297 }
0298
0299
0300 template <uint_fast8_t num_bits, typename OUT>
0301 StatusCode unpackZSB(const FEDChannel& channel, OUT&& out, uint8_t headerLength, uint16_t stripStart) {
0302 constexpr uint16_t mask = (1 << num_bits) - 1;
0303 if (channel.length() & 0xF000) {
0304 LogDebug("FEDBuffer") << "Channel length is invalid. Channel length is " << uint16_t(channel.length()) << ".";
0305 return StatusCode::BAD_CHANNEL_LENGTH;
0306 }
0307 const uint8_t* const data = channel.data();
0308 uint_fast16_t wOffset = channel.offset() + headerLength;
0309 uint_fast8_t bOffset{0}, firstStrip{0}, nInCluster{0}, inCluster{0};
0310 const uint_fast16_t chEnd = channel.offset() + channel.length();
0311 while (((wOffset + 1) < chEnd) ||
0312 ((inCluster != nInCluster) && ((chEnd - wOffset) * BITS_PER_BYTE - bOffset >= num_bits))) {
0313 if (inCluster == nInCluster) {
0314 if (wOffset + 2 >= chEnd) {
0315
0316 break;
0317 }
0318 if (bOffset) {
0319 ++wOffset;
0320 bOffset = 0;
0321 }
0322 const uint_fast8_t newFirstStrip = data[(wOffset++) ^ 7];
0323 if (newFirstStrip < (firstStrip + inCluster)) {
0324 LogDebug("FEDBuffer") << "First strip of new cluster is not greater than last strip of previous cluster. "
0325 << "Last strip of previous cluster is " << uint16_t(firstStrip + inCluster) << ". "
0326 << "First strip of new cluster is " << uint16_t(newFirstStrip) << ".";
0327 return StatusCode::UNORDERED_DATA;
0328 }
0329 firstStrip = newFirstStrip;
0330 nInCluster = data[(wOffset++) ^ 7];
0331 inCluster = 0;
0332 bOffset = 0;
0333 }
0334 bOffset += num_bits;
0335 if ((num_bits > BITS_PER_BYTE) || (bOffset > BITS_PER_BYTE)) {
0336 bOffset -= BITS_PER_BYTE;
0337 *out++ = SiStripDigi(stripStart + firstStrip + inCluster, getADC_B2<mask>(data, wOffset, bOffset));
0338 ++wOffset;
0339 } else {
0340 *out++ = SiStripDigi(stripStart + firstStrip + inCluster, getADC_B1<mask>(data, wOffset, bOffset));
0341 }
0342 ++inCluster;
0343 if (bOffset == BITS_PER_BYTE) {
0344 bOffset = 0;
0345 ++wOffset;
0346 }
0347 }
0348 return StatusCode::SUCCESS;
0349 }
0350
0351 inline uint16_t readoutOrder(uint16_t physical_order) {
0352 return (4 * ((static_cast<uint16_t>((static_cast<float>(physical_order) / 8.0))) % 4) +
0353 static_cast<uint16_t>(static_cast<float>(physical_order) / 32.0) + 16 * (physical_order % 8));
0354 }
0355 };
0356
0357 inline bool isZeroSuppressed(FEDReadoutMode mode,
0358 bool legacy = false,
0359 FEDLegacyReadoutMode lmode = READOUT_MODE_LEGACY_INVALID) {
0360 if (!legacy) {
0361 switch (mode) {
0362 case READOUT_MODE_ZERO_SUPPRESSED_LITE10:
0363 case READOUT_MODE_ZERO_SUPPRESSED_LITE10_CMOVERRIDE:
0364 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT:
0365 case READOUT_MODE_PREMIX_RAW:
0366 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT_CMOVERRIDE:
0367 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_CMOVERRIDE:
0368 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT:
0369 case READOUT_MODE_ZERO_SUPPRESSED:
0370 case READOUT_MODE_ZERO_SUPPRESSED_FAKE:
0371 case READOUT_MODE_ZERO_SUPPRESSED_LITE8:
0372 case READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT_CMOVERRIDE:
0373 return true;
0374 break;
0375 default:
0376 return false;
0377 }
0378 } else {
0379 switch (lmode) {
0380 case READOUT_MODE_LEGACY_ZERO_SUPPRESSED_REAL:
0381 case READOUT_MODE_LEGACY_ZERO_SUPPRESSED_FAKE:
0382 case READOUT_MODE_LEGACY_ZERO_SUPPRESSED_LITE_REAL:
0383 case READOUT_MODE_LEGACY_ZERO_SUPPRESSED_LITE_FAKE:
0384 case READOUT_MODE_LEGACY_PREMIX_RAW:
0385 return true;
0386 default:
0387 return false;
0388 }
0389 }
0390 }
0391 inline bool isNonLiteZS(FEDReadoutMode mode,
0392 bool legacy = false,
0393 FEDLegacyReadoutMode lmode = READOUT_MODE_LEGACY_INVALID) {
0394 return (!legacy) ? (mode == READOUT_MODE_ZERO_SUPPRESSED || mode == READOUT_MODE_ZERO_SUPPRESSED_FAKE)
0395 : (lmode == READOUT_MODE_LEGACY_ZERO_SUPPRESSED_REAL ||
0396 lmode == READOUT_MODE_LEGACY_ZERO_SUPPRESSED_FAKE);
0397 }
0398 inline bool isVirginRaw(FEDReadoutMode mode,
0399 bool legacy = false,
0400 FEDLegacyReadoutMode lmode = READOUT_MODE_LEGACY_INVALID) {
0401 return (!legacy) ? mode == READOUT_MODE_VIRGIN_RAW
0402 : (lmode == READOUT_MODE_LEGACY_VIRGIN_RAW_REAL || lmode == READOUT_MODE_LEGACY_VIRGIN_RAW_FAKE);
0403 }
0404 inline bool isProcessedRaw(FEDReadoutMode mode,
0405 bool legacy = false,
0406 FEDLegacyReadoutMode lmode = READOUT_MODE_LEGACY_INVALID) {
0407 return (!legacy) ? mode == READOUT_MODE_PROC_RAW
0408 : (lmode == READOUT_MODE_LEGACY_PROC_RAW_REAL || lmode == READOUT_MODE_LEGACY_PROC_RAW_FAKE);
0409 }
0410 inline bool isScopeMode(FEDReadoutMode mode,
0411 bool legacy = false,
0412 FEDLegacyReadoutMode lmode = READOUT_MODE_LEGACY_INVALID) {
0413 return (!legacy) ? mode == READOUT_MODE_SCOPE : lmode == READOUT_MODE_LEGACY_SCOPE;
0414 }
0415
0416 template <typename OUT>
0417 StatusCode unpackScope(const FEDChannel& channel, OUT&& out) {
0418 return detail::unpackRawW<16>(channel, out);
0419 }
0420 template <typename OUT>
0421 StatusCode unpackProcessedRaw(const FEDChannel& channel, OUT&& out) {
0422 return detail::unpackRawW<16>(channel, out);
0423 }
0424
0425 template <typename OUT>
0426 StatusCode unpackVirginRaw(const FEDChannel& channel, OUT&& out, uint8_t packetCode) {
0427 std::vector<SiStripRawDigi> samples;
0428 auto st = StatusCode::SUCCESS;
0429 if (PACKET_CODE_VIRGIN_RAW == packetCode) {
0430 samples.reserve((channel.length() - 3) / 2);
0431 st = detail::unpackRawW<16>(channel, std::back_inserter(samples));
0432 } else if (PACKET_CODE_VIRGIN_RAW10 == packetCode) {
0433 samples.reserve((channel.length() - 3) * 10 / 8);
0434 st = detail::unpackRawB<10>(channel, std::back_inserter(samples));
0435 } else if (PACKET_CODE_VIRGIN_RAW8_BOTBOT == packetCode || PACKET_CODE_VIRGIN_RAW8_TOPBOT == packetCode) {
0436 samples.reserve(channel.length() - 3);
0437 st = detail::unpackRawW<8>(
0438 channel, std::back_inserter(samples), (PACKET_CODE_VIRGIN_RAW8_BOTBOT == packetCode ? 2 : 1));
0439 }
0440 if (!samples.empty()) {
0441 for (uint_fast16_t i{0}; i != samples.size(); ++i) {
0442 const auto physical = i % 128;
0443 const auto readout = (detail::readoutOrder(physical) * 2
0444 + (i >= 128 ? 1 : 0));
0445 *out++ = samples[readout];
0446 }
0447 }
0448 return st;
0449 }
0450 template <typename OUT>
0451 StatusCode unpackZeroSuppressed(const FEDChannel& channel,
0452 OUT&& out,
0453 uint16_t stripStart,
0454 bool isNonLite,
0455 FEDReadoutMode mode,
0456 bool legacy = false,
0457 FEDLegacyReadoutMode lmode = READOUT_MODE_LEGACY_INVALID,
0458 uint8_t packetCode = 0) {
0459 if ((isNonLite && packetCode == PACKET_CODE_ZERO_SUPPRESSED10) ||
0460 ((!legacy) &&
0461 (mode == READOUT_MODE_ZERO_SUPPRESSED_LITE10 || mode == READOUT_MODE_ZERO_SUPPRESSED_LITE10_CMOVERRIDE))) {
0462 return detail::unpackZSB<10>(channel, out, (isNonLite ? 7 : 2), stripStart);
0463 } else if ((!legacy) ? mode == READOUT_MODE_PREMIX_RAW : lmode == READOUT_MODE_LEGACY_PREMIX_RAW) {
0464 return detail::unpackZSW<16>(channel, out, 7, stripStart);
0465 } else {
0466 uint8_t bits_shift = 0;
0467 if (isNonLite) {
0468 if (packetCode == PACKET_CODE_ZERO_SUPPRESSED8_TOPBOT)
0469 bits_shift = 1;
0470 else if (packetCode == PACKET_CODE_ZERO_SUPPRESSED8_BOTBOT)
0471 bits_shift = 2;
0472 } else {
0473 if (mode == READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT ||
0474 mode == READOUT_MODE_ZERO_SUPPRESSED_LITE8_TOPBOT_CMOVERRIDE)
0475 bits_shift = 1;
0476 else if (mode == READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT ||
0477 mode == READOUT_MODE_ZERO_SUPPRESSED_LITE8_BOTBOT_CMOVERRIDE)
0478 bits_shift = 2;
0479 }
0480 auto st = detail::unpackZSW<8>(channel, out, (isNonLite ? 7 : 2), stripStart, bits_shift);
0481 if (isNonLite && packetCode == 0 && StatusCode::SUCCESS == st) {
0482
0483 return StatusCode::ZERO_PACKET_CODE;
0484 }
0485 return st;
0486 }
0487 }
0488 };
0489 std::string toString(fedchannelunpacker::StatusCode status);
0490 }
0491
0492 #endif