1 #include "artdaq-demo/Generators/ToyHardwareInterface/ToyHardwareInterface.hh"
2 #define TRACE_NAME "ToyHardwareInterface"
3 #include "artdaq/DAQdata/Globals.hh"
4 #include "artdaq-core-demo/Overlays/ToyFragment.hh"
5 #include "artdaq-core-demo/Overlays/FragmentType.hh"
7 #include "fhiclcpp/ParameterSet.h"
8 #include "cetlib_except/exception.h"
24 , nADCcounts_(ps.get<size_t>(
"nADCcounts", 40))
25 , maxADCcounts_(ps.get<size_t>(
"maxADCcounts", 50000000))
26 , change_after_N_seconds_(ps.get<size_t>(
"change_after_N_seconds",
27 std::numeric_limits<size_t>::max()))
28 , nADCcounts_after_N_seconds_(ps.get<int>(
"nADCcounts_after_N_seconds",
30 , exception_after_N_seconds_(ps.get<bool>(
"exception_after_N_seconds",
32 , exit_after_N_seconds_(ps.get<bool>(
"exit_after_N_seconds",
34 , abort_after_N_seconds_(ps.get<bool>(
"abort_after_N_seconds",
36 , fragment_type_(demo::toFragmentType(ps.get<std::string>(
"fragment_type")))
37 , maxADCvalue_(pow(2, NumADCBits()) - 1)
39 throttle_usecs_(ps.get<size_t>(
"throttle_usecs", 100000))
40 , usecs_between_sends_(ps.get<size_t>(
"usecs_between_sends", 0))
41 , distribution_type_(static_cast<
DistributionType>(ps.get<int>(
"distribution_type")))
42 , engine_(ps.get<int64_t>(
"random_seed", 314159))
43 , uniform_distn_(new std::uniform_int_distribution<
data_t>(0, maxADCvalue_))
44 , gaussian_distn_(new std::normal_distribution<double>(0.5 * maxADCvalue_, 0.1 * maxADCvalue_))
45 , start_time_(fake_time_)
47 , serial_number_((*uniform_distn_)(engine_))
49 #pragma GCC diagnostic push
50 #pragma GCC diagnostic ignored "-Wsign-compare"
58 if (nADCcounts_ > maxADCcounts_ ||
59 (nADCcounts_after_N_seconds_ >= 0 && nADCcounts_after_N_seconds_ > maxADCcounts_))
61 throw cet::exception(
"HardwareInterface") <<
"Either (or both) of \"nADCcounts\" and \"nADCcounts_after_N_seconds\"" <<
62 " is larger than the \"maxADCcounts\" setting (currently at " << maxADCcounts_ <<
")";
65 bool planned_disruption = nADCcounts_after_N_seconds_ != nADCcounts_ ||
66 exception_after_N_seconds_ ||
67 exit_after_N_seconds_ ||
68 abort_after_N_seconds_;
70 if (planned_disruption &&
71 change_after_N_seconds_ == std::numeric_limits<size_t>::max())
73 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";
74 #pragma GCC diagnostic pop
93 start_time_ = fake_time_;
101 usleep(throttle_usecs_);
103 auto elapsed_secs_since_datataking_start = artdaq::TimeUtils::GetElapsedTime(start_time_);
105 #pragma GCC diagnostic push
106 #pragma GCC diagnostic ignored "-Wsign-compare"
107 if (elapsed_secs_since_datataking_start < change_after_N_seconds_ || send_calls_ == 0)
109 #pragma GCC diagnostic pop
111 *bytes_read =
sizeof(demo::ToyFragment::Header) + nADCcounts_ *
sizeof(
data_t);
115 if (abort_after_N_seconds_)
119 else if (exit_after_N_seconds_)
123 else if (exception_after_N_seconds_)
125 throw cet::exception(
"HardwareInterface") <<
"This is an engineered exception designed for testing purposes";
127 else if (nADCcounts_after_N_seconds_ >= 0)
129 *bytes_read =
sizeof(demo::ToyFragment::Header) + nADCcounts_after_N_seconds_ *
sizeof(
data_t);
143 assert(*bytes_read %
sizeof(demo::ToyFragment::Header::data_t) == 0);
145 demo::ToyFragment::Header* header =
reinterpret_cast<demo::ToyFragment::Header*
>(buffer);
147 header->event_size = *bytes_read /
sizeof(demo::ToyFragment::Header::data_t);
148 header->trigger_number = 99;
149 header->distribution_type =
static_cast<uint8_t
>(distribution_type_);
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 (send_calls_ == 0)
212 { start_time_ = std::chrono::steady_clock::now();
213 TLOG(50) <<
"FillBuffer has set the start_time_";
216 if (usecs_between_sends_ != 0)
219 if (send_calls_ != 0)
222 #pragma GCC diagnostic push
223 #pragma GCC diagnostic ignored "-Wsign-compare"
225 auto usecs_since_start = artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time_);
226 long delta = (long)(usecs_between_sends_ * send_calls_) - usecs_since_start;
230 TLOG(15) <<
"FillBuffer send_calls=" << send_calls_ <<
" usecs_since_start=" << usecs_since_start <<
" delta=" << delta ;
232 #pragma GCC diagnostic pop
240 *buffer =
reinterpret_cast<char*
>(
new uint8_t[
sizeof(demo::ToyFragment::Header) + maxADCcounts_ *
sizeof(
data_t)]);
254 return static_cast<int>(fragment_type_) + 1000;
259 switch (fragment_type_)
261 case demo::FragmentType::TOY1:
264 case demo::FragmentType::TOY2:
268 throw cet::exception(
"ToyHardwareInterface")
269 <<
"Unknown board type "
272 << demo::fragmentTypeToString(fragment_type_)
280 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.