Belle II Software  release-05-02-19
CDCTriggerUnpackerModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2013 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Tzu-An Sheng *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <trg/cdc/modules/unpacker/CDCTriggerUnpackerModule.h>
12 #include <framework/core/ModuleParam.templateDetails.h>
13 #include <trg/cdc/dbobjects/CDCTriggerNeuroConfig.h>
14 
15 #include <array>
16 #include <bitset>
17 #include <string>
18 #include <numeric>
19 #include <algorithm>
20 
21 using namespace Belle2;
22 using namespace CDCTriggerUnpacker;
23 
24 
25 //-----------------------------------------------------------------
26 // Register the Module
27 //-----------------------------------------------------------------
28 REG_MODULE(CDCTriggerUnpacker)
29 
30 //-----------------------------------------------------------------
31 // Implementation
32 //-----------------------------------------------------------------
33 
34 constexpr std::array<int, 9> CDCTriggerUnpackerModule::nMergers;
35 using dataWord = std::bitset<wordWidth>;
36 
37 namespace Belle2 {
42  //-----------------------------------------------------------------
43  // Definition of Subtriggers
44  //-----------------------------------------------------------------
45  /*
46  * To implement an unpacker for a new subtrigger module,
47  * 1. Declare a new struct, inherit from SubTrigger
48  * 2. Hold the pointers to the bitstream(s)
49  * 3. declare as many variables as needed
50  * 4. Implement the virtual methods reserve() and unpack()
51  * 5. Instantiate it in initialize() (one object for one UT3)
52  * 6. Push them back to m_subTrigger
53  */
54 
56  struct Merger : SubTrigger {
58  Merger(StoreArray<MergerBits>* inArrayPtr, std::string inName,
59  unsigned inEventWidth, unsigned inOffset,
60  int inHeaderSize, std::vector<int> inNodeID,
61  unsigned inNInnerMergers, int& inDelay,
62  int& inCnttrg,
63  int inDebugLevel) :
64  SubTrigger(inName, inEventWidth, inOffset,
65  inHeaderSize, inNodeID, inDelay, inCnttrg, inDebugLevel),
66  arrayPtr(inArrayPtr),
67  nInnerMergers(inNInnerMergers) {};
68 
70  StoreArray<MergerBits>* arrayPtr;
72  unsigned nInnerMergers;
74  void reserve(int subDetectorId, std::array<int, nFinesse> nWords) override
75  {
76  if (subDetectorId != iNode) {
77  return;
78  }
79  if (nWords[iFinesse] < headerSize) {
80  return;
81  }
82  size_t nClocks = (nWords[iFinesse] - headerSize) / eventWidth;
83  size_t entries = arrayPtr->getEntries();
84  if (entries == 0) {
85  for (unsigned i = 0; i < nClocks; ++i) {
86  arrayPtr->appendNew();
87  }
88  B2DEBUG(20, name << ": " << nClocks << " clocks");
89  } else if (entries != nClocks) {
90  B2DEBUG(20, "Number of clocks in " << name << " conflicts with others!");
91  }
92  };
93 
95  void unpack(int subDetectorId,
96  std::array<int*, 4> data32tab,
97  std::array<int, 4> nWords)
98  {
99  if (subDetectorId != iNode) {
100  return;
101  }
102  if (nWords[iFinesse] < headerSize) {
103  B2DEBUG(20, "The module " << name << " does not have enough data (" <<
104  nWords[iFinesse] << "). Nothing will be unpacked.");
105  // TODO: need to clear the output bitstream because we return early here
106  return;
107  }
108  // make bitstream
109  // loop over all clocks
110  for (int i = headerSize; i < nWords[iFinesse]; i += eventWidth) {
111  int iclock = (i - headerSize) / eventWidth;
112  auto mergerClock = (*arrayPtr)[iclock];
113  B2DEBUG(100, "clock " << iclock);
114  // loop over all mergers
115  for (unsigned j = offset; j < eventWidth; ++j) {
116  int iMerger = (eventWidth - j - 1) / 8 + nInnerMergers;
117  int pos = (eventWidth - j - 1) % 8;
118  dataWord word(data32tab[iFinesse][i + j]);
119  for (int k = 0; k < wordWidth; ++k) {
120  mergerClock->m_signal[iMerger].set(pos * wordWidth + k, word[k]);
121  }
122  }
123  }
124  if (debugLevel >= 300) {
125  printBuffer(data32tab[iFinesse] + headerSize, eventWidth);
126  B2DEBUG(20, "");
127  printBuffer(data32tab[iFinesse] + headerSize + eventWidth, eventWidth);
128  }
129  for (int i = 0; i < std::accumulate(nMergers.begin(), nMergers.end(), 0); ++i) {
130  B2DEBUG(99, (*arrayPtr)[0]->m_signal[i].to_string());
131  }
132  }
133  };
134 
139  StoreArray<T2DOutputBitStream>* outArrayPtr,
140  std::string inName, unsigned inEventWidth, unsigned inOffset,
141  unsigned inHeaderSize, std::vector<int> inNodeID,
142  unsigned inNumTS, int& inDelay,
143  int& inCnttrg,
144  int inDebugLevel) :
145  SubTrigger(inName, inEventWidth, inOffset / wordWidth, inHeaderSize, inNodeID,
146  inDelay, inCnttrg, inDebugLevel),
147  inputArrayPtr(inArrayPtr), outputArrayPtr(outArrayPtr),
148  iTracker(std::stoul(inName.substr(inName.length() - 1))),
149  numTS(inNumTS), offsetBitWidth(inOffset) {};
150 
152  StoreArray<TSFOutputBitStream>* inputArrayPtr;
156  unsigned iTracker;
158  unsigned numTS;
160  unsigned offsetBitWidth;
161 
170  void reserve(int subDetectorId, std::array<int, nFinesse> nWords) override
171  {
172  size_t nClocks = (nWords[iFinesse] - headerSize) / eventWidth;
173  size_t entries = inputArrayPtr->getEntries();
174  if (subDetectorId == iNode) {
175  if (entries == 0) {
176  for (unsigned i = 0; i < nClocks; ++i) {
177  TSFOutputBitStream* inputClock = inputArrayPtr->appendNew();
178  T2DOutputBitStream* outputClock = outputArrayPtr->appendNew();
179  // fill bitstreams for all trackers with zeros
180  for (unsigned j = 0; j < nTrackers; ++j) {
181  for (unsigned iAxialTSF = 0; iAxialTSF < nAxialTSF; ++iAxialTSF) {
182  inputClock->m_signal[iAxialTSF][j].fill(zero_val);
183  }
184  outputClock->m_signal[j].fill(zero_val);
185  }
186  }
187  B2DEBUG(20, name << ": " << nClocks << " clocks");
188  } else if (entries != nClocks) {
189  B2DEBUG(20, "Number of clocks in " << name << " conflicts with others!");
190  }
191  }
192  };
193 
203  void unpack(int subDetectorId,
204  std::array<int*, 4> data32tab,
205  std::array<int, 4> nWords)
206  {
207  if (subDetectorId != iNode) {
208  return;
209  }
210  // Recently, the content of the last clock appears at the beginning.
211  // Now we decide whether we will change the order of the clocks
212  // based on the 127MHz counter on the 2nd half of the first word [15:0]
213  int ccShift = 0;
214  using halfDataWord = std::bitset<16>;
215  std::vector<halfDataWord> counters;
216  counters.reserve(inputArrayPtr->getEntries());
217  for (int iclock = 0; iclock < inputArrayPtr->getEntries(); ++iclock) {
218  counters.emplace_back(data32tab[iFinesse]
219  [headerSize + eventWidth * iclock] & 0xffff);
220  B2DEBUG(100, "iclock " << iclock << " --> " << counters.at(iclock).to_ulong() << " : " << std::hex << counters.at(iclock));
221  }
222  bool counter_correct_error = false;
223  while (counters.at(1).to_ulong() - counters.at(0).to_ulong() != 4) {
224  std::rotate(counters.begin(), counters.begin() + 1, counters.end());
225  ccShift++;
226  // 2019,0410 This situation, looks like clockcounter shifted 6 bits left, was first seen in exp5 data.
227  // Later it has been understood that it is due to data from a dummy BRAM buffer, which is supposed to be used for suppressed data only.
228  // The data header is 0xbbbb instead of 0xdddd.
229  // getHeader in the CDCTriggerUnpackerModule.h is modified to skip this kind event.
230  // 2019,0419 unfortunately, clockcounter found disorder since expt 7, run 2553, after update of B2L firmware to replace the b2dly with trigger counter.
231  // for that run, it seems the problem happens only at 2D1, 2D2, and 2D3.
232  if (ccShift >= inputArrayPtr->getEntries()) {
233  B2DEBUG(90, "PHYSJG: clock counter rotation over one cycle: " << ccShift);
234  for (const auto& c : counters) {
235  B2DEBUG(90, "" << c.to_ulong() << " : " << std::hex << c);
236  }
237  counter_correct_error = true;
238  break;
239  }
240  }
241  if (counter_correct_error) {
242  B2DEBUG(20, "PHYSJG: " << name << " too many clock counter rotation corrections: " << ccShift << " data object skipped.");
243  // maybe implement an option for user to decide if this data block should be kept or not?!
244  return;
245  }
246  if (! std::is_sorted(counters.begin(), counters.end(),
247  [](halfDataWord i, halfDataWord j) {
248  return (j.to_ulong() - i.to_ulong() == 4);
249  })) {
250  B2DEBUG(20, "clock counters are still out of order");
251  for (const auto& c : counters) {
252  B2DEBUG(90, "" << c.to_ulong());
253  }
254  }
255  // This could happen when the clock counter is over 1279 and roll back to 0, since only 48 clock counter will be in the data.
256  if (ccShift) {
257  B2DEBUG(15, "shifting the first " << ccShift <<
258  " clock(s) to the end for " << name);
259  }
260 
261  // get event body information
262  // make bitstream
263  // loop over all clocks
264  for (int i = headerSize; i < nWords[iFinesse]; i += eventWidth) {
265  int iclock = (i - headerSize) / eventWidth - ccShift;
266  if (iclock < 0) {
267  iclock += inputArrayPtr->getEntries();
268  }
269  auto inputClock = (*inputArrayPtr)[iclock];
270  auto outputClock = (*outputArrayPtr)[iclock];
271  // clear output bitstream
272  outputClock->m_signal[iTracker].fill(zero_val);
273  B2DEBUG(90, "unpacker clock " << iclock);
274  if (debugLevel >= 300) {
275  printBuffer(data32tab[iFinesse] + headerSize + eventWidth * iclock,
276  eventWidth);
277  }
278  // get the clock counters
279  std::array<dataWord, 2> ccword({
280  data32tab[iFinesse][i + 2], data32tab[iFinesse][i + 3]
281  });
282  // fill input
283  // Careful! this iTSF is (8 - iSL) / 2
284  for (unsigned iTSF = 0; iTSF < nAxialTSF; ++iTSF) {
285  // clear input bitstream
286  inputClock->m_signal[nAxialTSF - 1 - iTSF][iTracker].fill(zero_val);
287 
288  if (firmwareVersion < "18012600") {
289  /*
290  data_b2l_r <=
291  x"dddd" & cntr125M(15 downto 0) &
292  cc(4) & cc(3) & cc(2) & cc(1) & cc(0) &
293  ccError &
294  -- 82
295  tsfs(4)(209 downto 0) &
296  tsfs(3)(209 downto 0) &
297  tsfs(2)(209 downto 0) &
298  tsfs(1)(209 downto 0) &
299  tsfs(0)(209 downto 0) &
300  */
301  // fill the clock counters
302  for (unsigned pos = 0; pos < clockCounterWidth; ++pos) {
303  const int j = (pos + iTSF * clockCounterWidth) / wordWidth;
304  const int k = (pos + iTSF * clockCounterWidth) % wordWidth;
305  /* The index behaves differently in each containers
306  Here is an example of a 64-bit wide MSB data
307  |-------- smaller index in the firmware ----->
308 
309  data in the firmware/VHDL std_logic_vector(63 downto 0)
310  63 62 61 60 ... 01 00
311 
312  data in B2L/RawTRG (when using std::bitset<32> for a word)
313  (31 30 29 28 ... 01 00) (31 30 29 28 ... 01 00)
314  |------ word 0 -------| |------ word 1 -------|
315 
316  XSim / Bitstream of std::array<char, N> / std::string
317  00 01 02 03 ... 62 63
318  */
319  // Here we are filling std::array<char, N>, which has reversed order
320  // to std::bitset, so there is a - sign in [wordWidth - k]
321  inputClock->m_signal[nAxialTSF - 1 - iTSF][iTracker][pos] =
322  std_logic(ccword[j][wordWidth - k]);
323  }
324  // fill the TS hit
325  offsetBitWidth = 82;
326  for (unsigned pos = 0; pos < numTS * lenTS; ++pos) {
327  const int j = (offsetBitWidth + pos + iTSF * numTS * lenTS) / wordWidth;
328  const int k = (offsetBitWidth + pos + iTSF * numTS * lenTS) % wordWidth;
329  dataWord word(data32tab[iFinesse][i + j]);
330  // MSB (leftmost) in firmware -> smallest index in Bitstream's
331  // std::array (due to XSIM) -> largest index in std::bitset
332  // so the index is reversed in this assignment
333  inputClock->m_signal[nAxialTSF - 1 - iTSF][iTracker]
334  [clockCounterWidth + pos] = std_logic(word[wordWidth - 1 - k]);
335  }
336  } else {
337  /*
338  x"dddd" & (15 downto 11 => '0') & revoclk &
339  cntr125M(15 downto 0) &
340  (15 downto 5 => '0') & ccError &
341  -- 64
342  cc(4) & tsfs(4)(209 downto 0) &
343  cc(3) & tsfs(3)(209 downto 0) &
344  cc(2) & tsfs(2)(209 downto 0) &
345  cc(1) & tsfs(1)(209 downto 0) &
346  cc(0) & tsfs(0)(209 downto 0) &
347  */
348  // fill the cc and TS hit
349  offsetBitWidth = 64;
350  unsigned TSFWidth = clockCounterWidth + numTS * lenTS;
351  for (unsigned pos = 0; pos < TSFWidth; ++pos) {
352  const int j = (offsetBitWidth + pos + iTSF * TSFWidth) / wordWidth;
353  const int k = (offsetBitWidth + pos + iTSF * TSFWidth) % wordWidth;
354  dataWord word(data32tab[iFinesse][i + j]);
355  inputClock->m_signal[nAxialTSF - 1 - iTSF][iTracker][pos] =
356  std_logic(word[wordWidth - 1 - k]);
357  }
358  }
359  if (debugLevel >= 100) {
360  display_hex(inputClock->m_signal[nAxialTSF - 1 - iTSF][iTracker]);
361  }
362  }
363  // fill output
364  if (firmwareVersion < "18012600") {
365  /*
366  -- 1132
367  Main_out(731 downto 0) &
368  */
369  const int outputOffset = nAxialTSF * numTS * lenTS;
370  const int oldtrackWidth = 6;
371  for (unsigned pos = 0; pos < 732; ++pos) {
372  const int j = (offsetBitWidth + pos + outputOffset) / wordWidth;
373  const int k = (offsetBitWidth + pos + outputOffset) % wordWidth;
374  dataWord word(data32tab[iFinesse][i + j]);
375  outputClock->m_signal[iTracker][clockCounterWidth + oldtrackWidth + pos]
376  = std_logic(word[wordWidth - 1 - k]);
377  }
378  } else {
379  /*
380  -- 1159
381  old_track(5 downto 0) &
382  Main_out(731 downto 0) &
383  */
384  //const int outputOffset = 1159;
385  const int outputOffset = offsetBitWidth + nAxialTSF * numTS * lenTS + 45; //1159 with numTS=10 , 1684 with numTS=15
386  for (unsigned pos = 0; pos < T2DOutputWidth; ++pos) {
387  const int j = (pos + outputOffset) / wordWidth;
388  const int k = (pos + outputOffset) % wordWidth;
389  dataWord word(data32tab[iFinesse][i + j]);
390  outputClock->m_signal[iTracker][clockCounterWidth + pos]
391  = std_logic(word[wordWidth - 1 - k]);
392  }
393  }
394  if (debugLevel >= 100) {
395  display_hex(outputClock->m_signal[iTracker]);
396  }
397  }
398  }
399  };
400 
402  struct Neuro : SubTrigger {
405  std::string inName, unsigned inEventWidth, unsigned inOffset,
406  unsigned inHeaderSize, std::vector<int> inNodeID, int& inDelay,
407  int& inCnttrg,
408  int inDebugLevel) :
409  SubTrigger(inName, inEventWidth, inOffset / wordWidth, inHeaderSize, inNodeID,
410  inDelay, inCnttrg, inDebugLevel),
411  ArrayPtr(arrPtr),
412  iTracker(std::stoul(inName.substr(inName.length() - 1))),
413  offsetBitWidth(inOffset) {};
414 
416  StoreArray<NNBitStream>* ArrayPtr;
418  unsigned iTracker;
420  unsigned offsetBitWidth;
421 
422  void reserve(int subDetectorId, std::array<int, nFinesse> nWords) override
423  {
424  size_t nClocks = (nWords[iFinesse] - headerSize) / eventWidth;
425  size_t entries = ArrayPtr->getEntries();
426  if (subDetectorId == iNode) {
427  if (entries == 0) {
428  for (unsigned i = 0; i < nClocks; ++i) {
429  NNBitStream* nnclock = ArrayPtr->appendNew();
430  // fill bitstreams for all trackers with zeros
431  for (unsigned j = 0; j < nTrackers; ++j) {
432  nnclock->m_signal[j].fill(zero_val);
433  }
434  }
435  B2DEBUG(20, name << ": " << nClocks << " clocks");
436  } else if (entries != nClocks) {
437  B2DEBUG(20, "Number of clocks in " << name << " conflicts with others!");
438  }
439  }
440  };
441 
442  void unpack(int subDetectorId,
443  std::array<int*, nFinesse> data32tab,
444  std::array<int, nFinesse> nWords) override
445  {
446  if (subDetectorId != iNode) {
447  return;
448  }
449  // make bitstream
450  // loop over all clocks
451  for (int i = headerSize; i < nWords[iFinesse]; i += eventWidth) {
452  int iclock = (i - headerSize) / eventWidth;
453  auto nnclock = (*ArrayPtr)[iclock];
454  B2DEBUG(20, "clock " << iclock);
455  if (debugLevel >= 300) {
456  printBuffer(data32tab[iFinesse] + headerSize + eventWidth * iclock,
457  eventWidth);
458  }
459  // fill output
460  for (unsigned pos = 0; pos < NN_WIDTH; ++pos) {
461  const int j = (offsetBitWidth + pos) / wordWidth;
462  const int k = (offsetBitWidth + pos) % wordWidth;
463  std::bitset<wordWidth> word(data32tab[iFinesse][i + j]);
464  nnclock->m_signal[iTracker][pos] = std_logic(word[wordWidth - 1 - k]);
465  }
466  if (debugLevel >= 100) {
467  display_hex(nnclock->m_signal[iTracker]);
468  }
469  }
470  }
471  };
473 };
474 
476 {
477  // Set module properties
478  setDescription("Unpack the CDC trigger data recorded in B2L");
480 
481  // Parameter definitions
482  addParam("unpackMerger", m_unpackMerger,
483  "whether to unpack merger data (recorded by Merger Reader / TSF)", false);
484  addParam("unpackTracker2D", m_unpackTracker2D,
485  "whether to unpack 2D tracker data", false);
486  addParam("unpackNeuro", m_unpackNeuro,
487  "whether to unpacker neurotrigger data", false);
488  addParam("decode2DFinderTrack", m_decode2DFinderTrack,
489  "flag to decode 2D finder track", false);
490  addParam("decode2DFinderInput", m_decode2DFinderInputTS,
491  "flag to decode input TS to 2D", false);
492  addParam("decodeNeuro", m_decodeNeuro,
493  "flag to decode neurotrigger data", false);
494  // https://confluence.desy.de/display/BI/DAQ+and+Operation for CPR/HSLB
495  NodeList defaultMergerNodeID = { // These should be very temporary ones since no merger to B2L yet.
496  {0x11000001, 0},
497  {0x11000003, 0},
498  {0x11000001, 1},
499  {0x11000002, 0},
500  {0x11000002, 1}
501  };
502  addParam("MergerNodeId", m_mergerNodeID,
503  "list of COPPER and HSLB ID of Merger reader (TSF)", defaultMergerNodeID);
504  NodeList defaultTracker2DNodeID = {
505  {0x11000001, 0},
506  {0x11000001, 1},
507  {0x11000002, 0},
508  {0x11000002, 1}
509  };
510  addParam("2DNodeId", m_tracker2DNodeID,
511  "list of COPPER and HSLB ID of 2D tracker", defaultTracker2DNodeID);
512  NodeList defaultNeuroNodeID = {
513  {0x11000005, 0},
514  {0x11000005, 1},
515  {0x11000006, 0},
516  {0x11000006, 1}
517  };
518  addParam("NeuroNodeId", m_neuroNodeID,
519  "list of COPPER and HSLB ID of neurotrigger", defaultNeuroNodeID);
520  addParam("headerSize", m_headerSize,
521  "number of words (number of bits / 32) of the B2L header", 3);
522  addParam("alignFoundTime", m_alignFoundTime,
523  "Whether to align out-of-sync Belle2Link data between different sub-modules", true);
524  addParam("useDB", m_useDB,
525  "Use values stored in the payload of the ConditionsDB."
526  "This affects the output scaling of the Neurotrigger as well as the"
527  "bit configuration of its unpacker. If false, an old unpacker version with fixed scalings and old bit adresses is used.",
528  true);
529  addParam("sim13dt", m_sim13dt,
530  "Simulate 13 bit drift time by using 2d clock counter value.",
531  false);
532 }
533 
535 {
537 
538  //m_rawTriggers.isRequired();
539  if (m_unpackMerger) {
540  m_mergerBits.registerInDataStore("CDCTriggerMergerBits");
541  }
542  if (m_unpackTracker2D) {
543  m_bitsTo2D.registerInDataStore("CDCTriggerTSFTo2DBits");
544  m_bits2DTo3D.registerInDataStore("CDCTrigger2DTo3DBits");
545  }
546  if (m_unpackNeuro) {
547  m_bitsNN.registerInDataStore("CDCTriggerNNBits");
548  }
551  m_TSHits.registerInDataStore("CDCTriggerSegmentHits");
552  }
553  if (m_decode2DFinderTrack) {
554  m_2DFinderTracks.registerInDataStore("CDCTrigger2DFinderTracks");
555  m_2DFinderTracks.registerRelationTo(m_TSHits);
556  m_2DFinderClones.registerInDataStore("CDCTrigger2DFinderClones");
557  m_2DFinderClones.registerRelationTo(m_2DFinderTracks);
558  }
559  if (m_decodeNeuro) {
560  m_NNInputTSHitsAll.registerInDataStore("CDCTriggerNNInputAllStereoSegmentHits");
561  m_NNInputTSHits.registerInDataStore("CDCTriggerNNInputSegmentHits");
562  m_NNInput2DFinderTracks.registerInDataStore("CDCTriggerNNInput2DFinderTracks");
563  m_NeuroTracks.registerInDataStore("CDCTriggerNeuroTracks");
564  m_NeuroInputs.registerInDataStore("CDCTriggerNeuroTracksInput");
565  m_NeuroTracks.registerRelationTo(m_NNInputTSHits);
566  m_NNInput2DFinderTracks.registerRelationTo(m_NNInputTSHits);
567  m_NNInput2DFinderTracks.registerRelationTo(m_NNInputTSHitsAll);
568  m_NNInput2DFinderTracks.registerRelationTo(m_NeuroTracks);
569  m_NeuroTracks.registerRelationTo(m_NNInput2DFinderTracks);
570  m_NeuroTracks.registerRelationTo(m_NeuroInputs);
571  }
572  for (int iSL = 0; iSL < 9; iSL += 2) {
573  if (m_unpackMerger) {
574  const int nInnerMergers = std::accumulate(nMergers.begin(),
575  nMergers.begin() + iSL, 0);
576  B2DEBUG(20, "in: " << nInnerMergers);
577  Merger* m_merger =
578  new Merger(&m_mergerBits,
579  "Merger" + std::to_string(iSL), mergerWidth * nMergers[8] / wordWidth,
581  m_mergerNodeID[iSL / 2], nInnerMergers,
583  m_debugLevel);
584  m_subTrigger.push_back(dynamic_cast<SubTrigger*>(m_merger));
585  }
586  }
587  // TODO In the default scenario, data in all trackers will be recorded.
588  // This is not the case for now (around first collision), where some coppers are lacking.
589  // Therefore it might help to make the following code more flexible
590  // so that we won't have a hard fail when some boards are missing
591 
592  m_n2DTS = m_dbn2DTS->getnTS();
593  int datasize_2D = 64;
594  if (m_n2DTS == 10) {
595  datasize_2D = 64;
596  } else if (m_n2DTS == 15) {
597  datasize_2D = 82;
598  }
599 
600  for (int iTracker = 0; iTracker < 4; ++iTracker) {
601  if (m_unpackTracker2D) {
602  Tracker2D* m_tracker2d =
604  "Tracker2D" + std::to_string(iTracker), datasize_2D, 82, m_headerSize,
605  m_tracker2DNodeID[iTracker], m_n2DTS,
607  m_debugLevel);
608  m_subTrigger.push_back(dynamic_cast<SubTrigger*>(m_tracker2d));
609  }
610  if (m_unpackNeuro) {
611  Neuro* m_neuro =
612  new Neuro(&m_bitsNN,
613  "Neuro" + std::to_string(iTracker), 64, 0, m_headerSize,
615  m_subTrigger.push_back(dynamic_cast<SubTrigger*>(m_neuro));
616  }
617  }
618 }
619 
621 {
622  for (auto bits : m_subTrigger) {
623  delete bits;
624  }
625 }
626 
628 {
629 
631  m_exp = bevt->getExperiment();
632  m_run = bevt->getRun();
633 
634  if (not m_cdctriggerneuroconfig.isValid())
635  B2FATAL("CDCTriggerNeuroConfig is not valid.");
636  if (m_useDB == true) {
637  B2DEBUG(2, "Load Neurotrigger configuration for network " << m_cdctriggerneuroconfig->getNNName() << " from database ");
638  B2DEBUG(10, padright("Name", 50) << padright("start", 10) << padright("end", 10) << padright("offset", 10));
639  for (auto x : m_cdctriggerneuroconfig->getB2Format()) {
640  B2DEBUG(10, padright(x.name, 48) << ": " << padright(std::to_string(x.start), 10) << padright(std::to_string(x.end),
641  10) << padright(std::to_string(x.offset), 10));
642  }
643  }
644 }
645 
646 
648 {
649 
650  B2DEBUG(10, padright(" ", 100));
651  B2DEBUG(10, "----------------------------------------------------------------------------------------------------");
652  B2DEBUG(10, padright(" ", 100));
653  StoreObjPtr<EventMetaData> eventMetaData;
654  std::string experimentstring = "Experiment " + std::to_string(eventMetaData->getExperiment()) + " Run " +
655  std::to_string(eventMetaData->getRun()) + " Event " + std::to_string(eventMetaData->getEvent());
656  B2DEBUG(10, padright(experimentstring, 100));
657 
658  setReturnValue(0);
659 
660  if (m_exp < 7) {
661  B2DEBUG(20, "exp<7: skip cdctrg unpacker for DQM");
662  return;
663  }
664 
665  // Read RawTRG data block.
666  B2DEBUG(99, m_rawTriggers.getEntries() << " COPPERs in RawTRGs");
667 
668  // loop over all COPPERs
669  for (auto& rawTRG : m_rawTriggers) {
670  const int subDetectorId = rawTRG.GetNodeID(0);
671  // const int iNode = (subDetectorId & 0xFFFFFF);
672  // number of entries in the rawTRG object.
673  const int nEntriesRawTRG = rawTRG.GetNumEntries();
674 
675  // number of entries in rawTRG object ()
676  B2DEBUG(99, "nEntries of rawTRG: " << nEntriesRawTRG);
677  for (int j = 0; j < nEntriesRawTRG; ++j) {
678  //
679  // Search Data from Finesse A to D (0->3).
680  //
681  std::array<int, nFinesse> nWords;
682  std::array<int*, nFinesse> data32tab;
683  nWords.fill(0);
684 
685  for (int iFinesse = 0; iFinesse < nFinesse; ++iFinesse) {
686  nWords[iFinesse] = rawTRG.GetDetectorNwords(j, iFinesse);
687  if (nWords[iFinesse] == 0) {
688  continue;
689  }
690  data32tab[iFinesse] = (int*)rawTRG.GetDetectorBuffer(j, iFinesse);
691  }
692 
693  for (auto trg : m_subTrigger) {
694  // only unpack when there are enough words in the event
695  if (trg->getHeaders(subDetectorId, data32tab, nWords)) {
696  trg->reserve(subDetectorId, nWords);
697  B2DEBUG(99, "starting to unpack a subTrigger, subDetectorId" << std::hex << subDetectorId);
698  trg->unpack(subDetectorId, data32tab, nWords);
699  setReturnValue(1);
700  }
701  }
702  }
703  B2DEBUG(99, "looped over entries and filled words " << nEntriesRawTRG);
704  }
705  B2DEBUG(99, "looped over rawTriggers, unpacking 2D ");
706 
707  // decode bitstream and make TSIM objects
708  if (m_decode2DFinderTrack) {
709  for (short iclock = 0; iclock < m_bits2DTo3D.getEntries(); ++iclock) {
710  decode2DOutput(iclock - m_2DFinderDelay,
711  m_bits2DTo3D[iclock],
714  &m_TSHits);
715  }
716  }
717  B2DEBUG(99, "unpack 2D Input TS ");
719  std::array<int, 4> clockCounter2D = {0, 0, 0, 0};
720  std::array<int, 4> timeOffset2D = {0, 0, 0, 0};
721  // Align the data in other boards to 2D0 by looking at the CC in the midpoint of the time window
722  for (int iTracker = 0; iTracker < nTrackers; ++iTracker) {
723  if (! m_alignFoundTime || m_bitsTo2D.getEntries() == 0) {
724  break;
725  }
726  auto& trackerData = m_bitsTo2D[m_bitsTo2D.getEntries() / 2]->signal()[0][iTracker];
727  std::string strInput = slv_to_bin_string(trackerData);
728  clockCounter2D[iTracker] = std::stoi(strInput.substr(0, clockCounterWidth), 0, 2);
729  int clockCounterDiff = clockCounter2D[iTracker] - clockCounter2D[0];
730  /*
731  // clock counter rolls back to 0 from 319
732  if (clockCounterDiff > 300) {
733  clockCounterDiff -= 320;
734  } else if (clockCounterDiff < -300) {
735  clockCounterDiff += 320;
736  }
737  */
738  // clock counter rolls back to 0 from 1279, since certain B2L version, it has been changed to like this
739  if (clockCounterDiff > 1250) {
740  clockCounterDiff -= 1280;
741  } else if (clockCounterDiff < -1250) {
742  clockCounterDiff += 1280;
743  }
744  timeOffset2D[iTracker] = clockCounterDiff;
745  if (clockCounterDiff != 0) {
746  B2DEBUG(100, "Adding " << clockCounterDiff << " clock(s) to 2D" << iTracker << " found time");
747  }
748  if (std::abs(clockCounterDiff) > 2) {
749  B2DEBUG(20, "Clock counters between 2D [0," << iTracker << "] differ by " << clockCounterDiff << " clocks! (" \
750  << clockCounter2D[0] << ", " << clockCounter2D[iTracker] << ")");
751  }
752  }
753  for (short iclock = 0; iclock < m_bitsTo2D.getEntries(); ++iclock) {
754  B2DEBUG(30, "clock " << iclock);
755  decode2DInput(iclock - m_2DFinderDelay, timeOffset2D, m_bitsTo2D[iclock], &m_TSHits);
756  }
757  }
758  B2DEBUG(99, "now unpack neuro ");
759  if (m_decodeNeuro) {
760  if (m_useDB == true) {
763  } else {
765  }
766  }
767  B2DEBUG(99, " all is unpacked ##### ");
768 }
769 
Belle2::CDCTriggerUnpackerModule::m_2DFinderClones
StoreArray< CDCTriggerFinderClone > m_2DFinderClones
additional information of the 2D finder track
Definition: CDCTriggerUnpackerModule.h:304
Belle2::StoreArray::appendNew
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:256
Belle2::CDCTriggerUnpackerModule::beginRun
virtual void beginRun()
begin Run
Definition: CDCTriggerUnpackerModule.cc:627
Belle2::nFinesse
static constexpr int nFinesse
Number of FINESSE in the copper.
Definition: CDCTriggerUnpackerModule.h:59
Belle2::SubTrigger
enum class SubTriggerType : unsigned char {Merger, TSF, T2D, T3D, Neuro, ETF};
Definition: CDCTriggerUnpackerModule.h:66
Belle2::wordWidth
static constexpr int wordWidth
width of a single word in the raw int buffer
Definition: CDCTriggerUnpackerModule.h:57
Belle2::CDCTriggerUnpackerModule::m_sim13dt
bool m_sim13dt
bool value wether to simulate 13 bit drift time by using 2dcc
Definition: CDCTriggerUnpackerModule.h:367
Belle2::Merger::reserve
void reserve(int subDetectorId, std::array< int, nFinesse > nWords) override
reserve enough number of clocks (entries) in the Bitstream StoreArray
Definition: CDCTriggerUnpackerModule.cc:74
Belle2::LogConfig::getDebugLevel
int getDebugLevel() const
Returns the configured debug messaging level.
Definition: LogConfig.h:101
Belle2::CDCTriggerUnpackerModule::m_bits2DTo3D
StoreArray< CDCTriggerUnpacker::T2DOutputBitStream > m_bits2DTo3D
bitstream of 2D output to 3D/Neuro
Definition: CDCTriggerUnpackerModule.h:298
Belle2::Neuro::offsetBitWidth
unsigned offsetBitWidth
Offset bit width.
Definition: CDCTriggerUnpackerModule.cc:420
Belle2::CDCTriggerUnpackerModule::m_headerSize
int m_headerSize
number of words (number of bits / 32) of the B2L header
Definition: CDCTriggerUnpackerModule.h:267
Belle2::Neuro
unpacker for the Neuro
Definition: CDCTriggerUnpackerModule.cc:402
Belle2::Module::setDescription
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:216
Belle2::Tracker2D::offsetBitWidth
unsigned offsetBitWidth
starting point of the input data in an Belle2Link event
Definition: CDCTriggerUnpackerModule.cc:160
Belle2::CDCTriggerUnpackerModule::m_NeuroTracks
StoreArray< CDCTriggerTrack > m_NeuroTracks
decoded Neuro tracks
Definition: CDCTriggerUnpackerModule.h:311
Belle2::Tracker2D
unpacker for the 2D tracker
Definition: CDCTriggerUnpackerModule.cc:136
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::Module::c_ParallelProcessingCertified
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:82
Belle2::CDCTriggerUnpackerModule::m_NeuroDelay
int m_NeuroDelay
Belle2Link delay of the neurotrigger.
Definition: CDCTriggerUnpackerModule.h:337
Belle2::CDCTriggerUnpackerModule::m_subTrigger
std::vector< SubTrigger * > m_subTrigger
vector holding the pointers to all the dynamically allocated SubTriggers
Definition: CDCTriggerUnpackerModule.h:354
Belle2::Bitstream
Class to hold one clock cycle of raw bit content.
Definition: Bitstream.h:47
Belle2::Tracker2D::numTS
unsigned numTS
Number of TS sent to 2D (0 to 20)
Definition: CDCTriggerUnpackerModule.cc:158
Belle2::CDCTriggerUnpackerModule::m_unpackTracker2D
bool m_unpackTracker2D
flag to unpack 2D tracker data
Definition: CDCTriggerUnpackerModule.h:278
Belle2::CDCTriggerUnpackerModule::m_debugLevel
int m_debugLevel
debug level specified in the steering file
Definition: CDCTriggerUnpackerModule.h:326
Belle2::CDCTriggerUnpackerModule::m_NNInputTSHitsAll
StoreArray< CDCTriggerSegmentHit > m_NNInputTSHitsAll
all decoded stereo track segment hits from the neural network input
Definition: CDCTriggerUnpackerModule.h:323
Belle2::CDCTriggerUnpackerModule::m_unpackMerger
bool m_unpackMerger
flag to unpack merger data (recorded by Merger Reader / TSF)
Definition: CDCTriggerUnpackerModule.h:272
Belle2::CDCTriggerUnpackerModule::m_2DFinderCnttrg
int m_2DFinderCnttrg
2D cnttrg
Definition: CDCTriggerUnpackerModule.h:344
Belle2::Neuro::Neuro
Neuro(StoreArray< NNBitStream > *arrPtr, std::string inName, unsigned inEventWidth, unsigned inOffset, unsigned inHeaderSize, std::vector< int > inNodeID, int &inDelay, int &inCnttrg, int inDebugLevel)
Constructor.
Definition: CDCTriggerUnpackerModule.cc:404
Belle2::CDCTriggerUnpackerModule::m_run
unsigned m_run
run number
Definition: CDCTriggerUnpackerModule.h:351
Belle2::CDCTriggerUnpackerModule::m_mergerDelay
int m_mergerDelay
Belle2Link delay of the merger reader.
Definition: CDCTriggerUnpackerModule.h:329
Belle2::CDCTriggerUnpackerModule::CDCTriggerUnpackerModule
CDCTriggerUnpackerModule()
Constructor: Sets the description, the properties and the parameters of the module.
Definition: CDCTriggerUnpackerModule.cc:475
Belle2::CDCTriggerUnpackerModule::m_mergerCnttrg
int m_mergerCnttrg
cnttrg
Definition: CDCTriggerUnpackerModule.h:342
Belle2::Merger::unpack
void unpack(int subDetectorId, std::array< int *, 4 > data32tab, std::array< int, 4 > nWords)
Unpack function.
Definition: CDCTriggerUnpackerModule.cc:95
Belle2::Merger
unpacker for the merger reader (TSF which reads the merger output)
Definition: CDCTriggerUnpackerModule.cc:56
Belle2::Neuro::unpack
void unpack(int subDetectorId, std::array< int *, nFinesse > data32tab, std::array< int, nFinesse > nWords) override
Unpack the Belle2Link data and fill the Bitstream.
Definition: CDCTriggerUnpackerModule.cc:442
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2::CDCTriggerUnpackerModule::nMergers
static constexpr std::array< int, 9 > nMergers
data width of a single merger unit
Definition: CDCTriggerUnpackerModule.h:263
Belle2::Module::setPropertyFlags
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:210
Belle2::CDCTriggerUnpackerModule::m_useDB
bool m_useDB
bool value for wether to use the conditions database
Definition: CDCTriggerUnpackerModule.h:365
Belle2::CDCTriggerUnpackerModule::terminate
virtual void terminate() override
Delete dynamically allocated variables.
Definition: CDCTriggerUnpackerModule.cc:620
Belle2::CDCTriggerUnpackerModule::initialize
virtual void initialize() override
Register input and output data.
Definition: CDCTriggerUnpackerModule.cc:534
Belle2::CDCTriggerUnpackerModule::m_alignFoundTime
bool m_alignFoundTime
flag to align found time in different sub-modules
Definition: CDCTriggerUnpackerModule.h:281
Belle2::mergerWidth
static constexpr int mergerWidth
Merger data width.
Definition: CDCTriggerUnpackerModule.h:53
Belle2::Neuro::reserve
void reserve(int subDetectorId, std::array< int, nFinesse > nWords) override
Calculate the number of clocks in the data, reserve that much of clocks in the Bitstream(s)
Definition: CDCTriggerUnpackerModule.cc:422
Belle2::Neuro::iTracker
unsigned iTracker
Tracker board ID.
Definition: CDCTriggerUnpackerModule.cc:418
Belle2::CDCTriggerUnpackerModule::m_tracker2DNodeID
NodeList m_tracker2DNodeID
list of (COPPER ID, HSLB ID) of 2D tracker
Definition: CDCTriggerUnpackerModule.h:277
Belle2::CDCTriggerUnpackerModule::m_unpackNeuro
bool m_unpackNeuro
flag to unpack neurotrigger data
Definition: CDCTriggerUnpackerModule.h:285
Belle2::CDCTriggerUnpackerModule::m_decodeTSHit
bool m_decodeTSHit
flag to decode track segment
Definition: CDCTriggerUnpackerModule.h:276
Belle2::CDCTriggerUnpackerModule::m_2DFinderDelay
int m_2DFinderDelay
Belle2Link delay of the 2D finder.
Definition: CDCTriggerUnpackerModule.h:334
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::StoreObjPtr
Type-safe access to single objects in the data store.
Definition: ParticleList.h:33
Belle2::CDCTriggerUnpackerModule::m_bitsNN
StoreArray< CDCTriggerUnpacker::NNBitStream > m_bitsNN
bitstream of Neuro input and output (including intermediate results)
Definition: CDCTriggerUnpackerModule.h:308
Belle2::CDCTriggerUnpackerModule::m_neuroNodeID
NodeList m_neuroNodeID
list of (COPPER ID, HSLB ID) of neurotrigger
Definition: CDCTriggerUnpackerModule.h:284
Belle2::CDCTriggerUnpackerModule::m_2DFinderTracks
StoreArray< CDCTriggerTrack > m_2DFinderTracks
decoded 2D finder track
Definition: CDCTriggerUnpackerModule.h:301
Belle2::Tracker2D::reserve
void reserve(int subDetectorId, std::array< int, nFinesse > nWords) override
Calculate the number of clocks in the data, reserve that much of clocks in the Bitstream(s)
Definition: CDCTriggerUnpackerModule.cc:170
Belle2::Tracker2D::outputArrayPtr
StoreArray< T2DOutputBitStream > * outputArrayPtr
pointer to the Bitstream of 2D output to 3D/Neuro
Definition: CDCTriggerUnpackerModule.cc:154
Belle2::CDCTriggerUnpackerModule::m_mergerBits
StoreArray< MergerBits > m_mergerBits
merger output bitstream
Definition: CDCTriggerUnpackerModule.h:274
Belle2::CDCTriggerUnpackerModule::m_decodeNeuro
bool m_decodeNeuro
flag to decode neurotrigger data
Definition: CDCTriggerUnpackerModule.h:286
Belle2::Module::setReturnValue
void setReturnValue(int value)
Sets the return value for this module as integer.
Definition: Module.cc:222
Belle2::CDCTriggerUnpackerModule::m_TSHits
StoreArray< CDCTriggerSegmentHit > m_TSHits
decoded track segment hit
Definition: CDCTriggerUnpackerModule.h:295
Belle2::Merger::nInnerMergers
unsigned nInnerMergers
number of merger units in the inner super layer than this one
Definition: CDCTriggerUnpackerModule.cc:72
Belle2::Merger::Merger
Merger(StoreArray< MergerBits > *inArrayPtr, std::string inName, unsigned inEventWidth, unsigned inOffset, int inHeaderSize, std::vector< int > inNodeID, unsigned inNInnerMergers, int &inDelay, int &inCnttrg, int inDebugLevel)
Constructor.
Definition: CDCTriggerUnpackerModule.cc:58
Belle2::Module::addParam
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:562
Belle2::Tracker2D::unpack
void unpack(int subDetectorId, std::array< int *, 4 > data32tab, std::array< int, 4 > nWords)
Unpack the Belle2Link data and fill the Bitstream.
Definition: CDCTriggerUnpackerModule.cc:203
Belle2::NodeList
std::vector< std::vector< int > > NodeList
Node list.
Definition: CDCTriggerUnpackerModule.h:50
Belle2::CDCTriggerUnpackerModule::m_exp
unsigned m_exp
exp number
Definition: CDCTriggerUnpackerModule.h:349
Belle2::CDCTriggerUnpackerModule::m_decode2DFinderTrack
bool m_decode2DFinderTrack
flag to decode 2D finder track
Definition: CDCTriggerUnpackerModule.h:279
Belle2::Bitstream::m_signal
SignalBus m_signal
SignalBus of the Bitstream.
Definition: Bitstream.h:73
Belle2::CDCTriggerUnpackerModule::m_NeuroCnttrg
int m_NeuroCnttrg
NN cnttrg.
Definition: CDCTriggerUnpackerModule.h:346
Belle2::CDCTriggerUnpackerModule::m_rawTriggers
StoreArray< RawTRG > m_rawTriggers
array containing the raw trigger data object
Definition: CDCTriggerUnpackerModule.h:269
Belle2::CDCTriggerUnpackerModule::m_NNInput2DFinderTracks
StoreArray< CDCTriggerTrack > m_NNInput2DFinderTracks
decoded 2D finder tracks from the neural network input
Definition: CDCTriggerUnpackerModule.h:317
Belle2::CDCTriggerUnpackerModule::m_NNInputTSHits
StoreArray< CDCTriggerSegmentHit > m_NNInputTSHits
decoded track segment hits from the neural network input
Definition: CDCTriggerUnpackerModule.h:320
Belle2::StoreArray
Accessor to arrays stored in the data store.
Definition: ECLMatchingPerformanceExpertModule.h:33
Belle2::CDCTriggerUnpackerModule::m_n2DTS
int m_n2DTS
flag to unpack 2D tracker data with 15TS
Definition: CDCTriggerUnpackerModule.h:282
Belle2::CDCTriggerUnpackerModule::event
virtual void event() override
convert raw data (in B2L buffer to bitstream)
Definition: CDCTriggerUnpackerModule.cc:647
Belle2::Tracker2D::iTracker
unsigned iTracker
ID of the 2D tracker (0 to 3)
Definition: CDCTriggerUnpackerModule.cc:156
Belle2::CDCTriggerUnpackerModule::m_NeuroInputs
StoreArray< CDCTriggerMLPInput > m_NeuroInputs
decoded input vector for neural network
Definition: CDCTriggerUnpackerModule.h:314
Belle2::Module::getLogConfig
LogConfig & getLogConfig()
Returns the log system configuration.
Definition: Module.h:227
Belle2::Tracker2D::Tracker2D
Tracker2D(StoreArray< TSFOutputBitStream > *inArrayPtr, StoreArray< T2DOutputBitStream > *outArrayPtr, std::string inName, unsigned inEventWidth, unsigned inOffset, unsigned inHeaderSize, std::vector< int > inNodeID, unsigned inNumTS, int &inDelay, int &inCnttrg, int inDebugLevel)
constructor
Definition: CDCTriggerUnpackerModule.cc:138
Belle2::CDCTriggerUnpackerModule::m_decode2DFinderInputTS
bool m_decode2DFinderInputTS
flag to decode 2D finder input TS
Definition: CDCTriggerUnpackerModule.h:280
Belle2::StoreArray::getEntries
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:226
Belle2::CDCTriggerUnpackerModule::m_mergerNodeID
NodeList m_mergerNodeID
list of (COPPER ID, HSLB ID) of Merger reader (TSF)
Definition: CDCTriggerUnpackerModule.h:271
Belle2::CDCTriggerUnpackerModule::m_bitsTo2D
StoreArray< CDCTriggerUnpacker::TSFOutputBitStream > m_bitsTo2D
bitstream of TSF output to 2D tracker
Definition: CDCTriggerUnpackerModule.h:292
Belle2::CDCTriggerUnpackerModule::m_cdctriggerneuroconfig
DBObjPtr< CDCTriggerNeuroConfig > m_cdctriggerneuroconfig
current neurotrigger config from database; used for unscaling network target
Definition: CDCTriggerUnpackerModule.h:359