mu2e_artdaq_core  v1_02_01a
 All Classes Functions
mu2eFragment.hh
1 #ifndef mu2e_artdaq_core_Overlays_mu2eFragment_hh
2 #define mu2e_artdaq_core_Overlays_mu2eFragment_hh
3 
4 #include "artdaq-core/Data/Fragment.hh"
5 #include "cetlib/exception.h"
6 
7 #include "trace.h"
8 
9 #include <ostream>
10 #include <vector>
11 
12 // Implementation of "mu2eFragment", an artdaq::Fragment overlay class
13 
14 // The "packing factor": How many DataBlocks are stored in each mu2eFragment
15 #define DATA_BLOCKS_PER_MU2E_FRAGMENT 2500
16 
17 namespace mu2e {
18  class mu2eFragment;
19 
20  static const int BLOCK_COUNT_MAX = DATA_BLOCKS_PER_MU2E_FRAGMENT;
21 
22  // Let the "<<" operator dump the mu2eFragment's data to stdout
23  std::ostream & operator << (std::ostream &, mu2eFragment const &);
24 }
25 
27 public:
28 
29  // The mu2eFragment represents its data through the adc_t type, which
30  // is a typedef of an 16-member uint8_t array.
31 
32  //typedef uint8_t packet_t[16];
33 
34  // The "Metadata" struct is used to store info primarily related to
35  // the upstream hardware environment from where the fragment came
36 
37  // "data_t" is a typedef of the fundamental unit of data the
38  // metadata structure thinks of itself as consisting of; it can give
39  // its size via the static "size_words" variable (
40  // mu2eFragment::Metadata::size_words )
41 
42  struct Metadata {
43 
44  typedef uint64_t data_t;
45 
46  data_t sim_mode : 4;
47  data_t unused : 4; // 4 + 4 = 8 bits
48 
49  data_t board_id : 8;
50  data_t unused2 : 16;
51 
52  data_t run_number : 32;
53 
54  static size_t const size_words = 1ul; // Units of Metadata::data_t
55  };
56 
57  static_assert (sizeof (Metadata) == Metadata::size_words * sizeof (Metadata::data_t), "mu2eFragment::Metadata size changed");
58 
59 
60  // The "Header" struct contains "metadata" specific to the fragment
61  // which is not hardware-related
62 
63  // Header::data_t -- not to be confused with Metadata::data_t ! --
64  // describes the standard size of a data type not just for the
65  // header data, but ALSO the physics data beyond it; the size of the
66  // header in units of Header::data_t is given by "size_words", and
67  // the size of the fragment beyond the header in units of
68  // Header::data_t is given by "event_size"
69 
70  struct Header {
71  typedef uint64_t data_t;
72  typedef uint64_t count_t;
73 
74  count_t block_count : 60;
75  count_t fragment_type : 4;
76 
77  size_t index[DATA_BLOCKS_PER_MU2E_FRAGMENT];
78 
79  static size_t constexpr size_words {1ul + (DATA_BLOCKS_PER_MU2E_FRAGMENT * sizeof(size_t)) / sizeof(uint64_t)}; // Units of Header::data_t
80  };
81 
82  static_assert (sizeof (Header) == sizeof(Header::data_t) * Header::size_words, "mu2eFragment::Header: incorrect size");
83 
84  // The constructor simply sets its const private member "artdaq_Fragment_"
85  // to refer to the artdaq::Fragment object
86 
87  mu2eFragment(artdaq::Fragment const & f ) : artdaq_Fragment_(f) {}
88 
89  // const getter functions for the data in the header
90  Header::count_t hdr_block_count() const { return header_()->block_count; }
91  Header::data_t hdr_fragment_type() const { return (Header::data_t)header_()->fragment_type; }
92 
93  static constexpr size_t hdr_size_words() { return Header::size_words; }
94 
95  // Start of the DTC packets, returned as a pointer to the packet type
96  Header::data_t const * dataBegin() const {
97  return reinterpret_cast<Header::data_t const *>(header_() + 1);
98  }
99 
100  Header::data_t const * dataEnd() const {
101  return dataAt(hdr_block_count());
102  }
103 
104  Header::data_t const * dataAt(const size_t index) const {
105  if(index == 0) return dataBegin();
106  auto block = header_()->index[ index - 1] / sizeof(Header::data_t);
107  return reinterpret_cast<Header::data_t const *>(dataBegin() + block);
108  }
109 
110  size_t blockSize(const size_t index) const {
111  auto start = blockOffset(index);
112  auto end = dataEndBytes();
113  if(index < hdr_block_count() - 1) {
114  end = blockOffset(index + 1);
115  }
116  return end - start;
117  }
118 
119  size_t blockOffset(const size_t index) const {
120  if(index == 0) { return 0; }
121  return header_()->index[ index - 1 ];
122  }
123 
124  size_t dataEndBytes() const {
125  return blockOffset(hdr_block_count());
126  }
127 
128  size_t dataSize() const { return artdaq_Fragment_.dataSize() * sizeof(artdaq::Fragment::value_type) - sizeof(Header) - sizeof(Metadata); }
129 
130 protected:
131 
132  static constexpr size_t words_per_frag_word_() {
133  return sizeof(artdaq::Fragment::value_type) / sizeof(Header::data_t);
134  }
135 
136  // header_() simply takes the address of the start of this overlay's
137  // data (i.e., where the mu2eFragment::Header object begins) and
138  // casts it as a pointer to mu2eFragment::Header
139 
140  Header const * header_() const {
141  return reinterpret_cast<mu2eFragment::Header const *>(&*artdaq_Fragment_.dataBegin());
142  }
143 
144 private:
145 
146  artdaq::Fragment const & artdaq_Fragment_;
147 };
148 
149 #endif /* mu2e_artdaq_Overlays_mu2eFragment_hh */