Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-04-06 08:15:46

0001 // @file GBTLink.h
0002 // @brief Declarations of helper classes for the ITS/MFT raw data decoding
0003 // @sa <O2/Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/GBTLink.>
0004 //     <760019308>
0005 
0006 #ifndef MVTXDECODER_GBTLINK_H
0007 #define MVTXDECODER_GBTLINK_H
0008 
0009 #define _RAW_READER_ERROR_CHECKS_  // comment this to disable error checking
0010 
0011 #include "DecodingStat.h"
0012 #include "GBTWord.h"
0013 #include "InteractionRecord.h"
0014 #include "PayLoadCont.h"
0015 #include "PayLoadSG.h"
0016 #include "RDH.h"
0017 #include "mvtx_utils.h"
0018 
0019 #include <iomanip>
0020 #include <iostream>
0021 #include <memory>
0022 
0023 using mvtx_utils::FLXWordLength;
0024 
0025 #define GBTLINK_DECODE_ERRORCHECK(errRes, errEval)                            \
0026   errRes = errEval;                                                           \
0027   if ((errRes) & uint8_t(ErrorPrinted))                                       \
0028   {                                                                           \
0029     ruPtr->linkHBFToDump[(uint64_t(subSpec) << 32) + hbfEntry] = irHBF.orbit; \
0030     errRes &= ~uint8_t(ErrorPrinted);                                         \
0031   }                                                                           \
0032   if ((errRes) & uint8_t(Abort))                                              \
0033   {                                                                           \
0034     discardData();                                                            \
0035     return AbortedOnError;                                                    \
0036   }
0037 
0038 namespace mvtx
0039 {
0040   struct TRGData
0041   {
0042     InteractionRecord ir = {};
0043     bool hasCDW = false;
0044     GBTCalibDataWord calWord = {};
0045     size_t first_hit_pos = 0;
0046     size_t n_hits = 0;
0047 
0048     TRGData(uint64_t orb, uint16_t b)
0049       : ir(orb, b) {};
0050 
0051     void clear()
0052     {
0053       ir.clear();
0054       hasCDW = false;
0055       calWord = {};
0056       first_hit_pos = 0;
0057       n_hits = 0;
0058     }
0059   };
0060 
0061   struct mvtx_hit
0062   {
0063     uint8_t chip_id = 0xf;
0064     uint16_t bunchcounter = 0xFFFF;
0065     uint16_t row_pos = 0xFFFF;
0066     uint16_t col_pos = 0xFFFF;
0067   };
0068 
0069   /// support for the GBT single link data
0070   struct GBTLink
0071   {
0072     //  enum RawDataDumps : int { DUMP_NONE, // no raw data dumps on error
0073     //                            DUMP_HBF,  // dump HBF for FEEID with error
0074     //                            DUMP_TF,   // dump whole TF at error
0075     //                            DUMP_NTYPES };
0076 
0077     enum CollectedDataStatus : int8_t
0078     {
0079       None,
0080       AbortedOnError,
0081       StoppedOnEndOfData,
0082       DataSeen
0083     };  // None is set before starting collectROFCableData
0084 
0085     //  enum ErrorType : uint8_t { NoError = 0x0,
0086     //                             Warning = 0x1,
0087     //                             Skip = 0x2,
0088     //                             Abort = 0x4,
0089     //                             ErrorPrinted = 0x1 << 7 };
0090 
0091     static constexpr int RawBufferMargin =
0092         5000000;  // keep uploaded at least this amount
0093     static constexpr int RawBufferSize =
0094         10000000 + 2 * RawBufferMargin;  // size in MB
0095     static constexpr uint8_t MaxCablesPerLink = 3;
0096 
0097     CollectedDataStatus status = None;
0098 
0099     uint16_t flxId = 0;  // FLX ID
0100     uint16_t feeId = 0;  // FEE ID
0101 
0102     PayLoadCont data;  // data buffer for single feeeid
0103     std::array<PayLoadCont, MaxCablesPerLink> cableData;
0104 
0105     uint32_t hbfEntry = 0;  // entry of the current HBF page in the rawData SG list
0106     InteractionRecord ir = {};
0107 
0108     GBTLinkDecodingStat statistics;  // link decoding statistics
0109 
0110     bool hbf_error = false;
0111 
0112     uint32_t hbf_length = 0;
0113     uint32_t prev_pck_cnt = 0;
0114     uint32_t hbf_count = 0;
0115 
0116     PayLoadSG rawData;      // scatter-gatter buffer for cached CRU pages, each
0117                             // starting with RDH
0118     size_t dataOffset = 0;  //
0119     std::vector<InteractionRecord> mL1TrgTime;
0120     std::vector<TRGData> mTrgData;
0121     int RDHErrors = 0;
0122 
0123     std::vector<mvtx_hit *> hit_vector = {};
0124 
0125     std::vector<uint64_t> tdt_lanestatus_error_vector = {};
0126 
0127     // std::vector<uint16_t> APE_error_vector = {};
0128 
0129     std::vector<std::pair<int, int>> decoder_error_vector = {};
0130 
0131     //------------------------------------------------------------------------
0132     GBTLink() = default;
0133     GBTLink(const uint16_t &_flx, const uint16_t &_fee);
0134     void clear(const bool &resetStat = true, const bool &resetTFRaw = false);
0135 
0136     CollectedDataStatus collectROFCableData();
0137 
0138     void cacheData(size_t start, size_t sz) { rawData.add(start, sz); }
0139 
0140     void clearCableData()
0141     {
0142       for (auto &&data : cableData)
0143       {
0144         data.clear();
0145       }
0146     }
0147 
0148     int readFlxWord(GBTWord *gbtwords, uint16_t &w16);
0149     int decode_lane(const uint8_t chipId, PayLoadCont &buffer);
0150 
0151     void getRowCol(const uint8_t reg, const uint16_t addr, uint16_t &row,
0152                    uint16_t &col)
0153     {
0154       row = (addr >> 0x1) & 0x1FF;
0155       col = (reg << 5 | ((addr >> 9) & 0x1E)) | ((addr ^ addr >> 1) & 0x1);
0156     }
0157 
0158     void addHit(const uint8_t laneId, const uint8_t bc, uint8_t reg,
0159                 const uint16_t addr)
0160     {
0161       auto *hit = new mvtx_hit();
0162       memset(hit, 0, sizeof(*hit));
0163 
0164       hit->chip_id = laneId;
0165       hit->bunchcounter = bc;
0166       getRowCol(reg, addr, hit->row_pos, hit->col_pos);
0167 
0168       hit_vector.push_back(hit);
0169     }
0170 
0171     void check_APE(const uint8_t &chipId, const uint8_t &dataC)
0172     {
0173       std::cerr << "Link: " << feeId << ", Chip: " << (int) chipId;
0174       switch (dataC)
0175       {
0176       case 0xF2:
0177         std::cerr << " APE_STRIP_START" << std::endl;
0178         decoder_error_vector.push_back(
0179             std::make_pair(static_cast<int>(chipId), 11));
0180         break;
0181       case 0xF4:
0182         std::cerr << " APE_DET_TIMEOUT" << std::endl;
0183         decoder_error_vector.push_back(
0184             std::make_pair(static_cast<int>(chipId), 12));
0185         break;
0186       case 0xF5:
0187         std::cerr << " APE_OOT" << std::endl;
0188         decoder_error_vector.push_back(
0189             std::make_pair(static_cast<int>(chipId), 13));
0190         break;
0191       case 0xF6:
0192         std::cerr << " APE_PROTOCOL_ERROR" << std::endl;
0193         decoder_error_vector.push_back(
0194             std::make_pair(static_cast<int>(chipId), 14));
0195         break;
0196       case 0xF7:
0197         std::cerr << " APE_LANE_FIFO_OVERFLOW_ERROR" << std::endl;
0198         decoder_error_vector.push_back(
0199             std::make_pair(static_cast<int>(chipId), 15));
0200         break;
0201       case 0xF8:
0202         std::cerr << " APE_FSM_ERROR" << std::endl;
0203         decoder_error_vector.push_back(
0204             std::make_pair(static_cast<int>(chipId), 16));
0205         break;
0206       case 0xF9:
0207         std::cerr << " APE_PENDING_DETECTOR_EVENT_LIMIT" << std::endl;
0208         decoder_error_vector.push_back(
0209             std::make_pair(static_cast<int>(chipId), 17));
0210         break;
0211       case 0xFA:
0212         std::cerr << " APE_PENDING_LANE_EVENT_LIMIT" << std::endl;
0213         decoder_error_vector.push_back(
0214             std::make_pair(static_cast<int>(chipId), 18));
0215         break;
0216       case 0xFB:
0217         std::cerr << " APE_O2N_ERROR" << std::endl;
0218         decoder_error_vector.push_back(
0219             std::make_pair(static_cast<int>(chipId), 19));
0220         break;
0221       case 0xFC:
0222         std::cerr << " APE_RATE_MISSING_TRG_ERROR" << std::endl;
0223         decoder_error_vector.push_back(
0224             std::make_pair(static_cast<int>(chipId), 20));
0225         break;
0226       case 0xFD:
0227         std::cerr << " APE_PE_DATA_MISSING" << std::endl;
0228         decoder_error_vector.push_back(
0229             std::make_pair(static_cast<int>(chipId), 21));
0230         break;
0231       case 0xFE:
0232         std::cerr << " APE_OOT_DATA_MISSING" << std::endl;
0233         decoder_error_vector.push_back(
0234             std::make_pair(static_cast<int>(chipId), 22));
0235         break;
0236       default:
0237         std::cerr << " Unknown APE code" << std::endl;
0238         decoder_error_vector.push_back(
0239             std::make_pair(static_cast<int>(chipId), 23));
0240       }
0241       return;
0242     }
0243 
0244     void AlpideByteError(const uint8_t &chipId, PayLoadCont &buffer)
0245     {
0246       uint8_t dataC = 0;
0247 
0248       std::cerr << "Link: " << feeId << ", Chip: " << (int) chipId;
0249       std::cerr << " invalid byte 0x" << std::hex << (int) (dataC) << std::endl;
0250       decoder_error_vector.push_back(
0251           std::make_pair(static_cast<int>(chipId), 10));
0252       while (buffer.next(dataC))
0253       {
0254         std::cerr << " " << std::hex << (int) (dataC) << " ";
0255       }
0256       std::cerr << std::endl;
0257       buffer.clear();
0258       return;
0259     }
0260 
0261     void PrintFlxWord(std::ostream &os, uint8_t *pos)
0262     {
0263       os << std::setfill('0');
0264       for (int i = 0; i < 32; i++)
0265       {
0266         os << std::hex << std::setw(2) << (int) pos[i] << " " << std::dec;
0267       }
0268       os << std::setfill(' ') << std::endl;
0269     }
0270 
0271     void PrintBlock(std::ostream &os, uint8_t *pos, size_t n)
0272     {
0273       for (uint32_t i = 0; i < n; ++i)
0274       {
0275         PrintFlxWord(os, pos + 32 * i);
0276       }
0277     }
0278 
0279     //  ClassDefNV(GBTLink, 1);
0280   };
0281 
0282   ///_________________________________________________________________
0283   /// collect cables data for single ROF, return number of real payload words
0284   /// seen, -1 in case of critical error
0285   inline GBTLink::CollectedDataStatus
0286       GBTLink::collectROFCableData(/*const Mapping& chmap*/)
0287   {
0288     bool prev_evt_complete = false;
0289     bool header_found = false;
0290     bool trailer_found = false;
0291     uint8_t *hbf_start = nullptr;
0292 
0293     status = None;
0294 
0295     auto currRawPiece = rawData.currentPiece();
0296     dataOffset = 0;
0297     while (currRawPiece)
0298     {  // we may loop over multiple FLX page
0299       uint32_t n_no_continuation = 0;
0300       uint32_t n_packet_done = 0;
0301 
0302       if (dataOffset >= currRawPiece->size)
0303       {
0304         data.movePtr(currRawPiece->size);
0305         dataOffset = 0;
0306         // start of the RDH
0307         if (!(currRawPiece = rawData.nextPiece()))
0308         {         // fetch next CRU page
0309           break;  // Data chunk (TF?) is done
0310         }
0311       }
0312 
0313       if (currRawPiece->hasError)  // Skip
0314       {
0315         decoder_error_vector.push_back(std::make_pair(-1, 1));
0316         dataOffset = currRawPiece->size;
0317         ++hbf_count;
0318         continue;
0319       }
0320 
0321       if (!dataOffset)
0322       {
0323         hbf_start = data.getPtr();
0324       }
0325 
0326       // here we always start with the RDH
0327       uint8_t *rdh_start = data.getPtr() + dataOffset;
0328       const auto *rdhP = reinterpret_cast<const mvtx::RDH *>(rdh_start);
0329       if (!mvtx::RDHUtils::checkRDH(mvtx::RDHAny::voidify(*rdhP), true, true))
0330       {
0331         dataOffset = currRawPiece->size;
0332         ++hbf_count;
0333         continue;
0334       }
0335 
0336       size_t pagesize = ((*rdhP).pageSize + 1) * FLXWordLength;
0337       const size_t nFlxWords = (pagesize - (2 * FLXWordLength)) / FLXWordLength;
0338       // Fill statistics
0339       if (!(*rdhP).packetCounter)
0340       {
0341         if (dataOffset)
0342         {
0343           log_error << "Wrong dataOffset value " << dataOffset
0344                     << " at the start of a HBF" << std::endl;
0345           decoder_error_vector.push_back(std::make_pair(-1, 2));
0346           return CollectedDataStatus::AbortedOnError;
0347         }
0348         statistics.clear();
0349         // TODO: initialize/clear alpide data buffer
0350         for (uint32_t trg = GBTLinkDecodingStat::BitMaps::ORBIT;
0351              trg < GBTLinkDecodingStat::nBitMap; ++trg)
0352         {
0353           if (((*rdhP).trgType >> trg) & 1)
0354           {
0355             statistics.trgBitCounts[trg]++;
0356           }
0357         }
0358         hbfEntry =
0359             rawData
0360                 .currentPieceId();  // in case of problems with RDH, dump full TF
0361         ++hbf_count;
0362       }
0363       else if (!(*rdhP).stopBit)
0364       {
0365         if (prev_evt_complete)
0366         {
0367           log_error << "Previous event was already completed" << std::endl;
0368           decoder_error_vector.push_back(std::make_pair(-1, 3));
0369           return CollectedDataStatus::AbortedOnError;
0370         }
0371       }
0372 
0373       dataOffset += 2 * FLXWordLength;
0374       int prev_gbt_cnt = 3;
0375       GBTWord gbtWords[3];
0376       uint16_t w16 = 0;
0377       for (size_t iflx = 0; iflx < nFlxWords; ++iflx)
0378       {
0379         readFlxWord(gbtWords, w16);
0380         int16_t n_gbt_cnt = (w16 & 0x3FF) - prev_gbt_cnt;
0381         prev_gbt_cnt = (w16 & 0x3FF);
0382         if (n_gbt_cnt < 1 || n_gbt_cnt > 3)
0383         {
0384           log_error << "Bad gbt counter in the flx packet. FLX: " << flxId
0385                     << ", Feeid: " << feeId << ", n_gbt_cnt: " << n_gbt_cnt
0386                     << ", prev_gbt_cnt: " << prev_gbt_cnt
0387                     << ", size: " << currRawPiece->size
0388                     << ", dataOffset: " << dataOffset << std::endl;
0389           decoder_error_vector.push_back(std::make_pair(-1, 4));
0390           // PrintBlock(std::cerr, rdh_start, nFlxWords + 2);
0391           log_error << "rdh_start length: " << (nFlxWords + 2) << std::endl;
0392           std::cerr << "Full HBF" << std::endl;
0393           // PrintBlock(std::cerr, hbf_start, (currRawPiece->size/32) );
0394           log_error << "hbf_start length: " << (currRawPiece->size / 32)
0395                     << std::endl;
0396           break;
0397         }
0398         for (int i = 0; i < n_gbt_cnt; ++i)
0399         {
0400           auto &gbtWord = gbtWords[i];
0401           if (gbtWord.isIHW())  // ITS HEADER WORD
0402           {
0403             // TODO assert first word after RDH and active lanes
0404             if (!(!gbtWord.activeLanes ||
0405                   ((gbtWord.activeLanes >> 0) & 0x7) == 0x7 ||
0406                   ((gbtWord.activeLanes >> 3) & 0x7) == 0x7 ||
0407                   ((gbtWord.activeLanes >> 6) & 0x7) == 0x7))
0408             {
0409               log_error << "Expected all active lanes for links, but "
0410                         << gbtWord.activeLanes << "found in HBF " << hbfEntry
0411                         << ", " << gbtWord.asString().data() << std::endl;
0412               decoder_error_vector.push_back(std::make_pair(-1, 5));
0413               return CollectedDataStatus::AbortedOnError;
0414             }
0415           }
0416           else if (gbtWord.isTDH())  // TRIGGER DATA HEADER (TDH)
0417           {
0418             header_found = true;
0419             ir.orbit = gbtWord.bco;
0420             ir.bc = gbtWord.bc;
0421             if (gbtWord
0422                     .bc)  // statistic trigger for first bc already filled on RDH
0423             {
0424               for (uint32_t trg = GBTLinkDecodingStat::BitMaps::ORBIT;
0425                    trg < GBTLinkDecodingStat::nBitMap; ++trg)
0426               {
0427                 if (trg ==
0428                     GBTLinkDecodingStat::BitMaps::FE_RST)  //  TDH save first 12
0429                                                            //  bits only
0430                   break;
0431                 if (((gbtWord.triggerType >> trg) & 1))
0432                 {
0433                   statistics.trgBitCounts[trg]++;
0434                 }
0435               }
0436             }
0437 
0438             if ((gbtWord.triggerType >> GBTLinkDecodingStat::BitMaps::PHYSICS) &
0439                 0x1)
0440             {
0441               mL1TrgTime.push_back(ir);
0442             }
0443 
0444             if (!gbtWord.continuation && !gbtWord.noData)
0445             {
0446               n_no_continuation++;
0447               mTrgData.emplace_back(ir.orbit, ir.bc);
0448             }  // end if not cont
0449           }  // end TDH
0450           else if (gbtWord.isCDW())  // CALIBRATION DATA WORD
0451           {
0452             mTrgData.back().hasCDW = true;
0453             mTrgData.back().calWord =
0454                 *(reinterpret_cast<GBTCalibDataWord *>(&gbtWord));
0455           }
0456           else if (gbtWord.isTDT())
0457           {
0458             trailer_found = true;
0459             if (gbtWord.packet_done)
0460             {
0461               n_packet_done++;
0462               if (n_packet_done < n_no_continuation)
0463               {
0464                 log_error << "TDT packet done before TDH no continuation "
0465                           << n_no_continuation << " != " << n_packet_done
0466                           << std::endl;
0467                 decoder_error_vector.push_back(std::make_pair(-1, 6));
0468                 return CollectedDataStatus::AbortedOnError;
0469               }
0470             }
0471 
0472             if (gbtWord.lane_status != 0x0)
0473               tdt_lanestatus_error_vector.push_back(gbtWord.lane_status);
0474 
0475             prev_evt_complete = gbtWord.packet_done;
0476             // TODO: YCM Add warning and counter for timeout and violation
0477           }
0478           else if (gbtWord.isDDW())  // DIAGNOSTIC DATA WORD (DDW)
0479           {
0480             if (!(*rdhP).stopBit)
0481             {
0482               log_error << "" << std::endl;
0483               decoder_error_vector.push_back(std::make_pair(-1, 7));
0484               return CollectedDataStatus::AbortedOnError;
0485             }
0486           }
0487           else if (gbtWord.isDiagnosticIB())  // IB DIAGNOSTIC DATA
0488           {
0489             std::cout << "WARNING: IB Diagnostic word found." << std::endl;
0490             std::cout << "diagnostic_lane_id: " << (gbtWord.id >> 5);
0491             std::cout << " lane_error_id: " << gbtWord.lane_error_id;
0492             std::cout << " diasnotic_data: 0x" << std::hex
0493                       << gbtWord.diagnostic_data << std::endl;
0494           }
0495           else if (gbtWord.isData())  // IS IB DATA
0496           {
0497             if (!header_found)
0498             {
0499               log_error << "Trigger header not found before chip data"
0500                         << std::endl;
0501               decoder_error_vector.push_back(std::make_pair(-1, 8));
0502               return CollectedDataStatus::AbortedOnError;
0503             }
0504             auto lane = (gbtWord.data8[9] & 0x1F) % 3;
0505             cableData[lane].add(gbtWord.getW8(), 9);
0506           }
0507 
0508           if (prev_evt_complete)
0509           {
0510             bool decode_failed = false;
0511             auto &&trgData = mTrgData.back();
0512             trgData.first_hit_pos = hit_vector.size();
0513             for (auto &&itr = cableData.begin(); itr != cableData.end(); ++itr)
0514             {
0515               if (!itr->isEmpty())
0516               {
0517                 int status =
0518                     decode_lane(std::distance(cableData.begin(), itr), *itr);
0519                 if (status == -1)
0520                   decode_failed = true;
0521               }
0522             }
0523             trgData.n_hits = hit_vector.size() - trgData.first_hit_pos;
0524             prev_evt_complete = false;
0525             header_found = false;
0526             trailer_found = false;
0527             clearCableData();
0528             if (decode_failed)
0529               return CollectedDataStatus::AbortedOnError;
0530           }
0531         }
0532       }
0533     }
0534     return (status = StoppedOnEndOfData);
0535   }
0536 
0537   //_________________________________________________
0538   inline int GBTLink::decode_lane(const uint8_t chipId, PayLoadCont &buffer)
0539   {
0540     int ret = 0;  // currently we just print stuff, but we will add stuff to our
0541                   // structures and return a status later (that's why it's not a
0542                   // const function)
0543     if (buffer.getSize() < 3)
0544     {
0545       log_error << "chip data is too short: " << buffer.getSize() << std::endl;
0546       decoder_error_vector.push_back(std::make_pair(static_cast<int>(chipId), 9));
0547       return -1;
0548     }
0549 
0550     uint8_t dataC = 0;
0551     uint16_t dataS = 0;
0552 
0553     bool busy_on = false, busy_off = false;
0554     bool chip_header_found = false;
0555     bool chip_trailer_found = false;
0556 
0557     uint8_t laneId = 0xFF;
0558     uint8_t bc = 0xFF;
0559     uint8_t reg = 0xFF;
0560 
0561     if (!((buffer[0] & 0xF0) == 0xE0 || (buffer[0] & 0xF0) == 0xA0 ||
0562           (buffer[0] == 0xF0) || (buffer[0] == 0xF1) ||
0563           (buffer[0] & 0xF0) == 0xF0))
0564     {
0565       AlpideByteError(chipId, buffer);
0566       return 0;
0567     }
0568 
0569     while (buffer.next(dataC))
0570     {
0571       if (dataC == 0xF1)  // BUSY ON
0572       {
0573         busy_on = true;
0574       }
0575       else if (dataC == 0xF0)  // BUSY OFF
0576       {
0577         busy_off = true;
0578       }
0579       else if ((dataC & 0xF0) == 0xF0)  // APE
0580       {
0581         check_APE(chipId, dataC);
0582         // APE_error_vector.push_back((((uint16_t)chipId << 8) | dataC));
0583         chip_trailer_found = 1;
0584         busy_on = busy_off = chip_header_found = 0;
0585       }
0586       else if ((dataC & 0xF0) == 0xE0)  // EMPTY
0587       {
0588         chip_header_found = false;
0589         chip_trailer_found = true;
0590         laneId = (dataC & 0x0F) % 3;
0591         if (laneId != chipId)
0592         {
0593           log_error << "Error laneId " << laneId << " (" << (dataC & 0xF)
0594                     << ") and chipId " << chipId << std::endl;
0595           decoder_error_vector.push_back(
0596               std::make_pair(static_cast<int>(chipId), 24));
0597           return -1;
0598         }
0599         buffer.next(bc);
0600         busy_on = busy_off = false;
0601       }
0602       else
0603       {
0604         if (chip_header_found)
0605         {
0606           if ((dataC & 0xE0) == 0xC0)  // REGION HEADER
0607           {
0608             if (buffer.getUnusedSize() < 2)
0609             {
0610               log_error << "No data short would fit (at least a data short after "
0611                            "region header!)"
0612                         << std::endl;
0613               decoder_error_vector.push_back(
0614                   std::make_pair(static_cast<int>(chipId), 25));
0615               return -1;
0616             }
0617             // TODO: move first region header out of loop, asserting its existence
0618             reg = dataC & 0x1F;
0619           }
0620           else if ((dataC & 0xC0) == 0x40)  // DATA SHORT
0621           {
0622             if (buffer.isEmpty())
0623             {
0624               log_error << "data short do not fit" << std::endl;
0625               return -1;
0626             }
0627             if (reg == 0xFF)
0628             {
0629               log_error << "data short at " << buffer.getOffset()
0630                         << " before region header" << std::endl;
0631               decoder_error_vector.push_back(
0632                   std::make_pair(static_cast<int>(chipId), 26));
0633               return -1;
0634             }
0635             dataS = (dataC << 8);
0636             buffer.next(dataC);
0637             dataS |= dataC;
0638             addHit(laneId, bc, reg, (dataS & 0x3FFF));
0639           }
0640           else if ((dataC & 0xC0) == 0x00)  // DATA LONG
0641           {
0642             if (buffer.getUnusedSize() < 3)
0643             {
0644               log_error << "No data long would fit (at least a data short after "
0645                            "region header!)"
0646                         << std::endl;
0647               decoder_error_vector.push_back(
0648                   std::make_pair(static_cast<int>(chipId), 27));
0649               return -1;
0650             }
0651             if (reg == 0xFF)
0652             {
0653               log_error << "data short at " << buffer.getOffset()
0654                         << " before region header" << std::endl;
0655               decoder_error_vector.push_back(
0656                   std::make_pair(static_cast<int>(chipId), 28));
0657               return -1;
0658             }
0659             buffer.next(dataS);
0660             uint16_t addr = ((dataC & 0x3F) << 8) | ((dataS >> 8) & 0xFF);
0661             addHit(laneId, bc, reg, addr);
0662             uint8_t hit_map = (dataS & 0xFF);
0663             if (hit_map & 0x80)
0664             {
0665               log_error << "Wrong bit before DATA LONG bit map" << std::endl;
0666               decoder_error_vector.push_back(
0667                   std::make_pair(static_cast<int>(chipId), 29));
0668               return -1;
0669             }
0670             while (hit_map != 0x00)
0671             {
0672               ++addr;
0673               if (hit_map & 1)
0674               {
0675                 addHit(laneId, bc, reg, addr);
0676               }
0677               hit_map >>= 1;
0678             }
0679           }
0680           else if ((dataC & 0xF0) == 0xB0)  // CHIP TRAILER
0681           {
0682             //          uint8_t flag = (dataC & 0x0F);
0683             // TODO: YCM add chipdata statistic
0684             chip_trailer_found = 1;
0685             busy_on = busy_off = chip_header_found = 0;
0686           }
0687           else  // ERROR
0688           {
0689             AlpideByteError(chipId, buffer);
0690             decoder_error_vector.push_back(
0691                 std::make_pair(static_cast<int>(chipId), 10));
0692           }
0693         }
0694         else
0695         {
0696           if ((dataC & 0xF0) == 0xA0)  // CHIP HEADER
0697           {
0698             chip_header_found = true;
0699             chip_trailer_found = false;
0700             laneId = (dataC & 0x0F) % 3;
0701             if (laneId != chipId)
0702             {
0703               log_error << "Error laneId " << laneId << " (" << (dataC & 0xF)
0704                         << ") and chipId " << chipId << std::endl;
0705               decoder_error_vector.push_back(
0706                   std::make_pair(static_cast<int>(chipId), 23));
0707               return -1;
0708             }
0709             buffer.next(bc);
0710             reg = 0xFF;
0711           }
0712           else if (dataC == 0x00)  // PADDING
0713           {
0714             continue;
0715           }
0716           else
0717           {  // ERROR
0718             AlpideByteError(chipId, buffer);
0719             decoder_error_vector.push_back(
0720                 std::make_pair(static_cast<int>(chipId), 10));
0721           }  // else !chip_header_found
0722         }  // if chip_header_found
0723       }  // busy_on, busy_off, chip_empty, other
0724     }  // while
0725 
0726     return ret;
0727   }
0728 
0729 }  // namespace mvtx
0730 
0731 #endif  // _MVTX_DECODER_ITSMFT_GBTLINK_H_