Belle II Software development
trgtopUnpackerWaveformModule.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/trgtopUnpackerWaveform/trgtopUnpackerWaveformModule.h>
10#include <trg/top/dataobjects/TRGTOPWaveFormTimeStampsSlot.h>
11#include <trg/top/dataobjects/TRGTOPWaveFormTimeStamp.h>
12#include <rawdata/dataobjects/RawTRG.h>
13
14/* --------------- WARNING ---------------------------------------------- *
15If you have more complex parameter types in your class then simple int,
16double or std::vector of those you might need to uncomment the following
17include directive to avoid an undefined reference on compilation.
18* ---------------------------------------------------------------------- */
19// #include <framework/core/ModuleParam.templateDetails.h>
20
21#include <iostream>
22
23//using namespace std;
24using namespace Belle2;
25
26//-----------------------------------------------------------------
27// Register the Module
28//-----------------------------------------------------------------
29REG_MODULE(TRGTOPUnpackerWaveform);
30
32{
33 return std::string("1.00");
34}
35
36//-----------------------------------------------------------------
37// Implementation
38//-----------------------------------------------------------------
39
41 : Module::Module(), m_eventNumber(0), m_trigType(0), m_nodeId(0), m_nWords(0), m_reportedAlreadyRun_1(false),
42 m_reportedAlreadyRun_2(false)
43{
44 // Set module properties
45
46
47 std::string desc = "TRGTOPUnpackerWaveformModule(" + version() + ")" + "Unpacks TOP TRG waveforms";
48 setDescription(desc);
50
51 B2DEBUG(20, "TRGTOPUnpackerWaveform: Constructor done.");
52
53 // Parameter definitions
54
55 addParam("outputTimeStampsSlotsName", m_outputWaveFormTimeStampsSlotsName,
56 "name of TRGTOPWaveFormTimeStampsSlot store array", std::string(""));
57
58 addParam("outputTimeStampsName", m_outputWaveFormTimeStampsName,
59 "name of TRGTOPWaveFormTimeStamp store array", std::string(""));
60
61 addParam("overrideControlBits", m_overrideControlBits,
62 "Override control bits in data",
63 true);
64 // false);
65
66}
67
68TRGTOPUnpackerWaveformModule::~TRGTOPUnpackerWaveformModule()
69{
70}
71
73{
74
75 // m_TRGTOPWaveFormTimeStampsSlots.isRequired(m_outputTimeStampsSlotsName);
76 // m_TRGTOPWaveFormTimeStamps.isRequired(m_outputTimeStampsName);
77
78 m_TRGTOPWaveFormTimeStampsSlots.registerInDataStore(m_outputWaveFormTimeStampsSlotsName);
79 m_TRGTOPWaveFormTimeStamps.registerInDataStore(m_outputWaveFormTimeStampsName);
80
81 m_TRGTOPWaveFormTimeStampsSlots.registerRelationTo(m_TRGTOPWaveFormTimeStamps);
82 m_TRGTOPWaveFormTimeStamps.registerRelationTo(m_TRGTOPWaveFormTimeStampsSlots);
83}
84
85
87{
88 m_reportedAlreadyRun_1 = false;
89 m_reportedAlreadyRun_2 = false;
90}
91
93{
94
95 StoreArray<RawTRG> raw_trgarray;
96
97 for (int i = 0; i < raw_trgarray.getEntries(); i++) {
98
99 // Check PCIe40 data or Copper data
100 if (raw_trgarray[i]->GetMaxNumOfCh(0) == 48) { m_pciedata = true; }
101 else if (raw_trgarray[i]->GetMaxNumOfCh(0) == 4) { m_pciedata = false; }
102 else { B2FATAL("TRGTOPUnpackerModule: Invalid value of GetMaxNumOfCh from raw data: " << LogVar("Number of ch: ", raw_trgarray[i]->GetMaxNumOfCh(0))); }
103
104 int node_id = 0;
105 int ch_id_1 = 0;
106 int ch_id_2 = 1;
107 if (m_pciedata) {
108 node_id = 0x10000001;
109 ch_id_1 = 23;
110 ch_id_2 = 24;
111 } else {
112 node_id = 0x12000001;
113 ch_id_1 = 0;
114 ch_id_2 = 1;
115 }
116
117 for (int j = 0; j < raw_trgarray[i]->GetNumEntries(); j++) {
118
119 m_nodeId = raw_trgarray[i]->GetNodeID(j);
120
121 if (m_nodeId == node_id) {
122
123 int numberOfChannels = raw_trgarray[i]->GetMaxNumOfCh(i);
124
125 // B2INFO("raw_trgarray.GetMaxNumOfCh() = " << numberOfChannels);
126
127 for (int channel = 0; channel < numberOfChannels; channel++) {
128
129 if (channel != ch_id_1 && channel != ch_id_2) continue;
130
131 m_nWords = raw_trgarray[i]->GetDetectorNwords(j, channel);
132
133 // B2INFO("raw_trgarray[" << i << "]->GetDetectorNwords(" << j << ", " << channel << ") = " << m_nWords);
134
135 // if ( m_nWords > 3 ) { ////general header is 3 words long
136 if (m_nWords > 0) {
137
138 m_eventNumber = raw_trgarray[i]->GetEveNo(j);
139 m_trigType = raw_trgarray[i]->GetTRGType(j);
140
141 // B2INFO("raw_trgarray.getEntries() = " << raw_trgarray.getEntries());
142 // B2INFO("raw_trgarray[i]->GetNumEntries() = " << raw_trgarray[i]->GetNumEntries());
143 // B2INFO("raw_trgarray[]->GetEveNo(j) = " << raw_trgarray[i]->GetEveNo(j));
144 // B2INFO("raw_trgarray[]->GetNodeID(j) = " << std::hex << raw_trgarray[i]->GetNodeID(j) << std::dec);
145 // B2INFO("raw_trgarray[]->GetDetectorNwords(j,0) = " << m_nWords);
146
147 readDAQEvent(raw_trgarray[i], j, channel);
148
149 }
150 }
151 }
152 }
153 }
154}
155
156void TRGTOPUnpackerWaveformModule::readDAQEvent(RawTRG* raw_daq, int j, int channel)
157{
158 // if (raw_daq->GetDetectorNwords(j, channel) > 3) { ///general header is 3 words long
159 if (raw_daq->GetDetectorNwords(j, channel) > 0) {
160 unpackWaveforms(raw_daq->GetDetectorBuffer(j, channel), channel);
161 }
162}
163
164
166{
167
168 // B2INFO("channel, data size (32bit words) = " << channel << ", " << m_nWords);
169
170 // Information for each data window
171
172 // rvc from the header of the buffer
173 // int l1_revo = rdat[2] & 0x7ff; /// L1 timestamp (11 bits)
174
175 // L1 event number
176 // int trgtag = (rdat[2] >> 12) & 0xfffff; /// 20 LSBs of trgtag (sequential trigger number)
177
178 // B2INFO("l1_rvc from header = " << l1_revo);
179 // B2INFO("trgtag (evt) from buffer header = " << trgtag);
180
181 bool dataFormatKnown = false;
182
183 int windowSize = -1;
184 int numberOfWindows = -1;
185
186 // int dataFormatVersionExpected = -1;
187 // int revoClockDeltaExpected = 4;
188 // int cntr127DeltaExpected = 4;
189
190 // 3 = 3: header only
191 // 1875 = 3 + 48*39: format used starting ~June 30 2019 and until Oct. 1, 2019 (until Receive FW version 0x02067301)
192 // 771 = 3 + 24*32: format used starting ~Oct. 1, 2019 (Receive FW version 0x02067301 and newer)
193 // 1539 = 3 + 48*32: format used starting ~Mar. 25, 2021 (Receive FW version 0x03020003 and newer)
194 // 3075 = 3 + 96*32: format used starting ~Mar. 25, 2021 (Receive FW version 0x03020003 and newer)
195
196 // m_nWords==3 means only a header
197 if (m_nWords == 3) {
198 windowSize = 0;
199 numberOfWindows = 0;
200 dataFormatKnown = true;
201 // dataFormatVersionExpected = 0;
202 } else if (m_nWords == 771) {
203 windowSize = 32;
204 numberOfWindows = 24;
205 dataFormatKnown = true;
206 // dataFormatVersionExpected = 2;
207 } else if (m_nWords == 1875) {
208 windowSize = 39;
209 numberOfWindows = 48;
210 dataFormatKnown = true;
211 // dataFormatVersionExpected = 1;
212 } else if (m_nWords == 1539) {
213 windowSize = 32;
214 numberOfWindows = 48;
215 dataFormatKnown = true;
216 // dataFormatVersionExpected = 4;
217 } else if (m_nWords == 3075) {
218 windowSize = 32;
219 numberOfWindows = 96;
220 dataFormatKnown = true;
221 // dataFormatVersionExpected = 4;
222 }
223
224 if (!dataFormatKnown) {
225 if (!m_reportedAlreadyRun_1) {
226 B2INFO("Unknown data format / error / exiting. This condition is reported only once per run.");
227 m_reportedAlreadyRun_1 = true;
228 }
229 return;
230 }
231
232 // FTSW / rvc / the difference is 1280 (expected)
233 // int revoClockDeltaJump1 = -92;
234 // int revoClockDeltaJump2 = 1188;
235
236 // VME / 16bit counter
237 // int cntr127DeltaJump1 = -92;
238 // int cntr127DeltaJump2 = -65532;
239
240 // if ( dataFormatVersionExpected > 0 ) B2INFO("---------------------------------------------------------------------------------------------------------------");
241
242 // B2INFO("Data format version (as expected according to data size) = " << dataFormatVersionExpected);
243
244 // if ( numberOfWindows != 0 ) {
245 // B2INFO("Number of 32bit words in TOP L1 data buffer = " << m_nWords);
246 // B2INFO("Number of windows = " << numberOfWindows);
247 // B2INFO("Window size in 32bit words = " << windowSize);
248 // }
249
250 // int revoClockLast = -1;
251 // int cntr127Last = -1;
252
253 // error counter for possible data corruption
254 // unsigned int errorCountEvent = 0;
255
256 // 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)
257 // int t0CombinedDecisionLast = -1;
258 // int logLSumLast = -1;
259 // int logLSumNow = 0;
260
261 bool performBufferAnalysis = true;
262 bool reportAllErrors = true;
263 // bool reportSummaryErrors = true;
264
265 // check if this event's buffer is a dummy buffer
266 int counterDummyWindows = 0;
267 unsigned int testPatternDummyEvent = 0xbbbb;
268 for (int iWindow = 0; iWindow < numberOfWindows; iWindow++) {
269 int index = iWindow * windowSize + 3;
270 // various test patterns will be used to check the data
271 unsigned int testPattern = (rdat[index] >> 16) & 0xffff;
272 if (testPattern == testPatternDummyEvent) {
273 counterDummyWindows++;
274 }
275
276 // March 30, 2022: need to be able to override the settings in data
277 if (!m_overrideControlBits) {
278 // Oct. 31, 2020: three most significant bits are now used to control unpacker from FW
279 // Note that setting either flag for any of the windows changes it for all windows here
280 testPattern = (rdat[index + 2] >> 29) & 0x7;
281 if (testPattern & 0x1) performBufferAnalysis = false;
282 if (testPattern & 0x2) reportAllErrors = false;
283 // if (testPattern & 0x4) reportSummaryErrors = false;
284 }
285 }
286
287 // note that events with empty buffer have numberOfWindows=0
288 if (counterDummyWindows == numberOfWindows) {
289 performBufferAnalysis = false;
290 } else {
291 if (counterDummyWindows != 0) {
292 if (reportAllErrors) B2ERROR("Corrupted data? numberOfWindows = " << numberOfWindows << ", counterDummyWindows = " <<
293 counterDummyWindows);
294 performBufferAnalysis = false;
295 }
296 }
297
298 /*
299 int numberRvcJumps = 0;
300 int numberCntr127Jumps = 0;
301 int windowRvcJumpFirst = -1;
302 int windowCntr127JumpFirst = -1;
303 // int clocksRvcJumpFirst = -1;
304 // int clocksCntr127JumpFirst = -1;
305
306 if (performBufferAnalysis) {
307 for (int iWindow = 0; iWindow < numberOfWindows; iWindow++) {
308 int index = iWindow * windowSize + 3;
309
310 // revoclk (comes from b2tt) has the range between 0 and 1279 @127MHz => 1279*7.8ns ~10us = 1 revolution (11bits are used)
311 int revoClockNow = rdat[index] & 0x7ff;
312 // B2INFO("rvc now = " << revoClockNow);
313 // first need to know max revoClock (1279)
314 if (revoClockLast != -1) {
315 // if (revoClockLast != -1 && revoClockNow > revoClockLast) {
316 int revoClockDeltaNow = revoClockNow - revoClockLast;
317 if (revoClockDeltaNow != revoClockDeltaExpected) {
318 // -1276 is simply going to the next cycle of rvc counting
319 if (revoClockDeltaNow != -1276) {
320 if (reportAllErrors) B2INFO("rvc changed by an unexpected number of units: " << revoClockDeltaNow << ", last rvc = " <<
321 revoClockLast <<
322 ", current rvc = " << revoClockNow << ", window " << iWindow << ", index = " << index);
323 numberRvcJumps++;
324 if (windowRvcJumpFirst < 0) {
325 windowRvcJumpFirst = iWindow;
326 // clocksRvcJumpFirst = revoClockDeltaNow;
327 }
328 }
329 }
330 }
331 revoClockLast = revoClockNow;
332
333 int cntr127Now = (rdat[index + 1] >> 16) & 0xffff;
334 // B2INFO("cntr127 now = " << cntr127Now);
335 // first need to know max cntr127
336 if (cntr127Last != -1) {
337 // if (cntr127Last != -1 && cntr127Now > cntr127Last) {
338 int cntr127DeltaNow = cntr127Now - cntr127Last;
339 if (cntr127DeltaNow != cntr127DeltaExpected) {
340 // 65444 is the value of the difference in cntr127 (VME counter) because we use 16 bits of 64 bit-long counter
341 if (cntr127DeltaNow != 65444) {
342 if (reportAllErrors) B2INFO("cntr127 changed by an unexpected number of units: " << cntr127DeltaNow << ", cntr127 last = " <<
343 cntr127Last <<
344 ", cntr127 now = " << cntr127Now << ", window " << iWindow << ", index = " << index + 1);
345 numberCntr127Jumps++;
346 if (windowCntr127JumpFirst < 0) {
347 windowCntr127JumpFirst = iWindow;
348 // clocksCntr127JumpFirst = cntr127DeltaNow;
349 }
350 }
351 }
352 }
353 cntr127Last = cntr127Now;
354 }
355 }
356 */
357
358 /*
359 if (numberRvcJumps > 0) {
360 B2INFO("The number of rvc jumps = " << numberRvcJumps);
361 B2INFO("The window of the first rvc jump = " << windowRvcJumpFirst);
362 B2INFO("The number of clock cycles associated with the first rvc jump = " << clocksRvcJumpFirst);
363 }
364
365 if (numberCntr127Jumps > 0) {
366 B2INFO("The number of cntr127 jumps = " << numberCntr127Jumps);
367 B2INFO("The window of the first cntr127 jump = " << windowCntr127JumpFirst);
368 B2INFO("The number of clock cycles associated with the first cntr127 jump = " << clocksCntr127JumpFirst);
369 }
370 */
371
372 // debugging: report everything from every single window when we are seeing unexpected jumps in either of the two counters
373 /*
374 if (numberRvcJumps > 0 || numberCntr127Jumps > 0) {
375 B2INFO("===========================================================================================================");
376 B2INFO("l1_rvc from header = " << l1_revo);
377 B2INFO("trgtag (evt) from buffer header = " << trgtag);
378 B2INFO("Reporting the entire data buffer");
379 B2INFO("Header 0 = : " << std::hex << rdat[0] << std::dec);
380 B2INFO("Header 1 = : " << std::hex << rdat[1] << std::dec);
381 B2INFO("Header 2 = : " << std::hex << rdat[2] << std::dec);
382 for (int iWindow = 0; iWindow < numberOfWindows; iWindow++) {
383 int index = iWindow * windowSize + 3;
384
385 B2INFO("---------------------------------------------------------------------------------");
386 int revoClockNow = rdat[index] & 0x7ff;
387 B2INFO("w rvc ---------------------------- = " << iWindow << " " << revoClockNow);
388
389 int cntr127Now = (rdat[index + 1] >> 16) & 0xffff;
390 B2INFO("w cntr127 ---------------------------- = " << iWindow << " " << cntr127Now);
391
392 for (int i = 0; i < 24; i++) {
393 B2INFO("w i = : " << iWindow << " " << i << " " << std::hex << rdat[index+i] << std::dec);
394 }
395 }
396 }
397 */
398
399 // events with no buffer (i.e. no payload), empty (i.e. dummy) windows and presumably corrupted events are NOT analyzed
400 if (performBufferAnalysis) {
401
402 for (int iWindow = 0; iWindow < numberOfWindows; iWindow++) {
403 int index = iWindow * windowSize + 3;
404 int dataFormatVersionNow = (rdat[index] >> 11) & 0x1f;
405 if (dataFormatVersionNow < 4) return;
406 }
407
408 // clear TimeStamps - this should be done elsewhere automatically
409 // m_TRGTOPWaveFormTimeStampsSlots.clear();
410 // m_TRGTOPWaveFormTimeStamps.clear();
411
412 // store waveforms in event store
413
414 for (int i = 0; i < 8; i++) {
415
416 int slot = i + 1;
417 if (channel == 0) slot = slot + 8;
418
419 auto* timeStampsSlotStore = m_TRGTOPWaveFormTimeStampsSlots.appendNew(slot, 4 * numberOfWindows);
420
421 int nActualTimeStamps = 0;
422
423 int firstActualTimeStampValue = -1;
424 int firstActualTimeStampClockCycle = -1;
425
426 // Loop over windows in B2L buffer and retrieve the waveforms
427 for (int iWindow = 0; iWindow < numberOfWindows; iWindow++) {
428
429 int clockCycle = iWindow * 4;
430
431 // a pointer-like variable for accessing the data in the buffer sequentially
432 int index = iWindow * windowSize + 3;
433
434 // data start at rdat[index+16]
435
436 int shift_data = i * 2;
437
438 int value1 = (rdat[index + 16 + shift_data] >> 16) & 0xffff;
439 int value2 = (rdat[index + 16 + shift_data]) & 0xffff;
440 int value3 = (rdat[index + 17 + shift_data] >> 16) & 0xffff;
441 int value4 = (rdat[index + 17 + shift_data]) & 0xffff;
442
443 TRGTOPWaveFormTimeStamp timeStamp1(value1, slot);
444 TRGTOPWaveFormTimeStamp timeStamp2(value2, slot);
445 TRGTOPWaveFormTimeStamp timeStamp3(value3, slot);
446 TRGTOPWaveFormTimeStamp timeStamp4(value4, slot);
447
448 auto* timeStampStore = m_TRGTOPWaveFormTimeStamps.appendNew(timeStamp1);
449 timeStampsSlotStore->addRelationTo(timeStampStore);
450 timeStampStore->addRelationTo(timeStampsSlotStore);
451
452 timeStampStore = m_TRGTOPWaveFormTimeStamps.appendNew(timeStamp2);
453 timeStampsSlotStore->addRelationTo(timeStampStore);
454 timeStampStore->addRelationTo(timeStampsSlotStore);
455
456 timeStampStore = m_TRGTOPWaveFormTimeStamps.appendNew(timeStamp3);
457 timeStampsSlotStore->addRelationTo(timeStampStore);
458 timeStampStore->addRelationTo(timeStampsSlotStore);
459
460 timeStampStore = m_TRGTOPWaveFormTimeStamps.appendNew(timeStamp4);
461 timeStampsSlotStore->addRelationTo(timeStampStore);
462 timeStampStore->addRelationTo(timeStampsSlotStore);
463
464 if (!timeStamp1.isEmptyClockCycle()) {
465 nActualTimeStamps++;
466 if (nActualTimeStamps == 1) {
467 firstActualTimeStampValue = value1;
468 firstActualTimeStampClockCycle = clockCycle;
469 }
470 }
471 clockCycle++;
472
473 if (!timeStamp2.isEmptyClockCycle()) {
474 nActualTimeStamps++;
475 if (nActualTimeStamps == 1) {
476 firstActualTimeStampValue = value2;
477 firstActualTimeStampClockCycle = clockCycle;
478 }
479 }
480 clockCycle++;
481
482 if (!timeStamp3.isEmptyClockCycle()) {
483 nActualTimeStamps++;
484 if (nActualTimeStamps == 1) {
485 firstActualTimeStampValue = value3;
486 firstActualTimeStampClockCycle = clockCycle;
487 }
488 }
489 clockCycle++;
490
491 if (!timeStamp4.isEmptyClockCycle()) {
492 nActualTimeStamps++;
493 if (nActualTimeStamps == 1) {
494 firstActualTimeStampValue = value4;
495 firstActualTimeStampClockCycle = clockCycle;
496 }
497 }
498 clockCycle++;
499
500 }
501
502 timeStampsSlotStore->setNumberOfActualTimeStamps(nActualTimeStamps);
503 timeStampsSlotStore->setFirstActualTimeStampValue(firstActualTimeStampValue);
504 timeStampsSlotStore->setFirstActualTimeStampClockCycle(firstActualTimeStampClockCycle);
505
506 }
507 }
508
509}
510
511
515
519
520
521
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
Module()
Constructor.
Definition Module.cc:30
@ 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 readDAQEvent(RawTRG *, int, int)
Read data from TRG DAQ.
std::string m_outputWaveFormTimeStampsSlotsName
name of TOPTRGTimeStampsSlot store array
virtual void initialize() override
Initialize the Module.
TRGTOPUnpackerWaveformModule()
Constructor: Sets the description, the properties and the parameters of 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 terminate() override
This method is called at the end of the event processing.
std::string m_outputWaveFormTimeStampsName
name of TOPTRGTimeStamp store array
int m_eventNumber
Event number (according to L1/global)
virtual void beginRun() override
Called when entering a new run.
virtual void unpackWaveforms(int *, int)
Unpacker main function.
std::string version() const
returns version of TRGTOPUnpackerWaveformModule.
Class to store variables with their name which were sent to the logging service.
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:559
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
int GetDetectorNwords(int n, int finesse_num)
get Detector buffer length
Definition RawCOPPER.h:657
int * GetDetectorBuffer(int n, int finesse_num)
get Detector buffer
Definition RawCOPPER.h:681
Abstract base class for different kinds of events.