1 #include "artdaq-demo/Generators/ToyHardwareInterface/ToyHardwareInterface.hh"
2 #include "artdaq/DAQdata/Globals.hh"
3 #include "artdaq-core-demo/Overlays/ToyFragment.hh"
4 #include "artdaq-core-demo/Overlays/FragmentType.hh"
6 #include "fhiclcpp/ParameterSet.h"
7 #include "cetlib/exception.h"
23 , nADCcounts_(ps.get<size_t>(
"nADCcounts", 40))
24 , maxADCcounts_(ps.get<size_t>(
"maxADCcounts", 50000000))
25 , change_after_N_seconds_(ps.get<size_t>(
"change_after_N_seconds",
26 std::numeric_limits<size_t>::max()))
27 , nADCcounts_after_N_seconds_(ps.get<int>(
"nADCcounts_after_N_seconds",
29 , exception_after_N_seconds_(ps.get<bool>(
"exception_after_N_seconds",
31 , exit_after_N_seconds_(ps.get<bool>(
"exit_after_N_seconds",
33 , abort_after_N_seconds_(ps.get<bool>(
"abort_after_N_seconds",
35 , fragment_type_(demo::toFragmentType(ps.get<std::string>(
"fragment_type")))
36 , maxADCvalue_(pow(2, NumADCBits()) - 1)
38 throttle_usecs_(ps.get<size_t>(
"throttle_usecs", 100000))
39 , usecs_between_sends_(ps.get<size_t>(
"usecs_between_sends", 0))
40 , distribution_type_(static_cast<
DistributionType>(ps.get<int>(
"distribution_type")))
41 , engine_(ps.get<int64_t>(
"random_seed", 314159))
42 , uniform_distn_(new std::uniform_int_distribution<
data_t>(0, maxADCvalue_))
43 , gaussian_distn_(new std::normal_distribution<double>(0.5 * maxADCvalue_, 0.1 * maxADCvalue_))
44 , start_time_(fake_time_)
46 , serial_number_((*uniform_distn_)(engine_))
48 #pragma GCC diagnostic push
49 #pragma GCC diagnostic ignored "-Wsign-compare"
57 if (nADCcounts_ > maxADCcounts_ ||
58 (nADCcounts_after_N_seconds_ >= 0 && nADCcounts_after_N_seconds_ > maxADCcounts_))
60 throw cet::exception(
"HardwareInterface") <<
"Either (or both) of \"nADCcounts\" and \"nADCcounts_after_N_seconds\"" <<
61 " is larger than the \"maxADCcounts\" setting (currently at " << maxADCcounts_ <<
")";
64 bool planned_disruption = nADCcounts_after_N_seconds_ != nADCcounts_ ||
65 exception_after_N_seconds_ ||
66 exit_after_N_seconds_ ||
67 abort_after_N_seconds_;
69 if (planned_disruption &&
70 change_after_N_seconds_ == std::numeric_limits<size_t>::max())
72 throw cet::exception(
"HardwareInterface") <<
"A FHiCL parameter designed to create a disruption has been set, so \"change_after_N_seconds\" should be set as well";
73 #pragma GCC diagnostic pop
92 start_time_ = fake_time_;
100 usleep(throttle_usecs_);
102 auto elapsed_secs_since_datataking_start =
103 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now()
104 - start_time_).count();
106 #pragma GCC diagnostic push
107 #pragma GCC diagnostic ignored "-Wsign-compare"
108 if (elapsed_secs_since_datataking_start < change_after_N_seconds_)
110 #pragma GCC diagnostic pop
112 *bytes_read =
sizeof(demo::ToyFragment::Header) + nADCcounts_ *
sizeof(
data_t);
116 if (abort_after_N_seconds_)
120 else if (exit_after_N_seconds_)
124 else if (exception_after_N_seconds_)
126 throw cet::exception(
"HardwareInterface") <<
"This is an engineered exception designed for testing purposes";
128 else if (nADCcounts_after_N_seconds_ >= 0)
130 *bytes_read =
sizeof(demo::ToyFragment::Header) + nADCcounts_after_N_seconds_ *
sizeof(
data_t);
144 assert(*bytes_read %
sizeof(demo::ToyFragment::Header::data_t) == 0);
146 demo::ToyFragment::Header* header =
reinterpret_cast<demo::ToyFragment::Header*
>(buffer);
148 header->event_size = *bytes_read /
sizeof(demo::ToyFragment::Header::data_t);
149 header->trigger_number = 99;
154 std::function<data_t()> generator;
157 switch (distribution_type_)
162 return static_cast<data_t>
163 ((*uniform_distn_)(engine_));
172 gen_seed =
static_cast<data_t>(std::round((*gaussian_distn_)(engine_)));
173 }
while (gen_seed > maxADCvalue_);
182 if (++gen_seed > maxADCvalue_) gen_seed = 0;
189 case DistributionType::uninit2:
193 throw cet::exception(
"HardwareInterface") <<
194 "Unknown distribution type specified";
199 std::generate_n(reinterpret_cast<data_t*>(reinterpret_cast<demo::ToyFragment::Header*>(buffer) + 1),
207 throw cet::exception(
"ToyHardwareInterface") <<
208 "Attempt to call FillBuffer when not sending data";
211 if (usecs_between_sends_ != 0)
213 if (send_calls_ == 0)
214 { start_time_ = std::chrono::high_resolution_clock::now();
215 TRACE( 50,
"ToyHardwareInterface::FillBuffer has set the start_time_" );
220 #pragma GCC diagnostic push
221 #pragma GCC diagnostic ignored "-Wsign-compare"
223 auto usecs_since_start =
224 std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()
225 - start_time_).count();
226 long delta = (long)(usecs_between_sends_ * send_calls_) - usecs_since_start;
230 TRACE(15,
"ToyHardwareInterface::FillBuffer send_calls=%d usecs_since_start=%ld delta=%ld"
231 , send_calls_, usecs_since_start, delta);
233 #pragma GCC diagnostic pop
241 *buffer =
reinterpret_cast<char*
>(
new uint8_t[
sizeof(demo::ToyFragment::Header) + maxADCcounts_ *
sizeof(
data_t)]);
255 return static_cast<int>(fragment_type_) + 1000;
260 switch (fragment_type_)
262 case demo::FragmentType::TOY1:
265 case demo::FragmentType::TOY2:
269 throw cet::exception(
"ToyHardwareInterface")
270 <<
"Unknown board type "
273 << demo::fragmentTypeToString(fragment_type_)
281 return serial_number_;
int NumADCBits() const
Get the number of ADC bits used in generating data.
void StartDatataking()
"StartDatataking" is meant to mimic actions one would take when telling the hardware to start sending...
uint16_t data_t
The type used to represent ADC counts (which are 12 or 14 bits, for TOY1 or TOY2) ...
void StopDatataking()
Performs shutdown actions.
void FillBuffer(char *buffer, size_t *bytes_read)
Use configured generator to fill a buffer with data.
DistributionType
Allow for the selection of output distribution.
void FreeReadoutBuffer(char *buffer)
Release the given buffer to the hardware.
A monotonically-increasing distribution.
ToyHardwareInterface(fhicl::ParameterSet const &ps)
Construct and configure ToyHardwareInterface.
A use-after-free expliot distribution.
void AllocateReadoutBuffer(char **buffer)
Request a buffer from the hardware.
int SerialNumber() const
Gets the serial number of the simulated hardware.
int BoardType() const
Return the "board type" of the simulated hardware.