Belle II Software  release-06-00-14
trgtopUnpackerModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <trg/top/modules/trgtopUnpacker/trgtopUnpackerModule.h>
10 
11 /* --------------- WARNING ---------------------------------------------- *
12 If you have more complex parameter types in your class then simple int,
13 double or std::vector of those you might need to uncomment the following
14 include directive to avoid an undefined reference on compilation.
15 * ---------------------------------------------------------------------- */
16 // #include <framework/core/ModuleParam.templateDetails.h>
17 
18 using namespace std;
19 using namespace Belle2;
20 
21 //-----------------------------------------------------------------
22 // Register the Module
23 //-----------------------------------------------------------------
24 REG_MODULE(TRGTOPUnpacker);
25 
26 string TRGTOPUnpackerModule::version() const
27 {
28  return string("1.00");
29 }
30 
31 //-----------------------------------------------------------------
32 // Implementation
33 //-----------------------------------------------------------------
34 
35 TRGTOPUnpackerModule::TRGTOPUnpackerModule()
36  : Module::Module(), m_eventNumber(0), m_trigType(0), m_nodeId(0), m_nWords(0)
37 {
38  // Set module properties
39 
40 
41  string desc = "TRGTOPUnpackerModule(" + version() + ")";
42  setDescription(desc);
44 
45  B2DEBUG(20, "TRGTOPUnpacker: Constructor done.");
46 
47 
48  // Parameter definitions
49 
50 }
51 
52 TRGTOPUnpackerModule::~TRGTOPUnpackerModule()
53 {
54 }
55 
57 {
58  m_TRGTOPCombinedTimingArray.registerInDataStore();
59 }
60 
61 
63 {
64 }
65 
67 {
68 
69  StoreArray<RawTRG> raw_trgarray;
70 
71  for (int i = 0; i < raw_trgarray.getEntries(); i++) {
72  for (int j = 0; j < raw_trgarray[i]->GetNumEntries(); j++) {
73 
74  m_nodeId = raw_trgarray[i]->GetNodeID(j);
75 
76  if (m_nodeId == 0x12000001) {
77 
78  m_nWords = raw_trgarray[i]->GetDetectorNwords(j, 0);
79  m_eventNumber = raw_trgarray[i]->GetEveNo(j);
80  m_trigType = raw_trgarray[i]->GetTRGType(j);
81 
82  // if ( m_nWords > 3 ) { ////general header is 3 words long
83  if (m_nWords > 0) {
84 
85  // B2INFO("raw_trgarray.getEntries() = " << raw_trgarray.getEntries());
86  // B2INFO("raw_trgarray[i]->GetNumEntries() = " << raw_trgarray[i]->GetNumEntries());
87  // B2INFO("raw_trgarray[]->GetEveNo(j) = " << raw_trgarray[i]->GetEveNo(j));
88  // B2INFO("raw_trgarray[]->GetNodeID(j) = " << std::hex << raw_trgarray[i]->GetNodeID(j) << std::dec);
89  // B2INFO("raw_trgarray[]->GetDetectorNwords(j,0) = " << m_nWords);
90 
91  readCOPPEREvent(raw_trgarray[i] , j);
92 
93  }
94  }
95  }
96  }
97 }
98 
100 {
101  // if (raw_copper->GetDetectorNwords(i, 0) > 3) { ///general header is 3 words long
102  if (raw_copper->GetDetectorNwords(i, 0) > 0) {
103  fillTreeTRGTOP(raw_copper->GetDetectorBuffer(i, 0));
104  }
105 }
106 
108 {
109 
110  // B2INFO("data size (32bit words) = " << m_nWords);
111 
112  // Information for each data window
113 
114  // rvc from the header of the buffer
115  int l1_revo = rdat[2] & 0x7ff;
116 
117  // L1 event number
118  int trgtag = (rdat[2] >> 12) & 0xfffff;
119 
120  // B2INFO("l1_rvc from header = " << l1_revo);
121  // B2INFO("trgtag (evt) from buffer header = " << trgtag);
122 
123  bool dataFormatKnown = false;
124 
125  int windowSize = -1;
126  int numberOfWindows = -1;
127 
128  int dataFormatVersionExpected = -1;
129  int revoClockDeltaExpected = 4;
130  int cntr127DeltaExpected = 4;
131 
132  // 3 = 3: header only
133  // 1875 = 3 + 48*39: format used starting ~June 30 2019 and until Oct. 1, 2019 (until Receive FW version 0x02067301)
134  // 771 = 3 + 24*32: format used starting ~Oct. 1, 2019 (Receive FW version 0x02067301 and newer)
135 
136  // m_nWords==3 means only a header
137  if (m_nWords == 3) {
138  windowSize = 0;
139  numberOfWindows = 0;
140  dataFormatKnown = true;
141  dataFormatVersionExpected = 0;
142  } else if (m_nWords == 771) {
143  windowSize = 32;
144  numberOfWindows = 24;
145  dataFormatKnown = true;
146  dataFormatVersionExpected = 2;
147  } else if (m_nWords == 1875) {
148  windowSize = 39;
149  numberOfWindows = 48;
150  dataFormatKnown = true;
151  dataFormatVersionExpected = 1;
152  }
153 
154  if (!dataFormatKnown) {
155  B2INFO("Unknown data format / error / exiting");
156  return;
157  }
158 
159  // if ( dataFormatVersionExpected > 0 ) B2INFO("---------------------------------------------------------------------------------------------------------------");
160 
161  // B2INFO("Data format version (as expected according to data size) = " << dataFormatVersionExpected);
162 
163  // if ( numberOfWindows != 0 ) {
164  // B2INFO("Number of 32bit words in TOP L1 data buffer = " << m_nWords);
165  // B2INFO("Number of windows = " << numberOfWindows);
166  // B2INFO("Window size in 32bit words = " << windowSize);
167  // }
168 
169  // various test patterns will be used to check the data
170  unsigned int testPattern;
171 
172  int revoClockLast = -1;
173  int cntr127Last = -1;
174 
175  // error counter for possible data corruption
176  unsigned int errorCountEvent = 0;
177 
178  // need to know when a new decision is made (there could be more than one TOP L1 timing decision stored in the same B2L buffer)
179  // cppcheck-suppress variableScope
180  int t0CombinedDecisionLast = -1;
181 
182  bool performBufferAnalysis = true;
183  bool reportAllErrors = true;
184  bool reportSummaryErrors = true;
185 
186  // check if this event's buffer is a dummy buffer
187  int counterDummyWindows = 0;
188  unsigned int testPatternDummyEvent = 0xbbbb;
189  for (int iWindow = 0; iWindow < numberOfWindows; iWindow++) {
190  int index = iWindow * windowSize + 3;
191  testPattern = (rdat[index] >> 16) & 0xffff;
192  if (testPattern == testPatternDummyEvent) {
193  counterDummyWindows++;
194  }
195  // Oct. 31, 2020: three most significant bits are now used to control unpacker from FW
196  // Note that setting either flag for any of the windows changes it for all windows here
197  testPattern = (rdat[index + 2] >> 29) & 0x7;
198  if (testPattern & 0x1) performBufferAnalysis = false;
199  if (testPattern & 0x2) reportAllErrors = false;
200  if (testPattern & 0x4) reportSummaryErrors = false;
201  }
202 
203  // note that events with empty buffer have numberOfWindows=0
204  if (counterDummyWindows == numberOfWindows) {
205  performBufferAnalysis = false;
206  } else {
207  if (counterDummyWindows != 0) {
208  if (reportAllErrors) B2ERROR("Corrupted data? numberOfWindows = " << numberOfWindows << ", counterDummyWindows = " <<
209  counterDummyWindows);
210  performBufferAnalysis = false;
211  }
212  }
213 
214  // the ID of the first actual window with data (depends on b2l_buffer_delay, which could be figured out from data
215  // iWindowFirst = 0 is correct for b2l_buffer_delay = 0
216  int iWindowFirst = 0;
217 
218  // identify the actual first window (either the first window (when b2l_buffer_delay=0) or the first window where we see the jump of rvc by -92 or by 1188 (1188+92 = 1280))
219 
220  int numberRvcJumps = 0;
221  int numberCntr127Jumps = 0;
222  int windowRvcJumpFirst = -1;
223  int windowCntr127JumpFirst = -1;
224  int clocksRvcJumpFirst = -1;
225  int clocksCntr127JumpFirst = -1;
226 
227  if (performBufferAnalysis) {
228  for (int iWindow = 0; iWindow < numberOfWindows; iWindow++) {
229  int index = iWindow * windowSize + 3;
230 
231  // revoclk (comes from b2tt) has the range between 0 and 1279 @127MHz => 1279*7.8ns ~10us = 1 revolution (11bits are used)
232  int revoClockNow = rdat[index] & 0x7ff;
233  // B2INFO("rvc now = " << revoClockNow);
234  // first need to know max revoClock (1279)
235  if (revoClockLast != -1) {
236  // if (revoClockLast != -1 && revoClockNow > revoClockLast) {
237  int revoClockDeltaNow = revoClockNow - revoClockLast;
238  if (revoClockDeltaNow != revoClockDeltaExpected) {
239  // -1276 is simply going to the next cycle of rvc counting, but 1188 or -92 means that we identified the first window (these numbers are such for 24 windows @ 32MHz)
240  if (revoClockDeltaNow == 1188 || revoClockDeltaNow == -92) {
241  // note that the first buffer window could not cause this condition because we would never get to execute this line on the first buffer window, yet it does not matter
242  if (iWindowFirst == 0) {
243  iWindowFirst = iWindow;
244  }
245  } else if (revoClockDeltaNow != -1276) {
246  if (reportAllErrors) B2ERROR("rvc changed by an unexpected number of units: " << revoClockDeltaNow << ", last rvc = " <<
247  revoClockLast <<
248  ", current rvc = " << revoClockNow << ", window " << iWindow << ", index = " << index);
249  numberRvcJumps++;
250  if (windowRvcJumpFirst < 0) {
251  windowRvcJumpFirst = iWindow;
252  clocksRvcJumpFirst = revoClockDeltaNow;
253  }
254  }
255  }
256  }
257  revoClockLast = revoClockNow;
258 
259  int cntr127Now = (rdat[index + 1] >> 16) & 0xffff;
260  // B2INFO("cntr127 now = " << cntr127Now);
261  // first need to know max cntr127
262  if (cntr127Last != -1) {
263  // if (cntr127Last != -1 && cntr127Now > cntr127Last) {
264  int cntr127DeltaNow = cntr127Now - cntr127Last;
265  if (cntr127DeltaNow != cntr127DeltaExpected) {
266  // 65444 is the value of the difference in cntr127 (VME counter) because we use 16 bits of 64 bit-long counter (these numbers are such for 24 windows @ 32MHz)
267  if (cntr127DeltaNow != 65444 && cntr127DeltaNow != -92 && cntr127DeltaNow != -65532) {
268  if (reportAllErrors) B2ERROR("cntr127 changed by an unexpected number of units: " << cntr127DeltaNow << ", cntr127 last = " <<
269  cntr127Last <<
270  ", cntr127 now = " << cntr127Now << ", window " << iWindow << ", index = " << index + 1);
271  numberCntr127Jumps++;
272  if (windowCntr127JumpFirst < 0) {
273  windowCntr127JumpFirst = iWindow;
274  clocksCntr127JumpFirst = cntr127DeltaNow;
275  }
276  }
277  }
278  }
279  cntr127Last = cntr127Now;
280  }
281  }
282 
283  /*
284  if (numberRvcJumps > 0) {
285  B2INFO("The number of rvc jumps = " << numberRvcJumps);
286  B2INFO("The window of the first rvc jump = " << windowRvcJumpFirst);
287  B2INFO("The number of clock cycles associated with the first rvc jump = " << clocksRvcJumpFirst);
288  }
289 
290  if (numberCntr127Jumps > 0) {
291  B2INFO("The number of cntr127 jumps = " << numberCntr127Jumps);
292  B2INFO("The window of the first cntr127 jump = " << windowCntr127JumpFirst);
293  B2INFO("The number of clock cycles associated with the first cntr127 jump = " << clocksCntr127JumpFirst);
294  }
295  */
296 
297  // debugging: report everything from every single window when we are seeing unexpected jumps in either of the two counters
298  /*
299  if (numberRvcJumps > 0 || numberCntr127Jumps > 0) {
300  B2INFO("===========================================================================================================");
301  B2INFO("l1_rvc from header = " << l1_revo);
302  B2INFO("trgtag (evt) from buffer header = " << trgtag);
303  B2INFO("Reporting the entire data buffer");
304  B2INFO("Header 0 = : " << std::hex << rdat[0] << std::dec);
305  B2INFO("Header 1 = : " << std::hex << rdat[1] << std::dec);
306  B2INFO("Header 2 = : " << std::hex << rdat[2] << std::dec);
307  for (int iWindow = 0; iWindow < numberOfWindows; iWindow++) {
308  int index = iWindow * windowSize + 3;
309 
310  B2INFO("---------------------------------------------------------------------------------");
311  int revoClockNow = rdat[index] & 0x7ff;
312  B2INFO("w rvc ---------------------------- = " << iWindow << " " << revoClockNow);
313 
314  int cntr127Now = (rdat[index + 1] >> 16) & 0xffff;
315  B2INFO("w cntr127 ---------------------------- = " << iWindow << " " << cntr127Now);
316 
317  for (int i = 0; i < 24; i++) {
318  B2INFO("w i = : " << iWindow << " " << i << " " << std::hex << rdat[index+i] << std::dec);
319  }
320  }
321  }
322  */
323 
324  // reset "most recent" rvc and cntr127
325  revoClockLast = -1;
326  cntr127Last = -1;
327 
328  // B2INFO("Start buffer analysis, iWindowFirst = " << iWindowFirst);
329 
330  // events with no buffer (i.e. no payload), empty (i.e. dummy) windows and presumably corrupted events are NOT analyzed
331  if (performBufferAnalysis) {
332 
333  // Loop over windows in B2L buffer and locate all unique TOP L1 decisions
334  for (int iWindowProvisional = 0; iWindowProvisional < numberOfWindows; iWindowProvisional++) {
335 
336  // we need to be smarter now about how to calculate window number in the buffer
337  int iWindow = iWindowProvisional + iWindowFirst;
338 
339  if (iWindow >= numberOfWindows) {
340  iWindow = iWindow - numberOfWindows;
341  }
342 
343  // B2INFO("REAL DEBUG: window number = " << iWindow);
344 
345  // error counters for possible data corruption in the current window
346  unsigned int errorCountWindowMinor = 0;
347  unsigned int errorCountWindowMajor = 0;
348 
349  // a pointer-like variable for accessing the data in the buffer sequentially
350  int index = iWindow * windowSize + 3;
351 
352  unsigned int testPatternExpected = 0;
353  if (dataFormatVersionExpected == 1) testPatternExpected = 0xbbba;
354  else if (dataFormatVersionExpected == 2 || dataFormatVersionExpected == 3) testPatternExpected = 0xdddd;
355 
356  testPattern = (rdat[index] >> 16) & 0xffff;
357  // B2INFO("testPattern = " << std::hex << testPattern << std::dec);
358  if (testPattern != testPatternExpected) {
359  // if (reportAllErrors) B2ERROR("Unexpected test pattern 1: " << std::hex << testPattern << std::dec);
360  if (reportAllErrors) B2ERROR("Unexpected test pattern 1: " << std::hex << testPattern << std::dec << ", window " << iWindow <<
361  ", index = " << index);
362  errorCountWindowMajor++;
363  }
364 
365  int dataFormatVersionNow = (rdat[index] >> 11) & 0x1f;
366  // B2INFO("dataFormatVersionNow = " << dataFormatVersionNow);
367  if (dataFormatVersionNow == 3 && dataFormatVersionExpected == 2) {
368  dataFormatVersionExpected = 3;
369  }
370 
371  if (dataFormatVersionNow != dataFormatVersionExpected) {
372  if (reportAllErrors) B2ERROR("Unexpected data format version: " << dataFormatVersionNow << ", window " << iWindow << ", index = " <<
373  index);
374  errorCountWindowMajor++;
375  }
376 
377  // revoclk (comes from b2tt) has the range between 0 and 1279 @127MHz => 1279*7.8ns ~10us = 1 revolution (11bits are used)
378  int revoClockNow = rdat[index] & 0x7ff;
379  // B2INFO("rvc now = " << revoClockNow);
380  // first need to know max revoClock (1279)
381  if (revoClockLast != -1) {
382  // if (revoClockLast != -1 && revoClockNow > revoClockLast) {
383  int revoClockDeltaNow = revoClockNow - revoClockLast;
384  if (revoClockDeltaNow != revoClockDeltaExpected) {
385  if (revoClockDeltaNow != 1188 && revoClockDeltaNow != -92 && revoClockDeltaNow != -1276) {
386  if (reportAllErrors) B2ERROR("rvc changed by an unexpected number of units: " << revoClockDeltaNow << ", last rvc = " <<
387  revoClockLast <<
388  ", current rvc = " << revoClockNow << ", window " << iWindow << ", index = " << index);
389  errorCountWindowMinor++;
390  }
391  }
392  }
393  if (revoClockNow > 1279) {
394  if (reportAllErrors) B2ERROR("Unexpected rvc value = " << revoClockNow << ", window " << iWindow << ", index = " << index);
395  errorCountWindowMajor++;
396  }
397  revoClockLast = revoClockNow;
398 
399  int cntr127Now = (rdat[index + 1] >> 16) & 0xffff;
400  // B2INFO("cntr127 now = " << cntr127Now);
401  // first need to know max cntr127
402  if (cntr127Last != -1) {
403  // if (cntr127Last != -1 && cntr127Now > cntr127Last) {
404  int cntr127DeltaNow = cntr127Now - cntr127Last;
405  if (cntr127DeltaNow != cntr127DeltaExpected) {
406  // 65444 is the value of the difference in cntr127 (VME counter) because we use 16 bits of 64 bit-long counter
407  if (cntr127DeltaNow != 65444 && cntr127DeltaNow != -92 && cntr127DeltaNow != -65532) {
408  if (reportAllErrors) B2ERROR("cntr127 changed by an unexpected number of units: " << cntr127DeltaNow << ", cntr127 last = " <<
409  cntr127Last <<
410  ", cntr127 now = " << cntr127Now << ", window " << iWindow << ", index = " << index + 1);
411  errorCountWindowMinor++;
412  }
413  }
414  }
415  cntr127Last = cntr127Now;
416 
417  testPattern = (rdat[index + 1]) & 0x0000ffff;
418  // B2INFO("testPattern = " << std::hex << testPattern << std::dec);
419  if (testPattern != 0) {
420  if (reportAllErrors) B2ERROR("Unexpected test pattern 2: " << testPattern << ", window " << iWindow << ", index = " << index + 1);
421  errorCountWindowMajor++;
422  }
423 
424  // combined t0 from the current window
425  int t0CombinedDecisionNow = (rdat[index + 2]) & 0x3ffff;
426  int t0CombinedDecisionNowEstimated = 0;
427  // B2INFO("Combined t0 (raw ns) = " << t0CombinedDecisionNow);
428 
429  // revo clock when t0 decision was supposed to be posted to GDL
430  int revoClockGDL = (rdat[index + 2] >> 18) & 0x7ff;
431  // B2INFO("rvc when t0 was supposed to be posted to GDL/GRL = " << revoClockGDL);
432 
433  // Oct. 31, 2020: these three bits are now used to control unpacker from FW
434  // testPattern = (rdat[index + 2] >> 29) & 0x7;
435  // B2INFO("testPattern = " << std::hex << testPattern << std::dec);
436  // if (testPattern != 0) {
437  // if (reportAllErrors) B2ERROR("Unexpected test pattern 3: " << testPattern << ", window " << iWindow << ", index = " << index + 2);
438  // errorCountWindowMajor++;
439  // }
440 
441  int t0CombinedSegments[16];
442 
443  t0CombinedSegments[15] = (rdat[index + 11] >> 28) & 0xf;
444  t0CombinedSegments[14] = (rdat[index + 11] >> 24) & 0xf;
445  t0CombinedSegments[13] = (rdat[index + 11] >> 20) & 0xf;
446  t0CombinedSegments[12] = (rdat[index + 11] >> 16) & 0xf;
447  t0CombinedSegments[11] = (rdat[index + 11] >> 12) & 0xf;
448  t0CombinedSegments[10] = (rdat[index + 11] >> 8) & 0xf;
449  t0CombinedSegments[9] = (rdat[index + 11] >> 4) & 0xf;
450  t0CombinedSegments[8] = (rdat[index + 11]) & 0xf;
451 
452  t0CombinedSegments[7] = (rdat[index + 12] >> 28) & 0xf;
453  t0CombinedSegments[6] = (rdat[index + 12] >> 24) & 0xf;
454  t0CombinedSegments[5] = (rdat[index + 12] >> 20) & 0xf;
455  t0CombinedSegments[4] = (rdat[index + 12] >> 16) & 0xf;
456  t0CombinedSegments[3] = (rdat[index + 12] >> 12) & 0xf;
457  t0CombinedSegments[2] = (rdat[index + 12] >> 8) & 0xf;
458  t0CombinedSegments[1] = (rdat[index + 12] >> 4) & 0xf;
459  t0CombinedSegments[0] = (rdat[index + 12]) & 0xf;
460 
461  int nSegmentsCombinedDecision = 0;
462 
463  for (int iSlot = 0; iSlot < NUMBER_OF_SLOTS; iSlot++) {
464  if (t0CombinedSegments[iSlot] != 0) {
465  // if (t0CombinedSegments[iSlot] != 0 && iWindow == 0) {
466  // B2INFO("Slot " << iSlot+1 << ", segment = " << t0CombinedSegments[iSlot]);
467  nSegmentsCombinedDecision++;
468  }
469  }
470 
471  int t0CombinedSlots[16];
472 
473  t0CombinedSlots[0] = (rdat[index + 3] >> 16) & 0xffff;
474  t0CombinedSlots[1] = (rdat[index + 3]) & 0xffff;
475  t0CombinedSlots[2] = (rdat[index + 4] >> 16) & 0xffff;
476  t0CombinedSlots[3] = (rdat[index + 4]) & 0xffff;
477  t0CombinedSlots[4] = (rdat[index + 5] >> 16) & 0xffff;
478  t0CombinedSlots[5] = (rdat[index + 5]) & 0xffff;
479  t0CombinedSlots[6] = (rdat[index + 6] >> 16) & 0xffff;
480  t0CombinedSlots[7] = (rdat[index + 6]) & 0xffff;
481  t0CombinedSlots[8] = (rdat[index + 7] >> 16) & 0xffff;
482  t0CombinedSlots[9] = (rdat[index + 7]) & 0xffff;
483  t0CombinedSlots[10] = (rdat[index + 8] >> 16) & 0xffff;
484  t0CombinedSlots[11] = (rdat[index + 8]) & 0xffff;
485  t0CombinedSlots[12] = (rdat[index + 9] >> 16) & 0xffff;
486  t0CombinedSlots[13] = (rdat[index + 9]) & 0xffff;
487  t0CombinedSlots[14] = (rdat[index + 10] >> 16) & 0xffff;
488  t0CombinedSlots[15] = (rdat[index + 10]) & 0xffff;
489 
490  int nSlotsCombinedDecision = 0;
491 
492  int nSegmentErrors = 0;
493 
494  for (int iSlot = 0; iSlot < NUMBER_OF_SLOTS; iSlot++) {
495  if (t0CombinedSegments[iSlot] != 0) {
496  // B2INFO("Slot " << iSlot+1 << ", t0 (raw ns) = " << 2 * t0CombinedSlots[iSlot]);
497  t0CombinedDecisionNowEstimated = t0CombinedDecisionNowEstimated + 2 * t0CombinedSlots[iSlot];
498  nSlotsCombinedDecision++;
499  } else if (t0CombinedSlots[iSlot] != 0) {
500  if (reportAllErrors) B2ERROR("Segment==0 for Slot " << iSlot + 1 << ", t0 (raw ns) = " << 2 * t0CombinedSlots[iSlot] <<
501  ", nSegmentsCombinedDecision = " << nSegmentsCombinedDecision << ", combined t0 decision (FW) = " << t0CombinedDecisionNow <<
502  ", window " << iWindow);
503  errorCountWindowMajor++;
504  nSegmentErrors++;
505  }
506  }
507 
508  // if ( nSlotsCombinedDecision == 0 ) error = true;
509 
510  int nHitsSlots[16];
511 
512  nHitsSlots[0] = (rdat[index + 13] >> 16) & 0x3ff;
513  nHitsSlots[1] = (rdat[index + 13]) & 0x3ff;
514  nHitsSlots[2] = (rdat[index + 14] >> 16) & 0x3ff;
515  nHitsSlots[3] = (rdat[index + 14]) & 0x3ff;
516  nHitsSlots[4] = (rdat[index + 15] >> 16) & 0x3ff;
517  nHitsSlots[5] = (rdat[index + 15]) & 0x3ff;
518  nHitsSlots[6] = (rdat[index + 16] >> 16) & 0x3ff;
519  nHitsSlots[7] = (rdat[index + 16]) & 0x3ff;
520  nHitsSlots[8] = (rdat[index + 17] >> 16) & 0x3ff;
521  nHitsSlots[9] = (rdat[index + 17]) & 0x3ff;
522  nHitsSlots[10] = (rdat[index + 18] >> 16) & 0x3ff;
523  nHitsSlots[11] = (rdat[index + 18]) & 0x3ff;
524  nHitsSlots[12] = (rdat[index + 19] >> 16) & 0x3ff;
525  nHitsSlots[13] = (rdat[index + 19]) & 0x3ff;
526  nHitsSlots[14] = (rdat[index + 20] >> 16) & 0x3ff;
527  nHitsSlots[15] = (rdat[index + 20]) & 0x3ff;
528 
529  int nHitsCombinedDecision = 0;
530  int nSlotsHitsCombinedDecision = 0;
531 
532  for (int iSlot = 0; iSlot < NUMBER_OF_SLOTS; iSlot++) {
533  if (t0CombinedSegments[iSlot] != 0) {
534  // B2INFO("Slot " << iSlot+1 << ", N hits = " << nHitsSlots[iSlot]);
535  nSlotsHitsCombinedDecision++;
536  nHitsCombinedDecision = nHitsCombinedDecision + nHitsSlots[iSlot];
537  } else if (nHitsSlots[iSlot] != 0) {
538  if (reportAllErrors) B2ERROR("Unexpected nHit (via segments) = " << nHitsSlots[iSlot] << " for slot " << iSlot + 1 <<
539  ", nSegmentsCombinedDecision = " << nSegmentsCombinedDecision << ", combined t0 decision (FW) = " << t0CombinedDecisionNow <<
540  ", window " << iWindow);
541  errorCountWindowMajor++;
542  }
543  }
544 
545  // nHits are packed in 10bits, 2 slots per 32bit word
546  for (int iWord = 0; iWord < NUMBER_OF_SLOTS / 2; iWord++) {
547  testPattern = (rdat[index + 13 + iWord]) & 0xfc00fc00;
548  // B2INFO("testPattern = " << std::hex << testPattern << std::dec);
549  if (testPattern != 0) {
550  if (reportAllErrors) B2ERROR("Unexpected test pattern 4: " << testPattern << ", window " << iWindow << ", index = " << index + 13 +
551  iWord);
552  errorCountWindowMajor++;
553  }
554  }
555 
556  int logLikelihoodsSlots[16];
557 
558  if (dataFormatVersionExpected == 2 || dataFormatVersionExpected == 3) {
559  logLikelihoodsSlots[0] = (rdat[index + 21]) & 0xffff;
560  logLikelihoodsSlots[1] = (rdat[index + 21] >> 16) & 0xffff;
561  logLikelihoodsSlots[2] = (rdat[index + 22]) & 0xffff;
562  logLikelihoodsSlots[3] = (rdat[index + 22] >> 16) & 0xffff;
563  logLikelihoodsSlots[4] = (rdat[index + 23]) & 0xffff;
564  logLikelihoodsSlots[5] = (rdat[index + 23] >> 16) & 0xffff;
565  logLikelihoodsSlots[6] = (rdat[index + 24]) & 0xffff;
566  logLikelihoodsSlots[7] = (rdat[index + 24] >> 16) & 0xffff;
567  logLikelihoodsSlots[8] = (rdat[index + 25]) & 0xffff;
568  logLikelihoodsSlots[9] = (rdat[index + 25] >> 16) & 0xffff;
569  logLikelihoodsSlots[10] = (rdat[index + 26]) & 0xffff;
570  logLikelihoodsSlots[11] = (rdat[index + 26] >> 16) & 0xffff;
571  logLikelihoodsSlots[12] = (rdat[index + 27]) & 0xffff;
572  logLikelihoodsSlots[13] = (rdat[index + 27] >> 16) & 0xffff;
573  logLikelihoodsSlots[14] = (rdat[index + 28]) & 0xffff;
574  logLikelihoodsSlots[15] = (rdat[index + 28] >> 16) & 0xffff;
575  } else if (dataFormatVersionExpected == 1) {
576  logLikelihoodsSlots[0] = (rdat[index + 21]);
577  logLikelihoodsSlots[1] = (rdat[index + 22]);
578  logLikelihoodsSlots[2] = (rdat[index + 23]);
579  logLikelihoodsSlots[3] = (rdat[index + 24]);
580  logLikelihoodsSlots[4] = (rdat[index + 25]);
581  logLikelihoodsSlots[5] = (rdat[index + 26]);
582  logLikelihoodsSlots[6] = (rdat[index + 27]);
583  logLikelihoodsSlots[7] = (rdat[index + 28]);
584  logLikelihoodsSlots[8] = (rdat[index + 29]);
585  logLikelihoodsSlots[9] = (rdat[index + 30]);
586  logLikelihoodsSlots[10] = (rdat[index + 31]);
587  logLikelihoodsSlots[11] = (rdat[index + 32]);
588  logLikelihoodsSlots[12] = (rdat[index + 33]);
589  logLikelihoodsSlots[13] = (rdat[index + 34]);
590  logLikelihoodsSlots[14] = (rdat[index + 35]);
591  logLikelihoodsSlots[15] = (rdat[index + 36]);
592  }
593 
594  int nLogLikelihoodsCombinedDecision = 0;
595 
596  for (int iSlot = 0; iSlot < NUMBER_OF_SLOTS; iSlot++) {
597  if (t0CombinedSegments[iSlot] != 0) {
598  // B2INFO("Slot " << iSlot+1 << ", log likelihood = " << logLikelihoodsSlots[iSlot]);
599  nLogLikelihoodsCombinedDecision++;
600  } else if (logLikelihoodsSlots[iSlot] != 0) {
601  if (reportAllErrors) B2ERROR("Unexpected log likelihood (via segments) = " << logLikelihoodsSlots[iSlot] << " for slot " << iSlot +
602  1 << ", nSegmentsCombinedDecision = " << nSegmentsCombinedDecision << ", combined t0 decision (FW) = " << t0CombinedDecisionNow <<
603  ", window " << iWindow);
604  errorCountWindowMajor++;
605  }
606  }
607 
608  if (nSlotsCombinedDecision != 0) {
609  t0CombinedDecisionNowEstimated = t0CombinedDecisionNowEstimated / nSlotsCombinedDecision;
610  } else {
611  t0CombinedDecisionNowEstimated = -1;
612  if (reportAllErrors) B2ERROR("nSlotsCombinedDecision (via segments) is zero! FW t0 decision = " << t0CombinedDecisionNow <<
613  ", window " << iWindow);
614  errorCountWindowMajor++;
615  }
616 
617  if (reportAllErrors) {
618  if (nSegmentErrors != 0) {
619  B2ERROR("nSegmentErrors = " << nSegmentErrors << ", nSegmentsCombinedDecision = " << nSegmentsCombinedDecision <<
620  ", combined t0 decision (FW) = " << t0CombinedDecisionNow << ", window " << iWindow);
621  for (int iSlot = 0; iSlot < NUMBER_OF_SLOTS; iSlot++) {
622  if (t0CombinedSegments[iSlot] == 0 && logLikelihoodsSlots[iSlot] != 0) {
623  B2ERROR("Segment==0, t0Combined (ns) = " << 2 * t0CombinedSlots[iSlot] << " for slot " << iSlot + 1);
624  B2ERROR("Segment==0, nHits = " << nHitsSlots[iSlot] << " for slot " << iSlot + 1);
625  B2ERROR("Segment==0, logLikelihood = " << logLikelihoodsSlots[iSlot] << " for slot " << iSlot + 1);
626  B2ERROR("Segment==0, t0CombinedSegment = " << t0CombinedSegments[iSlot] << " for slot " << iSlot + 1);
627  }
628  }
629  }
630  }
631 
632  // the rest of the window
633  if (dataFormatVersionExpected == 1) index = index + 37;
634  else if (dataFormatVersionExpected == 2 || dataFormatVersionExpected == 3) index = index + 29;
635  else index = index + 29;
636 
637  // trgCntr - currently not working (not incrementing in FW in v02067301, incorrectly implemented in v02007401)
638  // int trgCntrNow = rdat[index];
639  // B2INFO("trgCntrNow = " << trgCntrNow);
640 
641  int revoClockT0CombinedDecisionPrev = -1;
642  int revoClockT0CombinedDecisionNow = -1;
643 
644  // format version 1 does not have trgCntr info
645  if (dataFormatVersionExpected == 2 || dataFormatVersionExpected == 3) index++;
646 
647  if (dataFormatVersionExpected == 2) {
648  // 0xfeedbeef
649  testPatternExpected = 0xfeedbeef;
650  testPattern = rdat[index];
651  // B2INFO("testPattern = " << std::hex << testPattern << std::dec);
652  if (testPattern != testPatternExpected) {
653  if (reportAllErrors) B2ERROR("Unexpected test pattern 5: " << std::hex << testPattern << std::dec << ", window " << iWindow <<
654  ", index = " << index);
655  errorCountWindowMajor++;
656  }
657  } else if (dataFormatVersionExpected == 3) {
658  revoClockT0CombinedDecisionPrev = (rdat[index]) & 0x7ff;
659  revoClockT0CombinedDecisionNow = (rdat[index] >> 11) & 0x7ff;
660  }
661 
662  index++;
663 
664  // cnttrg: event number at the time of TOP combined t0 decision (should be current L1 event number - 1)
665  int cnttrgNow = rdat[index];
666  // B2INFO("trgtag (evt) from buffer header, cnttrg and rvc from window = " << trgtag <<", " << cnttrgNow << ", " << revoClockNow);
667 
668  // report and store combined t0 decision - this is where we can write all this info into persistent objects
669  if (t0CombinedDecisionNow != t0CombinedDecisionLast) {
670 
671  t0CombinedDecisionLast = t0CombinedDecisionNow;
672 
673  int t0Residual = t0CombinedDecisionNow - t0CombinedDecisionNowEstimated;
674 
675  //-------------------------------------------------------------------------------------------
676  /*
677  B2INFO("l1_rvc from buffer header, rvc for window# = "
678  << l1_revo << ", "
679  << revoClockNow << ", "
680  << iWindow
681  );
682 
683  if ( dataFormatVersionExpected == 3 ) {
684  B2INFO("rvc for previous and current combined t0 decisions, rvc when the current t0 decision was supposed to be posted to GDL/GRL, current window# = "
685  << revoClockT0CombinedDecisionPrev << ", "
686  << revoClockT0CombinedDecisionNow << ", "
687  << revoClockGDL << ", "
688  << iWindow
689  );
690  }
691 
692 
693  B2INFO("trgtag (evt) from buffer header, cnttrg for window# = "
694  << trgtag << ", "
695  << cnttrgNow << ", "
696  << iWindow
697  );
698 
699  B2INFO("TOP timing (+1735, ns, frame), actual and estimated combined t0 (raw ns, frame9), N slots, discrepancy (raw ns) = " << (int) ((t0CombinedDecisionNow%10240)*clkTo1ns+1735) << ", " << t0CombinedDecisionNow << ", " << t0CombinedDecisionNowEstimated << ", " << nSlotsCombinedDecision << ", " << t0Residual);
700 
701  // report slot-level t0 decisions
702  for ( int iSlot = 0; iSlot < NUMBER_OF_SLOTS; iSlot++ ) {
703  if ( t0CombinedSegments[iSlot] != 0 ) {
704  B2INFO("slot= " << iSlot+1
705  << ", segment= " << t0CombinedSegments[iSlot]
706  << ", TOP timing (+1735, ns, frame) = " << (int) (( 2 * t0CombinedSlots[iSlot])%10240*clkTo1ns+1735)
707  << ", t0 (raw ns, frame9) = " << 2 * t0CombinedSlots[iSlot]
708  << ", N hits= " << nHitsSlots[iSlot]
709  << ", log L= " << logLikelihoodsSlots[iSlot]
710  );
711  }
712  }
713  */
714  //-------------------------------------------------------------------------------------------
715 
716  // store decision in event store
717  m_TRGTOPCombinedTimingArray.appendNew();
718 
719  int i = m_TRGTOPCombinedTimingArray.getEntries() - 1;
720 
721  m_TRGTOPCombinedTimingArray[i]->setEventIdL1(trgtag);
722  m_TRGTOPCombinedTimingArray[i]->setEventIdTOP(cnttrgNow);
723  m_TRGTOPCombinedTimingArray[i]->setWindowIdTOP(iWindow);
724  m_TRGTOPCombinedTimingArray[i]->setRvcB2L(l1_revo);
725  m_TRGTOPCombinedTimingArray[i]->setRvcWindow(revoClockNow);
726  m_TRGTOPCombinedTimingArray[i]->setRvcTopTimingDecisionPrev(revoClockT0CombinedDecisionPrev);
727  m_TRGTOPCombinedTimingArray[i]->setRvcTopTimingDecisionNow(revoClockT0CombinedDecisionNow);
728  m_TRGTOPCombinedTimingArray[i]->setRvcTopTimingDecisionNowGdl(revoClockGDL);
729  m_TRGTOPCombinedTimingArray[i]->setCombinedTimingTop(t0CombinedDecisionNow);
730  m_TRGTOPCombinedTimingArray[i]->setNSlotsCombinedTimingTop(nSlotsCombinedDecision);
731  m_TRGTOPCombinedTimingArray[i]->setCombinedTimingTopResidual(t0Residual);
732  m_TRGTOPCombinedTimingArray[i]->setNErrorsMinor(errorCountWindowMinor);
733  m_TRGTOPCombinedTimingArray[i]->setNErrorsMajor(errorCountWindowMajor);
734  m_TRGTOPCombinedTimingArray[i]->setTrigType(m_trigType);
735 
736  // now store slot-level decisions
737 
738  int nSlots = 0;
739 
740  int nHitSum = 0;
741 
742  double logLSum_d = 0;
743  double logLSum2_d = 0;
744 
745  double timingSum_d = 0;
746  double timingSum2_d = 0;
747 
748  for (int iSlot = 0; iSlot < NUMBER_OF_SLOTS; iSlot++) {
749  int slotNErrors = 0;
750  // data corruption (no slot-level segment information available but N hits != 0)
751  if (t0CombinedSegments[iSlot] == 0 && nHitsSlots[iSlot] != 0) slotNErrors++;
752  // store compromised decisions also
753  if (t0CombinedSegments[iSlot] != 0 || nHitsSlots[iSlot] != 0) {
754 
755  nSlots++;
756  nHitSum = nHitSum + nHitsSlots[iSlot];
757 
758  logLSum_d = logLSum_d + logLikelihoodsSlots[iSlot];
759  logLSum2_d = logLSum2_d + logLikelihoodsSlots[iSlot] * logLikelihoodsSlots[iSlot];
760 
761  int timingNow = (2 * t0CombinedSlots[iSlot] % 10240);
762 
763  // B2INFO(" timingNow = " << timingNow );
764 
765  timingSum_d = timingSum_d + timingNow;
766  timingSum2_d = timingSum2_d + pow(timingNow, 2);
767 
768  TRGTOPSlotTiming slotTiming(iSlot + 1);
769  slotTiming.setSlotTiming(2 * t0CombinedSlots[iSlot]);
770  slotTiming.setSlotSegment(t0CombinedSegments[iSlot]);
771  slotTiming.setSlotNHits(nHitsSlots[iSlot]);
772  slotTiming.setSlotLogL(logLikelihoodsSlots[iSlot]);
773  slotTiming.setSlotNErrors(slotNErrors);
774  m_TRGTOPCombinedTimingArray[i]->setSlotTimingDecision(slotTiming);
775 
776  }
777  }
778 
779  if (nSlots == 0) nSlots = 1;
780 
781  double logLVar_d = logLSum2_d / nSlots - pow(logLSum_d / nSlots, 2);
782  int logLVar = (int)(logLVar_d + 0.5);
783  int logLSum = (int)(logLSum_d + 0.5);
784 
785  double timingVar_d = timingSum2_d / nSlots - pow(timingSum_d / nSlots, 2);
786  int timingVar = (int)(timingVar_d + 0.5);
787  // int timingSum = (int) (timingSum_d + 0.5);
788  // int timingSum2 = (int) (timingSum2_d + 0.5);
789 
790  // B2INFO("nSlots = " << nSlots );
791  // B2INFO("timingSum = " << timingSum );
792  // B2INFO("timingSum2 = " << timingSum2 );
793  // B2INFO("timingVar = " << timingVar );
794 
795  if (nSlots == 1) {
796  logLVar = -1;
797  timingVar = -1;
798  }
799 
800  m_TRGTOPCombinedTimingArray[i]->setNHitSum(nHitSum);
801  m_TRGTOPCombinedTimingArray[i]->setLogLSum(logLSum);
802  m_TRGTOPCombinedTimingArray[i]->setLogLVar(logLVar);
803  m_TRGTOPCombinedTimingArray[i]->setTimingVar(timingVar);
804 
805  //================================================================
806  // some inlined validation
807  /*
808  const vector<Belle2::TRGTOPSlotTiming> tmp = m_TRGTOPCombinedTimingArray[i]->getSlotTimingDecisions();
809 
810  cout << "-VS-D-the number of slots in this decision (SlotTimingDecisions.size()) = " << tmp.size() << endl;
811 
812  for ( vector<Belle2::TRGTOPSlotTiming>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) {
813  const TRGTOPSlotTiming& slotTiming = *it;
814 
815  cout << "-VS-D-slot number = " << slotTiming.getSlotId() << endl;
816  cout << "-VS-D-slot timing = " << slotTiming.getSlotTiming() << endl;
817  cout << "-VS-D-slot segment = " << slotTiming.getSlotSegment() << endl;
818  cout << "-VS-D-slot N hits = " << slotTiming.getSlotNHits() << endl;
819  cout << "-VS-D-slot logL = " << slotTiming.getSlotLogL() << endl;
820  cout << "-VS-D-slot N errors = " << slotTiming.getSlotNErrors() << endl;
821 
822  }
823  */
824  //
825  //================================================================
826 
827  }
828 
829  errorCountEvent = errorCountEvent + errorCountWindowMinor + errorCountWindowMajor;
830 
831  }
832  }
833 
834  // at this time any unexpected features in the data are lumped together
835  // this includes possibly corrupted data (checksum would be a better solution to diagnose such problem)
836  // AND incorrectly prepared (but not corrupted) data
837  if (reportSummaryErrors) {
838  if (errorCountEvent != 0) {
839  B2INFO("Number of instances of unexpected data diagnozed during unpacking = " << errorCountEvent);
840  }
841 
842  if (numberRvcJumps > 0) {
843  B2INFO("The number of rvc jumps = " << numberRvcJumps);
844  B2INFO("The window of the first rvc jump = " << windowRvcJumpFirst);
845  B2INFO("The number of clock cycles associated with the first rvc jump = " << clocksRvcJumpFirst);
846  B2INFO("The number of combined decisions = " << m_TRGTOPCombinedTimingArray.getEntries());
847  }
848 
849  if (numberCntr127Jumps > 0) {
850  B2INFO("The number of cntr127 jumps = " << numberCntr127Jumps);
851  B2INFO("The window of the first cntr127 jump = " << windowCntr127JumpFirst);
852  B2INFO("The number of clock cycles associated with the first cntr127 jump = " << clocksCntr127JumpFirst);
853  B2INFO("The number of combined decisions = " << m_TRGTOPCombinedTimingArray.getEntries());
854  }
855  }
856 
857  // need to store the info about error rate / type of errors in unpacking
858  // need a new TObject for that (NOT an Array)
859 
860 }
861 
862 
864 {
865 }
866 
868 {
869 }
870 
871 
872 
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ 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:80
The Raw TOP class Class for RawCOPPER class data taken by TOP Currently, this class is almost same as...
Definition: RawTRG.h:27
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
virtual void initialize() override
Initialize the Module.
virtual void event() override
This method is the core of the module.
virtual void endRun() override
This method is called if the current run ends.
virtual void fillTreeTRGTOP(int *)
Unpacker main function.
virtual void terminate() override
This method is called at the end of the event processing.
virtual void beginRun() override
Called when entering a new run.
StoreArray< TRGTOPUnpackerStore > m_TRGTOPCombinedTimingArray
N words in raw data.
int m_trigType
Event number (according to L1/global)
std::string version() const
returns version of TRGGDLUnpackerModule.
virtual void readCOPPEREvent(RawTRG *, int)
Read data from TRG copper.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
int GetDetectorNwords(int n, int finesse_num)
get Detector buffer length
Definition: RawCOPPER.h:654
int * GetDetectorBuffer(int n, int finesse_num)
get Detector buffer
Definition: RawCOPPER.h:678
Abstract base class for different kinds of events.