ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
oncsSub_idmvtxv2.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file oncsSub_idmvtxv2.cc
1 #include "oncsSub_idmvtxv2.h"
2 #include <cstring>
3 #include <bitset>
4 #include <map>
5 #include <vector>
6 #include <functional>
7 
8 #include <arpa/inet.h>
9 
10 using namespace std;
11 
13  :oncsSubevent_w4 (data)
14 {
15  _is_decoded = 0;
16  _highest_ruid = -1;
17  _decoder_error = 0;
18  for (int ruid=0; ruid<IDMVTXV2_MAXRUID+1; ruid++)
19  {
20  _bad_ruchns[ruid] = 0;
21  _lanes_active[ruid] = -1;
22  _lane_stops[ruid] = -1;
23  _lane_timeouts[ruid] = -1;
24  _inconsistent_bc[ruid] = -1;
25  for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
26  {
27  _chip_id[ruid][ruchn] = -1;
28  _bad_bytes[ruid][ruchn] = 0;
29  _excess_bytes[ruid][ruchn] = 0;
30  _bunchcounter[ruid][ruchn] = -1;
31  _header_found[ruid][ruchn] = false;
32  _trailer_found[ruid][ruchn] = false;
33  _readout_flags[ruid][ruchn] = -1;
34  }
35  }
37  _bad_ruids = 0;
38 }
39 
41 {
42 
43 }
44 
45 
46 typedef struct
47 {
48  unsigned char d0[3][10];
49  unsigned char counter;
50  unsigned char ruid;
51 } data32;
52 
53 
54 void oncsSub_idmvtxv2::print_stuff(OSTREAM& out, unsigned int data, int width, int shift, bool blank) const
55 {
56  unsigned int mask = 0xffffffff;
57  if (width<8) mask = ((1 << width*4)-1);
58  if (blank)
59  for (int i=0;i<width;i++) out << " ";
60  else
61  out << std::hex << SETW(width) << std::setfill('0') << ((data>>shift) & mask);
62 }
63 
64 int oncsSub_idmvtxv2::encode_hit(unsigned short row, unsigned short col) const
65 {
66  return (row << 16) + col;
67 }
68 
69 unsigned short oncsSub_idmvtxv2::decode_row(int hit) const
70 {
71  return hit >> 16;
72 }
73 
74 unsigned short oncsSub_idmvtxv2::decode_col(int hit) const
75 {
76  return hit & 0xffff;
77 }
78 
80 {
81  if (ruchn<=0) return false; //invalid ruchn
82  if (mask<0) return false;
83  return (((mask >> (ruchn-1)) & 1) == 1);
84 }
85 
87 {
88  if ( _is_decoded) return 0;
89  _is_decoded = 1;
90  _decoder_error = 0;
91 
92  unsigned int *payload = (unsigned int *) &SubeventHdr->data; // here begins the payload
93 
94  int dlength = getDataLength() - getPadding() - 1; //padding is supposed to be in units of dwords, this assumes dwords
95  unsigned char *the_end = ( unsigned char *) &payload[dlength];
96 
97  unsigned char *pos = (unsigned char *) payload;
98 
99  unsigned char b;
100 
101  vector<unsigned char> ruchn_stream[IDMVTXV2_MAXRUID+1][IDMVTXV2_MAXRUCHN+1];
102 
103  unsigned char felix_counter [IDMVTXV2_MAXRUID+1];
104 
105  for( int i=0; i < IDMVTXV2_MAXRUID+1; i++)
106  {
107  felix_counter[i] = 0;
108  }
109 
110  while ( pos < the_end )
111  {
112 
113  data32 *d32 = ( data32*) pos;
114 
115  //cout << hex << " pos = " << (unsigned long long ) pos << " the end " << (unsigned long long) the_end << dec << endl;
116  if (d32->ruid > IDMVTXV2_MAXRUID)
117  {
118  cout << __FILE__ << " " << __LINE__ << " --- invalid ruid " << hex << (int) d32->ruid << " at pos " << (long) pos << dec << endl;
119  _bad_ruids++;
120  _decoder_error |= ( 1 << 0 );
121  break;
122  }
123  else if (d32->ruid > _highest_ruid)
124  {
125  _highest_ruid = d32->ruid;
126  }
127  //FELIX counter is 8 bits, max value 256
128  //check that the new counter value is consistent with the previous value (it should have increased by no more than 3, and the amount of the difference is the number of data chunks in this FELIX word)
129  int counter_increment = (d32->counter + 256 - felix_counter[d32->ruid])%256;
130  if (counter_increment > 3)
131  {
132  if (d32->counter != 0)
133  {
134  //cout << __FILE__ << " " << __LINE__ << " --- unexpected FELIX counter " << hex << (int) d32->counter << " following previous counter value " << felix_counter << " at pos " << (long) pos << dec << endl;
136  }
137  break;
138  }
139  felix_counter[d32->ruid] = d32->counter;
140 
141  //for (int ichnk = 0; ichnk < 3; ichnk++)
142  for (int ichnk = 0; ichnk < counter_increment; ichnk++)
143  {
144  unsigned char ruchn = d32->d0[ichnk][9];
145  if (ruchn >> 4 == 0x2) {
146  ruchn &= 0x1F;
147  ruchn += 1;
148  }
149  if (ruchn == IDMVTXV2_RUHEADER)
150  {
151  memcpy(&_lanes_active[d32->ruid],&d32->d0[ichnk][2],4);
152  }
153  else if (ruchn == IDMVTXV2_RUTRAILER)
154  {
155  memcpy(&_lane_stops[d32->ruid],&d32->d0[ichnk][0],4);
156  memcpy(&_lane_timeouts[d32->ruid],&d32->d0[ichnk][4],4);
157  }
158  else if (ruchn > IDMVTXV2_MAXRUCHN)
159  {
160  _bad_ruchns[d32->ruid]++;
161  cout << __FILE__ << " " << __LINE__ << " --- invalid ruchn " << hex << ruchn << ", full RU word: ";
162  _decoder_error |= ( 1 << 1 );
163  for (int ibyte=9;ibyte>=0;ibyte--)
164  {
165  cout << setfill('0') << setw(2) << hex << (unsigned int) d32->d0[ichnk][ibyte] << " ";
166  }
167  cout << setfill(' ') << setw(0) << dec << endl;
168  }
169  else for ( int ibyte = 0; ibyte < 9; ibyte++)
170  {
171  //cout << __FILE__ << " " << __LINE__ << hex << " --- ruchn " << (unsigned int) ruchn << " byte " << (unsigned int) d32->d0[ichnk][ibyte] << dec << endl;
172  ruchn_stream[d32->ruid][ruchn].push_back(d32->d0[ichnk][ibyte]);
173  }
174  } // ichnk
175 
176  pos += sizeof(*d32);
177  } // while (pos < the_end)
178 
179  //we ignore ruchn 0 (trigger information and padding words) for now
180  /*
181  if (ruchn_stream[0].size()!=9) for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
182  {
183  cout << __FILE__ << " " << __LINE__ << " --- ruchn " << ruchn << " has " << ruchn_stream[ruchn].size() << " bytes" << endl;
184  }
185  */
186 
187  for ( int ruid = 1; ruid < IDMVTXV2_MAXRUID+1; ruid++)
188  {
189  for ( int ruchn = 1; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
190  {
191 
192  bool header_seen=false;
193  int status = 0;
194  int ibyte_endofdata = -1;
195  int the_region = -1;
196  unsigned int address = 0;
197  unsigned int encoder_id = 0;
198  for (unsigned int ibyte = 0; ibyte < ruchn_stream[ruid][ruchn].size(); ibyte++)
199  {
200  b = ruchn_stream[ruid][ruchn].at(ibyte);
201 
202  //cout << __FILE__ << " " << __LINE__ << " --- ruchn " << hex << ruchn << " next value " << (unsigned int) b << dec << " status:" << status << endl;
203 
204  if (status) // we mop up what we started in the last round -
205  // these are all cases with more than one byte
206  {
207  switch (status)
208  {
209  case CHIPHEADER:
210 
211  _bunchcounter[ruid][ruchn] = b;
212  //cout << __FILE__ << " " << __LINE__ << " chip header, ruchn= " << ruchn << " bunchctr= " << hex << _bunchcounter[ruchn] << dec << endl;
213  status = 0;
214  _header_found[ruid][ruchn] = true;
215  break;
216 
217  case CHIPEMPTYFRAME:
218 
219  _bunchcounter[ruid][ruchn] = b;
220  // cout << __FILE__ << " " << __LINE__ << " chip empty frame " << hex << ruchn << " " << _bunchcounter[ruchn] << dec << endl;
221  ibyte_endofdata = ibyte;
222  _header_found[ruid][ruchn] = true;
223  _trailer_found[ruid][ruchn] = true;
224  status = 0;
225  break;
226 
227  case DATASHORT:
228  address += b;
229  //cout << __FILE__ << " " << __LINE__ << " data short report, hex:" << hex << address << dec << " enc. id " << encoder_id << " address= " << address << " the_region:" << the_region << " ruchn:" << ruchn;
230  // the numbering "snakes" its way through a column (fig. 4.5 in the Alpide manual)
231  // 0 1 > > row 0
232  // 3 2 < < row 1
233  // 4 5 > > row 2
234  // 7 6 < < so we need to know if we are in an even or odd row
235  if ( the_region >= 0 && encoder_id >=0 )
236  {
237  unsigned int row = (address >> 1);
238  unsigned int col = (the_region * 32);
239  col += (encoder_id * 2) + ( (row & 1) ? ( (address & 1) ^ 1 ) : (address & 1) );
240  if ( row < 0 || row >= NROW || col < 0 || col >= NCOL )
241  {
242  cout << __FILE__ << " " << __LINE__ << " impossible pixel coord: " << row
243  << ", " << col << "." << endl;
244  cout << "Check region " << the_region << ", encoder " << encoder_id
245  << ", addr " << address << endl;
246  _decoder_error |= ( 1 << 2);
247  }
248  _hit_vectors[ruid][ruchn].push_back(encode_hit(row,col));
249  }
250 
251  //cout << endl;
252  status = 0;
253  break;
254 
255  case DATALONG0:
256  address += b;
257  status = DATALONG1;
258  break;
259 
260  case DATALONG1:
261  if ( (b & 0x80) != 0) //required to be 0
262  {
263  //cout << __FILE__ << " " << __LINE__ << " unexpected word " << hex << (unsigned int) b << dec << " at ibyte " << ibyte << endl;
264  _bad_bytes[ruid][ruchn]++;
265  }
266  //cout << __FILE__ << " " << __LINE__ << " data long report, hex:" << hex << address << dec << " enc. id " << encoder_id << " address= " << address << " the_region:" << the_region << " ruchn:" << ruchn << endl;
267  // Loop over the hits in the cluster. The pixel specified by the address always has a hit.
268  // The next 7 pixels (in priority encoder order) have hits if the corresponding bit in this byte is high.
269  // See ALPIDE manual section 3.4.1 on DATA LONG: page 63.
270  for (int ihit = 0; ihit<8; ihit++)
271  {
272  if (ihit==0 || ((b >> (ihit-1)) & 1))
273  {
274  int hit_address = address + ihit;
275  if ( the_region >= 0 && encoder_id >=0 )
276  {
277  unsigned int row = (hit_address >> 1);
278  unsigned int col = the_region*32;
279  col += (encoder_id * 2) + ( (row & 1) ? ( (hit_address & 1) ^ 1 ) : (hit_address & 1) );
280  if ( row < 0 || row >= NROW || col < 0 || col >= NCOL )
281  {
282  cout << __FILE__ << " " << __LINE__ << " impossible pixel coord: " << row
283  << ", " << col << "." << endl;
284  cout << "Check region " << the_region << ", encoder " << encoder_id
285  << ", addr " << hit_address << endl;
286  _decoder_error |= ( 1 << 2);
287  }
288  _hit_vectors[ruid][ruchn].push_back(encode_hit(row,col));
289  }
290  }
291  }
292  status = 0;
293  break;
294  }
295  continue;
296  }
297 
298  if (ibyte_endofdata != -1) break;
299 
300  if ( b == 0xff) // Idle byte, skip
301  {
302  //cout << __FILE__ << " " << __LINE__ << " IDLE byte " << hex << (unsigned int) b << dec << endl;
303  status = 0;
304  }
305 
306  else if ( ( b >> 4) == 0xa) // we have a chip header
307  {
308  _chip_id[ruid][ruchn] = ( b & 0xf);
309  header_seen = true;
310  status = CHIPHEADER;
311  }
312 
313  else if ( ( b >> 4) == 0xb) // we have a chip trailer
314  {
315  // cout << __FILE__ << " " << __LINE__ << " chip trailer, ruchn= " << hex << ruchn << dec << endl;
316  // break out of the loop, done with this chip
317  ibyte_endofdata = ibyte;
318  _trailer_found[ruid][ruchn] = true;
319  if (!_header_found[ruid][ruchn]) // shouldn't see a trailer without having seen a header
320  {
321  _bad_bytes[ruid][ruchn]++;
322  }
323  else
324  {
325  _readout_flags[ruid][ruchn] = (b & 0xf);
326  }
327  break;
328  }
329 
330  else if ( ( b >> 4) == 0xE) // we have a chip empty frame
331  {
332  _chip_id[ruid][ruchn] = ( b & 0xf);
333  header_seen = true;
334  status = CHIPEMPTYFRAME;
335  }
336 
337  else if ( ( b >> 5) == 0x6) // we have a region header
338  {
339  unsigned int region_id = (b & 0x1f);
340  if ( region_id <32)
341  {
342  the_region = region_id;
343  }
344  else //this is impossible since the region ID is 5 bits
345  {
346  cout << __FILE__ << " " << __LINE__ << " wrong region header, id= " << hex << region_id << dec << endl;
347  _decoder_error |= ( 1 << 3);
348  }
349  }
350 
351  else if ( ( b >> 6) == 0x1) // we have a DATA short report
352  {
353  encoder_id = ( b>>2) & 0xf;
354  address = (b & 0x3) << 8;
355  status = DATASHORT;
356  }
357 
358  else if ( ( b >> 6) == 0x0) // we have a DATA long report
359  {
360  encoder_id = ( b>>2) & 0xf;
361  address = (b & 0x3) << 8;
362  status = DATALONG0;
363  }
364 
365  else if ( b == 0xF1) // we have a BUSY on
366  {
367  //cout << __FILE__ << " " << __LINE__ << " Busy on " << endl;
368  }
369 
370  else if ( b == 0xF0) // we have a BUSY off
371  {
372  //cout << __FILE__ << " " << __LINE__ << " Busy off " << endl;
373  }
374 
375  else
376  {
377  cout << __FILE__ << " " << __LINE__ << " unexpected word " << hex << (unsigned int) b << dec << " at ibyte " << ibyte << endl;
378  _bad_bytes[ruid][ruchn]++;
379  _decoder_error |= ( 1 << 4 );
380  }
381 
382  if (ibyte==0 && !header_seen)
383  {
384  cout << __FILE__ << " " << __LINE__ << " " << "first byte of the ALPIDE stream must be a chip header or chip empty;" <<endl;
385  cout << "Aborting so we don't get confused by bad data." << endl;
386  _decoder_error |= ( 1 << 5 );
387  break;
388  }
389 
390  } // ibyte
391 
392  //cout << __FILE__ << " " << __LINE__ << " ruchn " << ruchn << " ibyte_endofdata " << ibyte_endofdata << endl;
393  for (unsigned int ibyte = ibyte_endofdata+1; ibyte < ruchn_stream[ruid][ruchn].size(); ibyte++)
394  {
395  b = ruchn_stream[ruid][ruchn].at(ibyte);
396  if (b!=0)
397  {
398  //cout << __FILE__ << " " << __LINE__ << " --- ruchn " << hex << ruchn << " unexpected nonzero value " << (unsigned int) b << dec << " at ibyte " << ibyte << " after ibyte_endofdata " << ibyte_endofdata << endl;
399  _excess_bytes[ruid][ruchn]++;
400  }
401  }
402  } // ruchn
403  if (_lanes_active[ruid] != -1)
404  {
405  _inconsistent_bc[ruid] = this->checkBC(ruid);
406  }
407  } // ruid
408 
409 
410  return 0;
411 }
412 
413 int oncsSub_idmvtxv2::iValue(const int ruid, const char *what)
414 {
415  decode();
416  if ( strcmp(what, "DECODER_ERROR") == 0 )
417  {
418  return _decoder_error;
419  }
420  if ( strcmp(what,"UNEXPECTED_FELIX_COUNTERS") == 0 )
421  {
423  }
424 
425  else if ( strcmp(what,"BAD_RUIDS") == 0 )
426  {
427  return _bad_ruids;
428  }
429 
430  if (ruid > _highest_ruid) return -1; // no such RU
431  if (_lanes_active[ruid]==-1) return -1; // no such RU
432 
433  if ( strcmp(what,"BAD_RUCHNS") == 0 )
434  {
435  return _bad_ruchns[ruid];
436  }
437 
438  else if ( strcmp(what,"LANE_STOPS") == 0 )
439  {
440  return _lane_stops[ruid];
441  }
442 
443  else if ( strcmp(what,"LANE_TIMEOUTS") == 0 )
444  {
445  return _lane_timeouts[ruid];
446  }
447 
448  else if ( strcmp(what,"CHECK_BC") == 0 )
449  {
450  return _inconsistent_bc[ruid];
451  }
452 
453  return 0;
454 }
455 
456 int oncsSub_idmvtxv2::iValue(const int ruid)
457 {
458  decode();
459 
460  if (ruid > _highest_ruid) return -1; // no such RU
461  return _lanes_active[ruid];
462 }
463 
464 int oncsSub_idmvtxv2::iValue(const int ruid, const int ruchn, const char *what)
465 {
466  decode();
467 
468  if (ruid > _highest_ruid) return -1; // no such RU
469  if (_lanes_active[ruid]==-1) return -1; // no such RU
470 
471  if ( strcmp(what,"CHIP_ID") == 0 )
472  {
473  return _chip_id[ruid][ruchn];
474  }
475 
476  else if ( strcmp(what,"BAD_BYTES") == 0 )
477  {
478  return _bad_bytes[ruid][ruchn];
479  }
480 
481  else if ( strcmp(what,"EXCESS_BYTES") == 0 )
482  {
483  return _excess_bytes[ruid][ruchn];
484  }
485 
486  else if ( strcmp(what,"BUNCHCOUNTER") == 0 )
487  {
488  return _bunchcounter[ruid][ruchn];
489  }
490 
491  else if ( strcmp(what,"HEADER_FOUND") == 0 )
492  {
493  return _header_found[ruid][ruchn]?1:0;
494  }
495 
496  else if ( strcmp(what,"TRAILER_FOUND") == 0 )
497  {
498  return _trailer_found[ruid][ruchn]?1:0;
499  }
500 
501  else if ( strcmp(what,"READOUT_FLAGS") == 0 )
502  {
503  return _readout_flags[ruid][ruchn];
504  }
505 
506  return 0;
507 }
508 
509 int oncsSub_idmvtxv2::iValue(const int ruid, const int ruchn)
510 {
511  decode();
512 
513  if (ruid > _highest_ruid) return -1; // no such RU
514  if (_lanes_active[ruid]==-1) return -1; // no such RU
515  if (!mask_contains_ruchn(_lanes_active[ruid],ruchn)) return -1; // no such RU channel
516  return _hit_vectors[ruid][ruchn].size();
517 }
518 
519 int oncsSub_idmvtxv2::iValue(const int ruid, const int ruchn, const int i)
520 {
521  decode();
522 
523  if (ruid > _highest_ruid) return -1; // no such RU
524  if (_lanes_active[ruid]==-1) return -1; // no such RU
525  if (!mask_contains_ruchn(_lanes_active[ruid],ruchn)) return -1; // no such RU channel
526  return _hit_vectors[ruid][ruchn].at(i);
527 }
528 
530 {
531 
532  identify(os);
533 
534  decode();
535  bool first;
536  for (int ruid=0; ruid<IDMVTXV2_MAXRUID+1; ruid++)
537  {
538  if (iValue(ruid)!=-1)
539  {
540  os << "RU ID: " << ruid;
541  os << ", bad_ruchns=" << iValue(ruid,"BAD_RUCHNS");
542  os << hex << setfill('0');
543  os << ", lanes_active 0x" << setw(7) << iValue(ruid);
544  os << dec;
545  first=true;
546  os << " (";
547  for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
548  {
549  if (mask_contains_ruchn(iValue(ruid),ruchn))
550  {
551  if (!first)
552  os << ", ";
553  os << ruchn;
554  first = false;
555  }
556  }
557  os << "), inconsistent_bc=" << setw(1) << iValue(ruid,"CHECK_BC");
558  os << hex << setfill('0');
559  os << ", lane_stops=0x" << setw(7) << iValue(ruid,"LANE_STOPS");
560  os << dec;
561  first=true;
562  os << " (";
563  for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
564  {
565  if (mask_contains_ruchn(iValue(ruid,"LANE_STOPS"),ruchn))
566  {
567  if (!first)
568  os << ", ";
569  os << ruchn;
570  first = false;
571  }
572  }
573  os << hex << setfill('0');
574  os << "), lane_timeouts=0x" << setw(7) << iValue(ruid,"LANE_TIMEOUTS");
575  os << dec;
576  first=true;
577  os << " (";
578  for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
579  {
580  if (mask_contains_ruchn(iValue(ruid,"LANE_TIMEOUTS"),ruchn))
581  {
582  if (!first)
583  os << ", ";
584  os << ruchn;
585  first = false;
586  }
587  }
588  os << ")";
589  os << dec << setfill(' ') << endl;
590  for ( int ruchn = 0; ruchn < IDMVTXV2_MAXRUCHN+1; ruchn++)
591  {
592  if (iValue(ruid,ruchn)!=-1)
593  {
594  os << "RU channel " << setw(2) << ruchn;
595  os << " bad_bytes=" << iValue(ruid,ruchn,"BAD_BYTES") << " excess_bytes=" << iValue(ruid,ruchn,"EXCESS_BYTES") <<" header_found=" << iValue(ruid,ruchn,"HEADER_FOUND") << " trailer_found=" << iValue(ruid,ruchn,"TRAILER_FOUND");
596  os << " bunchcounter=" << setw(3) << iValue(ruid,ruchn,"BUNCHCOUNTER") << " flags=" << iValue(ruid,ruchn,"READOUT_FLAGS");
597  os << ", chip ID " << iValue(ruid,ruchn,"CHIP_ID") << ", " << iValue(ruid,ruchn) << " hits: ";
598  for (int i=0;i<iValue(ruid,ruchn);i++)
599  {
600  int hit = iValue(ruid,ruchn,i);
601  os << "(row " << decode_row(hit) << ", col " << decode_col(hit) << ") ";
602  }
603  os << endl;
604  }
605  }
606  }
607  }
608 }
609 
610 //copied from oncsSubevent.cc for a generic dump 12/21/17
611 void oncsSub_idmvtxv2::gdump(const int i, OSTREAM& out) const
612 {
613 
614  int *SubeventData = &SubeventHdr->data;
615  unsigned int j,l;
616  identify(out);
617 
618  int current_offset;
619  const int DWORDS_PER_WORD = 8;
620 
621  switch (i)
622  {
623  case (EVT_HEXADECIMAL):
624  //j = 0;
625  current_offset = 0;
626  while (1)
627  {
628  //int dwords_remaining = getLength()-SEVTHEADERLENGTH - getPadding()/4 - current_offset; //padding is supposed to be in units of dwords, this assumes bytes
629  int dwords_remaining = getLength()-SEVTHEADERLENGTH - getPadding() - current_offset; //padding is supposed to be in units of dwords, this assumes dwords
630 
631  out << SETW(5) << current_offset << " | ";
632  //for (l=0;l<DWORDS_PER_WORD;l++)
633 
634  //FELIX header
635  print_stuff(out, SubeventData[current_offset+7], 4, 16, (dwords_remaining<=7));
636  out << " ";
637 
638  //RU word 2
639  print_stuff(out, SubeventData[current_offset+7], 4, 0, (dwords_remaining<=7));
640  print_stuff(out, SubeventData[current_offset+6], 8, 0, (dwords_remaining<=6));
641  print_stuff(out, SubeventData[current_offset+5], 8, 0, (dwords_remaining<=5));
642  out << " ";
643 
644  //RU word 1
645  print_stuff(out, SubeventData[current_offset+4], 8, 0, (dwords_remaining<=4));
646  print_stuff(out, SubeventData[current_offset+3], 8, 0, (dwords_remaining<=3));
647  print_stuff(out, SubeventData[current_offset+2], 4, 16, (dwords_remaining<=2));
648  out << " ";
649 
650  //RU word 0
651  print_stuff(out, SubeventData[current_offset+2], 4, 0, (dwords_remaining<=2));
652  print_stuff(out, SubeventData[current_offset+1], 8, 0, (dwords_remaining<=1));
653  print_stuff(out, SubeventData[current_offset+0], 8, 0, (dwords_remaining<=0));
654  out << " " << std::dec << std::endl << std::setfill(' ');
655 
656  if (dwords_remaining<8) break;
657 
658  current_offset += DWORDS_PER_WORD;
659  }
660  break;
661 
662  case (EVT_DECIMAL):
663  j = 0;
664  while (1)
665  {
666  out << std::dec << std::endl << SETW(5) << j << " | ";
667 
668  for (l=0;l<6;l++)
669  {
670  out << SETW(10) << SubeventData[j++] << " ";
672  }
674  }
675  break;
676 
677  default:
678  break;
679  }
680  out << std::endl;
681 
682 }
683 
684 bool oncsSub_idmvtxv2::checkBC(const int ruid)
685 {
686  bool first_active = true;
687  unsigned int first_active_lane;
688  for (int iruchn = 0; iruchn < IDMVTXV2_MAXRUCHN+1; ++iruchn)
689  {
690  if (this->mask_contains_ruchn(_lanes_active[ruid], iruchn))
691  {
692  if (first_active)
693  {
694  first_active_lane = iruchn;
695  first_active = false;
696  }
697  else if (_bunchcounter[ruid][iruchn] != _bunchcounter[ruid][first_active_lane])
698  return true;
699  }
700  }
701 
702  return false;
703 }