artdaq_demo  v3_03_02
ToySimulator_generator.cc
1 // For an explanation of this class, look at its header,
2 // ToySimulator.hh, as well as
3 // https://cdcvs.fnal.gov/redmine/projects/artdaq-demo/wiki/Fragments_and_FragmentGenerators_w_Toy_Fragments_as_Examples
4 
5 #include "artdaq-demo/Generators/ToySimulator.hh"
6 
7 #include "canvas/Utilities/Exception.h"
8 
9 #include "artdaq/Application/GeneratorMacros.hh"
10 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
11 
12 #include "artdaq-core-demo/Overlays/ToyFragment.hh"
13 #include "artdaq-core-demo/Overlays/FragmentType.hh"
14 
15 #include "fhiclcpp/ParameterSet.h"
16 
17 #include <fstream>
18 #include <iomanip>
19 #include <iterator>
20 #include <iostream>
21 
22 #include <unistd.h>
23 #define TRACE_NAME "ToySimulator"
24 #include "tracemf.h" // TRACE, TLOG*
25 #include "cetlib_except/exception.h"
26 
27 demo::ToySimulator::ToySimulator(fhicl::ParameterSet const& ps)
28  :
29  CommandableFragmentGenerator(ps)
30  , hardware_interface_(new ToyHardwareInterface(ps))
31  , timestamp_(0)
32  , timestampScale_(ps.get<int>("timestamp_scale_factor", 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  , generated_fragments_per_event_(ps.get<int>("generated_fragments_per_event", 1))
39 {
40  hardware_interface_->AllocateReadoutBuffer(&readout_buffer_);
41 
42  metadata_.board_serial_number = hardware_interface_->SerialNumber() & 0xFFFF;
43  metadata_.num_adc_bits = hardware_interface_->NumADCBits();
44  TLOG(TLVL_INFO) << "Constructor: metadata_.unused = 0x" << std::hex << metadata_.unused << " sizeof(metadata_) = " << std::dec << sizeof(metadata_);
45 
46  switch (hardware_interface_->BoardType())
47  {
48  case 1002:
49  fragment_type_ = toFragmentType("TOY1");
50  break;
51  case 1003:
52  fragment_type_ = toFragmentType("TOY2");
53  break;
54  default:
55  throw cet::exception("ToySimulator") << "Unable to determine board type supplied by hardware";
56  }
57 }
58 
60 {
61  hardware_interface_->FreeReadoutBuffer(readout_buffer_);
62 }
63 
64 bool demo::ToySimulator::getNext_(artdaq::FragmentPtrs& frags)
65 {
66  if (should_stop())
67  {
68  return false;
69  }
70 
71  // ToyHardwareInterface (an instance to which "hardware_interface_"
72  // is a unique_ptr object) is just one example of the sort of
73  // interface a hardware library might offer. For example, other
74  // interfaces might require you to allocate and free the memory used
75  // to store hardware data in your generator using standard C++ tools
76  // (rather than via the "AllocateReadoutBuffer" and
77  // "FreeReadoutBuffer" functions provided here), or could have a
78  // function which directly returns a pointer to the data buffer
79  // rather than sticking the data in the location pointed to by your
80  // pointer (which is what happens here with readout_buffer_)
81 
82  std::size_t bytes_read = 0;
83  hardware_interface_->FillBuffer(readout_buffer_, &bytes_read);
84 
85  // We'll use the static factory function
86 
87  // artdaq::Fragment::FragmentBytes(std::size_t payload_size_in_bytes, sequence_id_t sequence_id,
88  // fragment_id_t fragment_id, type_t type, const T & metadata)
89 
90  // which will then return a unique_ptr to an artdaq::Fragment
91  // object.
92 
93 #if 1
94  for (auto i_f = 0; i_f < generated_fragments_per_event_; ++i_f) {
95 
96  // The offset logic below is designed to both ensure
97  // backwards compatibility and to (help) avoid collisions
98  // with fragment_ids from other boardreaders if more than
99  // one fragment is generated per event
100 
101  auto offset = i_f == 0 ? 0 : i_f + 10000;
102  std::unique_ptr<artdaq::Fragment> fragptr(
103  artdaq::Fragment::FragmentBytes(bytes_read,
104  ev_counter(),
105  fragment_id() + offset,
106  fragment_type_,
107  metadata_, timestamp_));
108  frags.emplace_back(std::move(fragptr));
109  }
110 #else
111  std::unique_ptr<artdaq::Fragment> fragptr(
112  artdaq::Fragment::FragmentBytes(/*bytes_read*/ 1024 - 40,
113  ev_counter(), fragment_id(),
114  fragment_type_,
115  metadata_, timestamp_));
116  frags.emplace_back(std::move(fragptr));
117  artdaq::detail::RawFragmentHeader *hdr = (artdaq::detail::RawFragmentHeader*)(frags.back()->headerBeginBytes());
118  // Need a way to fake frag->sizeBytes() (which calls frag->size() which calls fragmentHeader()->word_count
119  hdr->word_count = ceil((bytes_read + 32) / static_cast<double>(sizeof(artdaq::RawDataType)));
120 #endif
121 
122  if ( !frags.empty() ) {
123 
125  memcpy(frags.back()->dataBeginBytes(), readout_buffer_, bytes_read);
126  else
127  {
128  // Must preserve the Header!
129  memcpy(frags.back()->dataBeginBytes(), readout_buffer_, sizeof(ToyFragment::Header));
130  }
131 
132  TLOG(50) << "getNext_ after memcpy " << bytes_read
133  << " bytes and std::move dataSizeBytes()=" << frags.back()->sizeBytes() << " metabytes=" << sizeof(metadata_);
134  }
135 
136  if (metricMan != nullptr)
137  {
138  metricMan->sendMetric("Fragments Sent", ev_counter(), "Events", 3, artdaq::MetricMode::LastPoint);
139  }
140 
141  ev_counter_inc();
142  timestamp_ += timestampScale_;
143 
144  if (rollover_subrun_interval_ > 0 && ev_counter() % rollover_subrun_interval_ == 0 && fragment_id() == 0)
145  {
146  artdaq::FragmentPtr endOfSubrunFrag(new artdaq::Fragment(static_cast<size_t>(ceil(sizeof(my_rank) / static_cast<double>(sizeof(artdaq::Fragment::value_type))))));
147  endOfSubrunFrag->setSystemType(artdaq::Fragment::EndOfSubrunFragmentType);
148  endOfSubrunFrag->setSequenceID(ev_counter());
149  *endOfSubrunFrag->dataBegin() = my_rank;
150  frags.emplace_back(std::move(endOfSubrunFrag));
151  }
152 
153 
154  return true;
155 }
156 
157 void demo::ToySimulator::start()
158 {
159  hardware_interface_->StartDatataking();
160  timestamp_ = 0;
161 }
162 
163 void demo::ToySimulator::stop()
164 {
165  hardware_interface_->StopDatataking();
166 }
167 
168 // The following macro is defined in artdaq's GeneratorMacros.hh header
169 DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(demo::ToySimulator)
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 ...
Definition: ToySimulator.hh:37