DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
EmulationUnit.hxx
Go to the documentation of this file.
1/* @file EmulationUnit.hxx
2 *
3 * This is part of the DUNE DAQ Application Framework, copyright 2023.
4 * Licensing/copyright details are in the COPYING file that you should have
5 * received with this code.
6 */
7
8#ifndef TRGTOOLS_EMULATIONUNIT_HXX_
9#define TRGTOOLS_EMULATIONUNIT_HXX_
10
12
13namespace dunedaq {
14namespace trgtools {
15
16template<typename T, typename U, typename V>
17std::unique_ptr<daqdataformats::Fragment>
18EmulationUnit<T, U, V>::emulate_vector(const std::vector<T>& inputs)
19{
20 // Create the output.
21 std::vector<U> output_buffer;
22 std::vector<U> temp_buffer;
23
24 // Create the output tp variables
25 std::vector<uint64_t> time_diffs;
26 // TODO: Figure out a way of saving channelid if TPs. TCs don't have it
27 std::vector<uint64_t> tp_adc_integral;
28 std::vector<uint64_t> tp_time_start;
29 std::vector<int> is_last_tp_in_ta;
30 // Only pre-allocate memory if we're actually saving the latencies
31 if (!m_timing_file_name.empty()) {
32 time_diffs.reserve(inputs.size());
33 tp_adc_integral.reserve(inputs.size());
34 tp_time_start.reserve(inputs.size());
35 is_last_tp_in_ta.reserve(inputs.size());
36 }
37
38 for (const T& input : inputs) {
39 size_t output_buffer_size = output_buffer.size();
40 uint64_t time_diff = emulate(input, temp_buffer);
41 if (temp_buffer.size() != 0) {
42 output_buffer.insert(output_buffer.end(), temp_buffer.begin(), temp_buffer.end());
43 temp_buffer.clear();
44 }
45 // 1 if it's the TP that creates a TA, 0 otherwise
46 int last_tp_in_ta = (output_buffer_size == output_buffer.size()) ? 0 : 1;
47
48 // Don't save any times if we're not saving latencies
49 if (m_timing_file_name.empty())
50 continue;
51 time_diffs.push_back(time_diff);
52
53 // Don't save time_start, number of TPs etc. unless it's TA latencies per TP
54 if (!std::is_same<T, dunedaq::trgdataformats::TriggerPrimitive>::value)
55 continue;
56
57 tp_time_start.push_back(input.time_start);
58 tp_adc_integral.push_back(input.adc_integral);
59 is_last_tp_in_ta.push_back(last_tp_in_ta);
60 }
61
62 // Write the timings for each new TP in this fragment.
63 if (!m_timing_file_name.empty()) {
64 std::fstream timings;
65 timings.open(m_timing_file_name, std::ios::out | std::ios::app);
66 for (size_t i = 0; i < time_diffs.size(); i++) {
67 if (std::is_same<T, dunedaq::trgdataformats::TriggerPrimitive>::value) {
68 timings << tp_time_start[i] << "," << tp_adc_integral[i] << "," << time_diffs[i] << "," << is_last_tp_in_ta[i]
69 << "\n";
70 } else {
71 timings << time_diffs[i] << "\n";
72 }
73 }
74 timings.close();
75 }
76
77 // Get the size to save on.
78 size_t payload_size(0);
79 for (const U& output : output_buffer) {
80 payload_size += triggeralgs::get_overlay_nbytes(output);
81 }
82
83 // Don't save empty fragments.
84 // The incomplete TX contents will get pushed onto the next fragment.
85 if (payload_size == 0)
86 return nullptr;
87
88 // Awkward type conversion to avoid compiler complaints on void* arithmetic.
89 char* payload = static_cast<char*>(malloc(payload_size));
90 size_t payload_offset(0);
91 for (const U& output : output_buffer) {
92 triggeralgs::write_overlay(output, static_cast<void*>(payload + payload_offset));
93 payload_offset += triggeralgs::get_overlay_nbytes(output);
94 }
95
96 // Hand it to a fragment,
97 std::unique_ptr<daqdataformats::Fragment> frag =
98 std::make_unique<daqdataformats::Fragment>(static_cast<void*>(payload), payload_size);
99 // And release it.
100 free(static_cast<void*>(payload));
101
102 m_last_output_buffer = output_buffer;
103 return frag;
104}
105
106template<typename T, typename U, typename V>
107uint64_t
108EmulationUnit<T, U, V>::emulate(const T& input, std::vector<U>& outputs)
109{
110 auto time_start = std::chrono::steady_clock::now();
111 (*m_maker)(input, outputs); // Feed TX into the TXMaker
112 auto time_end = std::chrono::steady_clock::now();
113
114 uint64_t time_diff = std::chrono::nanoseconds(time_end - time_start).count();
115 return time_diff;
116}
117
118template<typename T, typename U, typename V>
119std::vector<U>
124
125} // namespace trgtools
126} // namespace dunedaq
127
128#endif // TRGTOOLS_EMULATIONUNIT_HXX_
std::unique_ptr< daqdataformats::Fragment > emulate_vector(const std::vector< input_t > &inputs)
std::vector< output_t > get_last_output_buffer()
std::vector< output_t > m_last_output_buffer
The DUNE-DAQ namespace.
void write_overlay(const Object &object, void *buffer)
size_t get_overlay_nbytes(const Object &object)