Belle II Software  release-08-01-10
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, bool send_all, bool send_roi)
528 {
529  B2DEBUG(27, "PXD Packer Err --> pack_dhc ID " << dhc_id << " DHE act: " << dhe_active);
530 
532  start_frame();
533  append_int32((EDHCFrameHeaderDataType::c_ONSEN_TRG << 27) | (m_trigger_nr & 0xFFFF));
534  B2INFO("Trigger packet: $" << hex << m_run_nr_word1 << ", $" << m_run_nr_word2);
535  if (isErrorIn(23)) {
536  append_int32(0xDEAD8000);
537  } else if (isErrorIn(25)) {
538  append_int32(0xCAFE0000);// HLT HEADER, NO accepted flag
539  } else {
540  append_int32(0xCAFE8000 | (send_all ? 0x4000 : 0) | (send_roi ? 0x2000 : 0)); // HLT HEADER, accepted flag set
541  }
542  if (isErrorIn(26)) {
544  } else if (isErrorIn(36)) {
545  append_int32(0x10000000 | m_trigger_nr); // HLT Trigger Nr with Hi work messed up
546  } else {
547  append_int32(m_trigger_nr); // HLT Trigger Nr
548  }
549  append_int16(m_run_nr_word2); // HLT Run NR etc
550  append_int16(m_run_nr_word1); // HLT Run NR etc
551  if (isErrorIn(24)) append_int32(0xDEAD0000);
552  else append_int32(0xCAFE0000);// DATCON HEADER ...
553  if (isErrorIn(45)) {
554  // No Datcon
555  append_int32(0x0); // trigger nr
556  append_int32(0x0); // 2*16 trg tag
557  } else {
558  if (isErrorIn(22)) append_int32(m_trigger_nr + 1);
559  else append_int32(m_trigger_nr);// DATCON Trigger Nr
560  if (!isErrorIn(6)) {
561  append_int16(m_run_nr_word2); // DATCON Run NR etc
562  append_int16(m_run_nr_word1); // DATCON Run NR etc
563  }
564  }
565  if (!isErrorIn(12)) add_frame_to_payload();
566  if (isErrorIn(17)) {
567  // double frame
568  m_onsen_header.push_back(m_current_frame.size());
569  m_onsen_payload.push_back(m_current_frame);
570  }
571 
572  if (isErrorIn(30)) return; // empty event, no DHC frames
573 
575  if (!isErrorIn(67)) {
576 
577  dhc_byte_count = 0;
578  if (isErrorIn(76)) {
579  // add a faked DHC, "no data"
580  start_frame();
581  append_int32(EDHCFrameHeaderDataType::c_DHC_START << 27);
582  append_int16(0);
583  append_int16(0);
584  append_int16(0);
585  append_int16(0);
586  append_int16(0);
587  append_int16(0);
589  } else {
590  start_frame();
591  uint32_t header = (EDHCFrameHeaderDataType::c_DHC_START << 27) | ((dhc_id & 0xF) << 21) | ((dhe_active & 0x1F) << 16) |
592  (m_trigger_nr & 0xFFFF);
593  if (isErrorIn(59)) header++;
594  append_int32(header);
595  if (!isErrorIn(58)) append_int16(m_trigger_nr >> 16);
596  else append_int16((m_trigger_nr >> 16) + 1);
597 
598  uint32_t mm = (unsigned int)std::round((m_meta_time % 1000000000ull) * 0.127216); // in 127MHz Ticks
599  uint32_t ss = (unsigned int)(m_meta_time / 1000000000ull) ; // in seconds
600  if (isErrorIn(70)) mm++;
601  if (isErrorIn(70)) ss++;
602  append_int16(((mm << 4) & 0xFFF0) | 0x1); // TT 11-0 | Type --- fill with something usefull TODO
603  append_int16(((mm >> 12) & 0x7FFF) | ((ss & 1) ? 0x8000 : 0x0)); // TT 27-12 ... not clear if completely filled by DHC
604  append_int16((ss >> 1) & 0xFFFF); // TT 43-28 ... not clear if completely filled by DHC
605  if (!isErrorIn(7)) {
606  append_int16(m_run_nr_word1); // Run Nr 7-0 | Subrunnr 7-0
607  append_int16(m_run_nr_word2); // Exp NR 9-0 | Run Nr 13-8
608  }
609  if (!isErrorIn(13)) add_frame_to_payload();
610  if (isErrorIn(18)) {
611  // double frame
612  m_onsen_header.push_back(m_current_frame.size());
613  m_onsen_payload.push_back(m_current_frame);
614  }
615  }
616 
617  // loop for each DHE in system
618  // Run & TTT etc are zero until better idea
619 
620  if (isErrorIn(29)) dhe_active = 0; // dont send any DHE
621  for (int i = 0; i < 5; i++) {
622  if ((dhe_active & 0x1) or isErrorIn(28)) pack_dhe(dhe_ids[i], 0xF);
623  if (isErrorIn(71) && i == 2) {
624  pack_dhp(1, dhe_ids[i], 1);
625  }
626  dhe_active >>= 1;
627  }
628 
630 
631  if (isErrorIn(77)) {
632  // TODO add ROI Frame if header bit is set
633  int old = dhc_byte_count;
634  start_frame();
635  append_int32((EDHCFrameHeaderDataType::c_ONSEN_ROI << 27) | (m_trigger_nr & 0xFFFF));
637  dhc_byte_count = old; // dont count
638  }
639 
641  if (isErrorIn(75)) {
642  // add a faked DHC, "no data"
643  start_frame();
644  append_int32(EDHCFrameHeaderDataType::c_DHC_END << 27);
645  append_int32(0);
646  append_int32(0);
648  } else {
649  if (isErrorIn(31)) dhc_id += 1;
650  if (isErrorIn(33)) dhc_byte_count += 4;
651  unsigned int dlen = (dhc_byte_count / 4); // 32 bit words
652  start_frame();
653  append_int32((EDHCFrameHeaderDataType::c_DHC_END << 27) | ((dhc_id & 0xF) << 21) | (m_trigger_nr & 0xFFFF));
654  append_int32(dlen); // 32 bit word count
655  if (!isErrorIn(8)) append_int32(0x00000000); // Error Flags
656  if (!isErrorIn(14)) add_frame_to_payload();
657  if (isErrorIn(19)) {
658  // double frame
659  m_onsen_header.push_back(m_current_frame.size());
660  m_onsen_payload.push_back(m_current_frame);
661  }
662  }
663  if (isErrorIn(78)) {
664  // TODO add ROI Frame if header bit is set
665  int old = dhc_byte_count;
666  start_frame();
667  append_int32((EDHCFrameHeaderDataType::c_ONSEN_ROI << 27) | (m_trigger_nr & 0xFFFF));
669  dhc_byte_count = old; // dont count
670  }
671 
672  } else {
673  // add a faked DHC, "no data"
674  start_frame();
675  append_int32(EDHCFrameHeaderDataType::c_DHC_START << 27);
676  append_int16(0);
677  append_int16(0);
678  append_int16(0);
679  append_int16(0);
680  append_int16(0);
681  append_int16(0);
683 
684  start_frame();
685  append_int32(EDHCFrameHeaderDataType::c_DHC_END << 27);
686  append_int32(0);
687  append_int32(0);
689  }
690 }
691 
692 void PXDPackerErrModule::pack_dhe(int dhe_id, int dhp_active)
693 {
694  if (isErrorIn(37)) dhp_active = 0; // mark as no DHP, but send them (see below)
695  B2DEBUG(27, "PXD Packer Err --> pack_dhe ID " << dhe_id << " DHP act: " << dhp_active);
696  // dhe_id is not dhe_id ...
697  bool dhe_has_remapped = !m_InvertMapping;
698 
699  if (m_InvertMapping) {
700  // problem, we do not have an exact definition of if this bit is set in the new firmware and under which circumstances
701  // and its not clear if we have to translate the coordinates back to "DHP" layout! (look up tabel etc!)
702  B2FATAL("Inverse Mapping not implemented in Packer");
703  }
704 
705  if (isErrorIn(65)) dhe_id = 0x3F; // invalid
707  dhe_byte_count = 0;
708  start_frame();
709  uint32_t header = (EDHCFrameHeaderDataType::c_DHE_START << 27) | ((dhe_id & 0x3F) << 20) | ((dhp_active & 0xF) << 16) |
710  (m_trigger_nr & 0xFFFF);
711  if (isErrorIn(60)) header++;
712  append_int32(header);
713 
714  if (isErrorIn(35)) append_int16(0x1000);
715  else append_int16(m_trigger_nr >> 16); // Trigger Nr Hi
716  if (!isErrorIn(11)) {
717  append_int16(0x00000000); // DHE Timer Lo
718  }
719  if (!isErrorIn(9)) {
720  append_int16(0x00000000); // DHE Time Hi
721  append_int16(((m_trigger_dhp_framenr & 0x3F) << 10) |
722  (m_trigger_dhe_gate & 0xFF)); // Last DHP Frame Nr 15-10, Reserved 9-8, Trigger Offset 7-0
723  }
724  if (!isErrorIn(15)) add_frame_to_payload();
725  if (isErrorIn(20)) {
726  // double frame
727  m_onsen_header.push_back(m_current_frame.size());
728  m_onsen_payload.push_back(m_current_frame);
729  }
730 
731  // Now we add some undefined things
732  if (isErrorIn(46)) {
733  start_frame();
734  append_int32((EDHCFrameHeaderDataType::c_COMMODE << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
736  }
737  if (isErrorIn(47)) {
738  start_frame();
739  append_int32((EDHCFrameHeaderDataType::c_FCE_RAW << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
741  }
742  if (isErrorIn(48)) {
743  start_frame();
744  append_int32((EDHCFrameHeaderDataType::c_ONSEN_FCE << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
746  }
747  if (isErrorIn(49)) {
748  start_frame();
749  append_int32((EDHCFrameHeaderDataType::c_UNUSED_7 << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
751  }
752  if (isErrorIn(50)) {
753  start_frame();
754  append_int32((EDHCFrameHeaderDataType::c_UNUSED_8 << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
756  }
757  if (isErrorIn(51)) {
758  start_frame();
759  append_int32((EDHCFrameHeaderDataType::c_UNUSED_A << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF));
761  }
762 
763 // now prepare the data from one halfladder
764 // do the ROI selection??? optional...
765 // then loop for each DHP in system
766 // get active DHPs from a database?
767 // and pack data per halfladder.
768 // we fake the framenr and startframenr until we find some better solution
769 
770  if (dhp_active != 0) {
771 
773  bzero(halfladder_pixmap, sizeof(halfladder_pixmap));
774 
781  unsigned short sensor, ladder, layer;
782  sensor = (dhe_id & 0x1) + 1;
783  ladder = (dhe_id & 0x1E) >> 1; // no +1
784  layer = ((dhe_id & 0x20) >> 5) + 1;
785 
786  B2DEBUG(27, "pack_dhe: VxdId: " << VxdID(layer, ladder, sensor) << " " << (int)VxdID(layer, ladder, sensor));
787 
788  // Create some fixed hits (not too many, jut a few per ladder)
789  for (auto j = 0; j < 10; j++) {
790  unsigned int row, col;
791  unsigned char charge;
792  row = j * 23;
793  col = j * 23;
794  charge = 20 + j; // 0-255
795  if (!dhe_has_remapped) {
796  do_the_reverse_mapping(row, col, layer, sensor);
797  }
798  halfladder_pixmap[row][col] = charge;
799  }
800 
801  if (isErrorIn(38)) dhp_active = 0; // no DHP data even if we expect it
802  if (m_Clusterize) {
803  B2FATAL("Clusterizer not supported in Packer");
804  } else {
805  for (int i = 0; i < 4; i++) {
806  if ((dhp_active & 0x1) or isErrorIn(37)) {
807  pack_dhp(i, dhe_id, dhe_has_remapped ? 1 : 0);
809 // if (m_trigger_nr == 0x11) {
810 // pack_dhp_raw(i, dhe_id, false);
811 // pack_dhp_raw(i, dhe_id, true);
812 // }
813  }
814  dhp_active >>= 1;
815  }
816  }
817  }
818 
820  if (isErrorIn(32)) dhe_id += 1;
821  if (isErrorIn(34)) dhe_byte_count += 4;
822  unsigned int dlen = (dhe_byte_count / 2); // 16 bit words
823  start_frame();
824  header = (EDHCFrameHeaderDataType::c_DHE_END << 27) | ((dhe_id & 0x3F) << 20) | (m_trigger_nr & 0xFFFF);
825  if (isErrorIn(61)) header++;
826  if (isErrorIn(62)) header += 1 << 20;
827  if (isErrorIn(64)) header |= 0x80000000;
828  append_int32(header);
829  append_int16(dlen & 0xFFFF); // 16 bit word count
830  append_int16((dlen >> 16) & 0xFFFF); // 16 bit word count
831  if (!isErrorIn(10)) append_int32(0x00000000); // Error Flags
832  if (!isErrorIn(16)) add_frame_to_payload();
833  if (isErrorIn(21)) {
834  // double frame
835  m_onsen_header.push_back(m_current_frame.size());
836  m_onsen_payload.push_back(m_current_frame);
837  }
838 }
839 
840 void PXDPackerErrModule::do_the_reverse_mapping(unsigned int& /*row*/, unsigned int& /*col*/, unsigned short /*layer*/,
841  unsigned short /*sensor*/)
842 {
843  B2FATAL("code needs to be written");
844  // work to be done
845  //
846  // PXDMappingLookup::map_uv_to_rc_IF_OB(unsigned int& v_cellID, unsigned int& u_cellID, unsigned int& dhp_id, unsigned int dhe_ID)
847  // PXDMappingLookup::map_uv_to_rc_IB_OF(unsigned int& v_cellID, unsigned int& u_cellID, unsigned int& dhp_id, unsigned int dhe_ID)
848 }
849 
850 void PXDPackerErrModule::pack_dhp_raw(int chip_id, int dhe_id)
851 {
852  B2DEBUG(27, "PXD Packer Err --> pack_dhp Raw Chip " << chip_id << " of DHE id: " << dhe_id);
853  start_frame();
855  append_int32((EDHCFrameHeaderDataType::c_DHP_RAW << 27) | ((dhe_id & 0x3F) << 20) | ((chip_id & 0x03) << 16) |
856  (m_trigger_nr & 0xFFFF));
857  append_int32((EDHPFrameHeaderDataType::c_RAW << 29) | ((dhe_id & 0x3F) << 18) | ((chip_id & 0x03) << 16) |
858  (m_trigger_dhp_framenr & 0xFFFF));
859 
860  int c1, c2;
861  c1 = 64 * chip_id;
862  c2 = c1 + 64;
863  if (c2 >= PACKER_NUM_COLS) c2 = PACKER_NUM_COLS;
864 
865  // ADC data / memdump for pedestal calculation
866  for (int row = 0; row < PACKER_NUM_ROWS; row++) {
867  for (int col = c1; col < c2; col++) {
868  append_int8(halfladder_pixmap[row][col]);
869  }
870  // unconnected drain lines -> 0
871  for (int col = c2; col < c1 + 64; col++) {
872  append_int8(0);
873  }
874  }
875 
877 }
878 
879 void PXDPackerErrModule::pack_dhp(int chip_id, int dhe_id, int dhe_has_remapped)
880 {
881  B2DEBUG(27, "PXD Packer Err --> pack_dhp Chip " << chip_id << " of DHE id: " << dhe_id);
882  // remark: chip_id != port most of the time ...
883  bool empty = true;
884  unsigned short last_rowstart = 0;
885  bool error_done = false;
886 
887  if (dhe_has_remapped == 0) {
888  // problem, we do not have an exact definition of if this bit is set in the new firmware and under which circumstances
889  // and its not clear if we have to translate the coordinates back to "DHP" layout! (look up tabel etc!)
890  B2FATAL("dhe_has_remapped == 0");
891  }
892 
893  start_frame();
895  uint32_t header = (EDHCFrameHeaderDataType::c_DHP_ZSD << 27) | ((dhe_id & 0x3F) << 20) | ((dhe_has_remapped & 0x1) << 19) | ((
896  chip_id & 0x03) << 16) | (m_trigger_nr & 0xFFFF);
897  if (isErrorIn(63)) header += 1 << 20;
898  append_int32(header);
899 
900  if (isErrorIn(69)) {
902  return;
903  }
904 
905  if (isErrorIn(39)) dhe_id = 0; // mess up dhe_id in DHP header
906  if (isErrorIn(40)) chip_id = ~chip_id; // mess up chip id
907  header = (EDHPFrameHeaderDataType::c_ZSD << 29) | ((dhe_id & 0x3F) << 18) | ((chip_id & 0x03) << 16) |
908  (m_trigger_dhp_framenr & 0xFFFF);
909  if (isErrorIn(68)) header++;
910  append_int32(header);
911  if (isErrorIn(66)) append_int32(header + 1); // with inc trigger nr
912 
913  if (isErrorIn(41) or isErrorIn(42)) {
914  halfladder_pixmap[PACKER_NUM_ROWS - 1][PACKER_NUM_COLS - 1] = 0x42; // make sure we have a hit
915  }
916  for (int row = 0; row < PACKER_NUM_ROWS; row++) { // should be variable
917  bool rowstart;
918  if (isErrorIn(43) && !error_done) rowstart = false;
919  else rowstart = true;
920  int c1, c2;
921  c1 = 64 * chip_id;
922  c2 = c1 + 64;
923  if (c2 >= PACKER_NUM_COLS) c2 = PACKER_NUM_COLS;
924  for (int col = c1; col < c2; col++) {
925  if (halfladder_pixmap[row][col] != 0) {
926  unsigned char charge;
927  charge = halfladder_pixmap[row][col] & 0xFF; // before we make overflow error
928  if (isErrorIn(41) and row == PACKER_NUM_ROWS - 1 and col == PACKER_NUM_COLS - 1 and !error_done) {
929  row = PACKER_NUM_ROWS;
930  rowstart = true; // force a new row
931  error_done = true;
932  }
933  if (isErrorIn(42) and row == PACKER_NUM_ROWS - 1 and col == PACKER_NUM_COLS - 1 and !error_done) {
934  col = PACKER_NUM_COLS; // masked out to modulo 64 anway
935  error_done = true;
936  }
937  if (rowstart) {
938  last_rowstart = ((row & 0x3FE) << (6 - 1)) | 0; // plus common mode 6 bits ... set to 0
939  append_int16(last_rowstart);
940  rowstart = false;
941  }
942  int colout = col;
943  if (!isErrorIn(52)) append_int16(0x8000 | ((row & 0x1) << 14) | ((colout & 0x3F) << 8) | charge);
944  empty = false;
945  }
946  }
947  }
948  if (!empty && (m_current_frame.size() & 0x3)) {
949  B2DEBUG(27, "Repeat last rowstart to align to 32bit.");
950  append_int16(last_rowstart);
951  }
952 
953 
954  if (empty) {
955  B2DEBUG(27, "Found no data for halfladder! DHEID: " << dhe_id << " Chip: " << chip_id);
956  // we DROP the frame, thus we have to correct DHE and DHC counters
957  dhc_byte_count -= 8; // fixed size of Header
958  dhe_byte_count -= 8; // fixed size of Header
959  start_frame();
961  append_int32((EDHCFrameHeaderDataType::c_GHOST << 27) | ((dhe_id & 0x3F) << 20) | ((chip_id & 0x03) << 16) |
962  (m_trigger_nr & 0xFFFF));
963  } else {
964  //B2DEBUG(20,"Found data for halfladder DHEID: " << dhe_id << " Chip: " << chip_id);
965  }
967 
968 }
969 
971 {
972  if (m_real_trigger_nr == enr) return true; // oder modulo, oder oder
973  return false;
974 }
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.
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.
void pack_dhc(int dhc_id, int dhe_mask, int *dhe_ids, bool send_all=true, bool send_roi=false)
Pack one DHC (several DHE) stored in one RawPXD object.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
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.