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