Line data Source code
1 : #ifndef artdaq_DAQdata_GenericFragmentSimulator_hh
2 : #define artdaq_DAQdata_GenericFragmentSimulator_hh
3 :
4 : #include "TRACE/tracemf.h" // Pre-empt TRACE/trace.h from Fragment.hh.
5 : #include "artdaq-core/Data/Fragment.hh"
6 :
7 : #include "artdaq-core/Plugins/FragmentGenerator.hh"
8 :
9 : namespace fhicl {
10 : class ParameterSet;
11 : }
12 :
13 : #include "fhiclcpp/types/Atom.h"
14 : #include "fhiclcpp/types/Comment.h"
15 : #include "fhiclcpp/types/ConfigurationTable.h"
16 : #include "fhiclcpp/types/Name.h"
17 :
18 : #include <random>
19 : #include <vector>
20 :
21 : namespace artdaq {
22 : class GenericFragmentSimulator;
23 : }
24 :
25 : /**
26 : * \brief GenericFragmentSimulator creates simulated Generic events, with data
27 : * distributed according to a "histogram" provided in the configuration
28 : * data.
29 : *
30 : * With this implementation, a single call to getNext(frags) will return
31 : * a complete event (event ids are incremented automatically); fragment
32 : * ids are sequential.
33 : * Event size and content are both configurable; see the implementation for
34 : * details.
35 : */
36 : class artdaq::GenericFragmentSimulator : public artdaq::FragmentGenerator
37 : {
38 : public:
39 : /// <summary>
40 : /// Configuration of the GenericFragmentSimulator. May be used for parameter validation
41 : /// </summary>
42 : struct Config
43 : {
44 : /// "content_selection" (Default: 0) : What type of data to fill in generated Fragment payloads
45 : /// * 0 : Use uninitialized memory
46 : /// * 1 : Use the Fragment ID
47 : /// * 2 : Use random data
48 : /// * 3 : Use the word 0xDEADBEEFDEADBEEF
49 : fhicl::Atom<size_t> content_selection{fhicl::Name{"content_selection"}, fhicl::Comment{"What type of data to fill in generated Fragment payloads"}, 0};
50 : /// "payload_size" (Default: 10240) : The size(in words) of the Fragment payload
51 : fhicl::Atom<size_t> payload_size{fhicl::Name{"payload_size"}, fhicl::Comment{"The size (in words) of the Fragment payload"}, 10240};
52 : /// "want_random_payload_size" (Default: false) : Whether payload size should be sampled from a random distribution
53 : fhicl::Atom<bool> want_random_payload_size{fhicl::Name{"want_random_payload_size"}, fhicl::Comment{"Whether payload size should be sampled from a random distribution"}, false};
54 : /// "random_seed" (Default: 314159) : Random seed for random number distributions
55 : fhicl::Atom<int64_t> random_seed{fhicl::Name{"random_seed"}, fhicl::Comment{"Random seed for random number distributions"}, 314159};
56 : /// "fragments_per_event" (Default: 5) : The number of Fragment objects to generate for each sequence ID
57 : fhicl::Atom<size_t> fragments_per_event{fhicl::Name{"fragments_per_event"}, fhicl::Comment{"The number of Fragment objects to generate for each sequence ID"}, 5};
58 : /// "starting_fragment_id" (Default: 0) : The first Fragment ID handled by this GenericFragmentSimulator.
59 : /// * Fragment IDs will be starting_fragment_id to starting_fragment_id + fragments_per_event.
60 : fhicl::Atom<Fragment::fragment_id_t> starting_fragment_id{fhicl::Name{"starting_fragment_id"}, fhicl::Comment{"The first Fragment ID handled by this GenericFragmentSimulator."}, 0};
61 : };
62 : /// Used for ParameterSet validation (if desired)
63 : using Parameters = fhicl::WrappedTable<Config>;
64 :
65 : /**
66 : * \brief GenericFragmentSimulator Constructor
67 : * \param ps ParameterSet used to configure the GenericFragmentSimulator. See artdaq::GenericFragmentSimulator::Config
68 : */
69 : explicit GenericFragmentSimulator(fhicl::ParameterSet const& ps);
70 :
71 : /**
72 : * \brief What type of content should the GenericFragmentSimulator put in Fragment objects?
73 : */
74 : enum class content_selector_t : uint8_t
75 : {
76 : EMPTY = 0, ///< Nothing (Default-initialized Fragment)
77 : FRAG_ID = 1, ///< Fill the payload with the Fragment ID
78 : RANDOM = 2, ///< Use a random distribution to fill the payload
79 : DEAD_BEEF ///< Fill the payload with 0xDEADBEEFDEADBEEF
80 : };
81 :
82 : // Not part of virtual interface: generate a specific fragment.
83 : using FragmentGenerator::getNext;
84 :
85 : /**
86 : * \brief Generate a Fragment according to the value of the content_selectior_t enum
87 : * \param sequence_id Sequence ID of generated Fragment
88 : * \param fragment_id Fragment ID of generated Fragment
89 : * \param[out] frag_ptr Generated Fragment
90 : * \return True if no exception or assertion failure
91 : */
92 : bool getNext(Fragment::sequence_id_t sequence_id,
93 : Fragment::fragment_id_t fragment_id,
94 : FragmentPtr& frag_ptr);
95 :
96 : /**
97 : * \brief Get the next Fragment from the generator
98 : * \param[out] output List of FragmentPtr objects to add the new Fragment to
99 : * \return Whether data taking should continue
100 : */
101 410 : bool getNext(FragmentPtrs& output) override
102 : {
103 410 : return getNext_(output);
104 : }
105 :
106 : /**
107 : * \brief Get the Fragment IDs generated by this instance
108 : * \return The Fragment IDs generated by this instance
109 : */
110 2 : std::vector<Fragment::fragment_id_t> fragmentIDs() override
111 : {
112 2 : return fragmentIDs_();
113 : }
114 :
115 : private:
116 : bool getNext_(FragmentPtrs& frags);
117 :
118 : std::vector<Fragment::fragment_id_t> fragmentIDs_();
119 :
120 : std::size_t generateFragmentSize_();
121 :
122 : // Configuration
123 : content_selector_t const content_selection_;
124 : std::size_t const payload_size_spec_; // Poisson mean if random size wanted.
125 : std::vector<Fragment::fragment_id_t> fragment_ids_;
126 :
127 : bool const want_random_payload_size_;
128 :
129 : // State
130 : std::size_t current_event_num_;
131 : std::mt19937 engine_;
132 : std::poisson_distribution<size_t> payload_size_generator_;
133 : std::uniform_int_distribution<uint64_t> fragment_content_generator_;
134 : };
135 :
136 : #endif /* artdaq_DAQdata_GenericFragmentSimulator_hh */
|