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