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