CbmRoot
Loading...
Searching...
No Matches
CbmStsUnpackAlgoLegacy.cxx
Go to the documentation of this file.
1/* Copyright (C) 2019-2021 Fair GmbH, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Pierre-Alain Loizeau, Dominik Smith [committer] */
4
5
7
9//#include "CbmFormatMsHeaderPrintout.h"
10#include "CbmMcbm2018StsPar.h"
11#include "TCanvas.h"
12#include "TH1.h"
13#include "TH2.h"
14#include "TList.h"
15#include "TProfile.h"
16#include "TROOT.h"
17#include "TString.h"
18
19#include <Logger.h>
20
21#include <cstdint>
22#include <fstream>
23#include <iomanip>
24#include <iostream>
25
26// -------------------------------------------------------------------------
27
29 : CbmStsUnpackAlgoBase("CbmStsUnpackAlgoLegacy")
30 ,
33 , fUnpackPar(nullptr)
34 , fuNbFebs(0)
36 , fviFebType()
38 , fviFebSide()
41 , fdTimeOffsetNs(0.0)
42 , fbUseChannelMask(false)
45 , fuCurrDpbIdx(0)
47 , fdStartTime(0.0)
48 , fdStartTimeMsSz(-1.0)
49 , ftStartTimeUnix(std::chrono::steady_clock::now())
50 , fvmHitsInMs()
55{
56}
57
64
65// -------------------------------------------------------------------------
67{
68 LOG(info) << "Initializing mCBM STS 2019 unpacker algo";
69 return true;
70}
71
72// -------------------------------------------------------------------------
74
75
76// ---- initParSet(FairParGenericSet* parset) ----
78{
79 LOG(info) << fName << "::initParSet - for container " << parset->ClassName();
80 if (parset->IsA() == CbmMcbm2018StsPar::Class()) return initParSet(static_cast<CbmMcbm2018StsPar*>(parset));
81
82 // If we do not know the derived ParSet class we return false
83 LOG(error)
84 << fName << "::initParSet - for container " << parset->ClassName()
85 << " failed, since CbmStsUnpackAlgoLegacy::initParSet() does not know the derived ParSet and what to do with it!";
86 return kFALSE;
87}
88
89// ---- initParSet(CbmMcbm2018StsPar* parset) ----
91{
92 fUnpackPar = parset;
93 bool initOK = InitParameters();
94
95 if (fMonitor) initOK &= fMonitor->Init(parset);
96
97 return initOK;
98}
99
100// -------------------------------------------------------------------------
102{
103 //Type of each module: 0 for connectors on the right, 1 for connectors on the left
104 std::vector<int32_t> viModuleType;
105
106 // STS address for the first strip of each module
107 std::vector<int32_t> viModAddress;
108
109 // Idx of the STS module for each FEB, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], -1 if inactive
110 std::vector<std::vector<std::vector<int32_t>>> viFebModuleIdx;
111
112 // Array to hold the active flag for all CROBs, [ NbDpb ][ NbCrobPerDpb ]
113 std::vector<std::vector<bool>> vbCrobActiveFlag;
114
115 //STS module side for each FEB, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], 0 = P, 1 = N, -1 if inactive
116 std::vector<std::vector<std::vector<int32_t>>> viFebModuleSide;
117
118 // Total number of STS modules in the setup
119 const uint32_t uNbModules = fUnpackPar->GetNbOfModules();
120 LOG(info) << "Nr. of STS Modules: " << uNbModules;
121
122 //Initialize temporary "per Feb" fields
123 InitTempVectors(&viModuleType, &viModAddress, &viFebModuleIdx, &vbCrobActiveFlag, &viFebModuleSide);
124
125 // Total number of STS DPBs in system
126 const uint32_t uNbOfDpbs = fUnpackPar->GetNrOfDpbs();
127 LOG(info) << "Nr. of STS DPBs: " << uNbOfDpbs;
128
129 // Read dpb index map from parameter container
131
132 // Get Nr of Febs
133 fuNbFebs = fUnpackPar->GetNrOfFebs();
134 LOG(info) << "Nr. of FEBs: " << fuNbFebs;
135
136 // Get Nr of Asics
137 const uint32_t uNbStsXyters = fUnpackPar->GetNrOfAsics();
138 LOG(info) << "Nr. of StsXyter ASICs: " << uNbStsXyters;
139
140 if (fvdTimeOffsetNsAsics.size() < uNbStsXyters) {
141 fvdTimeOffsetNsAsics.resize(uNbStsXyters, 0.0);
142 }
143
144 //Initialize class-wide "per Feb" fields
145 fviFebType.resize(uNbOfDpbs);
146
147 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
148 fviFebType[uDpb].resize(fUnpackPar->GetNbCrobsPerDpb());
149 for (uint32_t uCrobIdx = 0; uCrobIdx < fUnpackPar->GetNbCrobsPerDpb(); ++uCrobIdx) {
150 fviFebType[uDpb][uCrobIdx].resize(fUnpackPar->GetNbFebsPerCrob(), -1);
151 for (uint32_t uFebIdx = 0; uFebIdx < fUnpackPar->GetNbFebsPerCrob(); ++uFebIdx) {
152 fvbFebPulser.push_back(fUnpackPar->IsFebPulser(uDpb, uCrobIdx, uFebIdx));
153 fvdFebAdcGain.push_back(fUnpackPar->GetFebAdcGain(uDpb, uCrobIdx, uFebIdx));
154 fvdFebAdcOffs.push_back(fUnpackPar->GetFebAdcOffset(uDpb, uCrobIdx, uFebIdx));
155
156 if (0 <= viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]
157 && static_cast<uint32_t>(viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]) < uNbModules
158 && 0 <= viFebModuleSide[uDpb][uCrobIdx][uFebIdx] && viFebModuleSide[uDpb][uCrobIdx][uFebIdx] < 2) {
159 switch (viModuleType[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]) {
160 case 0: // FEB-8-1 with ZIF connector on the right
161 {
162 // P side (0) has type A (0)
163 // N side (1) has type B (1)
164 fviFebType[uDpb][uCrobIdx][uFebIdx] = viFebModuleSide[uDpb][uCrobIdx][uFebIdx];
165
172 fviFebAddress.push_back(viModAddress[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
173 // + (viFebModuleSide[uDpb][uCrobIdx][uFebIdx] << 25));
174 fviFebSide.push_back(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
175 break;
176 } // case 0: // FEB-8-1 with ZIF connector on the right
177 case 1: // FEB-8-1 with ZIF connector on the left
178 {
179 // P side (0) has type B (1)
180 // N side (1) has type A (0)
181 fviFebType[uDpb][uCrobIdx][uFebIdx] = !(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
182
189 fviFebAddress.push_back(viModAddress[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
190 // + ((!viFebModuleSide[uDpb][uCrobIdx][uFebIdx]) << 25));
191 fviFebSide.push_back(viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
192 break;
193 } // case 1: // FEB-8-1 with ZIF connector on the left
194 default:
195 LOG(fatal) << Form("Bad module type for DPB #%02u CROB #%u FEB %02u: %d", uDpb, uCrobIdx, uFebIdx,
196 viModuleType[viFebModuleIdx[uDpb][uCrobIdx][uFebIdx]]);
197 break;
198 }
199 } // FEB active and module index OK
200 else if (-1 == viFebModuleIdx[uDpb][uCrobIdx][uFebIdx] || -1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx]) {
201 fviFebAddress.push_back(0);
202 fviFebSide.push_back(-1);
203 } // Module index or type is set to inactive
204 else {
205 LOG(fatal) << Form("Bad module Index and/or Side for DPB #%02u CROB "
206 "#%u FEB %02u: %d %d",
207 uDpb, uCrobIdx, uFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
208 viFebModuleSide[uDpb][uCrobIdx][uFebIdx]);
209 } // Bad module index or type for this FEB
210 }
211 }
212 }
213
214 PrintActiveCrobs(vbCrobActiveFlag);
215 PrintAddressMaps(viFebModuleIdx, viFebModuleSide);
216
217 LOG(info) << "Unpacking data in bin sorter FW mode";
219
220 return true;
221}
222
223// -------------------------------------------------------------------------
225{
226 fDpbIdIndexMap.clear();
227 for (uint32_t uDpb = 0; uDpb < fUnpackPar->GetNrOfDpbs(); ++uDpb) {
228 fDpbIdIndexMap[fUnpackPar->GetDpbId(uDpb)] = uDpb;
229 LOG(info) << "Eq. ID for DPB #" << std::setw(2) << uDpb << " = 0x" << std::setw(4) << std::hex
230 << fUnpackPar->GetDpbId(uDpb) << std::dec << " => " << fDpbIdIndexMap[fUnpackPar->GetDpbId(uDpb)];
231 }
232}
233
234// -------------------------------------------------------------------------
235void CbmStsUnpackAlgoLegacy::InitTempVectors(std::vector<int32_t>* viModuleType, std::vector<int32_t>* viModAddress,
236 std::vector<std::vector<std::vector<int32_t>>>* viFebModuleIdx,
237 std::vector<std::vector<bool>>* vbCrobActiveFlag,
238 std::vector<std::vector<std::vector<int32_t>>>* viFebModuleSide)
239{
240 const uint32_t uNbModules = fUnpackPar->GetNbOfModules();
241 const uint32_t uNbOfDpbs = fUnpackPar->GetNrOfDpbs();
242
243 viModuleType->resize(uNbModules);
244 viModAddress->resize(uNbModules);
245 for (uint32_t uModIdx = 0; uModIdx < uNbModules; ++uModIdx) {
246 (*viModuleType)[uModIdx] = fUnpackPar->GetModuleType(uModIdx);
247 (*viModAddress)[uModIdx] = fUnpackPar->GetModuleAddress(uModIdx);
248 LOG(info) << "Module #" << std::setw(2) << uModIdx << " Type " << std::setw(4) << (*viModuleType)[uModIdx]
249 << " Address 0x" << std::setw(8) << std::hex << (*viModAddress)[uModIdx] << std::dec;
250 }
251 vbCrobActiveFlag->resize(uNbOfDpbs);
252 viFebModuleIdx->resize(uNbOfDpbs);
253 viFebModuleSide->resize(uNbOfDpbs);
254
255 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
256 (*vbCrobActiveFlag)[uDpb].resize(fUnpackPar->GetNbCrobsPerDpb());
257 (*viFebModuleIdx)[uDpb].resize(fUnpackPar->GetNbCrobsPerDpb());
258 (*viFebModuleSide)[uDpb].resize(fUnpackPar->GetNbCrobsPerDpb());
259 for (uint32_t uCrobIdx = 0; uCrobIdx < fUnpackPar->GetNbCrobsPerDpb(); ++uCrobIdx) {
260 (*vbCrobActiveFlag)[uDpb][uCrobIdx] = fUnpackPar->IsCrobActive(uDpb, uCrobIdx);
261 (*viFebModuleIdx)[uDpb][uCrobIdx].resize(fUnpackPar->GetNbFebsPerCrob());
262 (*viFebModuleSide)[uDpb][uCrobIdx].resize(fUnpackPar->GetNbFebsPerCrob());
263 for (uint32_t uFebIdx = 0; uFebIdx < fUnpackPar->GetNbFebsPerCrob(); ++uFebIdx) {
264 (*viFebModuleIdx)[uDpb][uCrobIdx][uFebIdx] = fUnpackPar->GetFebModuleIdx(uDpb, uCrobIdx, uFebIdx);
265 (*viFebModuleSide)[uDpb][uCrobIdx][uFebIdx] = fUnpackPar->GetFebModuleSide(uDpb, uCrobIdx, uFebIdx);
266 }
267 }
268 }
269}
270
271// -------------------------------------------------------------------------
272void CbmStsUnpackAlgoLegacy::PrintActiveCrobs(const std::vector<std::vector<bool>>& vbCrobActiveFlag)
273{
274 for (uint32_t uDpb = 0; uDpb < fUnpackPar->GetNrOfDpbs(); ++uDpb) {
275 TString sPrintoutLine = Form("DPB #%02u CROB Active ?: ", uDpb);
276 for (uint32_t uCrobIdx = 0; uCrobIdx < fUnpackPar->GetNbCrobsPerDpb(); ++uCrobIdx) {
277 sPrintoutLine += Form("%1u", (vbCrobActiveFlag[uDpb][uCrobIdx] == true));
278 }
279 LOG(info) << sPrintoutLine;
280 }
281}
282
283// -------------------------------------------------------------------------
284void CbmStsUnpackAlgoLegacy::PrintAddressMaps(const std::vector<std::vector<std::vector<int32_t>>>& viFebModuleIdx,
285 const std::vector<std::vector<std::vector<int32_t>>>& viFebModuleSide)
286{
287 uint32_t uGlobalFebIdx = 0;
288 for (uint32_t uDpb = 0; uDpb < fUnpackPar->GetNrOfDpbs(); ++uDpb) {
289 for (uint32_t uCrobIdx = 0; uCrobIdx < fUnpackPar->GetNbCrobsPerDpb(); ++uCrobIdx) {
290 LOG(info) << Form("DPB #%02u CROB #%u: ", uDpb, uCrobIdx);
291 for (uint32_t uFebIdx = 0; uFebIdx < fUnpackPar->GetNbFebsPerCrob(); ++uFebIdx) {
292 if (0 <= viFebModuleIdx[uDpb][uCrobIdx][uFebIdx])
293 LOG(info) << Form(" FEB #%02u (%02u): Mod. Idx = %03d Side %c (%2d) Type %c "
294 "(%2d) (Addr. 0x%08x) ADC gain %4.0f e- ADC Offs %5.0f e-",
295 uFebIdx, uGlobalFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
296 1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx] ? 'N' : 'P',
297 viFebModuleSide[uDpb][uCrobIdx][uFebIdx],
298 1 == fviFebType[uDpb][uCrobIdx][uFebIdx] ? 'B' : 'A', fviFebType[uDpb][uCrobIdx][uFebIdx],
299 fviFebAddress[uGlobalFebIdx], fvdFebAdcGain[uGlobalFebIdx], fvdFebAdcOffs[uGlobalFebIdx]);
300 else
301 LOG(info) << Form("Disabled FEB #%02u (%02u): Mod. Idx = %03d Side %c (%2d) Type %c "
302 "(%2d) (Addr. 0x%08x) ADC gain %4.0f e- ADC Offs %5.0f e-",
303 uFebIdx, uGlobalFebIdx, viFebModuleIdx[uDpb][uCrobIdx][uFebIdx],
304 1 == viFebModuleSide[uDpb][uCrobIdx][uFebIdx] ? 'N' : 'P',
305 viFebModuleSide[uDpb][uCrobIdx][uFebIdx],
306 1 == fviFebType[uDpb][uCrobIdx][uFebIdx] ? 'B' : 'A', fviFebType[uDpb][uCrobIdx][uFebIdx],
307 fviFebAddress[uGlobalFebIdx], fvdFebAdcGain[uGlobalFebIdx], fvdFebAdcOffs[uGlobalFebIdx]);
308 uGlobalFebIdx++;
309 }
310 }
311 }
312}
313
314// -------------------------------------------------------------------------
316{
317 const uint32_t uNbOfDpbs = fUnpackPar->GetNrOfDpbs();
318 const uint32_t uNbStsXyters = fUnpackPar->GetNrOfAsics();
319
320 fvulCurrentTsMsb.resize(uNbOfDpbs);
321 fvuCurrentTsMsbCycle.resize(uNbOfDpbs);
322 for (uint32_t uDpb = 0; uDpb < uNbOfDpbs; ++uDpb) {
323 fvulCurrentTsMsb[uDpb] = 0;
324 fvuCurrentTsMsbCycle[uDpb] = 0;
325 }
326
327 fvvusLastTsChan.resize(uNbStsXyters);
328 fvvusLastAdcChan.resize(uNbStsXyters);
329 fvvuLastTsMsbChan.resize(uNbStsXyters);
330 fvvusLastTsMsbCycleChan.resize(uNbStsXyters);
331 for (uint32_t uAsicIdx = 0; uAsicIdx < uNbStsXyters; ++uAsicIdx) {
332 fvvusLastTsChan[uAsicIdx].resize(fUnpackPar->GetNbChanPerAsic(), 0);
333 fvvusLastAdcChan[uAsicIdx].resize(fUnpackPar->GetNbChanPerAsic(), 0);
334 fvvuLastTsMsbChan[uAsicIdx].resize(fUnpackPar->GetNbChanPerAsic(), 0);
335 fvvusLastTsMsbCycleChan[uAsicIdx].resize(fUnpackPar->GetNbChanPerAsic(), 0);
336 }
337}
338
339void CbmStsUnpackAlgoLegacy::AddHitsToDigiVect(std::vector<stsxyter::FinalHit>* vmHitsIn,
340 std::vector<CbmStsDigi>* vDigiVectOut)
341{
342 for (auto itHitIn = vmHitsIn->begin(); itHitIn < vmHitsIn->end(); ++itHitIn) {
343 const uint32_t uAsicIdx = itHitIn->GetAsic();
344 const uint32_t uFebIdx = itHitIn->GetAsic() / fUnpackPar->GetNbAsicsPerFeb();
345 uint32_t uChanInMod =
346 itHitIn->GetChan() + fUnpackPar->GetNbChanPerAsic() * (itHitIn->GetAsic() % fUnpackPar->GetNbAsicsPerFeb());
350 if (0 == fviFebSide[uFebIdx])
351 uChanInMod = fUnpackPar->GetNbChanPerFeb() - uChanInMod - 1 // Invert channel order
352 + fUnpackPar->GetNbChanPerFeb(); // Offset for P (back) side
353
354 double dTimeInNs = itHitIn->GetTs() * stsxyter::kdClockCycleNs - fdTimeOffsetNs;
355 if (uAsicIdx < fvdTimeOffsetNsAsics.size()) dTimeInNs -= fvdTimeOffsetNsAsics[uAsicIdx];
356
357 const uint64_t ulTimeInNs = static_cast<uint64_t>(dTimeInNs);
358 const double dCalAdc = fvdFebAdcOffs[uFebIdx] + (itHitIn->GetAdc() - 1) * fvdFebAdcGain[uFebIdx];
359
360 if (0 == fviFebAddress[uFebIdx] || -1 == fviFebSide[uFebIdx]) {
361 LOG(error) << Form("Digi on disabled FEB %02u has address 0x%08x and side %d", uFebIdx, fviFebAddress[uFebIdx],
362 fviFebSide[uFebIdx]);
363 }
364
366 if (fvbFebPulser[uFebIdx]) {
367 if (fOptOutAVec) {
368 fOptOutAVec->emplace_back(fviFebAddress[uFebIdx], uChanInMod, ulTimeInNs, dCalAdc);
369 } // if (fOptOutAVec)
370 } // if (fvbFebPulser[uFebIdx])
371 else {
372 vDigiVectOut->emplace_back(fviFebAddress[uFebIdx], uChanInMod, ulTimeInNs, dCalAdc);
373 } // else of if (fvbFebPulser[uFebIdx])
374 }
375}
376
377bool CbmStsUnpackAlgoLegacy::unpack(const fles::Timeslice* ts, uint16_t uMsCompIdx, UInt_t uMsIdx)
378{
380 if (0 == fTsIndex) {
381 return true;
382 }
383
384 auto msDescriptor = ts->descriptor(uMsCompIdx, uMsIdx);
385
386 //Current equipment ID, tells from which DPB the current MS is originating
387 const uint32_t uCurrentEquipmentId = msDescriptor.eq_id;
388 const uint8_t* msContent = reinterpret_cast<const uint8_t*>(ts->content(uMsCompIdx, uMsIdx));
389 const uint32_t uSize = msDescriptor.size;
390
391 fulCurrentMsIdx = msDescriptor.idx;
392 LOG(debug) << "Microslice: " << fulCurrentMsIdx << " from EqId " << std::hex << uCurrentEquipmentId << std::dec
393 << " has size: " << uSize;
394
395 if (0 == fvbMaskedComponents.size()) fvbMaskedComponents.resize(ts->num_components(), false);
396
397 //Temp holder until current equipment ID is properly filled in MS
398 const uint32_t uCurrDpbId = static_cast<uint32_t>(uCurrentEquipmentId & 0xFFFF);
399
400 if (fMonitor && fMonitor->GetDebugMode()) {
401 const double dMsTime = (1e-9) * static_cast<double>(fulCurrentMsIdx);
402 if (uMsCompIdx < fMonitor->GetMaxNbFlibLinks()) {
403 if (fdStartTimeMsSz < 0) fdStartTimeMsSz = dMsTime;
404 fMonitor->FillMsSize(uMsCompIdx, uSize);
405 fMonitor->FillMsSizeTime(uMsCompIdx, dMsTime - fdStartTimeMsSz, uSize);
406 }
407 }
408
410 auto it = fDpbIdIndexMap.find(uCurrDpbId);
411 if (it == fDpbIdIndexMap.end()) {
412 if (false == fvbMaskedComponents[uMsCompIdx]) {
413 LOG(info) << "---------------------------------------------------------------";
414 //LOG(info) << FormatMsHeaderPrintout(msDescriptor);
415 LOG(warning) << "Could not find the sDPB index for AFCK id 0x" << std::hex << uCurrDpbId << std::dec
416 << " in timeslice " << fTsIndex << " in microslice " << uMsIdx << " component " << uMsCompIdx << "\n"
417 << "If valid this index has to be added in the STS "
418 "parameter file in the DbpIdArray field";
419 fvbMaskedComponents[uMsCompIdx] = true;
420
423 if (1 == fTsIndex) return true;
424 }
425 else
426 return true;
427
428 return false;
429 }
430 else
431 fuCurrDpbIdx = fDpbIdIndexMap[uCurrDpbId];
432
433 if (fMonitor) fMonitor->FillMsCntEvo(fulCurrentMsIdx);
434
435 // Check the current TS_MSb cycle and correct it if wrong
436 RefreshTsMsbFields(uMsIdx);
437
438 //Reset internal monitor variables for debugging info
439 if (fMonitor && fMonitor->GetDebugMode()) {
440 fMonitor->ResetDebugInfo();
441 }
442
443 //Main processing of MS content
444 LoopMsMessages(msContent, uSize, uMsIdx);
445
446 //Output debugging info
447 if (fMonitor) {
448 if (fMonitor->GetDebugMode()) {
449 fMonitor->PrintDebugInfo(fulCurrentMsIdx, fTsIndex, msDescriptor.flags, uSize);
450 }
451 for (auto itHit = fOutputVec.begin(); itHit != fOutputVec.end(); ++itHit) {
452 fMonitor->FillDigisTimeInRun(itHit->GetTime()); //check whether this does what it should
453 }
454 fMonitor->FillVectorSize(ts->index(), fOutputVec.size()); //check whether this does what it should
455 //fMonitor->DrawCanvases();
456 }
457
458 AddHitsToDigiVect(&fvmHitsInMs, &fOutputVec);
459
461 fvmHitsInMs.clear();
462
463 return true;
464}
465
466// -------------------------------------------------------------------------
468{
469 uint32_t uTsMsbCycleHeader;
470 if (fbUseFwBinning) {
472 }
473 else {
474 uTsMsbCycleHeader = std::floor(fulCurrentMsIdx / (stsxyter::kulTsCycleNbBins * stsxyter::kdClockCycleNs));
475 }
476
477 if (0 == uMsIdx) {
478 if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx])
479 LOG(info) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MS Idx "
480 << std::setw(4) << uMsIdx << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2) << fuCurrDpbIdx
481 << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy " << std::setw(5)
482 << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " New MsbCy " << uTsMsbCycleHeader;
483 fvuCurrentTsMsbCycle[fuCurrDpbIdx] = uTsMsbCycleHeader;
485 }
486 else if (uTsMsbCycleHeader != fvuCurrentTsMsbCycle[fuCurrDpbIdx]) {
487 if (4194303 == fvulCurrentTsMsb[fuCurrDpbIdx]) {
488 LOG(info) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MS Idx "
489 << std::setw(4) << uMsIdx << " Msg Idx " << std::setw(5) << 0 << " DPB " << std::setw(2) << fuCurrDpbIdx
490 << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy " << std::setw(5)
491 << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " New MsbCy " << uTsMsbCycleHeader;
492 }
493 else {
494 LOG(warning) << "TS MSB cycle from MS header does not match current cycle from data "
495 << "for TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MsInTs "
496 << std::setw(3) << uMsIdx << " ====> " << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " (cnt) VS "
497 << uTsMsbCycleHeader << " (header)";
498 }
499 fvuCurrentTsMsbCycle[fuCurrDpbIdx] = uTsMsbCycleHeader;
500 }
501}
502
503// -------------------------------------------------------------------------
504void CbmStsUnpackAlgoLegacy::LoopMsMessages(const uint8_t* msContent, const uint32_t uSize, const size_t uMsIdx)
505{
506 // If not integer number of message in input buffer, print warning/error
507 if (0 != (uSize % sizeof(stsxyter::Message))) {
508 LOG(error) << "The input microslice buffer does NOT "
509 << "contain only complete sDPB messages!";
510 }
511 // Compute the number of complete messages in the input microslice buffer
512 const uint32_t uNbMessages = (uSize - (uSize % sizeof(stsxyter::Message))) / sizeof(stsxyter::Message);
513
514 // Prepare variables for the loop on contents
515 const stsxyter::Message* pMess = reinterpret_cast<const stsxyter::Message*>(msContent);
516
517 for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx++) {
519 const stsxyter::MessType typeMess = pMess[uIdx].GetMessType();
520
521 if (fMonitor && fMonitor->GetDebugMode()) {
522 fMonitor->ProcessDebugInfo(pMess[uIdx], fuCurrDpbIdx);
523 }
524 switch (typeMess) {
526 ProcessHitInfo(pMess[uIdx]);
527 break;
528 }
530 ProcessTsMsbInfo(pMess[uIdx], uIdx, uMsIdx);
531 break;
532 }
534 ProcessEpochInfo(pMess[uIdx]);
535 if (0 < uIdx) {
536 LOG(info) << "CbmStsUnpackAlgoLegacy::DoUnpack => "
537 << "EPOCH message at unexpected position in MS: message " << uIdx << " VS message 0 expected!";
538 }
539 break;
540 }
542 ProcessStatusInfo(pMess[uIdx], uIdx);
543 break;
544 }
546 break;
547 }
549 ProcessErrorInfo(pMess[uIdx]);
550 break;
551 }
553 break;
554 }
555 default: {
556 LOG(fatal) << "CbmStsUnpackAlgoLegacy::DoUnpack => "
557 << "Unknown message type, should never happen, stopping "
558 "here! Type found was: "
559 << static_cast<int>(typeMess);
560 }
561 }
562 }
563}
564
565// -------------------------------------------------------------------------
567{
568 uint16_t usElinkIdx;
569 if (fbUseFwBinning) {
570 usElinkIdx = mess.GetLinkIndexHitBinning();
571 }
572 else {
573 usElinkIdx = mess.GetLinkIndex();
574 }
575 const uint32_t uCrobIdx = usElinkIdx / fUnpackPar->GetNbElinkPerCrob();
576 const int32_t uFebIdx = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
577 if (-1 == uFebIdx) {
578 LOG(warning) << "CbmStsUnpackAlgoLegacy::ProcessHitInfo => "
579 << "Wrong elink Idx! Elink raw " << Form("%d remap %d", usElinkIdx, uFebIdx);
580 return;
581 }
582 const uint32_t uAsicIdx =
583 (fuCurrDpbIdx * fUnpackPar->GetNbCrobsPerDpb() + uCrobIdx) * fUnpackPar->GetNbAsicsPerCrob()
584 + fUnpackPar->ElinkIdxToAsicIdx(1 == fviFebType[fuCurrDpbIdx][uCrobIdx][uFebIdx], usElinkIdx);
585 //LOG(info) << "Test " << uFebIdx << " " << uAsicIdx / fUnpackPar->GetNbAsicsPerFeb();
586 //const uint32_t uFebIdx = uAsicIdx / fUnpackPar->GetNbAsicsPerFeb(); // delete this?
587
588 const uint16_t usChan = mess.GetHitChannel();
589 const uint16_t usRawAdc = mess.GetHitAdc();
590 uint16_t usRawTs;
591 if (fbUseFwBinning) {
592 usRawTs = mess.GetHitTimeBinning();
593 }
594 else {
595 usRawTs = mess.GetHitTimeFull();
596 }
597 const uint32_t uChanInFeb = usChan + fUnpackPar->GetNbChanPerAsic() * (uAsicIdx % fUnpackPar->GetNbAsicsPerFeb());
598
601 if (usRawTs == fvvusLastTsChan[uAsicIdx][usChan]
602 && (fbDupliWithoutAdc || usRawAdc == fvvusLastAdcChan[uAsicIdx][usChan])
606 LOG(debug) << "CbmStsUnpackAlgoLegacy::ProcessHitInfo => "
607 << Form("Rejecting duplicate on Asic %3u channel %3u, TS %3u, MSB %lu, Cycle %u, ADC %2u", uAsicIdx,
608 usChan, usRawTs, fvulCurrentTsMsb[fuCurrDpbIdx], fvuCurrentTsMsbCycle[fuCurrDpbIdx], usRawAdc);
609 return;
610 } // if SMX 2.0 DPB and same TS, ADC, TS MSB, TS MSB cycle!
611 } // if (fbRejectDuplicateDigis)
612 fvvusLastTsChan[uAsicIdx][usChan] = usRawTs;
613 fvvusLastAdcChan[uAsicIdx][usChan] = usRawAdc;
616
617 // Compute the Full time stamp
618 const uint64_t ulHitTime = GetFullTimeStamp(usRawTs);
619
621 if (0 != fviFebAddress[uFebIdx] && fdAdcCut < usRawAdc) {
624 if (false == fbUseChannelMask || false == fvvbMaskedChannels[uFebIdx][uChanInFeb])
625 fvmHitsInMs.push_back(stsxyter::FinalHit(ulHitTime, usRawAdc, uAsicIdx, usChan, fuCurrDpbIdx, uCrobIdx));
626 }
627
628 // Convert the Hit time in bins to Hit time in ns
629 const double dHitTimeNs = ulHitTime * stsxyter::kdClockCycleNs;
630
632 if (mess.IsHitMissedEvts() && fOptOutBVec != nullptr)
633 fOptOutBVec->push_back(
634 CbmErrorMessage(ECbmModuleId::kSts, dHitTimeNs, uAsicIdx, 1 << stsxyter::kusLenStatStatus, usChan));
635
636 if (fMonitor) {
637 // Check Starting point of histos with time as X axis
638 if (-1 == fdStartTime) {
639 fdStartTime = dHitTimeNs;
640 }
641 if (fMonitor->GetDebugMode()) {
642 fMonitor->FillHitDebugMonitoringHistos(uAsicIdx, usChan, usRawAdc, usRawTs, mess.IsHitMissedEvts());
643 }
644 const uint32_t uAsicInFeb = uAsicIdx % fUnpackPar->GetNbAsicsPerFeb();
645 const double dTimeSinceStartSec = (dHitTimeNs - fdStartTime) * 1e-9;
646 const double dCalAdc = fvdFebAdcOffs[uFebIdx] + (usRawAdc - 1) * fvdFebAdcGain[uFebIdx];
647 fMonitor->FillHitMonitoringHistos(uFebIdx, usChan, uChanInFeb, usRawAdc, dCalAdc, usRawTs, mess.IsHitMissedEvts());
648 fMonitor->FillHitEvoMonitoringHistos(uFebIdx, uAsicIdx, uAsicInFeb, uChanInFeb, dTimeSinceStartSec,
649 mess.IsHitMissedEvts());
650 }
651}
652
653
654void CbmStsUnpackAlgoLegacy::ProcessTsMsbInfo(const stsxyter::Message& mess, uint32_t uMessIdx, uint32_t uMsIdx)
655{
656 uint32_t uVal;
657 if (fbUseFwBinning) {
658 uVal = mess.GetTsMsbValBinning();
659 }
660 else {
661 uVal = mess.GetTsMsbVal();
662 }
663
664 // Update Status counters
665 if (uVal < fvulCurrentTsMsb[fuCurrDpbIdx]) {
666
667 LOG(info) << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MS Idx "
668 << std::setw(4) << uMsIdx << " Msg Idx " << std::setw(5) << uMessIdx << " DPB " << std::setw(2)
669 << fuCurrDpbIdx << " Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " Old MsbCy "
670 << std::setw(5) << fvuCurrentTsMsbCycle[fuCurrDpbIdx] << " new TsMsb " << std::setw(5) << uVal;
671
673 }
674 if (
675 uVal != fvulCurrentTsMsb[fuCurrDpbIdx] + 1 && !(0 == uVal && 4194303 == fvulCurrentTsMsb[fuCurrDpbIdx])
676 &&
677 1 != uMessIdx &&
678 !(0 == uVal && 0 == fvulCurrentTsMsb[fuCurrDpbIdx] && 2 == uMessIdx) &&
679 !(uVal == fvulCurrentTsMsb[fuCurrDpbIdx] && 2 == uMessIdx)
680 &&
681 uVal < fvulCurrentTsMsb
682 [fuCurrDpbIdx]
683 ) {
684 LOG(info) << "TS MSb Jump in "
685 << " TS " << std::setw(12) << fTsIndex << " MS " << std::setw(12) << fulCurrentMsIdx << " MS Idx "
686 << std::setw(4) << uMsIdx << " Msg Idx " << std::setw(5) << uMessIdx << " DPB " << std::setw(2)
687 << fuCurrDpbIdx << " => Old TsMsb " << std::setw(5) << fvulCurrentTsMsb[fuCurrDpbIdx] << " new TsMsb "
688 << std::setw(5) << uVal;
689 }
690
693 if (4194303 == uVal && 1 == uMessIdx)
695 else
697
698 if (fMonitor && fMonitor->GetDebugMode()) { //also if( 1 < uMessIdx )?
699 fMonitor->FillStsDpbRawTsMsb(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
700 fMonitor->FillStsDpbRawTsMsbSx(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
701 fMonitor->FillStsDpbRawTsMsbDpb(fuCurrDpbIdx, fvulCurrentTsMsb[fuCurrDpbIdx]);
702 }
703}
704
706{
707 // Currently not used
708 // uint32_t uVal = mess.GetEpochVal();
709 // uint32_t uCurrentCycle = uVal % stsxyter::kulTsCycleNbBins;
710}
711
712// -------------------------------------------------------------------------
714{
715 if (fMonitor && fMonitor->GetDebugMode()) {
716 std::cout << Form("DPB %2u TS %12lu MS %12lu mess %5u ", fuCurrDpbIdx, fTsIndex, fulCurrentMsIdx, uIdx);
718 }
719
720 const uint16_t usElinkIdx = mess.GetStatusLink();
721 const uint32_t uCrobIdx = usElinkIdx / fUnpackPar->GetNbElinkPerCrob();
722 const int32_t uFebIdx = fUnpackPar->ElinkIdxToFebIdx(usElinkIdx);
723 if (-1 == uFebIdx) {
724 LOG(warning) << "CbmStsUnpackAlgoLegacy::DoUnpack => "
725 << "Wrong elink Idx! Elink raw " << Form("%d remap %d", usElinkIdx, uFebIdx);
726 return;
727 }
728 const uint32_t uAsicIdx =
729 (fuCurrDpbIdx * fUnpackPar->GetNbCrobsPerDpb() + uCrobIdx) * fUnpackPar->GetNbAsicsPerCrob()
730 + fUnpackPar->ElinkIdxToAsicIdx(1 == fviFebType[fuCurrDpbIdx][uCrobIdx][uFebIdx], usElinkIdx);
731
732 if (fMonitor) {
733 const uint16_t usStatusField = mess.GetStatusStatus();
734 fMonitor->FillStsStatusMessType(uAsicIdx, usStatusField);
735 }
737 const int64_t ulTime = GetFullTimeStamp(0);
738
740 const double dTimeNs = ulTime * stsxyter::kdClockCycleNs;
741 if (fOptOutBVec) {
742 fOptOutBVec->push_back(
743 CbmErrorMessage(ECbmModuleId::kSts, dTimeNs, uAsicIdx, mess.GetStatusStatus(), mess.GetData()));
744 }
745}
746
747// -------------------------------------------------------------------------
748uint64_t CbmStsUnpackAlgoLegacy::GetFullTimeStamp(const uint16_t usRawTs)
749{
750 // Use TS w/o overlap bits as they will anyway come from the TS_MSB
751
752 uint64_t ulTime;
753 if (fbUseFwBinning) {
754 ulTime =
755 usRawTs
756 + static_cast<uint64_t>(stsxyter::kuHitNbTsBinsBinning) * static_cast<uint64_t>(fvulCurrentTsMsb[fuCurrDpbIdx])
757 + static_cast<uint64_t>(stsxyter::kulTsCycleNbBinsBinning)
758 * static_cast<uint64_t>(fvuCurrentTsMsbCycle[fuCurrDpbIdx]);
759 }
760 else {
761 ulTime =
762 usRawTs
763 + static_cast<uint64_t>(stsxyter::kuHitNbTsBins) * (static_cast<uint64_t>(fvulCurrentTsMsb[fuCurrDpbIdx]) % 4);
764 }
765 return ulTime;
766}
767
768// -------------------------------------------------------------------------
770{
771 if (mess.IsMsErrorFlagOn()) {
772 if (fMonitor) {
773 fMonitor->FillMsErrorsEvo(fulCurrentMsIdx, mess.GetMsErrorType());
774 }
775 if (fOptOutBVec) {
776 fOptOutBVec->push_back(
778 }
779 }
780}
781
782// -------------------------------------------------------------------------
783void CbmStsUnpackAlgoLegacy::MaskNoisyChannel(const uint32_t uFeb, const uint32_t uChan, const bool bMasked)
784{
785 if (false == fbUseChannelMask) {
786 fbUseChannelMask = true;
788 for (uint32_t uFebIdx = 0; uFebIdx < fuNbFebs; ++uFebIdx) {
789 fvvbMaskedChannels[uFebIdx].resize(fUnpackPar->GetNbChanPerFeb(), false);
790 }
791 }
792 if (uFeb < fuNbFebs && uChan < fUnpackPar->GetNbChanPerFeb())
793 fvvbMaskedChannels[uFeb][uChan] = bMasked;
794 else
795 LOG(fatal) << "CbmStsUnpackAlgoLegacy::MaskNoisyChannel => Invalid FEB "
796 "and/or CHAN index:"
797 << Form(" %u vs %u and %u vs %u", uFeb, fuNbFebs, uChan, fUnpackPar->GetNbChanPerFeb());
798}
799// -------------------------------------------------------------------------
@ kSts
Silicon Tracking System.
Definition CbmDefs.h:48
bool Bool_t
CbmRoot (+externals) headers.
std::vector< double > fvdTimeOffsetNsAsics
Time offsets per Asic???
bool fbUseFwBinning
Enables firmware binning (some implementations ignore this)
uint32_t fdAdcCut
Minimum adc cut to store a hit.
bool fbRejectDuplicateDigis
Enables the rejection of duplicate digis.
std::shared_ptr< CbmStsUnpackMonitor > fMonitor
Potential (online) monitor for the unpacking process.
CbmStsUnpackAlgoBase(std::string name)
Create the Cbm Sts Unpack AlgoBase object.
bool fbDupliWithoutAdc
If rejecting duplicate digis, enables rejection even if ADC differs.
uint64_t GetFullTimeStamp(const uint16_t usRawTs)
Get full time stamp from raw time stamp.
std::vector< double > fvdFebAdcGain
Module side for each FEB, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
void PrintAddressMaps(const std::vector< std::vector< std::vector< int32_t > > > &viFebModuleIdx, const std::vector< std::vector< std::vector< int32_t > > > &viFebModuleSide)
void ProcessEpochInfo(const stsxyter::Message &mess)
void ProcessErrorInfo(const stsxyter::Message &mess)
void InitTempVectors(std::vector< int32_t > *viModuleType, std::vector< int32_t > *viModAddress, std::vector< std::vector< std::vector< int32_t > > > *viFebModuleIdx, std::vector< std::vector< bool > > *vbCrobActiveFlag, std::vector< std::vector< std::vector< int32_t > > > *viFebModuleSide)
std::vector< uint64_t > fvulCurrentTsMsb
std::map< uint32_t, uint32_t > fDpbIdIndexMap
Number of FEBs with StsXyter ASICs.
std::vector< stsxyter::FinalHit > fvmHitsInMs
Hits time-sorting.
CbmMcbm2018StsPar * fUnpackPar
Settings from parameter file.
bool initParSet(FairParGenericSet *parset)
ADC offset in e-, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
void InitDpbIdIndexMap()
Map of DPB Identifier to DPB index.
std::vector< bool > fvbMaskedComponents
Control flags.
std::vector< std::vector< uint16_t > > fvvusLastTsChan
std::vector< std::vector< bool > > fvvbMaskedChannels
uint32_t fuCurrDpbIdx
Current data properties.
void RefreshTsMsbFields(const size_t uMsIdx)
std::vector< int32_t > fviFebSide
STS address for each FEB, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
virtual void MaskNoisyChannel(const uint32_t uFeb, const uint32_t uChan, const bool bMasked=true)
Mask a Noisy Channel.
void PrintActiveCrobs(const std::vector< std::vector< bool > > &vbCrobActiveFlag)
void ProcessStatusInfo(const stsxyter::Message &mess, uint32_t uIdx)
std::chrono::steady_clock::time_point ftStartTimeUnix
void ProcessHitInfo(const stsxyter::Message &mess)
TS MSB cycle of last hit message for each channel, [ AsicIdx ][ Chan ].
std::vector< std::vector< std::vector< int32_t > > > fviFebType
std::vector< std::vector< uint32_t > > fvvuLastTsMsbChan
ADC of last hit message for each channel, [ AsicIdx ][ Chan ].
void ProcessTsMsbInfo(const stsxyter::Message &mess, uint32_t uMessIdx=0, uint32_t uMsIdx=0)
void AddHitsToDigiVect(std::vector< stsxyter::FinalHit > *vmHitsIn, std::vector< CbmStsDigi > *vDigiVectOut)
Add the hits to the output buffer as Digis.
void LoopMsMessages(const uint8_t *msContent, const uint32_t uSize, const size_t uMsIdx)
uint64_t fulCurrentMsIdx
Vector of channel masks, [ NbFeb ][ NbCHanInFeb ], used only if fbUseChannelMask is true.
std::vector< double > fvdFebAdcOffs
ADC gain in e-/b, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
bool unpack(const fles::Timeslice *ts, uint16_t icomp, UInt_t imslice)
Unpack a given microslice. To be implemented in the derived unpacker algos.
double fdTimeOffsetNs
User settings: Data correction parameters.
std::vector< uint32_t > fvuCurrentTsMsbCycle
Current TS MSB for each DPB.
std::vector< std::vector< uint16_t > > fvvusLastTsMsbCycleChan
TS MSB of last hit message for each channel, [ AsicIdx ][ Chan ].
std::vector< int32_t > fviFebAddress
Pulser flag for each FEB, [ NbDpb * NbCrobPerDpb * NbFebsPerCrob ].
std::vector< std::vector< uint16_t > > fvvusLastAdcChan
TS of last hit message for each channel, [ AsicIdx ][ Chan ].
std::vector< bool > fvbFebPulser
FEB type, [ NbDpb ][ NbCrobPerDpb ][ NbFebsPerCrob ], 0 = A, 1 = B, -1 if inactive.
static const uint32_t kuMaxTsMsbDiffDuplicates
All hits (time in bins, ADC in bins, asic, channel) in last MS, sorted with "<" operator.
XPU_D bool IsHitMissedEvts() const
For Hit data: Returns Missed event flag (1 bit field)
XPU_D uint32_t GetTsMsbValBinning() const
For TS MSB data: Returns the TS MSB 29 bit field)
XPU_D uint16_t GetHitAdc() const
For Hit data: Returns ADC value (5 bit field)
XPU_D uint16_t GetHitChannel() const
For Hit data: Returns StsXYTER channel number (7 bit field)
bool PrintMess(std::ostream &os, MessagePrintMask ctrl=MessagePrintMask::msg_print_Human, bool bBinning=true) const
XPU_D uint16_t GetLinkIndex() const
For all data: Returns the (global) index of the eLink on which the message was received (n bit field)
XPU_D uint16_t GetStatusStatus() const
For Status data: Returns the Status field from ACK frame (4 bit field)
XPU_D MessType GetMessType() const
Returns the message type, see enum MessType.
XPU_D uint16_t GetLinkIndexHitBinning() const
XPU_D uint32_t GetData() const
XPU_D uint32_t GetTsMsbVal() const
For TS MSB data: Returns the TS MSB 22 bit field)
XPU_D uint16_t GetHitTimeFull() const
For Hit data: Returns Full timestamp (10 bit field including 2 bits overlap)
XPU_D uint16_t GetHitTimeBinning() const
XPU_D uint16_t GetStatusLink() const
For Status data: Returns the Link Inedx (9 bit field)
XPU_D uint16_t GetMsErrorType() const
For End of MS data: Returns the MS error type field (2 bit field)
XPU_D bool IsMsErrorFlagOn() const
For End of MS data: Returns the MS error flag (1 bit field)
Hash for CbmL1LinkKey.
static constexpr uint32_t kuHitNbTsBinsBinning
static constexpr uint64_t kulTsCycleNbBins
static constexpr uint64_t kulTsCycleNbBinsBinning
static constexpr uint32_t kuHitNbTsBins
static constexpr double kdClockCycleNs
MessType
Message types.
static constexpr uint16_t kusLenStatStatus