Line data Source code
1 : /**
2 : * @file generate_modules.cpp
3 : *
4 : * Implementation of TPReplayApplication's generate_modules dal method
5 : *
6 : * This is part of the DUNE DAQ Software Suite, copyright 2023.
7 : * Licensing/copyright details are in the COPYING file that you should have
8 : * received with this code.
9 : */
10 :
11 : #include "ConfigObjectFactory.hpp"
12 :
13 : #include "conffwk/Configuration.hpp"
14 :
15 : #include "confmodel/Connection.hpp"
16 : #include "confmodel/NetworkConnection.hpp"
17 : #include "confmodel/Service.hpp"
18 :
19 : #include "appmodel/DataHandlerConf.hpp"
20 : #include "appmodel/DataHandlerModule.hpp"
21 : #include "appmodel/DataReaderConf.hpp"
22 : #include "appmodel/DataSubscriberModule.hpp"
23 : #include "appmodel/NetworkConnectionDescriptor.hpp"
24 : #include "appmodel/NetworkConnectionRule.hpp"
25 : #include "appmodel/QueueConnectionRule.hpp"
26 : #include "appmodel/QueueDescriptor.hpp"
27 : #include "appmodel/SourceIDConf.hpp"
28 : #include "appmodel/TCDataProcessor.hpp"
29 : #include "appmodel/TPReplayApplication.hpp"
30 : #include "appmodel/TPReplayModule.hpp"
31 : #include "appmodel/TPReplayModuleConf.hpp"
32 : #include "appmodel/TPStreamConf.hpp"
33 : #include "appmodel/TriggerApplication.hpp"
34 : #include "appmodel/appmodelIssues.hpp"
35 :
36 : #include "logging/Logging.hpp"
37 :
38 : #include <iomanip>
39 : #include <set>
40 : #include <string>
41 : #include <vector>
42 :
43 : namespace dunedaq {
44 : namespace appmodel {
45 :
46 : void
47 0 : TPReplayApplication::generate_modules(const confmodel::Session* /*session*/) const
48 : {
49 :
50 0 : std::vector<const confmodel::DaqModule*> modules;
51 :
52 0 : ConfigObjectFactory obj_fac(this);
53 :
54 : /**************************************************************
55 : * Instantiate the Trigger Primitive Maker Module module
56 : **************************************************************/
57 :
58 0 : auto tprm_conf = get_tprm_conf();
59 :
60 0 : if (!tprm_conf) {
61 0 : throw(BadConf(ERS_HERE, "No TPPM configuration in TPReplayApplication given"));
62 : }
63 :
64 0 : const std::string tprm_uid(tprm_conf->UID());
65 0 : const std::string tprm_class = tprm_conf->get_template_for();
66 0 : auto tpm_obj = obj_fac.create(tprm_class, tprm_uid);
67 0 : tpm_obj.set_obj("configuration", &(tprm_conf->config_object()));
68 :
69 : /**************************************************************
70 : * Get total planes from config
71 : **************************************************************/
72 0 : const int total_planes = tprm_conf->get_total_planes();
73 :
74 : /**************************************************************
75 : * Extract # of filtered planes
76 : **************************************************************/
77 0 : const auto plane_filtering = tprm_conf->get_filter_out_plane();
78 0 : if (plane_filtering.size() >= 3) {
79 0 : throw(BadConf(ERS_HERE,
80 0 : "TPReplayApplication: too many planes configured for filtering! At most 2 planes can be filtered!"));
81 : }
82 :
83 : /**************************************************************
84 : * Instantiate the TP Handler (TA Maker) module(s)
85 : **************************************************************/
86 0 : auto tph_conf = get_tp_handler();
87 0 : if (!tph_conf) {
88 0 : throw(BadConf(ERS_HERE, "TP handler configuration object is missing"));
89 : }
90 0 : std::string tph_class = "";
91 0 : if (tph_conf != nullptr) {
92 0 : tph_class = tph_conf->get_template_for();
93 : }
94 :
95 : // For now, have X (X=total_planes) identical config TP Handlers
96 0 : std::vector<conffwk::ConfigObject> TPHs;
97 0 : std::vector<std::string> TPHs_uids;
98 :
99 : // Source IDs
100 0 : auto tpsrc_ids = get_tp_source_ids();
101 0 : if (tpsrc_ids.size() < static_cast<size_t>(total_planes)) {
102 0 : throw(BadConf(ERS_HERE, "Not enough TP source IDs provided"));
103 : }
104 :
105 0 : const auto tph_conf_obj = tph_conf->config_object();
106 0 : for (int i = 0; i < total_planes; i++) {
107 0 : std::string tp_uid = "tphandler-tpreplay-" + std::to_string(i + 1);
108 0 : TPHs_uids.push_back(tp_uid);
109 0 : auto tph_obj = obj_fac.create(tph_class, tp_uid);
110 0 : tph_obj.set_by_val<uint32_t>("source_id", tpsrc_ids[i]->get_sid());
111 0 : tph_obj.set_by_val<uint32_t>("detector_id", 1); // 1 == kDAQ
112 0 : tph_obj.set_by_val<bool>("post_processing_enabled", true);
113 0 : tph_obj.set_obj("module_configuration", &tph_conf_obj);
114 0 : TPHs.push_back(tph_obj);
115 0 : }
116 :
117 : /**************************************************************
118 : * Deal with queues
119 : **************************************************************/
120 : // Load queue configurations
121 0 : const QueueDescriptor* tp_inputq_desc = nullptr;
122 :
123 0 : for (const auto& rule : get_queue_rules()) {
124 0 : auto destination_class = rule->get_destination_class();
125 0 : auto data_type = rule->get_descriptor()->get_data_type();
126 0 : if (destination_class == "TriggerDataHandlerModule" && data_type == "TriggerPrimitiveVector") {
127 0 : tp_inputq_desc = rule->get_descriptor();
128 : }
129 0 : }
130 0 : if (!tp_inputq_desc) {
131 0 : throw(BadConf(ERS_HERE, "No matching queue descriptor found for TP input"));
132 : }
133 :
134 : // Same as above (ROUs * planes queues), later dynamically
135 0 : std::vector<conffwk::ConfigObject> TP_queues;
136 0 : for (int i = 0; i < total_planes; i++) {
137 0 : std::string tp_q_uid = "tpinput-" + std::to_string(i + 1);
138 0 : auto tp_q_obj = obj_fac.create_queue_obj(tp_inputq_desc, tp_q_uid);
139 0 : TP_queues.push_back(tp_q_obj);
140 0 : }
141 :
142 : /**************************************************************
143 : * Deal with network connections
144 : **************************************************************/
145 0 : const NetworkConnectionDescriptor* ta_net_desc = nullptr;
146 0 : const NetworkConnectionDescriptor* dr_net_desc = nullptr;
147 :
148 0 : for (const auto& rule : get_network_rules()) {
149 0 : auto endpoint_class = rule->get_endpoint_class();
150 0 : auto data_type = rule->get_descriptor()->get_data_type();
151 0 : if (data_type == "TriggerActivity") {
152 0 : ta_net_desc = rule->get_descriptor();
153 0 : } else if (data_type == "DataRequest") {
154 0 : dr_net_desc = rule->get_descriptor();
155 : }
156 0 : }
157 0 : if (!ta_net_desc || !dr_net_desc) {
158 0 : throw(BadConf(ERS_HERE, "Missing network descriptors for TA or DR"));
159 : }
160 :
161 : // Create vectors for network connections
162 0 : std::vector<conffwk::ConfigObject> ta_net_objects;
163 0 : std::vector<conffwk::ConfigObject> dr_net_objects;
164 :
165 : // Outputs for each handler
166 0 : for (int i = 0; i < total_planes; i++) {
167 0 : const auto ta_service_obj = ta_net_desc->get_associated_service()->config_object();
168 0 : const std::string ta_stream_uid = ta_net_desc->get_uid_base() + UID() + "-" + std::to_string(i + 1);
169 0 : auto ta_net_obj = obj_fac.create_net_obj(ta_net_desc, ta_stream_uid);
170 0 : ta_net_obj.set_obj("associated_service", &ta_service_obj);
171 0 : ta_net_objects.push_back(ta_net_obj);
172 0 : }
173 :
174 : // Data requests
175 0 : for (int i = 0; i < total_planes; i++) {
176 0 : const auto dr_service_obj = dr_net_desc->get_associated_service()->config_object();
177 : // Format the integer with leading zeros to maintain consistent length
178 0 : std::ostringstream oss;
179 0 : oss << UID() << "-1000" << std::setfill('0') << std::setw(2) // Ensures at least 2 digits (e.g., 01, 10)
180 0 : << (i + 1);
181 0 : const std::string dr_stream_uid = oss.str();
182 0 : auto dr_net_obj = obj_fac.create_net_obj(dr_net_desc, dr_stream_uid);
183 0 : dr_net_obj.set_obj("associated_service", &dr_service_obj);
184 : dr_net_objects.push_back(dr_net_obj);
185 0 : }
186 :
187 : /**************************************************************
188 : * Finally set inputs & outputs
189 : **************************************************************/
190 : // Convert TP_queues to a vector of raw pointers
191 0 : std::vector<const conffwk::ConfigObject*> raw_tp_queues;
192 0 : for (const auto& tp_queue : TP_queues) {
193 0 : raw_tp_queues.push_back(&tp_queue);
194 : }
195 0 : tpm_obj.set_objs("outputs", raw_tp_queues);
196 :
197 0 : for (int i = 0; i < total_planes; i++) {
198 : // Convert network objects to raw pointers
199 0 : const std::vector<const conffwk::ConfigObject*> temp_inputs = { &TP_queues[i], &dr_net_objects[i] };
200 0 : const std::vector<const conffwk::ConfigObject*> temp_outputs = { &ta_net_objects[i] };
201 0 : TPHs[i].set_objs("inputs", temp_inputs);
202 0 : TPHs[i].set_objs("outputs", temp_outputs);
203 0 : }
204 :
205 : // Store modules
206 0 : modules.push_back(obj_fac.get_dal<confmodel::DaqModule>(tprm_conf->UID()));
207 0 : for (int i = 0; i < total_planes; i++) {
208 0 : modules.push_back(obj_fac.get_dal<confmodel::DaqModule>(TPHs_uids[i]));
209 : }
210 :
211 0 : obj_fac.update_modules(modules);
212 0 : }
213 :
214 : } // namespace appmodel
215 : } // namespace dunedaq
|