Belle II Software  release-06-02-00
PXDPackerErrModule.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 <pxd/unpacking/PXDRawDataDefinitions.h>
10 #include <pxd/modules/pxdUnpacking/PXDPackerErrModule.h>
11 #include <framework/datastore/DataStore.h>
12 #include <framework/logging/Logger.h>
13 #include <framework/dataobjects/EventMetaData.h>
14 #include <framework/datastore/StoreObjPtr.h>
15 #include <framework/core/ModuleParam.templateDetails.h>
16 
17 #include <boost/crc.hpp>
18 
19 #include <numeric>
20 
21 #include <TRandom.h>
22 
23 using namespace std;
24 using namespace Belle2;
25 using namespace Belle2::PXD;
26 using namespace Belle2::PXD::PXDError;
27 
28 //-----------------------------------------------------------------
29 // Register the Module
30 //-----------------------------------------------------------------
31 REG_MODULE(PXDPackerErr)
32 
33 
34 using boost::crc_optimal;
35 typedef crc_optimal<32, 0x04C11DB7, 0, 0, false, false> dhc_crc_32_type;
36 
40 std::vector <PXDErrorFlags> PXDPackerErrModule::m_errors = {
41  // Event 0 does not exist...
42  c_NO_ERROR,
43  /* 1 - HLT-Onsen Trigger differs from Meta (meta changed! thus all differ)
44  * 2 - HLT-Onsen Trigger is zero
45  * 3 - Run Nr differs between HLT-Onsen and Meta
46  * 4 - Subrun Nr differs between HLT-Onsen and Meta
47  * 5 - Exp differs between HLT-Onsen and Meta */
48  c_META_MM | c_META_MM_DHC | c_META_MM_DHE | c_META_MM_ONS_HLT | c_META_MM_ONS_DC,
49  c_META_MM | c_META_MM_DHC | c_META_MM_DHE | c_META_MM_ONS_HLT | c_META_MM_ONS_DC,
50  c_META_MM_DHC_ERS | c_META_MM_ONS_HLT | c_META_MM_ONS_DC,
51  c_META_MM_DHC_ERS | c_META_MM_ONS_HLT | c_META_MM_ONS_DC,
52  c_META_MM_DHC_ERS | c_META_MM_ONS_HLT | c_META_MM_ONS_DC,
53  /* 6 - Wrong ONS Trigger frame length
54  * 7 - Wrong DHC Start frame length
55  * 8 - Wrong DHC End frame length
56  * 9 - Wrong DHE Start frame length
57  * 10 - Wrong DHE End frame length */
58  c_FIX_SIZE, // TODO why mismatch?
59  c_FIX_SIZE, // TODO Problem
60  c_FIX_SIZE, // TODO why is DHC End missing not detected?
61  c_FIX_SIZE, // TODO why is DHE Start missing not detected?
62  c_FIX_SIZE, // TODO why is DHE End missing not detected?
63  /* 11 - Wrong DHE Start frame length (by 2 bytes), unalign 32 bit frame
64  * 12 - Missing ONS Trig frame
65  * 13 - Missing DHC Start frame
66  * 14 - Missing DHC End frame
67  * 15 - Missing DHE Start frame */
68  c_FRAME_SIZE, // TODO can check more errors
69  c_ONSEN_TRG_FIRST | c_DHC_START_SECOND | c_DHE_START_THIRD | c_EVENT_STRUCT, // TODO
70  c_DHC_START_SECOND, // TODO
71  c_DHC_END_MISS,
72  c_DHE_END_WO_START | c_DHE_START_THIRD, // TODO
73  /* 16 - Missing DHE End frame
74  * 17 - Double ONS Trig frame
75  * 18 - Double DHC Start frame
76  * 19 - Double DHC End frame
77  * 20 - Double DHE Start frame*/
78  c_DHE_START_WO_END, // TODO if two DHE, another error condition shoudl trigger, too
79  c_ONSEN_TRG_FIRST | c_DHC_START_SECOND | c_DHE_START_THIRD | c_EVENT_STRUCT, // TODO why data outside of ...
80  c_DHC_START_SECOND | c_DHE_START_THIRD, // TODO why data outside of ...
81  c_DHC_END_DBL, // TODO
82  c_DHE_WRONG_ID_SEQ | c_DHE_START_WO_END, // TODO
83  /* 21 - Double DHE End frame
84  * 22 - DATCON triggernr+1
85  * 23 - HLT Magic broken
86  * 24 - DATCON Magic broken
87  * 25 - HLT with Accepted not set */
88  c_DHE_END_WO_START | c_DHE_START_END_ID, // TODO
89  c_MERGER_TRIGNR | c_META_MM_ONS_DC,
90  c_HLTROI_MAGIC,
91  c_HLTROI_MAGIC,
92  c_NO_ERROR | c_NOTSENDALL_TYPE, // TODO =============================================== CHECK TODO Unpacker is not detecting this yet
93  /* 26 - HLT triggernr+1
94  * 27 - CRC error in second frame (DHC start)
95  * 28 - data for all DHE even if disabled in mask
96  * 29 - no DHE at all, even so mask tell us otherwise
97  * 30 - no DHC at all */
98  c_MERGER_TRIGNR | c_META_MM_ONS_HLT,
99  c_DHE_CRC, // TODO why DHE start missing not detected?
100  c_DHE_ACTIVE, // TODO why | c_DHE_WRONG_ID_SEQ | c_DHE_ID_INVALID,
101  c_DHE_START_THIRD | c_DHE_ACTIVE,
102  c_DHC_END_MISS, // TODO need some better checks
103  /* 31 - DHC end has wrong DHC id
104  * 32 - DHE end has wrong DHE id
105  * 33 - DHC wordcount wrong by 4 bytes
106  * 34 - DHE wordcount wrong by 4 bytes
107  * 35 - DHE Trigger Nr Hi word messed up */
108  c_DHC_DHCID_START_END_MM,
109  c_DHE_START_END_ID,
110  c_DHC_WIE,
111  c_DHE_WIE,
112  c_META_MM_DHE,
113  /* 36 - ONS Trigger Nr Hi word messed up
114  * 37 - DHP data, even if mask says no DHP TODO Check
115  * 38 - No DHP data, even if mask tell otherwise
116  * 39 - DHE id differ in DHE and DHP header
117  * 40 - Chip ID differ in DHE and DHP header */
118  c_META_MM_ONS_HLT | c_MERGER_TRIGNR,
119  c_NO_ERROR, // TODO ===========================================TODO Unpacker is not detecting this
120  c_DHP_ACTIVE,
121  c_DHE_DHP_DHEID,
122  c_DHE_DHP_PORT,
123  /* 41 - Row overflow by 1
124  * 42 - Col overflow by 1
125  * 43 - Missing Start Row (Pixel w/o row)
126  * 44 - No PXD raw packet at all
127  * 45 - No DATCON data */
128  c_ROW_OVERFLOW,
129  c_COL_OVERFLOW,
130  c_DHP_PIX_WO_ROW,
131  c_NO_PXD,
132  c_NO_DATCON,
133  /* 46 - unused frame type: common mode
134  * 47 - unused frame type: FCE
135  * 48 - unused frame type: ONS FCE
136  * 49 - unused frame type: 0x7
137  * 50 - unused frame type: 0x8 */
138  c_UNEXPECTED_FRAME_TYPE,
139  c_UNEXPECTED_FRAME_TYPE,
140  c_UNEXPECTED_FRAME_TYPE,
141  c_DHC_UNKNOWN,
142  c_DHC_UNKNOWN,
143  /* 51 - unused frame type: 0xA
144  * 52 - Rows w/o Pixel (several rows after each other)
145  * 53 - no frames in packet (this should be an error)
146  * 54 - broken PXD packet magic
147  * 55 - exceeding allowed nr of frames by far */
148  c_DHC_UNKNOWN,
149  c_DHP_ROW_WO_PIX,
150  c_NR_FRAMES_TO_SMALL,
151  c_MAGIC,
152  c_FRAME_NR,
153  /* 56 - more frames than actual available, exceeding packet size
154  * 57 - one frame payload exceeding packet size
155  * 58 - DHC Start frame has wrong trigger Nr HI
156  * 59 - DHC Start frame has wrong trigger Nr LO
157  * 60 - DHE Start frame has wrong trigger Nr LO */
158  c_FRAME_SIZE,
159  c_FRAME_SIZE,
160  c_META_MM_DHC,
161  c_FRAME_TNR_MM | c_META_MM | c_META_MM_DHC,
162  c_FRAME_TNR_MM | c_META_MM | c_META_MM_DHE,
163  /* 61 - DHE End frame has wrong trigger Nr LO
164  * 62 - DHE End has different DHE Id
165  * 63 - DHE Z_DHP Header DHE ID differ from Start
166  * 64 - Set ERROR Flag in DHE END
167  * 65 - Invalid DHE ID ($3F) in DHE */
168  c_FRAME_TNR_MM | c_META_MM, // TODO why not |c_META_MM_DHE
169  c_DHE_START_END_ID, // TODO why not c_DHE_START_ID,
170  c_DHE_START_ID | c_DHE_DHP_DHEID,
171  c_HEADER_ERR,
172  c_DHE_ID_INVALID,
173  /* 66 - Doubled DHP Header
174  * 67 - 'FAKE' DHC START/END (=no data)
175  * 68 - wrong readout frame number in DHP header TODO
176  * 69 - DHP frame with too small size
177  * 70 - TimeTag Mismatch for DHC/Meta */
178  c_DHP_DBL_HEADER,
179  c_FAKE_NO_DATA_TRIG,
180  c_NO_ERROR,// TODO ===========================================TODO Unpacker is not detecting this
181  c_DHP_SIZE,
182  c_META_MM_DHC_TT,
183  /*
184  * 71 data outside of DHE
185  * 72 Fake no Fake mix, plus a second DHC
186  * 73 Fake no Fake mix, plus double DHC End
187  * 74 Fake no Fake mix, plus double DHC Start
188  * 75 Fake no Fake mix, replaced DHC End
189  */
190  c_DATA_OUTSIDE,
191  c_FAKE_NO_FAKE_DATA,
192  c_FAKE_NO_FAKE_DATA,
193  c_FAKE_NO_FAKE_DATA,
194  c_FAKE_NO_FAKE_DATA,
195  /*
196  * 76 Fake no Fake mix, replaced DHC Start
197  * 77 ROI Frame without header/content, inside DHC Start/End
198  * 78 ROI Frame without header/content, outside DHC Start/End ... this is not allowed (ONSEN)
199  * 79 TODO ROI Frame with header & content
200  * 80 TODO ROI Frame with header & content but errors
201  */
202  c_FAKE_NO_FAKE_DATA,
203  c_ROI_PACKET_INV_SIZE,
204  c_ROI_PACKET_INV_SIZE,// no error flag for this?
205  c_NO_ERROR,
206  c_NO_ERROR, // not error bit for this?
207 };
208 
209 bool PXDPackerErrModule::CheckErrorMaskInEvent(unsigned int eventnr, PXDErrorFlags mask)
210 {
213  PXDErrorFlags expected; // constructed to no error
214  if (eventnr > 0 && eventnr < m_errors.size()) {
215  expected = m_errors[eventnr];
216  }
217  B2INFO("-- PXD Packer Error Check for Event Nr: " << eventnr);
218  for (int i = 0; i < ONSEN_MAX_TYPE_ERR; i++) {
219  PXDErrorFlags m;
220  m[i] = true;
221  if ((m & (mask | expected)) == m) {
222  if ((m & expected) == m && (m & mask) != m) {
223  B2ERROR("Bit " << i << ": Was NOT Set: " << getPXDBitErrorName(i));
224  m_found_fatal = true;
225  } else if ((m & expected) != m && (m & mask) == m) {
226  B2RESULT("Bit " << i << ": Optional : " << getPXDBitErrorName(i));
227  } else if ((m & expected) == m && (m & mask) == m) {
228  B2INFO("Bit " << i << ": As Expected: " << getPXDBitErrorName(i));
229  }
230  }
231  }
232  bool flag = (mask & expected) == expected;
233  if (expected == PXDErrorFlags(0)) {
234  // special check, this event should not contain any error!
235  if (mask != PXDErrorFlags(0)) {
236  B2ERROR("There should be no error in this event, but there were (see above)!");
237  m_found_fatal = true;
238  }
239  flag = (mask == PXDErrorFlags(0));
240  }
241  B2INFO("-- PXD Packer Error Check END --- ");
242  // Bail out on the first check which fails.
243  if (m_found_fatal) B2FATAL("This check failed (see details above)!");
244  return flag;
245 }
246 
247 PXDPackerErrModule::PXDPackerErrModule() :
248  Module(),
249  m_storeRaws()
250 {
251  m_trigger_nr = 0;
252  m_packed_events = 0;
253  m_run_nr_word1 = 0;
254  m_run_nr_word2 = 0;
255  //Set module properties
256  setDescription("Create 'broken' PXD raw data to challenge Unpacker");
258 
259  addParam("RawPXDsName", m_RawPXDsName, "The name of the StoreArray of generated RawPXDs", std::string(""));
260  addParam("dhe_to_dhc", m_dhe_to_dhc, "DHE to DHC mapping (DHC_ID, DHE1, DHE2, ..., DHE5) ; -1 disable port");
261  addParam("InvertMapping", m_InvertMapping, "Use invers mapping to DHP row/col instead of \"remapped\" coordinates", false);
262  addParam("Clusterize", m_Clusterize, "Use clusterizer (FCE format)", false);
263  addParam("Check", m_Check, "Check the result of Unpacking", false);
264  addParam("PXDDAQEvtStatsName", m_PXDDAQEvtStatsName, "The name of the StoreObjPtr of read PXDDAQEvtStats", std::string(""));
265 
266 }
267 
269 {
270  m_found_fatal = false;
271  B2DEBUG(27, "PXD Packer Err --> Init");
272  if (m_Check) {
273  B2WARNING("=== Important! A lot of intentional errors will follow. To find the reason for a failing test, check the lines before the FATAL. ====");
274  m_daqStatus.isRequired();
275  } else {
276  //Register output collections
277  m_storeRaws.registerInDataStore(m_RawPXDsName, DataStore::EStoreFlags::c_ErrorIfAlreadyRegistered);
278  m_packed_events = 0;
279 
283  for (auto& it : m_dhe_to_dhc) {
284  bool flag;
285  int dhc_id;
286  B2DEBUG(27, "PXD Packer Err --> DHC/DHE");
287  flag = false;
288  if (it.size() != 6) {
290  B2WARNING("PXD Packer Err --> DHC/DHE maps 1 dhc to 5 dhe (1+5 values), but I found " << it.size());
291  }
292  for (auto& it2 : it) {
293  if (flag) {
294  int v;
295  v = it2;
296  B2DEBUG(27, "PXD Packer Err --> ... DHE " << it2);
297  if (it2 < -1 || it2 >= 64) {
298  if (it2 != -1) B2ERROR("PXD Packer Err --> DHC id " << it2 << " is out of range (0-64 or -1)! disable channel.");
299  v = -1;
300  }
301  m_dhc_mapto_dhe[dhc_id].push_back(v);
302  } else {
303  dhc_id = it2;
304  B2DEBUG(27, "PXD Packer Err --> DHC .. " << it2);
305  if (dhc_id < 0 || dhc_id >= 16) {
306  B2ERROR("PXD Packer Err --> DHC id " << it2 << " is out of range (0-15)! skip");
307  break;
308  }
309  }
310  flag = true;
311  }
312  }
313  B2DEBUG(27, "PXD Packer Err --> DHC/DHE done");
314 
315  for (auto& it : m_dhc_mapto_dhe) {
316  int port = 0;
317  B2DEBUG(27, "PXD Packer Err --> DHC " << it.first);
318  for (auto& it2 : it.second) {
319  B2DEBUG(27, "PXD Packer Err --> .. connects to DHE " << it2 << " port " << port);
320  port++;
321  }
322  }
323  }
324 }
325 
327 {
328  if (m_Check) {
329  // Bail out if error detected
330  if (m_found_fatal) B2FATAL("At least one of the checks failed (see details above)!");
331  // Check kindof test coverage
332  B2INFO("Check Test coverage:");
333  PXDErrorFlags mask = c_NO_ERROR;
334  mask = std::accumulate(m_errors.begin(), m_errors.end(), mask, std::bit_or<PXDErrorFlags>());
335  for (int i = 0; i < ONSEN_MAX_TYPE_ERR; i++) {
336  PXDErrorFlags m;
337  m[i] = true;
338  if ((m & mask) == 0) {
339  B2WARNING("Bit " << i << ": Not Covered : " << getPXDBitErrorName(i));
340  }
341  }
342  }
343 }
344 
346 {
347  B2DEBUG(27, "PXD Packer Err --> Event");
349 
350  m_real_trigger_nr = m_trigger_nr = evtPtr->getEvent();
351 
352  if (m_Check) {
354  } else {
355 
356  // First, throw the dices for a few event-wise properties
357 
358  m_trigger_dhp_framenr = gRandom->Integer(0x10000);
359  m_trigger_dhe_gate = gRandom->Integer(192);
360 
361 
362  if (isErrorIn(1)) m_trigger_nr += 10;
363  if (isErrorIn(2)) m_trigger_nr = 0;
364 
365  uint32_t run = evtPtr->getRun();
366  uint32_t exp = evtPtr->getExperiment();
367  uint32_t sub = evtPtr->getSubrun();
368 
369  if (isErrorIn(3)) run++;
370  if (isErrorIn(4)) sub++;
371  if (isErrorIn(5)) exp++;
372 
373  m_run_nr_word1 = ((run & 0xFF) << 8) | (sub & 0xFF);
374  m_run_nr_word2 = ((exp & 0x3FF) << 6) | ((run >> 8) & 0x3F);
375  m_meta_time = evtPtr->getTime();
376 
377  B2INFO("Pack Event : " << evtPtr->getEvent() << "," << evtPtr->getRun() << "," << evtPtr->getSubrun() << "," <<
378  evtPtr->getExperiment() << "," << evtPtr->getTime() << " (MetaInfo)");
379 
380  if (!isErrorIn(44)) {
381  pack_event();
382  m_packed_events++;
383  }
384  }
385 }
386 
388 {
389  int dhe_ids[5] = {0, 0, 0, 0, 0};
390  B2DEBUG(27, "PXD Packer Err --> pack_event");
391 
392  // loop for each DHC in system
393  // get active DHCs from a database?
394  for (auto& it : m_dhc_mapto_dhe) {
395  int port = 1, port_inx = 0;
396  int act_port = 0;
397 
398  for (auto& it2 : it.second) {
399  if (it2 >= 0) act_port += port;
400  port += port;
401  dhe_ids[port_inx] = it2;
402  port_inx++;
403  if (port_inx == 5) break; // not more than five.. checked above
404  }
405 
406  // if(act_port&0x1F) B2ERROR();... checked above
407  // act_port&=0x1F;... checked above
408 
409  // get active DHE mask from a database?
410 
411  m_onsen_header.clear();// Reset
412  m_onsen_payload.clear();// Reset
413  if (isErrorIn(74)) {
414  // add a faked DHC, "no data"
415  start_frame();
416  append_int32(EDHCFrameHeaderDataType::c_DHC_START << 27);
417  append_int16(0);
418  append_int16(0);
419  append_int16(0);
420  append_int16(0);
421  append_int16(0);
422  append_int16(0);
424  }
425  if (!isErrorIn(53)) pack_dhc(it.first, act_port, dhe_ids);
426  // and write to PxdRaw object
427  // header will be finished and endian swapped by constructor; payload already has be on filling the vector
428  if (isErrorIn(73)) {
429  // add a faked DHC, "no data"
430  start_frame();
431  append_int32(EDHCFrameHeaderDataType::c_DHC_END << 27);
432  append_int32(0);
433  append_int32(0);
435  }
436  if (isErrorIn(72)) {
437  // add a faked DHC, "no data"
438  start_frame();
439  append_int32(EDHCFrameHeaderDataType::c_DHC_START << 27);
440  append_int16(0);
441  append_int16(0);
442  append_int16(0);
443  append_int16(0);
444  append_int16(0);
445  append_int16(0);
447 
448  start_frame();
449  append_int32(EDHCFrameHeaderDataType::c_DHC_END << 27);
450  append_int32(0);
451  append_int32(0);
453  }
454  auto objptr = m_storeRaws.appendNew(m_onsen_header, m_onsen_payload);
455  if (isErrorIn(54)) {
456  objptr->data()[0] = 0xDEADBEAF; // invalid magic
457  }
458  if (isErrorIn(55)) {
459  objptr->data()[1] = 0x00110000; // invalid #frames
460  }
461  if (isErrorIn(56)) {
462  objptr->data()[1] = 0x00010000; // valid #frames, but will exceed size
463  }
464  if (isErrorIn(57)) {
465  objptr->data()[2] = 0x01010101; // extremely large frame
466  }
467  }
468 
469 }
470 
472 {
473  if (m_current_frame.size() & 0x3) {
474  B2WARNING("Frame is not 32bit aligned!!! Unsupported by Unpacker!");
475  }
476  // checksum frame
477  dhc_crc_32_type current_crc;
478  current_crc.process_bytes(m_current_frame.data(), m_current_frame.size());
479  if (isErrorIn(27) and m_onsen_header.size() == 1) current_crc.process_byte(0x42); // mess up CRC in second frame
480  append_int32(current_crc.checksum());
481 
482  // and add it
483  m_onsen_header.push_back(m_current_frame.size());
484  m_onsen_payload.push_back(m_current_frame);
485 }
486 
487 void PXDPackerErrModule::append_int8(unsigned char w)
488 {
489  m_current_frame.push_back(w);
490  dhe_byte_count++;
491  dhc_byte_count++;
492 }
493 
494 void PXDPackerErrModule::append_int16(unsigned short w)
495 {
496  m_current_frame.push_back((unsigned char)(w >> 8));
497  m_current_frame.push_back((unsigned char)(w));
498  dhe_byte_count += 2;
499  dhc_byte_count += 2;
500 }
501 
503 {
504  m_current_frame.push_back((unsigned char)(w >> 24));
505  m_current_frame.push_back((unsigned char)(w >> 16));
506  m_current_frame.push_back((unsigned char)(w >> 8));
507  m_current_frame.push_back((unsigned char)(w));
508  dhe_byte_count += 4;
509  dhc_byte_count += 4;
510 }
511 
512 // void PXDPackerErrModule::remove_back_int32(void)
513 // {
514 // m_current_frame.pop_back();
515 // m_current_frame.pop_back();
516 // m_current_frame.pop_back();
517 // m_current_frame.pop_back();
518 // dhe_byte_count -= 4;
519 // dhc_byte_count -= 4;
520 // }
521 
523 {
524  m_current_frame.clear();
525 }
526 
527 void PXDPackerErrModule::pack_dhc(int dhc_id, int dhe_active, int* dhe_ids)
528 {
529  B2DEBUG(27, "PXD Packer Err --> pack_dhc ID " << dhc_id << " DHE act: " << dhe_active);
530 
531  bool m_send_all = true;
532  bool m_send_roi = false;
533 
535  start_frame();
536  append_int32((EDHCFrameHeaderDataType::c_ONSEN_TRG << 27) | (m_trigger_nr & 0xFFFF));
537  B2INFO("Trigger packet: $" << hex << m_run_nr_word1 << ", $" << m_run_nr_word2);
538  if (isErrorIn(23)) {
539  append_int32(0xDEAD8000);
540  } else if (isErrorIn(25)) {
541  append_int32(0xCAFE0000);// HLT HEADER, NO accepted flag
542  } else {
543  append_int32(0xCAFE8000 | (m_send_all ? 0x4000 : 0) | (m_send_roi ? 0x2000 : 0)); // HLT HEADER, accepted flag set
544  }
545  if (isErrorIn(26)) {
547  } else if (isErrorIn(36)) {
548  append_int32(0x10000000 | m_trigger_nr); // HLT Trigger Nr with Hi work messed up
549  } else {
550  append_int32(m_trigger_nr); // HLT Trigger Nr
551  }
552  append_int16(m_run_nr_word2); // HLT Run NR etc
553  append_int16(m_run_nr_word1); // HLT Run NR etc
554  if (isErrorIn(24)) append_int32(0xDEAD0000);
555  else append_int32(0xCAFE0000);// DATCON HEADER ...
556  if (isErrorIn(45)) {
557  // No Datcon
558  append_int32(0x0); // trigger nr
559  append_int32(0x0); // 2*16 trg tag
560  } else {
561  if (isErrorIn(22)) append_int32(m_trigger_nr + 1);
562  else append_int32(m_trigger_nr);// DATCON Trigger Nr
563  if (!isErrorIn(6)) {
564  append_int16(m_run_nr_word2); // DATCON Run NR etc
565  append_int16(m_run_nr_word1); // DATCON Run NR etc
566  }
567  }
568  if (!isErrorIn(12)) add_frame_to_payload();
569  if (isErrorIn(17)) {
570  // double frame
571  m_onsen_header.push_back(m_current_frame.size());
572  m_onsen_payload.push_back(m_current_frame);
573  }
574 
575  if (isErrorIn(30)) return; // empty event, no DHC frames
576 
578  if (!isErrorIn(67)) {
579 
580  dhc_byte_count = 0;
581  if (isErrorIn(76)) {
582  // add a faked DHC, "no data"
583  start_frame();
584  append_int32(EDHCFrameHeaderDataType::c_DHC_START << 27);
585  append_int16(0);
586  append_int16(0);
587  append_int16(0);
588  append_int16(0);
589  append_int16(0);
590  append_int16(0);
592  } else {
593  start_frame();
594  uint32_t header = (EDHCFrameHeaderDataType::c_DHC_START << 27) | ((dhc_id & 0xF) << 21) | ((dhe_active & 0x1F) << 16) |
595  (m_trigger_nr & 0xFFFF);
596  if (isErrorIn(59)) header++;
597  append_int32(header);
598  if (!isErrorIn(58)) append_int16(m_trigger_nr >> 16);
599  else append_int16((m_trigger_nr >> 16) + 1);
600 
601  uint32_t mm = (unsigned int)std::round((m_meta_time % 1000000000ull) * 0.127216); // in 127MHz Ticks
602  uint32_t ss = (unsigned int)(m_meta_time / 1000000000ull) ; // in seconds
603  if (isErrorIn(70)) mm++;
604  if (isErrorIn(70)) ss++;
605  append_int16(((mm << 4) & 0xFFF0) | 0x1); // TT 11-0 | Type --- fill with something usefull TODO
606  append_int16(((mm >> 12) & 0x7FFF) | ((ss & 1) ? 0x8000 : 0x0)); // TT 27-12 ... not clear if completely filled by DHC
607  append_int16((ss >> 1) & 0xFFFF); // TT 43-28 ... not clear if completely filled by DHC
608  if (!isErrorIn(7)) {
609  append_int16(m_run_nr_word1); // Run Nr 7-0 | Subrunnr 7-0
610  append_int16(m_run_nr_word2); // Exp NR 9-0 | Run Nr 13-8
611  }
612  if (!isErrorIn(13)) add_frame_to_payload();
613  if (isErrorIn(18)) {
614  // double frame
615  m_onsen_header.push_back(m_current_frame.size());
616  m_onsen_payload.push_back(m_current_frame);
617  }
618  }
619 
620  // loop for each DHE in system
621  // Run & TTT etc are zero until better idea
622 
623  if (isErrorIn(29)) dhe_active = 0; // dont send any DHE
624  for (int i = 0; i < 5; i++) {
625  if ((dhe_active & 0x1) or isErrorIn(28)) pack_dhe(dhe_ids[i], 0xF);
626  if (isErrorIn(71) && i == 2) {
627  pack_dhp(1, dhe_ids[i], 1);
628  }
629  dhe_active >>= 1;
630  }
631 
633 
634  if (isErrorIn(77)) {
635  // TODO add ROI Frame if header bit is set
636  int old = dhc_byte_count;
637  start_frame();
638  append_int32((EDHCFrameHeaderDataType::c_ONSEN_ROI << 27) | (m_trigger_nr & 0xFFFF));
640  dhc_byte_count = old; // dont count
641  }
642 
644  if (isErrorIn(75)) {
645  // add a faked DHC, "no data"
646  start_frame();
647  append_int32(EDHCFrameHeaderDataType::c_DHC_END << 27);
648  append_int32(0);
649  append_int32(0);
651  } else {
652  if (isErrorIn(31)) dhc_id += 1;
653  if (isErrorIn(33)) dhc_byte_count += 4;
654  unsigned int dlen = (dhc_byte_count / 4); // 32 bit words
655  start_frame();
656  append_int32((EDHCFrameHeaderDataType::c_DHC_END << 27) | ((dhc_id & 0xF) << 21) | (m_trigger_nr & 0xFFFF));
657  append_int32(dlen); // 32 bit word count
658  if (!isErrorIn(8)) append_int32(0x00000000); // Error Flags
659  if (!isErrorIn(14)) add_frame_to_payload();
660  if (isErrorIn(19)) {
661  // double frame
662  m_onsen_header.push_back(m_current_frame.size());
663  m_onsen_payload.push_back(m_current_frame);
664  }
665  }
666  if (isErrorIn(78)) {
667  // TODO add ROI Frame if header bit is set
668  int old = dhc_byte_count;
669  start_frame();
670  append_int32((EDHCFrameHeaderDataType::c_ONSEN_ROI << 27) | (m_trigger_nr & 0xFFFF));
672  dhc_byte_count = old; // dont count
673  }
674 
675  } else {
676  // add a faked DHC, "no data"
677  start_frame();
678  append_int32(EDHCFrameHeaderDataType::c_DHC_START << 27);
679  append_int16(0);
680  append_int16(0);
681  append_int16(0);
682  append_int16(0);
683  append_int16(0);
684  append_int16(0);
686 
687  start_frame();
688  append_int32(EDHCFrameHeaderDataType::c_DHC_END << 27);
689  append_int32(0);
690  append_int32(0);
692  }
693 }
694 
695 void PXDPackerErrModule::pack_dhe(int dhe_id, int dhp_active)
696 {
697  if (isErrorIn(37)) dhp_active = 0; // mark as no DHP, but send them (see below)
698  B2DEBUG(27, "PXD Packer Err --> pack_dhe ID " << dhe_id << " DHP act: " << dhp_active);
699  // dhe_id is not dhe_id ...
700  bool dhe_has_remapped = !m_InvertMapping;
701 
702  if (m_InvertMapping) {
703  // problem, we do not have an exact definition of if this bit is set in the new firmware and under which circumstances
704  // and its not clear if we have to translate the coordinates back to "DHP" layout! (look up tabel etc!)
705  B2FATAL("Inverse Mapping not implemented in Packer");
706  }
707 
708  if (isErrorIn(65)) dhe_id = 0x3F; // invalid
710  dhe_byte_count = 0;
711  start_frame();
712  uint32_t header = (EDHCFrameHeaderDataType::c_DHE_START << 27) | ((dhe_id & 0x3F) << 20) | ((dhp_active & 0xF) << 16) |
713  (m_trigger_nr & 0xFFFF);
714  if (isErrorIn(60)) header++;
715  append_int32(header);
716 
717  if (isErrorIn(35)) append_int16(0x1000);
718  else append_int16(m_trigger_nr >> 16); // Trigger Nr Hi
719  if (!isErrorIn(11)) {
720  append_int16(0x00000000); // DHE Timer Lo
721  }
722  if (!isErrorIn(9)) {
723  append_int16(0x00000000); // DHE Time Hi
724  append_int16(((m_trigger_dhp_framenr & 0x3F) << 10) |
725  (m_trigger_dhe_gate & 0xFF)); // Last DHP Frame Nr 15-10, Reserved 9-8, Trigger Offset 7-0
726  }
727  if (!isErrorIn(15)) add_frame_to_payload();
728  if (isErrorIn(20)) {
729  // double frame
730  m_onsen_header.push_back(m_current_frame.size());
731  m_onsen_payload.push_back(m_current_frame);
732  }
733 
734  // Now we add some undefined things
735  if (isErrorIn(46)) {
736  start_frame();
737  append_int32((EDHCFrameHeaderDataType::c_COMMODE << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
739  }
740  if (isErrorIn(47)) {
741  start_frame();
742  append_int32((EDHCFrameHeaderDataType::c_FCE_RAW << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
744  }
745  if (isErrorIn(48)) {
746  start_frame();
747  append_int32((EDHCFrameHeaderDataType::c_ONSEN_FCE << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
749  }
750  if (isErrorIn(49)) {
751  start_frame();
752  append_int32((EDHCFrameHeaderDataType::c_UNUSED_7 << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
754  }
755  if (isErrorIn(50)) {
756  start_frame();
757  append_int32((EDHCFrameHeaderDataType::c_UNUSED_8 << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
759  }
760  if (isErrorIn(51)) {
761  start_frame();
762  append_int32((EDHCFrameHeaderDataType::c_UNUSED_A << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
764  }
765 
766 // now prepare the data from one halfladder
767 // do the ROI selection??? optional...
768 // then loop for each DHP in system
769 // get active DHPs from a database?
770 // and pack data per halfladder.
771 // we fake the framenr and startframenr until we find some better solution
772 
773  if (dhp_active != 0) {
774 
776  bzero(halfladder_pixmap, sizeof(halfladder_pixmap));
777 
784  unsigned short sensor, ladder, layer;
785  sensor = (dhe_id & 0x1) + 1;
786  ladder = (dhe_id & 0x1E) >> 1; // no +1
787  layer = ((dhe_id & 0x20) >> 5) + 1;
788 
789  B2DEBUG(27, "pack_dhe: VxdId: " << VxdID(layer, ladder, sensor) << " " << (int)VxdID(layer, ladder, sensor));
790 
791  // Create some fixed hits (not too many, jut a few per ladder)
792  for (auto j = 0; j < 10; j++) {
793  unsigned int row, col;
794  unsigned char charge;
795  row = j * 23;
796  col = j * 23;
797  charge = 20 + j; // 0-255
798  if (!dhe_has_remapped) {
799  do_the_reverse_mapping(row, col, layer, sensor);
800  }
801  halfladder_pixmap[row][col] = charge;
802  }
803 
804  if (isErrorIn(38)) dhp_active = 0; // no DHP data even if we expect it
805  if (m_Clusterize) {
806  B2FATAL("Clusterizer not supported in Packer");
807  } else {
808  for (int i = 0; i < 4; i++) {
809  if ((dhp_active & 0x1) or isErrorIn(37)) {
810  pack_dhp(i, dhe_id, dhe_has_remapped ? 1 : 0);
812 // if (m_trigger_nr == 0x11) {
813 // pack_dhp_raw(i, dhe_id, false);
814 // pack_dhp_raw(i, dhe_id, true);
815 // }
816  }
817  dhp_active >>= 1;
818  }
819  }
820  }
821 
823  if (isErrorIn(32)) dhe_id += 1;
824  if (isErrorIn(34)) dhe_byte_count += 4;
825  unsigned int dlen = (dhe_byte_count / 2); // 16 bit words
826  start_frame();
827  header = (EDHCFrameHeaderDataType::c_DHE_END << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF);
828  if (isErrorIn(61)) header++;
829  if (isErrorIn(62)) header += 1 << 20;
830  if (isErrorIn(64)) header |= 0x80000000;
831  append_int32(header);
832  append_int16(dlen & 0xFFFF); // 16 bit word count
833  append_int16((dlen >> 16) & 0xFFFF); // 16 bit word count
834  if (!isErrorIn(10)) append_int32(0x00000000); // Error Flags
835  if (!isErrorIn(16)) add_frame_to_payload();
836  if (isErrorIn(21)) {
837  // double frame
838  m_onsen_header.push_back(m_current_frame.size());
839  m_onsen_payload.push_back(m_current_frame);
840  }
841 }
842 
843 void PXDPackerErrModule::do_the_reverse_mapping(unsigned int& /*row*/, unsigned int& /*col*/, unsigned short /*layer*/,
844  unsigned short /*sensor*/)
845 {
846  B2FATAL("code needs to be written");
847  // work to be done
848  //
849  // PXDMappingLookup::map_uv_to_rc_IF_OB(unsigned int& v_cellID, unsigned int& u_cellID, unsigned int& dhp_id, unsigned int dhe_ID)
850  // PXDMappingLookup::map_uv_to_rc_IB_OF(unsigned int& v_cellID, unsigned int& u_cellID, unsigned int& dhp_id, unsigned int dhe_ID)
851 }
852 
853 void PXDPackerErrModule::pack_dhp_raw(int chip_id, int dhe_id)
854 {
855  B2DEBUG(27, "PXD Packer Err --> pack_dhp Raw Chip " << chip_id << " of DHE id: " << dhe_id);
856  start_frame();
858  append_int32((EDHCFrameHeaderDataType::c_DHP_RAW << 27) | ((dhe_id & 0x3F) << 20) | ((chip_id & 0x03) << 16) |
859  (m_trigger_nr & 0xFFFF));
860  append_int32((EDHPFrameHeaderDataType::c_RAW << 29) | ((dhe_id & 0x3F) << 18) | ((chip_id & 0x03) << 16) |
861  (m_trigger_dhp_framenr & 0xFFFF));
862 
863  int c1, c2;
864  c1 = 64 * chip_id;
865  c2 = c1 + 64;
866  if (c2 >= PACKER_NUM_COLS) c2 = PACKER_NUM_COLS;
867 
868  // ADC data / memdump for pedestal calculation
869  for (int row = 0; row < PACKER_NUM_ROWS; row++) {
870  for (int col = c1; col < c2; col++) {
871  append_int8(halfladder_pixmap[row][col]);
872  }
873  // unconnected drain lines -> 0
874  for (int col = c2; col < c1 + 64; col++) {
875  append_int8(0);
876  }
877  }
878 
880 }
881 
882 void PXDPackerErrModule::pack_dhp(int chip_id, int dhe_id, int dhe_has_remapped)
883 {
884  B2DEBUG(27, "PXD Packer Err --> pack_dhp Chip " << chip_id << " of DHE id: " << dhe_id);
885  // remark: chip_id != port most of the time ...
886  bool empty = true;
887  unsigned short last_rowstart = 0;
888  bool error_done = false;
889 
890  if (dhe_has_remapped == 0) {
891  // problem, we do not have an exact definition of if this bit is set in the new firmware and under which circumstances
892  // and its not clear if we have to translate the coordinates back to "DHP" layout! (look up tabel etc!)
893  B2FATAL("dhe_has_remapped == 0");
894  }
895 
896  start_frame();
898  uint32_t header = (EDHCFrameHeaderDataType::c_DHP_ZSD << 27) | ((dhe_id & 0x3F) << 20) | ((dhe_has_remapped & 0x1) << 19) | ((
899  chip_id & 0x03) << 16) | (m_trigger_nr & 0xFFFF);
900  if (isErrorIn(63)) header += 1 << 20;
901  append_int32(header);
902 
903  if (isErrorIn(69)) {
905  return;
906  }
907 
908  if (isErrorIn(39)) dhe_id = 0; // mess up dhe_id in DHP header
909  if (isErrorIn(40)) chip_id = ~chip_id; // mess up chip id
910  header = (EDHPFrameHeaderDataType::c_ZSD << 29) | ((dhe_id & 0x3F) << 18) | ((chip_id & 0x03) << 16) |
911  (m_trigger_dhp_framenr & 0xFFFF);
912  if (isErrorIn(68)) header++;
913  append_int32(header);
914  if (isErrorIn(66)) append_int32(header + 1); // with inc trigger nr
915 
916  if (isErrorIn(41) or isErrorIn(42)) {
917  halfladder_pixmap[PACKER_NUM_ROWS - 1][PACKER_NUM_COLS - 1] = 0x42; // make sure we have a hit
918  }
919  for (int row = 0; row < PACKER_NUM_ROWS; row++) { // should be variable
920  bool rowstart;
921  if (isErrorIn(43) && !error_done) rowstart = false;
922  else rowstart = true;
923  int c1, c2;
924  c1 = 64 * chip_id;
925  c2 = c1 + 64;
926  if (c2 >= PACKER_NUM_COLS) c2 = PACKER_NUM_COLS;
927  for (int col = c1; col < c2; col++) {
928  if (halfladder_pixmap[row][col] != 0) {
929  unsigned char charge;
930  charge = halfladder_pixmap[row][col] & 0xFF; // before we make overflow error
931  if (isErrorIn(41) and row == PACKER_NUM_ROWS - 1 and col == PACKER_NUM_COLS - 1 and !error_done) {
932  row = PACKER_NUM_ROWS;
933  rowstart = true; // force a new row
934  error_done = true;
935  }
936  if (isErrorIn(42) and row == PACKER_NUM_ROWS - 1 and col == PACKER_NUM_COLS - 1 and !error_done) {
937  col = PACKER_NUM_COLS; // masked out to modulo 64 anway
938  error_done = true;
939  }
940  if (rowstart) {
941  last_rowstart = ((row & 0x3FE) << (6 - 1)) | 0; // plus common mode 6 bits ... set to 0
942  append_int16(last_rowstart);
943  rowstart = false;
944  }
945  int colout = col;
946  if (!isErrorIn(52)) append_int16(0x8000 | ((row & 0x1) << 14) | ((colout & 0x3F) << 8) | charge);
947  empty = false;
948  }
949  }
950  }
951  if (!empty && (m_current_frame.size() & 0x3)) {
952  B2DEBUG(27, "Repeat last rowstart to align to 32bit.");
953  append_int16(last_rowstart);
954  }
955 
956 
957  if (empty) {
958  B2DEBUG(27, "Found no data for halfladder! DHEID: " << dhe_id << " Chip: " << chip_id);
959  // we DROP the frame, thus we have to correct DHE and DHC counters
960  dhc_byte_count -= 8; // fixed size of Header
961  dhe_byte_count -= 8; // fixed size of Header
962  start_frame();
964  append_int32((EDHCFrameHeaderDataType::c_GHOST << 27) | ((dhe_id & 0x3F) << 20) | ((chip_id & 0x03) << 16) |
965  (m_trigger_nr & 0xFFFF));
966  } else {
967  //B2DEBUG(20,"Found data for halfladder DHEID: " << dhe_id << " Chip: " << chip_id);
968  }
970 
971 }
972 
974 {
975  if (m_real_trigger_nr == enr) return true; // oder modulo, oder oder
976  return false;
977 }
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
void do_the_reverse_mapping(unsigned int &row, unsigned int &col, unsigned short layer, unsigned short sensor)
function still to be implemented
std::vector< std::vector< unsigned char > > m_onsen_payload
For one DHC event, we utilize one payload for all DHE/DHP frames.
void initialize() override final
Initialize the module.
bool m_Check
false=Pack Raw Data, true=Check unpacked result
void add_frame_to_payload(void)
Add Frame to Event payload.
unsigned short m_run_nr_word2
Exp+Run Nr.
std::string m_PXDDAQEvtStatsName
The name of the StoreObjPtr of PXDDAQStatus to be read.
void append_int16(unsigned short w)
cat 16bit value to frame
StoreObjPtr< PXDDAQStatus > m_daqStatus
Output array for RawPxds.
void pack_dhe(int dhe_id, int dhp_mask)
Pack one DHE (several DHP) to buffer.
bool m_found_fatal
flag if we found one test failing
void pack_dhp_raw(int dhp_id, int dhe_id)
Pack one DHP RAW to buffer.
std::string m_RawPXDsName
The name of the StoreArray of generated RawPXDs.
void pack_dhc(int dhc_id, int dhe_mask, int *dhe_ids)
Pack one DHC (several DHE) stored in one RawPXD object.
bool CheckErrorMaskInEvent(unsigned int eventnr, PXDError::PXDErrorFlags mask)
void pack_event(void)
Pack one event (several DHC) stored in seperate RawPXD object.
void terminate() override final
Terminate the module.
void event() override final
do the packing
unsigned int dhc_byte_count
Byte count in current DHC package.
std::vector< std::vector< int > > m_dhe_to_dhc
Parameter dhc<->dhe list, mapping from steering file.
bool m_Clusterize
Use clusterizer (FCE format)
unsigned short m_run_nr_word1
Run+Subrun Nr.
bool isErrorIn(uint32_t enr)
Check if we want this type of error in this event.
std::vector< unsigned int > m_onsen_header
For one DHC event, we utilize one header (writing out, beware of endianess!)
unsigned int m_real_trigger_nr
Real Trigger Nr.
void append_int32(unsigned int w)
cat 32value value to frame
StoreArray< RawPXD > m_storeRaws
Output array for RawPxds.
unsigned int m_trigger_dhp_framenr
DHP Readout Frame Nr for DHP and DHE headers.
unsigned int dhe_byte_count
Byte count in current DHE package.
static std::vector< PXDErrorFlags > m_errors
The pxd error flags.
void pack_dhp(int dhp_id, int dhe_id, int dhe_reformat)
Pack one DHP to buffer.
std::map< int, std::vector< int > > m_dhc_mapto_dhe
mapping calculated from m_dhe_to_dhc for easier handling
void start_frame(void)
Start with a new Frame.
void append_int8(unsigned char w)
cat 8bit value to frame
unsigned int m_trigger_dhe_gate
DHE Trigger Gate for DHE headers.
unsigned int m_packed_events
Event counter.
bool m_InvertMapping
Flag if we invert mapping to DHP row/col or use premapped coordinates.
unsigned long long int m_meta_time
Time(Tag) from MetaInfo.
std::vector< unsigned char > m_current_frame
For current processed frames.
unsigned char halfladder_pixmap[PACKER_NUM_ROWS][PACKER_NUM_COLS]
temporary hitmap buffer for pixel to raw data conversion
unsigned int m_trigger_nr
Trigger Nr.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Class to uniquely identify a any structure of the PXD and SVD.
Definition: VxdID.h:33
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:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Namespace to encapsulate code needed for simulation and reconstrucion of the PXD.
boost::crc_optimal< 32, 0x04C11DB7, 0, 0, false, false > dhc_crc_32_type
define our CRC function
Abstract base class for different kinds of events.