Line data Source code
1 : /**
2 : * @file CTBApplication.cpp
3 : *
4 : * Implementation of CTBApplication'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 "conffwk/Configuration.hpp"
12 : #include "oks/kernel.hpp"
13 : #include "logging/Logging.hpp"
14 :
15 : #include "confmodel/DetectorToDaqConnection.hpp"
16 : #include "confmodel/DetDataSender.hpp"
17 :
18 : #include "ConfigObjectFactory.hpp"
19 : #include "appmodel/appmodelIssues.hpp"
20 : #include "appmodel/CTBApplication.hpp"
21 : #include "appmodel/CTBoardConf.hpp"
22 : #include "appmodel/CTBConf.hpp"
23 : #include "appmodel/CTBModule.hpp"
24 : #include "appmodel/CTBSockets.hpp"
25 : #include "appmodel/CTBTrigger.hpp"
26 : #include "appmodel/CTBMisc.hpp"
27 : #include "appmodel/CTBRandomTrigger.hpp"
28 : #include "appmodel/CTBPulser.hpp"
29 : #include "appmodel/CTBTiming.hpp"
30 : #include "appmodel/CTBHLT.hpp"
31 : #include "appmodel/CTBLLT.hpp"
32 : #include "appmodel/CTBCountLLT.hpp"
33 : #include "appmodel/CTBSubsystem.hpp"
34 : #include "appmodel/CTBCRTSubsystem.hpp"
35 : #include "appmodel/CTBPDSSubsystem.hpp"
36 : #include "appmodel/CTBStatisticsSocket.hpp"
37 : #include "appmodel/CTBSocket.hpp"
38 : #include "appmodel/CTBReceiverSocket.hpp"
39 : #include "appmodel/CTBMonitorSocket.hpp"
40 :
41 :
42 : #include "appmodel/DataHandlerConf.hpp"
43 : #include "appmodel/QueueConnectionRule.hpp"
44 : #include "appmodel/QueueDescriptor.hpp"
45 : #include "appmodel/NetworkConnectionDescriptor.hpp"
46 : #include "appmodel/NetworkConnectionRule.hpp"
47 : #include "appmodel/SourceIDConf.hpp"
48 : #include "appmodel/DFApplication.hpp"
49 : #include "appmodel/DataHandlerModule.hpp"
50 :
51 : #include <string>
52 : #include <vector>
53 : #include <bitset>
54 : #include <iostream>
55 : #include <fmt/core.h>
56 : #include <set>
57 :
58 : using namespace dunedaq;
59 : using namespace dunedaq::appmodel;
60 :
61 : std::vector<const confmodel::Resource*>
62 0 : CTBApplication::contained_resources() const {
63 0 : std::vector<const confmodel::Resource*> resources;
64 0 : resources.push_back(dynamic_cast<const confmodel::Resource*>(get_board()));
65 0 : return resources;
66 0 : }
67 :
68 :
69 : void
70 0 : CTBApplication::generate_modules(const confmodel::Session* session) const
71 : {
72 0 : std::vector<const confmodel::DaqModule*> modules;
73 :
74 0 : ConfigObjectFactory obj_fac(this);
75 :
76 0 : auto dlhConf = get_link_handler();
77 0 : auto dlhClass = dlhConf->get_template_for();
78 :
79 0 : const QueueDescriptor* dlhInputQDesc = nullptr;
80 :
81 0 : for (auto rule : get_queue_rules()) {
82 0 : auto destination_class = rule->get_destination_class();
83 0 : auto data_type = rule->get_descriptor()->get_data_type();
84 0 : if (destination_class == "DataHandlerModule" || destination_class == dlhClass) {
85 0 : dlhInputQDesc = rule->get_descriptor();
86 : }
87 0 : }
88 :
89 0 : const NetworkConnectionDescriptor* dlhReqInputNetDesc = nullptr;
90 0 : const NetworkConnectionDescriptor* tsNetDesc = nullptr;
91 0 : const NetworkConnectionDescriptor* hsiNetDesc = nullptr;
92 :
93 0 : for (auto rule : get_network_rules()) {
94 0 : auto endpoint_class = rule->get_endpoint_class();
95 0 : auto data_type = rule->get_descriptor()->get_data_type();
96 :
97 0 : if (endpoint_class == "DataHandlerModule" || endpoint_class == dlhClass) {
98 0 : if (data_type == "TimeSync") {
99 0 : tsNetDesc = rule->get_descriptor();
100 : }
101 0 : if (data_type == "DataRequest") {
102 0 : dlhReqInputNetDesc = rule->get_descriptor();
103 : }
104 : }
105 0 : if (data_type == "HSIEvent") {
106 0 : hsiNetDesc = rule->get_descriptor();
107 : }
108 0 : }
109 :
110 0 : auto ctb_conf = get_generator();
111 0 : if (ctb_conf ==nullptr) {
112 : throw(BadConf(ERS_HERE, "No CTBModule configuration given"));
113 : }
114 0 : if (dlhInputQDesc == nullptr) {
115 0 : throw(BadConf(ERS_HERE, "No DLH data input queue descriptor given"));
116 : }
117 0 : if (dlhReqInputNetDesc == nullptr) {
118 0 : throw(BadConf(ERS_HERE, "No DLH request input network descriptor given"));
119 : }
120 0 : if (hsiNetDesc == nullptr) {
121 0 : throw(BadConf(ERS_HERE, "No HSIEvent output network descriptor given"));
122 : }
123 :
124 : // Process special Network rules!
125 : // Looking for Fragment rules from DFAppplications in current Session
126 0 : auto sessionApps = session->enabled_applications();
127 0 : std::vector<conffwk::ConfigObject> fragOutObjs;
128 0 : for (auto app : sessionApps) {
129 0 : auto dfapp = app->cast<appmodel::DFApplication>();
130 0 : if (dfapp == nullptr)
131 0 : continue;
132 :
133 0 : auto dfNRules = dfapp->get_network_rules();
134 0 : for (auto rule : dfNRules) {
135 0 : auto descriptor = rule->get_descriptor();
136 0 : auto data_type = descriptor->get_data_type();
137 0 : if (data_type == "Fragment") {
138 0 : std::string dreqNetUid(descriptor->get_uid_base() + dfapp->UID());
139 0 : conffwk::ConfigObject frag_conn = obj_fac.create_net_obj(descriptor, dreqNetUid);
140 0 : fragOutObjs.push_back(frag_conn);
141 0 : } // If network rule has TriggerDecision type of data
142 0 : } // Loop over Apps network rules
143 0 : } // loop over Session specific Apps
144 :
145 : // start building the list of outputs
146 0 : std::vector<const conffwk::ConfigObject*> fh_output_objs;
147 0 : for (auto& fNet : fragOutObjs) {
148 0 : fh_output_objs.push_back(&fNet);
149 : }
150 :
151 0 : std::vector<conffwk::ConfigObject> ctb_module_outputs;
152 0 : auto sources = get_sources();
153 :
154 0 : for ( const auto & s : sources ) {
155 0 : if (s.second == nullptr) {
156 0 : throw(BadConf(ERS_HERE, "No SourceIDConf given for " + s.first));
157 : }
158 :
159 0 : auto id = s.second->get_sid();
160 : // ----------------------------
161 : // create DLH
162 : // ----------------------------
163 0 : auto det_id = 1; // TODO Eric Flumerfelt <eflumerf@fnal.gov>, 08-Feb-2024: This is a magic number corresponding to kDAQ
164 0 : TLOG() << "creating OKS configuration object for " + s.first + " Data Link Handler class " << dlhClass << ", id " << id;
165 0 : std::string uid("DLH-" + s.first);
166 0 : conffwk::ConfigObject dlhObj = obj_fac.create( dlhClass, uid );
167 0 : dlhObj.set_by_val<uint32_t>("source_id", id);
168 0 : dlhObj.set_by_val<uint32_t>("detector_id", det_id);
169 0 : dlhObj.set_by_val<bool>("post_processing_enabled", false);
170 0 : dlhObj.set_obj("module_configuration", &dlhConf->config_object());
171 :
172 0 : auto net_objc(fh_output_objs);
173 :
174 : // Time Sync network connection
175 0 : if (dlhConf->get_generate_timesync()) {
176 0 : std::string tsStreamUid = tsNetDesc->get_uid_base() + std::to_string(id);
177 0 : conffwk::ConfigObject tsNetObj = obj_fac.create_net_obj(tsNetDesc, tsStreamUid);
178 0 : net_objc.push_back(&tsNetObj);
179 0 : }
180 :
181 0 : dlhObj.set_objs("outputs", net_objc);
182 :
183 : // create Queues from CTB to DLH
184 0 : std::string dataQueueUid(dlhInputQDesc->get_uid_base() + s.first);
185 0 : conffwk::ConfigObject queueObj = obj_fac.create_queue_sid_obj(dlhInputQDesc, id);
186 0 : queueObj.rename(dataQueueUid);
187 :
188 0 : ctb_module_outputs.push_back(queueObj);
189 :
190 : // Create network connections to DLHs
191 0 : std::string faNetUid = dlhReqInputNetDesc->get_uid_base() + UID() + '_' + s.first;
192 0 : conffwk::ConfigObject faNetObj = obj_fac.create_net_obj(dlhReqInputNetDesc, faNetUid);
193 :
194 0 : dlhObj.set_objs("inputs", { &queueObj, &faNetObj });
195 :
196 0 : modules.push_back(obj_fac.get_dal<appmodel::DataHandlerModule>(uid));
197 :
198 0 : } // loop over CTB sources
199 :
200 :
201 0 : conffwk::ConfigObject hsiNetObj = obj_fac.create_net_obj(hsiNetDesc, "");
202 0 : ctb_module_outputs.push_back(hsiNetObj);
203 :
204 0 : auto board = get_board();
205 :
206 0 : conffwk::ConfigObject module_obj = obj_fac.create( "CTBModule", "ctb-module");
207 0 : module_obj.set_obj("configuration", & ctb_conf -> config_object() );
208 0 : module_obj.set_obj("board", & board -> config_object() );
209 :
210 0 : std::vector<const conffwk::ConfigObject*> ctb_module_output_ptrs;
211 0 : for ( const auto & o : ctb_module_outputs ) {
212 0 : ctb_module_output_ptrs.push_back( & o );
213 : }
214 :
215 0 : module_obj.set_objs("outputs", ctb_module_output_ptrs);
216 :
217 0 : auto module = obj_fac.get_dal<appmodel::CTBModule>(module_obj.UID());
218 :
219 0 : modules.push_back(module);
220 :
221 0 : obj_fac.update_modules(modules);
222 0 : }
223 :
224 :
225 :
226 : std::vector<const confmodel::Resource*>
227 0 : CTBoardConf::contained_resources() const {
228 0 : std::vector<const confmodel::Resource*> resources;
229 0 : resources.push_back(get_misc());
230 :
231 0 : auto hlts = get_HLTs();
232 0 : resources.insert(resources.end(), hlts.begin(), hlts.end());
233 :
234 0 : auto crt_llts = get_CRT_LLTs();
235 0 : resources.insert(resources.end(), crt_llts.begin(), crt_llts.end());
236 :
237 0 : auto llts = get_beam_LLTs();
238 0 : resources.insert(resources.end(), llts.begin(), llts.end());
239 :
240 0 : return resources;
241 0 : }
242 :
243 :
244 0 : nlohmann::json CTBoardConf::get_ctb_json(const dunedaq::confmodel::Session& session, std::optional<std::string> socket_host) const {
245 :
246 0 : nlohmann::json json;
247 0 : json["sockets"] = get_sockets() -> get_ctb_json( socket_host );
248 0 : json["misc"] = get_misc()->get_ctb_json(session);
249 :
250 0 : nlohmann::json hlt;
251 :
252 : // constant block that we don't even want to configure
253 0 : auto & mask = hlt["command_mask"];
254 0 : mask["C"]="0x0";
255 0 : mask["D"]="0x0";
256 0 : mask["E"]="0x0";
257 0 : mask["F"]="0x0";
258 :
259 0 : auto hlts = get_HLTs();
260 :
261 0 : std::list<nlohmann::json> json_hlts;
262 0 : for ( const auto & hlt : hlts ) {
263 0 : json_hlts.push_back(hlt->get_ctb_json(session));
264 : }
265 :
266 0 : hlt["trigger"] = nlohmann::json(json_hlts);
267 :
268 0 : json["HLT"] = hlt;
269 :
270 : // --------------------------
271 : // Subsystems
272 : // --------------------------
273 :
274 0 : auto & subsystems = json["subsystems"];
275 :
276 : // ---- Beam ----
277 :
278 0 : auto & beam_block = subsystems["beam"] = get_beam() -> to_json(false, true);
279 0 : std::list<nlohmann::json> json_beam_llts;
280 0 : auto beam_llts = get_beam_LLTs();
281 0 : for ( const auto & llt : beam_llts ) {
282 0 : json_beam_llts.push_back(llt->get_ctb_json(session));
283 : }
284 :
285 0 : beam_block["triggers"] = nlohmann::json(json_beam_llts);
286 :
287 : // ---- CRT ----
288 :
289 0 : auto & crt_block = subsystems["crt"] = get_CRT() -> to_json(false, true);
290 0 : std::list<nlohmann::json> json_crt_llts;
291 0 : auto crt_llts = get_CRT_LLTs();
292 0 : for ( const auto & llt : crt_llts ) {
293 0 : json_crt_llts.push_back(llt->get_ctb_json(session));
294 : }
295 0 : crt_block["triggers"] = nlohmann::json(json_crt_llts);
296 :
297 : // ---- PDS ----
298 :
299 0 : subsystems["pds"] = get_pds() -> to_json(false, true);
300 :
301 0 : nlohmann::json ret;
302 0 : ret["ctb"] = json;
303 :
304 0 : return ret;
305 :
306 0 : }
307 :
308 0 : std::vector<const confmodel::Resource*> CTBMisc::contained_resources() const {
309 0 : return std::vector<const confmodel::Resource*>{ get_randomtrigger_1(), get_randomtrigger_2() };
310 : }
311 :
312 :
313 :
314 0 : nlohmann::json CTBMisc::get_ctb_json(const dunedaq::confmodel::Session& session) const {
315 :
316 0 : nlohmann::json ret;
317 0 : ret["randomtrigger_1"] = get_randomtrigger_1()->get_ctb_json(session);
318 0 : ret["randomtrigger_2"] = get_randomtrigger_2()->get_ctb_json(session);
319 0 : ret["pulser"] = get_pulser() -> to_json(false, true);
320 0 : ret["timing"] = get_timing() -> to_json(false, true);
321 :
322 0 : static std::string ch_status_flag = "ch_status";
323 0 : if ( get_ch_status() ) ret[ch_status_flag] = true;
324 0 : else ret[ch_status_flag] = false;
325 :
326 0 : static std::string standalong_flag = "standalone_enable";
327 0 : ret[standalong_flag] = false;
328 :
329 0 : return ret;
330 :
331 0 : }
332 :
333 :
334 0 : nlohmann::json CTBTrigger::get_ctb_json(const dunedaq::confmodel::Session& session) const {
335 :
336 0 : auto json = this -> to_json(false, true);
337 0 : static std::string enable_tag = "enable";
338 0 : if ( this -> is_disabled(session) ) {
339 0 : json[enable_tag] = false;
340 : }
341 : else {
342 0 : json[enable_tag] = true;
343 : }
344 :
345 0 : json["id"] = this -> UID();
346 :
347 0 : return json;
348 :
349 0 : }
350 :
351 0 : nlohmann::json CTBSockets::get_ctb_json(std::optional<std::string> socket_host) const {
352 :
353 0 : nlohmann::json json;
354 0 : json["receiver"] = get_receiver() -> get_ctb_json(socket_host);
355 0 : json["monitor"] = get_monitor() -> get_ctb_json(socket_host);
356 0 : json["statistics"] = get_statistics() -> to_json(false, true);
357 0 : return json;
358 :
359 0 : }
360 :
361 0 : nlohmann::json CTBSocket::get_ctb_json(std::optional<std::string> socket_host) const {
362 :
363 0 : auto json = to_json(false, true);
364 0 : if ( socket_host ) {
365 0 : json["host"] = socket_host.value();
366 : }
367 0 : return json;
368 :
369 0 : }
370 :
371 :
372 :
|