mu2e_artdaq_core  v1_03_01
 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 // #define DATA_BLOCKS_PER_MU2E_FRAGMENT 500
15 #define DATA_BLOCKS_PER_MU2E_FRAGMENT 5
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 } // namespace mu2e
25 
27 {
28 public:
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),
58  "mu2eFragment::Metadata size changed");
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  {
72  typedef uint64_t data_t;
73  typedef uint64_t count_t;
74 
75  count_t block_count : 60;
76  count_t fragment_type : 4;
77 
78  size_t index[DATA_BLOCKS_PER_MU2E_FRAGMENT];
79 
80  static size_t constexpr size_words{1ul + (DATA_BLOCKS_PER_MU2E_FRAGMENT * sizeof(size_t)) /
81  sizeof(uint64_t)}; // Units of Header::data_t
82  };
83 
84  static_assert(sizeof(Header) == sizeof(Header::data_t) * Header::size_words, "mu2eFragment::Header: incorrect size");
85 
86  // The constructor simply sets its const private member "artdaq_Fragment_"
87  // to refer to the artdaq::Fragment object
88 
89  mu2eFragment(artdaq::Fragment const &f)
90  : artdaq_Fragment_(f) {}
91 
92  // const getter functions for the data in the header
93  Header::count_t hdr_block_count() const { return header_()->block_count; }
94  Header::data_t hdr_fragment_type() const { return (Header::data_t)header_()->fragment_type; }
95 
96  static constexpr size_t hdr_size_words() { return Header::size_words; }
97 
98  // Start of the DTC packets, returned as a pointer to the packet type
99  Header::data_t const *dataBegin() const { return reinterpret_cast<Header::data_t const *>(header_() + 1); }
100 
101  Header::data_t const *dataEnd() const { return dataAt(hdr_block_count()); }
102 
103  Header::data_t const *dataAt(const size_t index) const
104  {
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  {
112  auto start = blockOffset(index);
113  auto end = dataEndBytes();
114  if (index < hdr_block_count() - 1) {
115  end = blockOffset(index + 1);
116  }
117  return end - start;
118  }
119 
120  size_t blockOffset(const size_t index) const
121  {
122  if (index == 0) {
123  return 0;
124  }
125  return header_()->index[index - 1];
126  }
127 
128  size_t dataEndBytes() const { return blockOffset(hdr_block_count()); }
129 
130  size_t dataSize() const
131  {
132  return artdaq_Fragment_.dataSize() * sizeof(artdaq::Fragment::value_type) - sizeof(Header) - sizeof(Metadata);
133  }
134 
135 protected:
136  static constexpr size_t words_per_frag_word_()
137  {
138  return sizeof(artdaq::Fragment::value_type) / sizeof(Header::data_t);
139  }
140 
141  // header_() simply takes the address of the start of this overlay's
142  // data (i.e., where the mu2eFragment::Header object begins) and
143  // casts it as a pointer to mu2eFragment::Header
144 
145  Header const *header_() const
146  {
147  return reinterpret_cast<mu2eFragment::Header const *>(&*artdaq_Fragment_.dataBegin());
148  }
149 
150 private:
151  artdaq::Fragment const &artdaq_Fragment_;
152 };
153 
154 #endif /* mu2e_artdaq_Overlays_mu2eFragment_hh */