5 #include "artdaq-demo/Generators/ToySimulator.hh"
6 #include "artdaq/DAQdata/Globals.hh"
8 #include "cetlib_except/exception.h"
9 #include "fhiclcpp/ParameterSet.h"
11 #include "artdaq-core-demo/Overlays/FragmentType.hh"
12 #include "artdaq-core-demo/Overlays/ToyFragment.hh"
13 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
14 #include "artdaq/Generators/GeneratorMacros.hh"
16 #define TRACE_NAME "ToySimulator"
17 #include "TRACE/tracemf.h"
26 : CommandableFragmentGenerator(ps)
29 , starting_timestamp_(0)
30 , timestampScale_(ps.get<int>(
"timestamp_scale_factor", 1))
31 , sequence_id_scale_(ps.get<size_t>(
"sequence_scale_factor", 1))
32 , initial_sequence_id_(ps.get<size_t>(
"initial_sequence_id", 1))
33 , rollover_subrun_interval_(ps.get<int>(
"rollover_subrun_interval", 0))
34 , metadata_({0, 0, 0})
35 , readout_buffer_(
nullptr)
36 , fragment_type_(
static_cast<decltype(fragment_type_)
>(artdaq::Fragment::InvalidFragmentType))
37 , distribution_type_(static_cast<ToyHardwareInterface::DistributionType>(ps.get<
int>(
"distribution_type")))
38 , fragment_group_size_(ps.get<
int>(
"fragment_group_size", 1))
39 , fragment_group_timeout_(ps.get<
int>(
"fragment_group_timeout_us", 1000000))
40 , exception_on_config_(ps.get<
bool>(
"exception_on_config",
false))
41 , dies_on_config_(ps.get<
bool>(
"dies_on_config",
false))
42 , lazy_mode_(ps.get<
bool>(
"lazy_mode",
false))
45 hardware_interface_->AllocateReadoutBuffer(&readout_buffer_);
47 auto ts = ps.get<
int>(
"starting_timestamp", 0);
48 if (ts < 0) { starting_timestamp_ = artdaq::Fragment::InvalidTimestamp; }
51 starting_timestamp_ =
static_cast<artdaq::Fragment::timestamp_t
>(ts);
53 timestamp_ = starting_timestamp_;
55 if (exception_on_config_)
57 throw cet::exception(
"ToySimulator") <<
"This is an engineered exception designed for testing purposes, set "
58 "by the exception_on_config FHiCL variable";
62 TLOG(TLVL_ERROR) <<
"This is an engineered process death, set by the dies_on_config FHiCL variable";
66 metadata_.board_serial_number = hardware_interface_->SerialNumber() & 0xFFFF;
67 metadata_.num_adc_bits = hardware_interface_->NumADCBits();
68 TLOG(TLVL_INFO) <<
"Constructor: metadata_.unused = 0x" << std::hex << metadata_.unused
69 <<
" sizeof(metadata_) = " << std::dec <<
sizeof(metadata_);
71 switch (hardware_interface_->BoardType())
74 fragment_type_ = toFragmentType(
"TOY1");
77 fragment_type_ = toFragmentType(
"TOY2");
80 throw cet::exception(
"ToySimulator") <<
"Unable to determine board type supplied by hardware";
86 bool demo::ToySimulator::getNext_(artdaq::FragmentPtrs& frags)
93 auto start = std::chrono::steady_clock::now();
106 while (frags.size() < fragment_group_size_ * fragmentIDs().size() && std::chrono::steady_clock::now() - start < fragment_group_timeout_)
125 auto requests = GetRequestBuffer();
126 if (requests ==
nullptr)
128 throw cet::exception(
"ToySimulator") <<
"Lazy mode is enabled, but the RequestBuffer is nullptr";
131 auto request = requests->GetNextRequest();
132 if (request.first == 0)
138 timestamp_ = request.second;
139 TLOG(51) <<
"Received a request for the fragment with timestamp " << timestamp_
140 <<
" and sequenceId " << request.first <<
". Proceeding to fill the fragment buffer, etc.";
142 auto requests = GetRequests();
143 auto request_iterator = requests.begin();
144 std::pair<artdaq::Fragment::sequence_id_t, artdaq::Fragment::timestamp_t> new_request(0, 0);
145 TLOG(52) <<
"Looping through " << requests.size() <<
" requests to see if there is a new one.";
146 while (request_iterator != requests.end())
148 if (lazily_handled_requests_.find(request_iterator->first) == lazily_handled_requests_.end())
150 lazily_handled_requests_.insert(request_iterator->first);
151 new_request = *request_iterator;
156 if (new_request.first == 0)
161 timestamp_ = new_request.second;
162 TLOG(51) <<
"Found a new request for the fragment with timestamp " << timestamp_
163 <<
" and sequenceId " << new_request.first <<
". Proceeding to fill the fragment buffer, etc.";
167 TLOG(TLVL_DEBUG + 3) <<
"getNext_: Calling ToyHardwareInterface::FillBuffer";
168 std::size_t bytes_read = 0;
169 hardware_interface_->FillBuffer(readout_buffer_, &bytes_read);
170 TLOG(TLVL_DEBUG + 3) <<
"getNext_: Done with FillBuffer";
180 TLOG(TLVL_DEBUG + 3) <<
"getNext_: Creating Fragments for configured Fragment IDs";
181 for (
auto&
id : fragmentIDs())
188 std::unique_ptr<artdaq::Fragment> fragptr(
189 artdaq::Fragment::FragmentBytes(bytes_read, ev_counter(),
id, fragment_type_, metadata_, timestamp_));
190 frags.emplace_back(std::move(fragptr));
192 TLOG(TLVL_DEBUG + 4) <<
"getNext_: Before memcpy";
195 memcpy(frags.back()->dataBeginBytes(), readout_buffer_, bytes_read);
200 memcpy(frags.back()->dataBeginBytes(), readout_buffer_,
sizeof(ToyFragment::Header));
203 TLOG(TLVL_DEBUG + 4) <<
"getNext_ after memcpy " << bytes_read
204 <<
" bytes and std::move dataSizeBytes()=" << frags.back()->sizeBytes()
205 <<
" metabytes=" <<
sizeof(metadata_);
208 if (metricMan !=
nullptr)
210 metricMan->sendMetric(
"Fragments Sent", ev_counter(),
"Events", 3, artdaq::MetricMode::LastPoint);
213 TLOG(TLVL_DEBUG + 3) <<
"getNext_: Checking for subrun rollover";
214 if (rollover_subrun_interval_ > 0 && ev_counter() % rollover_subrun_interval_ == 0 && fragment_id() == 0)
216 bool fragmentIdZero =
false;
217 for (
auto&
id : fragmentIDs())
221 fragmentIdZero =
true;
226 artdaq::FragmentPtr endOfSubrunFrag(
new artdaq::Fragment(static_cast<size_t>(
227 ceil(
sizeof(my_rank) / static_cast<double>(
sizeof(artdaq::Fragment::value_type))))));
228 endOfSubrunFrag->setSystemType(artdaq::Fragment::EndOfSubrunFragmentType);
230 endOfSubrunFrag->setSequenceID(ev_counter() + 1);
231 endOfSubrunFrag->setTimestamp(1 + (ev_counter() / rollover_subrun_interval_));
233 *endOfSubrunFrag->dataBegin() = my_rank;
234 frags.emplace_back(std::move(endOfSubrunFrag));
238 ev_counter_inc(sequence_id_scale_);
239 timestamp_ += timestampScale_;
241 TLOG(TLVL_DEBUG + 3) <<
"getNext_: DONE";
245 void demo::ToySimulator::start()
247 hardware_interface_->StartDatataking();
248 while (ev_counter() < initial_sequence_id_)
252 timestamp_ = starting_timestamp_;
253 lazily_handled_requests_.clear();
256 void demo::ToySimulator::stop() { hardware_interface_->StopDatataking(); }
A use-after-free expliot distribution.
ToySimulator(fhicl::ParameterSet const &ps)
ToySimulator Constructor.
JCF, Mar-17-2016: ToyHardwareInterface is meant to mimic a vendor-provided hardware API...
virtual ~ToySimulator()
Shutdown the ToySimulator.
ToySimulator is a simple type of fragment generator intended to be studied by new users of artdaq as ...