artdaq_demo  v3_00_01
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  , metadata_({0,0,0})
34  , readout_buffer_(nullptr)
35  , fragment_type_(static_cast<decltype(fragment_type_)>(artdaq::Fragment::InvalidFragmentType))
36  , distribution_type_(static_cast<ToyHardwareInterface::DistributionType>(ps.get<int>("distribution_type")))
37 {
38  hardware_interface_->AllocateReadoutBuffer(&readout_buffer_);
39 
40  metadata_.board_serial_number = hardware_interface_->SerialNumber();
41  metadata_.num_adc_bits = hardware_interface_->NumADCBits();
42  TRACE( TLVL_INFO, "ToySimulator ctor metadata_.unused=0x%zu sizeof(metadata_)=%zd"
43  , metadata_.unused, sizeof(metadata_) );
44 
45  switch (hardware_interface_->BoardType())
46  {
47  case 1002:
48  fragment_type_ = toFragmentType("TOY1");
49  break;
50  case 1003:
51  fragment_type_ = toFragmentType("TOY2");
52  break;
53  default:
54  throw cet::exception("ToySimulator") << "Unable to determine board type supplied by hardware";
55  }
56 }
57 
59 {
60  hardware_interface_->FreeReadoutBuffer(readout_buffer_);
61 }
62 
63 bool demo::ToySimulator::getNext_(artdaq::FragmentPtrs& frags)
64 {
65  if (should_stop())
66  {
67  return false;
68  }
69 
70  // ToyHardwareInterface (an instance to which "hardware_interface_"
71  // is a unique_ptr object) is just one example of the sort of
72  // interface a hardware library might offer. For example, other
73  // interfaces might require you to allocate and free the memory used
74  // to store hardware data in your generator using standard C++ tools
75  // (rather than via the "AllocateReadoutBuffer" and
76  // "FreeReadoutBuffer" functions provided here), or could have a
77  // function which directly returns a pointer to the data buffer
78  // rather than sticking the data in the location pointed to by your
79  // pointer (which is what happens here with readout_buffer_)
80 
81  std::size_t bytes_read = 0;
82  hardware_interface_->FillBuffer(readout_buffer_, &bytes_read);
83 
84  // We'll use the static factory function
85 
86  // artdaq::Fragment::FragmentBytes(std::size_t payload_size_in_bytes, sequence_id_t sequence_id,
87  // fragment_id_t fragment_id, type_t type, const T & metadata)
88 
89  // which will then return a unique_ptr to an artdaq::Fragment
90  // object.
91 
92 #if 1
93  std::unique_ptr<artdaq::Fragment> fragptr(
94  artdaq::Fragment::FragmentBytes(bytes_read,
95  ev_counter(), fragment_id(),
96  fragment_type_,
97  metadata_, timestamp_));
98  frags.emplace_back(std::move(fragptr));
99 #else
100  std::unique_ptr<artdaq::Fragment> fragptr(
101  artdaq::Fragment::FragmentBytes(/*bytes_read*/ 1024 - 40,
102  ev_counter(), fragment_id(),
103  fragment_type_,
104  metadata_, timestamp_));
105  frags.emplace_back(std::move(fragptr));
106  artdaq::detail::RawFragmentHeader *hdr = (artdaq::detail::RawFragmentHeader*)(frags.back()->headerBeginBytes());
107  // Need a way to fake frag->sizeBytes() (which calls frag->size() which calls fragmentHeader()->word_count
108  hdr->word_count = ceil((bytes_read + 32) / static_cast<double>(sizeof(artdaq::RawDataType)));
109 #endif
110 
112  memcpy(frags.back()->dataBeginBytes(), readout_buffer_, bytes_read);
113 
114  TLOG_ARB(50, "ToySimulator") << "ToySimulator::getNext_ after memcpy " << std::to_string(bytes_read)
115  << " bytes and std::move dataSizeBytes()=" << std::to_string(frags.back()->sizeBytes()) << " metabytes=" << std::to_string(sizeof(metadata_)) << TLOG_ENDL;
116 
117  if (metricMan != nullptr)
118  {
119  metricMan->sendMetric("Fragments Sent", ev_counter(), "Events", 3, artdaq::MetricMode::LastPoint);
120  }
121 
122  ev_counter_inc();
123  timestamp_ += timestampScale_;
124 
125  return true;
126 }
127 
128 void demo::ToySimulator::start()
129 {
130  hardware_interface_->StartDatataking();
131 }
132 
133 void demo::ToySimulator::stop()
134 {
135  hardware_interface_->StopDatataking();
136 }
137 
138 // The following macro is defined in artdaq's GeneratorMacros.hh header
139 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