File indexing completed on 2024-04-06 12:10:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "EventFilter/CTPPSRawToDigi/interface/RawDataUnpacker.h"
0011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0012 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0013
0014 using namespace std;
0015 using namespace edm;
0016 using namespace pps;
0017
0018 RawDataUnpacker::RawDataUnpacker(const edm::ParameterSet &iConfig)
0019 : verbosity(iConfig.getUntrackedParameter<unsigned int>("verbosity", 0)) {}
0020
0021 int RawDataUnpacker::run(int fedId,
0022 const FEDRawData &data,
0023 vector<TotemFEDInfo> &fedInfoColl,
0024 SimpleVFATFrameCollection &coll) const {
0025 unsigned int size_in_words = data.size() / 8;
0026 if (size_in_words < 2) {
0027 if (verbosity)
0028 LogWarning("Totem") << "Error in RawDataUnpacker::run > "
0029 << "Data in FED " << fedId << " too short (size = " << size_in_words << " words).";
0030 return 1;
0031 }
0032
0033 fedInfoColl.emplace_back(fedId);
0034
0035 return processOptoRxFrame((const word *)data.data(), size_in_words, fedInfoColl.back(), &coll);
0036 }
0037
0038 int RawDataUnpacker::processOptoRxFrame(const word *buf,
0039 unsigned int frameSize,
0040 TotemFEDInfo &fedInfo,
0041 SimpleVFATFrameCollection *fc) const {
0042
0043 unsigned long long head = buf[0];
0044 unsigned long long foot = buf[frameSize - 1];
0045
0046 fedInfo.setHeader(head);
0047 fedInfo.setFooter(foot);
0048
0049 unsigned int boe = (head >> 60) & 0xF;
0050 unsigned int h0 = (head >> 0) & 0xF;
0051
0052 unsigned long lv1 = (head >> 32) & 0xFFFFFF;
0053 unsigned long bx = (head >> 20) & 0xFFF;
0054 unsigned int optoRxId = (head >> 8) & 0xFFF;
0055 unsigned int fov = (head >> 4) & 0xF;
0056
0057 unsigned int eoe = (foot >> 60) & 0xF;
0058 unsigned int f0 = (foot >> 0) & 0xF;
0059 unsigned int fSize = (foot >> 32) & 0x3FF;
0060
0061
0062 if (boe != 5 || h0 != 0 || eoe != 10 || f0 != 0 || fSize != frameSize) {
0063 if (verbosity)
0064 LogWarning("Totem") << "Error in RawDataUnpacker::processOptoRxFrame > "
0065 << "Wrong structure of OptoRx header/footer: "
0066 << "BOE=" << boe << ", H0=" << h0 << ", EOE=" << eoe << ", F0=" << f0
0067 << ", size (OptoRx)=" << fSize << ", size (DATE)=" << frameSize << ". OptoRxID=" << optoRxId
0068 << ". Skipping frame." << endl;
0069 return 0;
0070 }
0071
0072 LogDebug("Totem") << "RawDataUnpacker::processOptoRxFrame: "
0073 << "OptoRxId = " << optoRxId << ", BX = " << bx << ", LV1 = " << lv1
0074 << ", frameSize = " << frameSize << ", fov = " << fov;
0075
0076 if ((optoRxId >= FEDNumbering::MINTotemRPTimingVerticalFEDID &&
0077 optoRxId <= FEDNumbering::MAXTotemRPTimingVerticalFEDID)) {
0078 processOptoRxFrameSampic(buf, frameSize, fedInfo, fc);
0079 return 0;
0080 }
0081 if ((optoRxId >= FEDNumbering::MINTotemT2FEDID && optoRxId <= FEDNumbering::MAXTotemT2FEDID)) {
0082 processOptoRxFrameSampic(buf, frameSize, fedInfo, fc);
0083 return 0;
0084 }
0085
0086
0087 switch (fov) {
0088 case 1:
0089 return processOptoRxFrameSerial(buf, frameSize, fc);
0090 case 2:
0091 case 3:
0092 return processOptoRxFrameParallel(buf, frameSize, fedInfo, fc);
0093 default:
0094 break;
0095 }
0096
0097 if (verbosity)
0098 LogWarning("Totem") << "Error in RawDataUnpacker::processOptoRxFrame > "
0099 << "Unknown FOV = " << fov << endl;
0100
0101 return 0;
0102 }
0103
0104 int RawDataUnpacker::processOptoRxFrameSerial(const word *buf,
0105 unsigned int frameSize,
0106 SimpleVFATFrameCollection *fc) const {
0107
0108 unsigned int optoRxId = (buf[0] >> 8) & 0xFFF;
0109
0110
0111 unsigned int subFrames = (frameSize - 2) / 194;
0112
0113
0114 unsigned int errorCounter = 0;
0115 for (unsigned int r = 0; r < subFrames; ++r) {
0116 for (unsigned int c = 0; c < 4; ++c) {
0117 unsigned int head = (buf[1 + 194 * r] >> (16 * c)) & 0xFFFF;
0118 unsigned int foot = (buf[194 + 194 * r] >> (16 * c)) & 0xFFFF;
0119
0120 LogDebug("Totem") << "r = " << r << ", c = " << c << ": "
0121 << "S = " << (head & 0x1) << ", BOF = " << (head >> 12) << ", EOF = " << (foot >> 12)
0122 << ", ID = " << ((head >> 8) & 0xF) << ", ID' = " << ((foot >> 8) & 0xF);
0123
0124
0125 if ((head & 0x1) == 0)
0126 continue;
0127
0128 LogDebug("Totem") << "Header active (" << head << " -> " << (head & 0x1) << ").";
0129
0130
0131 if (head >> 12 != 0x4 || foot >> 12 != 0xB || ((head >> 8) & 0xF) != ((foot >> 8) & 0xF)) {
0132 std::ostringstream oss;
0133 if (head >> 12 != 0x4)
0134 oss << "\n\tHeader is not 0x4 as expected (0x" << std::hex << head << ").";
0135 if (foot >> 12 != 0xB)
0136 oss << "\n\tFooter is not 0xB as expected (0x" << std::hex << foot << ").";
0137 if (((head >> 8) & 0xF) != ((foot >> 8) & 0xF))
0138 oss << "\n\tIncompatible GOH IDs in header (0x" << std::hex << ((head >> 8) & 0xF) << ") and footer (0x"
0139 << std::hex << ((foot >> 8) & 0xF) << ").";
0140
0141 if (verbosity)
0142 LogWarning("Totem") << "Error in RawDataUnpacker::processOptoRxFrame > "
0143 << "Wrong payload structure (in GOH block row " << r << " and column " << c
0144 << ") in OptoRx frame ID " << optoRxId << ". GOH block omitted." << oss.str() << endl;
0145
0146 errorCounter++;
0147 continue;
0148 }
0149
0150
0151 unsigned int goh = (head >> 8) & 0xF;
0152 vector<VFATFrame::word *> dataPtrs;
0153 for (unsigned int fi = 0; fi < 16; fi++) {
0154 TotemFramePosition fp(0, 0, optoRxId, goh, fi);
0155 dataPtrs.push_back(fc->InsertEmptyFrame(fp)->getData());
0156 }
0157
0158 LogDebug("Totem").log([&](auto &l) {
0159 l << "transposing GOH block at prefix: " << (optoRxId * 192 + goh * 16) << ", dataPtrs = ";
0160 for (auto p : dataPtrs) {
0161 l << p << " ";
0162 }
0163 });
0164
0165 for (int i = 0; i < 192; i++) {
0166 int iword = 11 - i / 16;
0167 int ibit = 15 - i % 16;
0168 unsigned int w = (buf[i + 2 + 194 * r] >> (16 * c)) & 0xFFFF;
0169
0170
0171 for (int idx = 0; idx < 16; idx++) {
0172 if (w & (1 << idx))
0173 dataPtrs[idx][iword] |= (1 << ibit);
0174 }
0175 }
0176 }
0177 }
0178
0179 return errorCounter;
0180 }
0181
0182 int RawDataUnpacker::processOptoRxFrameParallel(const word *buf,
0183 unsigned int frameSize,
0184 TotemFEDInfo &fedInfo,
0185 SimpleVFATFrameCollection *fc) const {
0186
0187 unsigned long long head = buf[0];
0188 unsigned int optoRxId = (head >> 8) & 0xFFF;
0189
0190
0191 const uint16_t *payload = (const uint16_t *)(buf + 1);
0192
0193
0194 const uint32_t *ocPtr = (const uint32_t *)payload;
0195 fedInfo.setOrbitCounter(*ocPtr);
0196 payload += 2;
0197
0198
0199 unsigned int nWords = (frameSize - 2) * 4 - 2;
0200
0201
0202 for (unsigned int offset = 0; offset < nWords;) {
0203 unsigned int wordsProcessed = processVFATDataParallel(payload + offset, nWords, optoRxId, fc);
0204 offset += wordsProcessed;
0205 }
0206
0207 return 0;
0208 }
0209
0210 int RawDataUnpacker::processVFATDataParallel(const uint16_t *buf,
0211 unsigned int maxWords,
0212 unsigned int optoRxId,
0213 SimpleVFATFrameCollection *fc) const {
0214
0215 unsigned int wordsProcessed = 1;
0216
0217
0218 if (buf[0] == 0xFFFF)
0219 return wordsProcessed;
0220
0221
0222 unsigned int hFlag = (buf[0] >> 8) & 0xFF;
0223 if (hFlag != vmCluster && hFlag != vmRaw && hFlag != vmDiamondCompact) {
0224 if (verbosity)
0225 LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > "
0226 << "Unknown header flag " << hFlag << ". Skipping this word." << endl;
0227 return wordsProcessed;
0228 }
0229
0230
0231
0232 unsigned int gohIdx = (buf[0] >> 4) & 0xF;
0233 unsigned int fiberIdx = (buf[0] >> 0) & 0xF;
0234 TotemFramePosition fp(0, 0, optoRxId, gohIdx, fiberIdx);
0235
0236
0237 VFATFrame f;
0238 VFATFrame::word *fd = f.getData();
0239
0240
0241 uint8_t presenceFlags = 0;
0242
0243 if (((buf[wordsProcessed] >> 12) & 0xF) == 0xA)
0244 {
0245 presenceFlags |= 0x1;
0246 fd[11] = buf[wordsProcessed];
0247 wordsProcessed++;
0248 }
0249
0250 if (((buf[wordsProcessed] >> 12) & 0xF) == 0xC)
0251 {
0252 presenceFlags |= 0x2;
0253 fd[10] = buf[wordsProcessed];
0254 wordsProcessed++;
0255 }
0256
0257 if (((buf[wordsProcessed] >> 12) & 0xF) == 0xE)
0258 {
0259 presenceFlags |= 0x4;
0260 fd[9] = buf[wordsProcessed];
0261 wordsProcessed++;
0262 }
0263
0264
0265 unsigned int dataOffset = wordsProcessed;
0266
0267
0268 switch (hFlag) {
0269 case vmCluster: {
0270 unsigned int nCl = 0;
0271 while ((buf[wordsProcessed + nCl] >> 12) != 0xF && (wordsProcessed + nCl < maxWords))
0272 nCl++;
0273 wordsProcessed += nCl;
0274 } break;
0275 case vmRaw:
0276 wordsProcessed += 9;
0277 break;
0278 case vmDiamondCompact: {
0279 wordsProcessed--;
0280 while ((buf[wordsProcessed] & 0xFFF0) != 0xF000 && (wordsProcessed < maxWords))
0281 wordsProcessed++;
0282 } break;
0283 }
0284
0285
0286 unsigned int tSig = buf[wordsProcessed] >> 12;
0287 unsigned int tErrFlags = (buf[wordsProcessed] >> 8) & 0xF;
0288 unsigned int tSize = buf[wordsProcessed] & 0xFF;
0289
0290 f.setDAQErrorFlags(tErrFlags);
0291
0292
0293 bool skipFrame = false;
0294 stringstream ess;
0295
0296 if (tSig != 0xF) {
0297 if (verbosity)
0298 ess << " Wrong trailer signature (" << tSig << ")." << endl;
0299 skipFrame = true;
0300 }
0301
0302 if (tErrFlags != 0) {
0303 if (verbosity)
0304 ess << " Error flags not zero (" << tErrFlags << ")." << endl;
0305 skipFrame = true;
0306 }
0307
0308 wordsProcessed++;
0309
0310 if (tSize != wordsProcessed) {
0311 if (verbosity)
0312 ess << " Trailer size (" << tSize << ") does not match with words processed (" << wordsProcessed << ")."
0313 << endl;
0314 skipFrame = true;
0315 }
0316
0317 if (skipFrame) {
0318 if (verbosity)
0319 LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > Frame at " << fp
0320 << " has the following problems and will be skipped.\n"
0321 << endl
0322 << ess.rdbuf();
0323
0324 return wordsProcessed;
0325 }
0326
0327
0328 if (hFlag == vmCluster) {
0329 for (unsigned int nCl = 0; (buf[dataOffset + nCl] >> 12) != 0xF && (dataOffset + nCl < maxWords); ++nCl) {
0330 const uint16_t &w = buf[dataOffset + nCl];
0331 unsigned int upperBlock = w >> 8;
0332 unsigned int clSize = upperBlock & 0x7F;
0333 unsigned int clPos = (w >> 0) & 0xFF;
0334
0335
0336 if (upperBlock == 0xD0) {
0337 presenceFlags |= 0x10;
0338 f.setNumberOfClusters(clPos);
0339 continue;
0340 }
0341
0342
0343 if (clSize == 0)
0344 clSize = 128;
0345
0346
0347
0348 signed int chMax = clPos;
0349 signed int chMin = clPos - clSize + 1;
0350 if (chMax < 0 || chMax > 127 || chMin < 0 || chMin > 127 || chMin > chMax) {
0351 if (verbosity)
0352 LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > "
0353 << "Invalid cluster (pos=" << clPos << ", size=" << clSize << ", min=" << chMin
0354 << ", max=" << chMax << ") at " << fp << ". Skipping this cluster." << endl;
0355 continue;
0356 }
0357
0358 for (signed int ch = chMin; ch <= chMax; ch++) {
0359 unsigned int wi = ch / 16;
0360 unsigned int bi = ch % 16;
0361 fd[wi + 1] |= (1 << bi);
0362 }
0363 }
0364 }
0365
0366
0367 if (hFlag == vmRaw) {
0368 for (unsigned int i = 0; i < 8; i++)
0369 fd[8 - i] = buf[dataOffset + i];
0370
0371
0372 presenceFlags |= 0x8;
0373 fd[0] = buf[dataOffset + 8];
0374 }
0375
0376
0377 if (hFlag == vmDiamondCompact) {
0378 for (unsigned int i = 1; (buf[i + 1] & 0xFFF0) != 0xF000 && (i + 1 < maxWords); i++) {
0379 if ((buf[i] & 0xF000) == VFAT_HEADER_OF_EC) {
0380
0381 fd[10] = buf[i];
0382 continue;
0383 }
0384 switch (buf[i] & 0xF800) {
0385 case VFAT_DIAMOND_HEADER_OF_WORD_2:
0386
0387 fd[1] = buf[i + 1];
0388 fd[2] = buf[i];
0389 break;
0390 case VFAT_DIAMOND_HEADER_OF_WORD_3:
0391
0392 fd[3] = buf[i];
0393 fd[4] = buf[i - 1];
0394 break;
0395 case VFAT_DIAMOND_HEADER_OF_WORD_5:
0396
0397 fd[5] = buf[i];
0398 fd[6] = buf[i - 1];
0399 break;
0400 case VFAT_DIAMOND_HEADER_OF_WORD_7:
0401
0402 fd[7] = buf[i];
0403 fd[8] = buf[i - 1];
0404 break;
0405 default:
0406 break;
0407 }
0408 presenceFlags |= 0x8;
0409 }
0410 }
0411
0412
0413 f.setPresenceFlags(presenceFlags);
0414 fc->Insert(fp, f);
0415
0416 return wordsProcessed;
0417 }
0418
0419 int RawDataUnpacker::processOptoRxFrameSampic(const word *buf,
0420 unsigned int frameSize,
0421 TotemFEDInfo &fedInfo,
0422 SimpleVFATFrameCollection *fc) const {
0423 unsigned int optoRxId = (buf[0] >> 8) & 0xFFF;
0424
0425 LogDebug("RawDataUnpacker::processOptoRxFrameSampic")
0426 << "Processing sampic frame: OptoRx " << optoRxId << " framesize: " << frameSize;
0427
0428 unsigned int orbitCounterVFATFrameWords = 6;
0429 unsigned int sizeofVFATPayload = 12;
0430
0431 const VFATFrame::word *VFATFrameWordPtr = (const VFATFrame::word *)buf;
0432 VFATFrameWordPtr += orbitCounterVFATFrameWords - 1;
0433
0434 LogDebug("RawDataUnpacker::processOptoRxFrameSampic")
0435 << "Framesize: " << frameSize << "\tframes: " << frameSize / (sizeofVFATPayload + 2);
0436
0437 unsigned int nWords = (frameSize - 2) * 4 - 2;
0438
0439 for (unsigned int i = 1; i * (sizeofVFATPayload + 2) < nWords; ++i) {
0440
0441
0442 unsigned int fiberIdx = (*(++VFATFrameWordPtr)) & 0xF;
0443 unsigned int gohIdx = (*VFATFrameWordPtr >> 4) & 0xF;
0444 TotemFramePosition fp(0, 0, optoRxId, gohIdx, fiberIdx);
0445 TotemT2FramePosition fp2a(0, 0, optoRxId, gohIdx, fiberIdx, 0);
0446 TotemT2FramePosition fp2b(0, 0, optoRxId, gohIdx, fiberIdx, 1);
0447
0448 LogDebug("RawDataUnpacker::processOptoRxFrameSampic")
0449 << "OptoRx: " << optoRxId << " Goh: " << gohIdx << " Idx: " << fiberIdx;
0450
0451
0452 VFATFrame frame(++VFATFrameWordPtr);
0453 VFATFrameWordPtr += sizeofVFATPayload;
0454
0455 if (*(VFATFrameWordPtr) != 0xf00e) {
0456 edm::LogError("RawDataUnpacker::processOptoRxFrameSampic") << "Wrong trailer " << *VFATFrameWordPtr;
0457 continue;
0458 }
0459
0460 frame.setPresenceFlags(1);
0461 if ((optoRxId >= FEDNumbering::MINTotemT2FEDID && optoRxId <= FEDNumbering::MAXTotemT2FEDID)) {
0462 frame.setPresenceFlags(15);
0463 if (verbosity > 0)
0464 edm::LogWarning("Totem") << "T2 Frame Positions created: " << fp2a << "/" << fp2b << std::endl;
0465
0466 fc->Insert(
0467 fp2a,
0468 frame);
0469 fc->Insert(fp2b, frame);
0470 } else
0471 fc->Insert(fp, frame);
0472
0473 LogDebug("RawDataUnpacker::processOptoRxFrameSampic") << "Trailer: " << std::hex << *VFATFrameWordPtr;
0474 }
0475
0476 return 0;
0477 }