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_)
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;
153 std::function<data_t()> generator;
156 switch (distribution_type_)
161 return static_cast<data_t>
162 ((*uniform_distn_)(engine_));
171 gen_seed =
static_cast<data_t>(std::round((*gaussian_distn_)(engine_)));
172 }
while (gen_seed > maxADCvalue_);
181 if (++gen_seed > maxADCvalue_) gen_seed = 0;
188 case DistributionType::uninit2:
192 throw cet::exception(
"HardwareInterface") <<
193 "Unknown distribution type specified";
198 std::generate_n(reinterpret_cast<data_t*>(reinterpret_cast<demo::ToyFragment::Header*>(buffer) + 1),
206 throw cet::exception(
"ToyHardwareInterface") <<
207 "Attempt to call FillBuffer when not sending data";
210 if (send_calls_ == 0)
211 { start_time_ = std::chrono::steady_clock::now();
212 TRACE( 50,
"ToyHardwareInterface::FillBuffer has set the start_time_" );
215 if (usecs_between_sends_ != 0)
218 if (send_calls_ != 0)
221 #pragma GCC diagnostic push
222 #pragma GCC diagnostic ignored "-Wsign-compare"
224 auto usecs_since_start = artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time_);
225 long delta = (long)(usecs_between_sends_ * send_calls_) - usecs_since_start;
229 TLOG_ARB(15,
"ToyHardwareInterface") <<
"FillBuffer send_calls=" << std::to_string(send_calls_) <<
" usecs_since_start=" << std::to_string(usecs_since_start) <<
" delta=" << std::to_string(delta) << TLOG_ENDL;
231 #pragma GCC diagnostic pop
239 *buffer =
reinterpret_cast<char*
>(
new uint8_t[
sizeof(demo::ToyFragment::Header) + maxADCcounts_ *
sizeof(
data_t)]);
253 return static_cast<int>(fragment_type_) + 1000;
258 switch (fragment_type_)
260 case demo::FragmentType::TOY1:
263 case demo::FragmentType::TOY2:
267 throw cet::exception(
"ToyHardwareInterface")
268 <<
"Unknown board type "
271 << demo::fragmentTypeToString(fragment_type_)
279 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.