Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tpc_pool.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file tpc_pool.cc
1 #include "tpc_pool.h"
2 
3 #include <string.h>
4 #include <stdint.h>
5 
6 #include <Event/packet.h>
7 
8 
9 #define coutfl cout << __FILE__<< " " << __LINE__ << " "
10 #define cerrfl cerr << __FILE__<< " " << __LINE__ << " "
11 
12 using namespace std;
13 
14 tpc_pool::tpc_pool( const unsigned int depth, const unsigned int low_mark )
15 {
16 
17  if ( depth < 4000000)
18  {
19  _required_depth = 4000000;
20  cout << " Adjusted the depth to the minimum value " << endl;
21  }
22  else
23  {
24  _required_depth = depth;
25  }
26 
27  if ( low_mark > _required_depth)
28  {
29  _low_mark = _required_depth;
30  cout << " Adjusted the low mark to not exceed minimum depth " << endl;
31  }
32  else
33  {
34  _low_mark = low_mark;
35  }
36 
37  _is_decoded = 0;
38  _last_requested_element = -1; // impossible value to mark "unnused"
39  _progress_index = 0;
40 
41 
42 }
43 
44 
46 {
47 
48  for (auto itr = waveforms.begin() ; itr != waveforms.end() ; ++itr)
49  {
50  delete (*itr);
51  }
52  waveforms.clear();
53 
54 
55  for (auto itr = gtm_data.begin() ; itr != gtm_data.end() ; ++itr)
56  {
57  delete (*itr);
58  }
59  gtm_data.clear();
60 
61 }
62 
64 {
65  _is_decoded = 0;
66  for (auto itr = waveforms.begin() ; itr != waveforms.end() ; ++itr)
67  {
68  delete (*itr);
69  }
70  waveforms.clear();
71 
72 
73  for (auto itr = gtm_data.begin() ; itr != gtm_data.end() ; ++itr)
74  {
75  delete (*itr);
76  }
77  gtm_data.clear();
78 
79  for (int fee_id = 0; fee_id < MAX_FEECOUNT; fee_id++)
80  {
81  fee_data[fee_id].clear();
82  }
83 
84  // coutfl << "erasing " << _progress_index << " elements vector size is " << _thebuffer.size() << endl;
85  _thebuffer.erase(_thebuffer.begin(), _thebuffer.begin() + _progress_index );
86  //coutfl << " done, new size is " << _thebuffer.size() << endl;
87 
88 
89  return 0;
90 
91 }
92 
93 bool tpc_pool::depth_ok() const
94 {
95  return ( min_depth() >= _required_depth);
96 }
97 
98 
99 
101 {
102 
103  if (!p) return 0;
104 
105  p->identify();
106 
107  int l = p->getDataLength()+16;
108  int b[l];
109 
110  int l2;
111  // int l3 = p->fillIntArray(b, l, &l2, "DATA");
112 
113  p->fillIntArray(b, l, &l2, "DATA");
114 
115  for ( int i = 0; i < l2; i++)
116  {
117  unsigned short x = b[i] & 0xffff;
118  _thebuffer.push_back(x);
119  x = (b[i] >> 16) & 0xffff;
120  _thebuffer.push_back(x);
121  }
122 
123  return 0;
124 }
125 
126 
127 
128 
130 {
131  if ( n < 0) return 0; // not ok
132  if ( _last_requested_element == n) return 1; // say "ok"
133 
134  unsigned int i = n;
135 
136  if ( i >= waveforms.size() )
137  {
138  _last_requested_element = -1;
139  return 0;
140  }
141 
142  auto it = std::next(waveforms.begin(), i);
143  _cached_iter = it;
144  _last_requested_element = i;
145  return 1;
146 }
147 
148 int tpc_pool::decode_gtm_data(unsigned short dat[16])
149 {
150  unsigned char *gtm = (unsigned char *)dat;
151  gtm_payload *payload = new gtm_payload;
152 
153  payload->pkt_type = gtm[0] | ((unsigned short)gtm[1] << 8);
154  if (payload->pkt_type != GTM_LVL1_ACCEPT_MAGIC_KEY && payload->pkt_type != GTM_ENDAT_MAGIC_KEY)
155  {
156  delete payload;
157  return -1;
158  }
159 
160  payload->is_lvl1 = payload->pkt_type == GTM_LVL1_ACCEPT_MAGIC_KEY;
161  payload->is_endat = payload->pkt_type == GTM_ENDAT_MAGIC_KEY;
162 
163  payload->bco = ((unsigned long long)gtm[2] << 0)
164  | ((unsigned long long)gtm[3] << 8)
165  | ((unsigned long long)gtm[4] << 16)
166  | ((unsigned long long)gtm[5] << 24)
167  | ((unsigned long long)gtm[6] << 32)
168  | (((unsigned long long)gtm[7]) << 40);
169  payload->lvl1_count = ((unsigned int)gtm[8] << 0)
170  | ((unsigned int)gtm[9] << 8)
171  | ((unsigned int)gtm[10] << 16)
172  | ((unsigned int)gtm[11] << 24);
173  payload->endat_count = ((unsigned int)gtm[12] << 0)
174  | ((unsigned int)gtm[13] << 8)
175  | ((unsigned int)gtm[14] << 16)
176  | ((unsigned int)gtm[15] << 24);
177  payload->last_bco = ((unsigned long long)gtm[16] << 0)
178  | ((unsigned long long)gtm[17] << 8)
179  | ((unsigned long long)gtm[18] << 16)
180  | ((unsigned long long)gtm[19] << 24)
181  | ((unsigned long long)gtm[20] << 32)
182  | (((unsigned long long)gtm[21]) << 40);
183  payload->modebits = gtm[22];
184 
185  this->gtm_data.push_back(payload);
186 
187  return 0;
188 }
189 
191 {
192 
193 
194  unsigned long long old_bco = 0;
195 
196 
197  if (_is_decoded ) return 0;
198  _is_decoded = 1;
199 
200 
201  unsigned int payload_length = _thebuffer.size();
202 
203  unsigned int index = 0;
204 
205 
206  // demultiplexer
207  while (index < payload_length)
208  {
209 
210  //if ( index < 4) coutfl << index << " " << hex << _thebuffer[index] << dec << endl;
211 
212  // Length for the 256-bit wide Round Robin Multiplexer for the data stream
213  const unsigned int datalength = 0xf;
214 
215  if ((_thebuffer[index] & 0xFF00) == FEE_MAGIC_KEY)
216  {
217 
218  unsigned int fee_id = _thebuffer[index] & 0xff;
219  //coutfl << " index = " << index << " fee_id = " << fee_id << " len = " << datalength << endl;
220  ++index;
221  if (fee_id < MAX_FEECOUNT)
222  {
223  for (unsigned int i = 0; i < datalength; i++)
224  {
225  // watch out for any data corruption
226  if (index >= payload_length) break;
227 
228  fee_data[fee_id].push_back(_thebuffer[index++]);
229  }
230  }
231  }
232 
233  else if ((_thebuffer[index] & 0xFF00) == GTM_MAGIC_KEY)
234  {
235 
236 
237  // if we hit the LVL1 BCO, we call it a day for this round
238  if ( (_thebuffer[index] & 0xFFFF) == GTM_LVL1_ACCEPT_MAGIC_KEY)
239  {
240 
241  if (old_bco == 0)
242  {
243  old_bco = (_thebuffer[index+3] & 0xff);
244  old_bco <<=8;
245  old_bco |= (_thebuffer[index+2] & 0xffff);
246  old_bco <<=16;
247  old_bco |= (_thebuffer[index+1] & 0xffff);
248  }
249  else
250  {
251  unsigned long long this_bco = 0;
252  this_bco = (_thebuffer[index+3] & 0xff);
253  this_bco <<=8;
254  this_bco |= (_thebuffer[index+2] & 0xffff);
255  this_bco <<=16;
256  this_bco |= (_thebuffer[index+1] & 0xffff);
257 
258  if ( this_bco != old_bco )
259  {
260  //coutfl << "new GTM BCO, old " << hex << old_bco << " new: " << this_bco << dec << endl;
261  // coutfl << "erasing " << index << " elements vector size is " << _the_thebuffer.size() << endl;
262  // _thebuffer.erase(_thebuffer.begin(), _thebuffer.begin() + index );
263  // coutfl << " done, new size is " << _thebuffer.size() << endl;
264  _progress_index = index; // we are done until here
265  break;
266  }
267  }
268  }
269  unsigned short buf[16];
270 
271  // memcpy?
272  for (unsigned int i = 0; i < 16; i++)
273  {
274  buf[i] = _thebuffer[index++];
275  }
276 
277  decode_gtm_data(buf);
278  }
279  else
280  {
281  // not FEE data, e.g. GTM data or other stream, to be decoded
282  index += datalength + 1;
283  }
284 
285  }
286 
287  _progress_index = index; // we are done until here
288 
289 
290  for ( int ifee = 0 ; ifee < MAX_FEECOUNT ; ifee++)
291  {
292 
293  unsigned int pos; // I'm too tired to play with iterators; pos is the position in a FEE vector
294 
295  //for ( fee_data_itr = fee_data[ifee].begin(); fee_data_itr != fee_data[ifee].end(); )
296  for ( pos = 0; pos < fee_data[ifee].size() ; )
297  {
298  // itr = fee_data_itr;
299  int skip_amount = find_header (pos, fee_data[ifee]);
300  if ( skip_amount < 0) break;
301  //for ( int i = 0; i < skip_amount; i++) ++fee_data_itr; // skip that many words
302  pos += skip_amount;
303 
304  // as we advance pos, let's remember where the start is
305  unsigned int startpos = pos;
306 
307  // first the check if our vector cuts off before the fixed-length header, then we are already done
308  if ( startpos + HEADER_LENGTH >= fee_data[ifee].size() || startpos + fee_data[ifee][startpos] > fee_data[ifee].size())
309  {
310  pos = fee_data[ifee].size() + 1; // make sure we really terminate the loop
311  }
312  else
313  {
314  // capture the header so we can easier get the bit shift stuff
315  unsigned short header[HEADER_LENGTH];
316  for ( int i = 0; i < HEADER_LENGTH; i++ ) header[i] = (fee_data[ifee][pos++]) ;
317 
318  sampa_waveform *sw = new sampa_waveform;
319 
320  sw->fee = ifee;
321  sw->pkt_length = header[0];
322  sw->adc_length = header[5];
323  sw->sampa_address = (header[1] >> 5) & 0xf;
324  sw->sampa_channel = header[1] & 0x1f;
325  sw->channel = header[1] & 0x1ff;
326  sw->bx_timestamp = ((header[3] & 0x1ff) << 11)
327  | ((header[2] & 0x3ff) << 1)
328  | (header[1] >> 9);
329 
330  // now we add the actual waveform
331  unsigned short data_size = header[5] -1 ;
332 
333  // coutfl << " Fee: " << ifee << " Sampa " << sw->sampa_address
334  // << " sampa channel: " << sw->sampa_channel
335  // << " channel: " << sw->channel
336  // << " waveform length: " << data_size << endl;
337 
338  for (int i = 0 ; i < data_size ; i++)
339  {
340  sw->waveform.push_back( fee_data[ifee][pos++]);
341  }
342 
343  // we calculate the checksum here because "pos" is at the right place
344  unsigned short crc = crc16(ifee, startpos, header[0]-1);
345  // coutfl << "fee " << setw(3) << sw->fee
346  // << " sampla channel " << setw(3) << sw->channel
347  // << " crc and value " << hex << setw(5) << crc << " " << setw(5) << fee_data[ifee][pos] << dec;
348  // if ( crc != fee_data[ifee][pos] ) cout << " *********";
349  // cout << endl;
350 
351  sw->checksum = crc;
352  sw->valid = ( crc == fee_data[ifee][pos]);
353 
354  waveforms.insert(sw);
355  }
356 
357  //coutfl << "inserting at " << ifee*MAX_CHANNELS + sw->channel << " size is " << waveforms.size() << endl;
358  //waveform_vector[ifee*MAX_CHANNELS + sw->channel].push_back(sw);
359  }
360  }
361 
362 
363  return 0;
364 }
365 
366 long long tpc_pool::lValue(const int n, const char *what)
367 {
368  tpc_decode();
369 
370  const size_t i = n;
371 
372  if (strcmp(what, "N_TAGGER") == 0) // the number of datasets
373  {
374  return gtm_data.size();
375  }
376 
377  else if (strcmp(what, "TAGGER_TYPE") == 0 )
378  {
379  if (i < gtm_data.size())
380  {
381  return gtm_data[i]->pkt_type;
382  }
383  }
384 
385  else if (strcmp(what, "IS_ENDAT") == 0 )
386  {
387  if (i < gtm_data.size())
388  {
389  return gtm_data[i]->is_endat;
390  }
391  }
392 
393  else if (strcmp(what, "IS_LEVEL1_TRIGGER") == 0 )
394  {
395  if (i < gtm_data.size())
396  {
397  return gtm_data[i]->is_lvl1;
398  }
399  }
400 
401  else if (strcmp(what, "BCO") == 0 )
402  {
403  if (i < gtm_data.size())
404  {
405  return gtm_data[i]->bco;
406  }
407  }
408 
409  else if (strcmp(what, "LEVEL1_COUNT") == 0 )
410  {
411  if (i < gtm_data.size())
412  {
413  return gtm_data[i]->lvl1_count;
414  }
415  }
416 
417  else if (strcmp(what, "ENDAT_COUNT") == 0 )
418  {
419  if (i < gtm_data.size())
420  {
421  return gtm_data[i]->endat_count;
422  }
423  }
424 
425  else if (strcmp(what, "LAST_BCO") == 0 )
426  {
427  if (i < gtm_data.size())
428  {
429  return gtm_data[i]->last_bco;
430  }
431  }
432 
433  else if (strcmp(what, "MODEBITS") == 0 )
434  {
435  if (i < gtm_data.size())
436  {
437  return gtm_data[i]->modebits;
438  }
439  }
440 
441  return 0;
442 }
443 
444 int tpc_pool::iValue(const int n, const int sample)
445 {
446  if ( n < 0) return 0;
447 
448  tpc_decode();
449 
450  if ( cacheIterator(n) )
451  {
452  unsigned int m = sample;
453  if ( m >= (*_cached_iter)->waveform.size() ) return 0;
454  return (*_cached_iter)->waveform[m];
455  }
456  return 0;
457 }
458 
459 
460 
461 
462 
463 int tpc_pool::iValue(const int n, const char *what)
464 {
465 
466  tpc_decode();
467 
468  if ( strcmp(what,"NR_WF") == 0 ) // the number of datasets
469  {
470  return waveforms.size();
471  }
472 
473  else if ( strcmp(what,"MAX_FEECOUNT") == 0 )
474  {
475  return MAX_FEECOUNT;
476  }
477 
478  // see how many samples we have
479  else if ( strcmp(what,"SAMPLES") == 0 )
480  {
481  if ( cacheIterator(n) )
482  {
483  return (int) (*_cached_iter)->waveform.size();
484  }
485  return 0;
486  }
487 
488  else if ( strcmp(what,"FEE") == 0 )
489  {
490  if ( cacheIterator(n) )
491  {
492  return (int) (*_cached_iter)->fee;
493  }
494  return 0;
495  }
496 
497  else if ( strcmp(what,"SAMPAADDRESS") == 0 )
498  {
499  if ( cacheIterator(n) )
500  {
501  return (int) (*_cached_iter)->sampa_address;
502  }
503  return 0;
504  }
505 
506  else if ( strcmp(what,"SAMPACHANNEL") == 0 )
507  {
508  if ( cacheIterator(n) )
509  {
510  return (int) (*_cached_iter)->sampa_channel;
511  }
512  return 0;
513  }
514 
515  else if ( strcmp(what,"CHANNEL") == 0 )
516  {
517  if ( cacheIterator(n) )
518  {
519  return (int) (*_cached_iter)->channel;
520  }
521  return 0;
522  }
523 
524  else if ( strcmp(what,"BCO") == 0 )
525  {
526  if ( cacheIterator(n) )
527  {
528  return (int) (*_cached_iter)->bx_timestamp;
529  }
530  return 0;
531  }
532 
533  else if ( strcmp(what,"CHECKSUM") == 0 )
534  {
535  if ( cacheIterator(n) )
536  {
537  return (int) (*_cached_iter)->checksum;
538  }
539  return 0;
540  }
541 
542  else if ( strcmp(what,"CHECKSUMERROR") == 0 )
543  {
544  if ( cacheIterator(n) )
545  {
546  if ( (*_cached_iter)->valid ) return 0;
547  return 1;
548  }
549  return 0;
550  }
551 
552  return 0;
553 
554 }
555 
556 //int tpc_pool::find_header ( std::vector<unsigned short>::const_iterator &itr, const std::vector<unsigned short> &orig)
557 int tpc_pool::find_header ( const unsigned int yy, const std::vector<unsigned short> &orig)
558 {
559  bool found = false;
560  unsigned int pos = yy;
561  std::vector<unsigned short> header_candidate;
562 
563  // we slide over the data and find the header, if any.
564  // we calculate and return the amount of words we need to skip to find the vector.
565  // if we find it right away, the amount returned is 0;
566  // -1 for an error condition or end, like we hit the end without finding another header.
567  // the complication here is that we look ahead a few words to recognize it.
568 
569  for ( unsigned int i = 0; i < HEADER_LENGTH ; i++) // we start out with one "header candidate" = 7 entries
570  {
571  if ( pos >= orig.size()) // if we reached the end, no more header here
572  {
573  return -1;
574  }
575 
576  header_candidate.push_back(orig[pos]);
577  pos++;
578  }
579 
580  int skip_amount = 0;
581  while ( ! found)
582  {
583  // coutfl << " current pos is " << pos << " vector length " << orig.size() << endl;
584 
585  if (header_candidate[4] == MAGIC_KEY_0 && header_candidate[6] == MAGIC_KEY_1 && (header_candidate[0] - header_candidate[5] == HEADER_LENGTH))
586  {
587  // found it!
588  found = true;
589  // coutfl << " found header skip value = " << skip_amount << endl;
590  break;
591  }
592  skip_amount++;
593  if ( pos >= orig.size()) // if we reached the end, no more header here
594  {
595  return -1;
596  }
597 
598  // coutfl << " next value " << pos << " " << hex << orig[pos] << dec << endl;
599  header_candidate.erase(header_candidate.begin()); // delete the vector 1st element
600  header_candidate.push_back(orig[pos]); // push a new value, rinse and repeat
601  pos++;
602  }
603 
604  return skip_amount;
605 }
606 
607 void tpc_pool::dump ( std::ostream& os )
608 {
609  tpc_decode();
610 
611  if (lValue(0, "N_TAGGER") == 0)
612  os << " No lvl1 and Endat taggers" << endl;
613  else
614  {
615  os << " TAGGER_TYPE BCO LEVEL1 CNT ENDAT CNT LAST_BCO MODEBITS" << endl;
616 
617  for (int i = 0; i < lValue(0, "N_TAGGER"); ++i) // go through the datasets
618  {
619  os << " 0x" << setw(4) << hex << lValue(i, "TAGGER_TYPE") << dec
620  << " (" << (lValue(i, "IS_ENDAT") ? "ENDAT" : "") << (lValue(i, "IS_LEVEL1_TRIGGER") ? "LVL1 " : "")
621  << ") "
622  << setw(12) << lValue(i, "BCO") << " "
623  << setw(10) << lValue(i, "LEVEL1_COUNT") << " "
624  << setw(10) << lValue(i, "ENDAT_COUNT") << " "
625  << setw(12) << lValue(i, "LAST_BCO")
626  << " 0x" << std::setfill('0') << setw(2) << hex << lValue(i, "MODEBITS") << std::setfill(' ')<< dec
627  << endl;
628  }
629 
630  os << endl;
631  }
632  waveform_set::const_iterator wf_iter;
633 
634  for ( int i = 0; i < iValue(0, "NR_WF") ; i++) // go through the datasets
635  {
636  os << " FEE Channel Sampachannel Samples BCO CRC_ERR" << endl;
637 
638  os << setw(5) << iValue(i, "FEE") << " "
639  << setw(9) << iValue(i, "CHANNEL") << " "
640  << setw(9) << iValue(i, "SAMPACHANNEL") << " "
641  << setw(12) << iValue(i, "SAMPLES") << " "
642  << " 0x" << setw(5) << hex << iValue(i, "BCO") << dec
643  // << " 0x" << setw(4) << hex << iValue(i, "CHECKSUM") << dec
644  << setw(4) << iValue(i, "CHECKSUMERROR")
645  << endl;
646 
647  for (int j = 0; j < iValue(i, "SAMPLES") ; j += 10)
648  {
649  os << " ";
650  for (int k = 0; k < 10 ; k++)
651  {
652  os << setw(4) << iValue(i,j+k) << " ";
653  }
654  os << endl;
655  }
656  os << endl;
657 
658  }
659 }
660 
661 
662 unsigned short tpc_pool::reverseBits(const unsigned short x) const
663 {
664  unsigned short n = x;
665  n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
666  n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
667  n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
668  n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
669  //n = (n >> 16) & 0x0000ffff | (n << 16) & 0xffff0000;
670  return n;
671 }
672 
673 
674 
675 unsigned short tpc_pool::crc16(const unsigned int fee, const unsigned int index, const int l) const
676 {
677 
678  unsigned short crc = 0xffff;
679 
680  for ( int i = 0; i < l; i++)
681  {
682  unsigned short x = fee_data[fee][index+i];
683  // cout << "in crc " << hex << x << dec << endl;
684  crc ^= reverseBits( x);
685  for (unsigned short k = 0; k < 16; k++)
686  {
687  crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
688  }
689  }
690  crc = reverseBits(crc);
691  return crc;
692 }
693 
694 
695