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