quic/qbox
Loading...
Searching...
No Matches
module_factory_container.h
1/*
2 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause-Clear
5 */
6
7#ifndef GREENSOCS_MODULE_FACTORY_H
8#define GREENSOCS_MODULE_FACTORY_H
9
10#include "cciutils.h"
11#include <cci_configuration>
12#include <systemc>
13#include <tlm>
14#include <tlm_utils/multi_passthrough_target_socket.h>
15#include <tlm_utils/simple_initiator_socket.h>
16#include <tlm_utils/simple_target_socket.h>
17
18#include <dynlib_loader.h>
19#include <scp/report.h>
20#include <scp/helpers.h>
21
22#include <libgsutils.h>
23#include <libgssync.h>
24
25#include <map>
26
27#include <ports/target-signal-socket.h>
28#include <ports/initiator-signal-socket.h>
29
30#ifndef WITHOUT_QEMU
31#include <ports/target.h>
32#include <ports/initiator.h>
33#include <ports/qemu-target-signal-socket.h>
34#include <ports/qemu-initiator-signal-socket.h>
35#endif
36
37#include <ports/biflow-socket.h>
38#include <module_factory_registery.h>
39#include <transaction_forwarder_if.h>
40#include <tlm_sockets_buswidth.h>
41#include <algorithm>
42#include <vector>
43#include <iterator>
44#include <regex>
45#include <cctype>
46
47namespace gs {
48namespace ModuleFactory {
49
50class ContainerBase : public virtual sc_core::sc_module, public transaction_forwarder_if<CONTAINER>
51{
62private:
63 // Performance optimization caches (lazy initialization)
64 mutable std::map<std::string, cci::cci_value_list> m_module_args_cache;
65 mutable std::map<std::string, bool> m_is_absolute_path_cache;
66 mutable std::map<std::string, std::map<std::string, std::set<std::string>>>
67 m_bind_refs_cache; // [module_name][target] -> referrers
68 mutable std::map<std::string, std::vector<std::pair<std::string, cci::cci_value>>>
69 m_moduletype_params_cache; // container_full_name -> params
70 mutable std::map<std::string, std::set<std::string>>
71 m_per_pass_nested_deps_cache; // Per-pass cache: container_name -> deps (cleared each pass)
72 mutable std::map<std::string, bool> m_is_container_type_cache; // Cache for is_container_type() results
73
74public:
75 SCP_LOGGER(());
76
77 sc_core::sc_module* construct_module(std::string moduletype, sc_core::sc_module_name name, cci::cci_value_list args)
78 {
80 cci::cci_value v = cci::cci_value::from_json("\"" + moduletype + "\"");
81 if (!v.try_get<gs::cci_constructor_vl>(m_fac)) {
82 register_module_from_dylib(name);
83 }
84
85 if (v.try_get<gs::cci_constructor_vl>(m_fac)) {
90 sc_core::sc_module* mod = (m_fac)(name, args);
91 if (mod) {
92 m_constructedModules.emplace_back(mod);
93 return mod;
94 } else {
95 SC_REPORT_ERROR("ModuleFactory", ("Null module type: " + moduletype).c_str());
96 }
97 } else {
98 SC_REPORT_ERROR("ModuleFactory", ("Can't find module type: " + moduletype).c_str());
99 }
101 }
102
107 sc_core::sc_module* construct_module(std::string moduletype, sc_core::sc_module_name name)
108 {
109 cci::cci_value_list emptyargs;
110 return construct_module(moduletype, name, emptyargs);
111 }
112
113 std::string get_parent_name(const std::string& module_name)
114 {
115 return module_name.substr(0, module_name.find_last_of("."));
116 }
117
124 bool is_absolute_path(const std::string& name)
125 {
126 // Check cache first
127 auto it = m_is_absolute_path_cache.find(name);
128 if (it != m_is_absolute_path_cache.end()) {
129 return it->second;
130 }
131
132 bool result = false;
133 std::string container_name = std::string(this->name());
134
135 // If the name starts with the container's name followed by a dot, it's relative
136 if (name.size() > container_name.size() && name.substr(0, container_name.size()) == container_name &&
137 name[container_name.size()] == '.') {
138 result = false;
139 } else if (name.find('.') != std::string::npos) {
140 // If the name contains dots, it's a hierarchical path
141 // Get the parent container name (e.g., "parent" from "parent.child_container")
142 std::string parent_name = get_parent_name(container_name);
143 if (parent_name.empty()) {
144 // We're at the top level, everything with dots is relative to us
145 result = false;
146 } else if (name.find(parent_name + ".") == 0) {
147 // Check if the name starts with the parent or any ancestor
148 // If it starts with parent name, it's an absolute path from parent's perspective
149 result = true;
150 } else {
151 // Check if it exists in the global hierarchy
152 sc_core::sc_object* obj = find_sc_obj(nullptr, name, true);
153 if (obj != nullptr) {
154 // Object exists, check if it's inside this container
155 std::string obj_name = std::string(obj->name());
156 result = obj_name.find(container_name + ".") != 0;
157 } else {
158 result = false;
159 }
160 }
161 } else {
162 // For simple names (no dots), check if they exist in global hierarchy
163 result = find_sc_obj(nullptr, name, true) != nullptr;
164 }
165
166 // Cache the result
167 m_is_absolute_path_cache[name] = result;
168 return result;
169 }
170
171 bool is_container_arg_mod_name(const std::string& name)
172 {
173 if (!this->container_mod_arg) return false;
174 std::string arg_mod_full_name_str = std::string(this->container_mod_arg->name());
175 std::string arg_mod_name_str = arg_mod_full_name_str.substr(get_parent_name(arg_mod_full_name_str).size() + 1);
176 return name == arg_mod_name_str;
177 }
178
185 cci::cci_value_list get_module_args(std::string modulename)
186 {
187 // Check cache first
188 auto cache_it = m_module_args_cache.find(modulename);
189 if (cache_it != m_module_args_cache.end()) {
190 return cache_it->second;
191 }
192
193 cci::cci_value_list args;
194 for (int i = 0; cci::cci_get_broker().has_preset_value(modulename + ".args." + std::to_string(i)); i++) {
195 SCP_TRACE(())("Looking for : {}.args.{}", modulename, std::to_string(i));
196
197 gs::cci_clear_unused(m_broker, modulename + ".args." + std::to_string(i));
198 auto arg = cci::cci_get_broker().get_preset_cci_value(modulename + ".args." + std::to_string(i));
199 if (arg.is_string() && std::string(arg.get_string())[0] == '&') {
200 std::string arg_path = std::string(arg.get_string()).substr(1); // Remove leading '&'
201
202 // Check if it's an absolute path (exists in global hierarchy)
204 // It's a relative path, prepend the parent
205 std::string parent = is_container_arg_mod_name(arg_path)
206 ? get_parent_name(std::string(this->container_mod_arg->name()))
207 : get_parent_name(modulename);
208 // Only prepend if parent is not already in the path
209 if (arg_path.find(parent) == std::string::npos) {
210 arg.set_string("&" + parent + "." + arg_path);
211 } else {
212 arg.set_string("&" + arg_path);
213 }
214 } else {
215 // It's an absolute path, use as-is
216 arg.set_string("&" + arg_path);
217 }
218 }
219 args.push_back(arg);
220 }
221
222 // Cache the result
223 m_module_args_cache[modulename] = args;
224 return args;
225 }
226
227 template <typename I, typename T>
228 bool try_bind(sc_core::sc_object* i_obj, sc_core::sc_object* t_obj)
229 {
230 auto i = dynamic_cast<I*>(i_obj);
231 auto t = dynamic_cast<T*>(t_obj);
232 if (i && t) {
233 i->bind(*t);
234 SCP_INFO(())
235 ("Binding initiator socket: {}({}) with the target socket: {}({})", i_obj->name(), typeid(i).name(),
236 t_obj->name(), typeid(t).name());
237 return true;
238 }
239 t = dynamic_cast<T*>(i_obj);
240 i = dynamic_cast<I*>(t_obj);
241 if (i && t) {
242 i->bind(*t);
243 SCP_INFO(())
244 ("Binding initiator socket: {}({}) with the target socket: {}({})", t_obj->name(), typeid(i).name(),
245 i_obj->name(), typeid(t).name());
246 return true;
247 }
248 return false;
249 }
250
251 /* bind all know port types */
259 void name_bind(sc_core::sc_module* m)
260 {
261 for (auto param : sc_cci_children(m->name())) {
262 /* We should have a param like
263 * foo = &a.baa
264 * foo should relate to an object in this model. a.b.bar should relate to an other
265 * object Note that the names are relative to the current module (this).
266 */
267 std::string targetname = std::string(m->name()) + "." + param;
268 gs::cci_clear_unused(m_broker, targetname + ".0");
269 if (m_broker.get_preset_cci_value(targetname + ".0").is_string()) {
270 // deal with an alias
271 std::string src = m_broker.get_preset_cci_value(targetname + ".0").get_string();
272 m_broker.set_preset_cci_value(targetname + ".address", m_broker.get_preset_cci_value(src + ".address"));
273 m_broker.set_preset_cci_value(targetname + ".size", m_broker.get_preset_cci_value(src + ".size"));
274 }
275 std::string bindname = targetname + ".bind";
276 gs::cci_clear_unused(m_broker, bindname);
277 if (!m_broker.get_preset_cci_value(bindname).is_string()) {
278 continue;
279 }
280 std::string initname = m_broker.get_preset_cci_value(bindname).get_string();
281
282 if (initname.at(0) != '&') continue; // all port binds are donated with a '&', so not for us
283
284 if (initname.find(';') != std::string::npos) {
285 order_bind(m, initname, targetname);
286 } else {
287 initname.erase(0, 1); // remove leading '&'
288 // Check if it's an absolute path (exists in global hierarchy)
290 // It's a relative path, prepend the container name
291 initname = std::string(name()) + "." + initname;
292 }
293 SCP_TRACE(())("Bind {} to {}", targetname, initname);
294 do_binding(m, initname, targetname);
295 }
296 }
297 }
298
304 template <unsigned int BIND_BUSWIDTH>
305 bool try_bind_all(sc_core::sc_object* i_obj, sc_core::sc_object* t_obj)
306 {
307 if ((try_bind<tlm_utils::multi_init_base<BIND_BUSWIDTH>, tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(i_obj,
308 t_obj)) ||
309 (try_bind<tlm_utils::multi_init_base<BIND_BUSWIDTH>, tlm_utils::multi_target_base<BIND_BUSWIDTH>>(i_obj,
310 t_obj)) ||
311 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH>, tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(
312 i_obj, t_obj)) ||
313 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH>, tlm_utils::multi_target_base<BIND_BUSWIDTH>>(
314 i_obj, t_obj)) ||
315 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH, tlm::tlm_fw_transport_if<>,
316 tlm::tlm_bw_transport_if<>, 1, sc_core::SC_ZERO_OR_MORE_BOUND>,
317 tlm_utils::multi_target_base<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
319 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH, tlm::tlm_fw_transport_if<>,
320 tlm::tlm_bw_transport_if<>, 1, sc_core::SC_ZERO_OR_MORE_BOUND>,
321 tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
322 (try_bind<
323 tlm::tlm_initiator_socket<BIND_BUSWIDTH, tlm::tlm_base_protocol_types, 1,
324 sc_core::SC_ONE_OR_MORE_BOUND>,
325 tlm::tlm_target_socket<BIND_BUSWIDTH, tlm::tlm_base_protocol_types, 1, sc_core::SC_ZERO_OR_MORE_BOUND>>(
326 i_obj, t_obj)) ||
327 (try_bind<
328 tlm_utils::multi_init_base<BIND_BUSWIDTH>,
329 tlm::tlm_target_socket<BIND_BUSWIDTH, tlm::tlm_base_protocol_types, 1, sc_core::SC_ZERO_OR_MORE_BOUND>>(
330 i_obj, t_obj)) ||
331 (try_bind<
332 tlm::tlm_base_initiator_socket<BIND_BUSWIDTH, tlm::tlm_fw_transport_if<>, tlm::tlm_bw_transport_if<>, 1,
333 sc_core::SC_ZERO_OR_MORE_BOUND>,
334 tlm::tlm_target_socket<BIND_BUSWIDTH, tlm::tlm_base_protocol_types, 1, sc_core::SC_ZERO_OR_MORE_BOUND>>(
335 i_obj, t_obj)) ||
336 (try_bind<sc_core::sc_port<sc_core::sc_signal_inout_if<bool>, 0, sc_core::SC_ZERO_OR_MORE_BOUND>,
340 ||
341 (try_bind<QemuInitiatorSocket<BIND_BUSWIDTH>, tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
342 (try_bind<QemuInitiatorSocket<BIND_BUSWIDTH>, tlm_utils::multi_target_base<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
343 (try_bind<tlm_utils::multi_init_base<BIND_BUSWIDTH>, QemuTargetSocket<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
344 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH>, QemuTargetSocket<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
349#endif
350 ) {
351 return true;
352 } else {
353 return false;
354 }
355 }
356
363 bool is_container_type(const std::string& name)
364 {
365 // Check cache first
366 auto cache_it = m_is_container_type_cache.find(name);
367 if (cache_it != m_is_container_type_cache.end()) {
368 return cache_it->second;
369 }
370
371 std::string module_name = std::string(sc_module::name());
372 std::string mod_type_name = module_name + "." + name + ".moduletype";
373
374 bool result = false;
375 if (m_broker.has_preset_value(mod_type_name)) {
376 cci::cci_value cci_type = m_broker.get_preset_cci_value(mod_type_name);
377 if (cci_type.is_string()) {
378 std::string mod_type = cci_type.get_string();
379 result = (mod_type == "Container" || mod_type == "ContainerWithArgs" ||
380 mod_type == "ContainerDeferModulesConstruct" || mod_type == "container_builder");
381 }
382 }
383
384 // Cache the result
385 m_is_container_type_cache[name] = result;
386 return result;
387 }
388
398 void get_nested_dependencies(const std::string& container_name, std::set<std::string>& dependencies)
399 {
400 auto cache_it = m_per_pass_nested_deps_cache.find(container_name);
401 if (cache_it != m_per_pass_nested_deps_cache.end()) {
402 dependencies.insert(cache_it->second.begin(), cache_it->second.end());
403 return;
404 }
405
406 std::string module_name = std::string(sc_module::name());
407 std::string container_full_name = module_name + "." + container_name;
408 std::set<std::string> computed_deps;
409
410 std::vector<std::pair<std::string, cci::cci_value>> all_params;
411 auto params_cache_it = m_moduletype_params_cache.find(container_full_name);
412 if (params_cache_it != m_moduletype_params_cache.end()) {
413 all_params = params_cache_it->second;
414 } else {
415 auto params_range = m_broker.get_unconsumed_preset_values(
416 [&container_full_name](const std::pair<std::string, cci::cci_value>& iv) {
417 return iv.first.find(container_full_name + ".") == 0 &&
418 iv.first.find(".moduletype") != std::string::npos &&
419 iv.first.find(".moduletype") == iv.first.length() - 11;
420 });
421 for (const auto& param : params_range) {
422 all_params.push_back(param);
423 }
424 m_moduletype_params_cache[container_full_name] = all_params;
425 }
426
427 std::set<std::string> child_modules;
428 bool config_prefix_used = false;
429 std::string config_prefix = container_full_name + ".config.";
430
431 for (const auto& param : all_params) {
432 std::string param_name = param.first;
433 if (param_name == container_full_name + ".moduletype") continue;
434
435 if (param_name.find(config_prefix) == 0 && param_name.find(".moduletype") == param_name.length() - 11) {
436 std::string child_path = param_name.substr(config_prefix.length());
437 child_path = child_path.substr(0, child_path.length() - 11);
438 size_t dot_pos = child_path.find('.');
439 if (dot_pos != std::string::npos) {
440 child_path = child_path.substr(0, dot_pos);
441 }
443 config_prefix_used = true;
444 } else if (param_name.length() > container_full_name.length() + 12) {
445 std::string child_path = param_name.substr(container_full_name.length() + 1);
446 if (child_path.find("config.") == 0) continue;
447
448 child_path = child_path.substr(0, child_path.length() - 11);
449 size_t dot_pos = child_path.find('.');
450 if (dot_pos != std::string::npos) {
451 child_path = child_path.substr(0, dot_pos);
452 }
454 }
455 }
456
457 for (const auto& child : child_modules) {
458 std::string child_config_name;
459 if (config_prefix_used) {
461 } else {
463 }
464
465 cci::cci_value_list child_args;
466 auto args_cache_it = m_module_args_cache.find(child_config_name);
467 if (args_cache_it != m_module_args_cache.end()) {
468 child_args = args_cache_it->second;
469 } else {
470 for (int i = 0; m_broker.has_preset_value(child_config_name + ".args." + std::to_string(i)); i++) {
471 child_args.push_back(
472 m_broker.get_preset_cci_value(child_config_name + ".args." + std::to_string(i)));
473 }
474 m_module_args_cache[child_config_name] = child_args;
475 }
476
477 for (auto arg : child_args) {
478 if (arg.is_string()) {
479 std::string a = arg.get_string();
480 if (a.length() > 0 && a[0] == '&') {
481 std::string ref_path = a.substr(1);
482
483 if (ref_path.find(module_name) != 0) {
485 }
486
487 if (!(ref_path.length() >= container_full_name.size() &&
488 ref_path.substr(0, container_full_name.size()) == container_full_name &&
489 (ref_path.length() == container_full_name.size() ||
490 ref_path[container_full_name.size()] == '.'))) {
491 computed_deps.insert(ref_path);
492 }
493 }
494 }
495 }
496
497 // Check bind parameters only if this child is a container type
498 bool child_is_container = false;
499 auto container_cache_it = m_is_container_type_cache.find(child);
500 if (container_cache_it != m_is_container_type_cache.end()) {
502 } else {
503 if (m_broker.has_preset_value(child_config_name + ".moduletype")) {
504 cci::cci_value mt = m_broker.get_preset_cci_value(child_config_name + ".moduletype");
505 if (mt.is_string()) {
506 std::string moduletype = mt.get_string();
507 child_is_container = (moduletype == "Container" || moduletype == "container_builder");
508 }
509 }
510 m_is_container_type_cache[child] = child_is_container;
511 }
512
513 if (child_is_container) {
514 // Get bind parameters for this container child
515 auto child_params = m_broker.get_unconsumed_preset_values(
516 [&child_config_name](const std::pair<std::string, cci::cci_value>& iv) {
517 return iv.first.find(child_config_name + ".") == 0 &&
518 iv.first.find(".bind") != std::string::npos;
519 });
520
521 for (const auto& param : child_params) {
522 if (param.second.is_string()) {
523 std::string bind_value = param.second.get_string();
524 // Handle semicolon-separated bind strings
525 size_t pos = 0;
526 while (pos < bind_value.length()) {
527 size_t end = bind_value.find(';', pos);
528 if (end == std::string::npos) end = bind_value.length();
529
530 std::string single_bind = bind_value.substr(pos, end - pos);
531 // Trim whitespace
532 size_t start = single_bind.find_first_not_of(" \t\n\r");
533 if (start != std::string::npos) {
534 size_t finish = single_bind.find_last_not_of(" \t\n\r");
535 single_bind = single_bind.substr(start, finish - start + 1);
536 }
537
538 if (single_bind.length() > 0 && single_bind[0] == '&') {
539 std::string ref_path = single_bind.substr(1);
540
541 // Make absolute if relative
542 if (ref_path.find(module_name) != 0) {
544 }
545
546 // Only add if it's external to this container
547 if (!(ref_path.length() >= container_full_name.size() &&
548 ref_path.substr(0, container_full_name.size()) == container_full_name &&
549 (ref_path.length() == container_full_name.size() ||
550 ref_path[container_full_name.size()] == '.'))) {
551 computed_deps.insert(ref_path);
552 }
553 }
554
555 pos = (end == bind_value.length()) ? end : end + 1;
556 }
557 }
558 }
559 }
560 }
561
562 // Check the container's own bind parameters (outside config table)
563 auto container_params = m_broker.get_unconsumed_preset_values(
564 [&container_full_name](const std::pair<std::string, cci::cci_value>& iv) {
565 std::string param_name = iv.first;
566 // Match pattern: container_full_name.<param>.bind but not container_full_name.config.*
567 return param_name.find(container_full_name + ".") == 0 &&
568 param_name.find(".config.") == std::string::npos &&
569 param_name.find(".bind") != std::string::npos;
570 });
571
572 for (const auto& param : container_params) {
573 if (param.second.is_string()) {
574 std::string bind_value = param.second.get_string();
575 // Handle semicolon-separated bind strings
576 size_t pos = 0;
577 while (pos < bind_value.length()) {
578 size_t end = bind_value.find(';', pos);
579 if (end == std::string::npos) end = bind_value.length();
580
581 std::string single_bind = bind_value.substr(pos, end - pos);
582 // Trim whitespace
583 size_t start = single_bind.find_first_not_of(" \t\n\r");
584 if (start != std::string::npos) {
585 size_t finish = single_bind.find_last_not_of(" \t\n\r");
586 single_bind = single_bind.substr(start, finish - start + 1);
587 }
588
589 if (single_bind.length() > 0 && single_bind[0] == '&') {
590 std::string ref_path = single_bind.substr(1);
591
592 // Make absolute if relative
593 if (ref_path.find(module_name) != 0) {
595 }
596
597 // Only add if it's external to this container
598 if (!(ref_path.length() >= container_full_name.size() &&
599 ref_path.substr(0, container_full_name.size()) == container_full_name &&
600 (ref_path.length() == container_full_name.size() ||
601 ref_path[container_full_name.size()] == '.'))) {
602 computed_deps.insert(ref_path);
603 }
604 }
605
606 pos = (end == bind_value.length()) ? end : end + 1;
607 }
608 }
609 }
610
611 m_per_pass_nested_deps_cache[container_name] = computed_deps;
612 dependencies.insert(computed_deps.begin(), computed_deps.end());
613 }
614
615 bool are_dependencies_available(const std::string& name, const std::set<std::string>& done)
616 {
617 std::string module_name = std::string(sc_module::name());
618 std::set<std::string> all_dependencies;
619
620 cci::cci_value_list mod_args = get_module_args(module_name + "." + name);
621 for (auto arg : mod_args) {
622 if (arg.is_string()) {
623 std::string a = arg.get_string();
624 if (a.length() > 0 && a[0] == '&') {
625 std::string ref_path = a.substr(1);
626 if (!ref_path.empty()) {
628 }
629 }
630 }
631 }
632
633 if (is_container_type(name)) {
635 }
636
637 for (const auto& ref_path : all_dependencies) {
638 if (ref_path.substr(0, module_name.size()) == module_name && ref_path.length() > module_name.size() &&
639 ref_path[module_name.size()] == '.') {
640 std::string referenced_module = ref_path.substr(module_name.size() + 1);
641 size_t dot_pos = referenced_module.find('.');
642 if (dot_pos != std::string::npos) {
644 }
645 if (done.count(referenced_module) == 0) {
646 return false;
647 }
648 } else {
649 sc_core::sc_object* dep_obj = find_sc_obj(nullptr, ref_path, true);
650 if (dep_obj == nullptr) {
651 return false;
652 }
653 }
654 }
655 return true;
656 }
657
658 // Find modules with bind parameters pointing to target_module
659 std::set<std::string> get_bind_references_to_module(const std::string& module_name,
660 const std::string& target_module_name,
661 const std::list<std::string>& all_modules)
662 {
663 // Check cache first
664 auto& module_cache = m_bind_refs_cache[module_name];
666 if (cache_it != module_cache.end()) {
667 return cache_it->second;
668 }
669
670 std::set<std::string> modules_that_reference_target;
671 std::string target_full_path = module_name + "." + target_module_name;
672
673 for (const auto& mod : all_modules) {
674 if (mod == target_module_name) continue;
675
676 std::string mod_full_path = module_name + "." + mod;
677
678 // Query broker for this module's parameters
679 auto mod_params = m_broker.get_unconsumed_preset_values(
680 [&mod_full_path](const std::pair<std::string, cci::cci_value>& iv) {
681 return iv.first.find(mod_full_path + ".") == 0;
682 });
683
684 for (const auto& param : mod_params) {
685 const std::string& param_name = param.first;
686 const cci::cci_value& param_value = param.second;
687
688 if (param_name.length() > 5 && param_name.substr(param_name.length() - 5) == ".bind") {
689 if (param_value.is_string()) {
690 std::string bind_target = param_value.get_string();
691 if (bind_target.length() > 0 && bind_target[0] == '&') {
692 std::string ref_path = bind_target.substr(1);
693 if (ref_path == target_full_path ||
694 (ref_path.length() > target_full_path.length() &&
695 ref_path.substr(0, target_full_path.length() + 1) == target_full_path + ".")) {
697 break;
698 }
699 }
700 }
701 }
702 }
703 }
704
705 // Cache the result
708 }
709
710 int get_construction_priority(const std::string& name)
711 {
712 std::string module_name = std::string(sc_module::name());
713 std::string priority_param = module_name + "." + name + ".construction_priority";
714
715 if (m_broker.has_preset_value(priority_param)) {
716 cci::cci_value cci_priority = m_broker.get_preset_cci_value(priority_param);
717 if (cci_priority.is_int()) {
718 return cci_priority.get_int();
719 } else if (cci_priority.is_int64()) {
720 return static_cast<int>(cci_priority.get_int64());
721 }
722 }
723 return 0; // Default priority
724 }
725
726 std::list<std::string> PriorityConstruct(void)
727 {
728 std::list<std::string> args;
729 std::set<std::string> done;
730 std::list<std::string> all_modules;
731 std::string module_name = std::string(sc_module::name());
732
734
735 for (auto it = all_modules.begin(); it != all_modules.end();) {
736 std::string mod_type_name = module_name + "." + *it + ".moduletype";
737 if (!m_broker.has_preset_value(mod_type_name)) {
738 it = all_modules.erase(it);
739 } else {
740 ++it;
741 }
742 }
743
744 std::map<int, std::list<std::string>> priority_groups;
745 for (const auto& mod : all_modules) {
746 int priority = get_construction_priority(mod);
747 priority_groups[priority].push_back(mod);
748 }
749
750 for (auto& priority_pair : priority_groups) {
751 std::list<std::string> todo = priority_pair.second;
752 int max_passes = todo.size() + 1;
753 int pass = 0;
754
755 bool enforce_bind_deps = true;
756 while (todo.size() > 0 && pass < max_passes) {
757 pass++;
758 int constructed_this_pass = 0;
759
760 m_per_pass_nested_deps_cache.clear();
761
762 std::map<std::string, std::set<std::string>> depends_on_me;
763 std::map<std::string, std::set<std::string>> bind_reverse_index;
764
765 for (const auto& source_mod : todo) {
767 continue;
768 }
769
770 std::string source_full_path = module_name + "." + source_mod;
771
772 // Check if source module is a router
773 std::string source_modtype;
774 auto source_type_param = m_broker.get_preset_cci_value(source_full_path + ".moduletype");
775 if (source_type_param.is_string()) {
776 source_modtype = source_type_param.get_string();
777 }
778 bool source_is_router = (source_modtype.find("router") != std::string::npos ||
779 source_modtype.find("Router") != std::string::npos);
780
781 auto mod_params = m_broker.get_unconsumed_preset_values(
782 [&source_full_path](const std::pair<std::string, cci::cci_value>& iv) {
783 return iv.first.find(source_full_path + ".") == 0;
784 });
785
786 for (const auto& param : mod_params) {
787 const std::string& param_name = param.first;
788 const cci::cci_value& param_value = param.second;
789
790 if (param_name.length() > 5 && param_name.substr(param_name.length() - 5) == ".bind") {
791 if (param_value.is_string()) {
792 std::string bind_target = param_value.get_string();
793 if (bind_target.length() > 0 && bind_target[0] == '&') {
794 std::string ref_path = bind_target.substr(1);
795 std::string target_mod;
796
797 if (ref_path.find(module_name + ".") == 0) {
798 target_mod = ref_path.substr(module_name.length() + 1);
799 } else {
801 }
802
803 size_t dot_pos = target_mod.find('.');
804 if (dot_pos != std::string::npos) {
805 target_mod = target_mod.substr(0, dot_pos);
806 }
807
808 // Only track bind dependencies for router modules
809 if (source_is_router &&
810 std::find(todo.begin(), todo.end(), target_mod) != todo.end()) {
812 }
813 }
814 }
815 }
816 }
817 }
818
819 for (const auto& mod : todo) {
820 std::set<std::string> all_deps;
821 cci::cci_value_list mod_args = get_module_args(module_name + "." + mod);
822 for (auto arg : mod_args) {
823 if (arg.is_string()) {
824 std::string a = arg.get_string();
825 if (a.length() > 0 && a[0] == '&') {
826 std::string ref_path = a.substr(1);
827 if (!ref_path.empty()) {
828 all_deps.insert(ref_path);
829 }
830 }
831 }
832 }
833
834 if (is_container_type(mod)) {
836 }
837
838 for (const auto& ref_path : all_deps) {
839 if (ref_path.substr(0, module_name.size()) == module_name &&
840 ref_path.length() > module_name.size() && ref_path[module_name.size()] == '.') {
841 std::string sibling_name = ref_path.substr(module_name.size() + 1);
842 size_t dot_pos = sibling_name.find('.');
843 if (dot_pos != std::string::npos) {
844 sibling_name = sibling_name.substr(0, dot_pos);
845 }
846 if (std::find(todo.begin(), todo.end(), sibling_name) != todo.end()) {
847 depends_on_me[sibling_name].insert(mod);
848 }
849 }
850 }
851
852 auto bind_it = bind_reverse_index.find(mod);
853 if (bind_it != bind_reverse_index.end()) {
854 for (const auto& bind_source : bind_it->second) {
855 depends_on_me[mod].insert(bind_source);
856 }
857 }
858 }
859
860 for (auto it = todo.begin(); it != todo.end();) {
861 std::string name = *it;
862
863 bool deps_available = are_dependencies_available(name, done);
864
865 bool bind_deps_ready = true;
867 for (const auto& dep_pair : depends_on_me) {
868 const std::string& required_module = dep_pair.first;
869 const std::set<std::string>& modules_depending_on_it = dep_pair.second;
870
871 if (modules_depending_on_it.count(name) > 0) {
872 if (done.count(required_module) == 0) {
873 bind_deps_ready = false;
874 break;
875 }
876 }
877 }
878 }
879
881 done.insert(name);
882 it = todo.erase(it);
884 args.push_back(name);
885 } else {
886 ++it;
887 }
888 }
889
890 if (constructed_this_pass == 0 && todo.size() > 0) {
891 if (enforce_bind_deps) {
892 enforce_bind_deps = false;
893 pass--;
894 continue;
895 }
896 SCP_WARN(())("No progress in dependency resolution, {} modules remaining", todo.size());
897 for (auto t : todo) {
898 SCP_WARN(())("Module with unresolved dependencies: {}", t);
899 std::set<std::string> all_deps;
900 cci::cci_value_list mod_args = get_module_args(module_name + "." + t);
901 for (auto arg : mod_args) {
902 if (arg.is_string()) {
903 std::string a = arg.get_string();
904 if (a.length() > 0 && a[0] == '&') {
905 std::string ref_path = a.substr(1);
906 if (!ref_path.empty()) {
907 all_deps.insert(ref_path);
908 }
909 }
910 }
911 }
912 if (is_container_type(t)) {
914 }
915 for (const auto& ref_path : all_deps) {
916 sc_core::sc_object* dep_obj = find_sc_obj(nullptr, ref_path, true);
917 if (dep_obj == nullptr) {
918 SCP_WARN(())(" Missing dependency: {}", ref_path);
919 }
920 }
921 }
922 SCP_FATAL(())("Unresolvable module dependencies");
923 }
924 }
925 }
926
927 return args;
928 }
929
930 void register_module_from_dylib(sc_core::sc_module_name name)
931 {
932 std::string libname;
933 std::vector<std::string> lib_types = { ".moduletype", ".dylib_path" };
934
935 for (const auto& type : lib_types) {
936 const std::string base_name = std::string(sc_module::name()) + "." + std::string(name) + type;
937 if (m_broker.has_preset_value(base_name)) {
938 libname = std::string(m_broker.get_preset_cci_value(base_name).get_string()) + "." +
939 std::string(m_library_loader.get_lib_ext());
940 }
941 }
942
943 qemu::LibraryLoaderIface::LibraryIfacePtr libraryHandle = m_library_loader.load_library(libname);
944 if (!libraryHandle) {
945 SCP_FATAL(())("Failed to load library {}: {}", libname, m_library_loader.get_last_error());
946 }
947
948 m_dls.insert(libraryHandle);
949
950 void (*module_register)() = nullptr;
951 if (libraryHandle->symbol_exists("module_register")) {
952 module_register = reinterpret_cast<void (*)()>(libraryHandle->get_symbol("module_register"));
953 module_register();
954 } else {
955 SCP_WARN(()) << "module_register not found in library " << libname;
956 }
957 }
958
959 void ModulesConstruct(void)
960 {
961 for (auto name : PriorityConstruct()) {
962 auto mod_type_name = std::string(sc_module::name()) + "." + name + ".moduletype";
963 if (m_broker.has_preset_value(mod_type_name)) {
964 if (m_broker.has_preset_value(std::string(sc_module::name()) + "." + name + ".dont_construct")) {
965 sc_core::sc_object* no_construct_mod_obj = nullptr;
966 std::string no_construct_mod_name = std::string(sc_module::name()) + "." + name;
968 auto no_construct_mod = dynamic_cast<sc_core::sc_module*>(no_construct_mod_obj);
969 if (!no_construct_mod) {
970 SCP_FATAL(()) << "The object " << std::string(sc_module::name()) + "." + name
971 << " is not yet constructed";
972 }
973 m_allModules.push_back(no_construct_mod);
974 } else {
975 gs::cci_clear_unused(m_broker, mod_type_name);
976 cci::cci_value cci_type = gs::cci_get(m_broker, mod_type_name);
977 if (cci_type.is_string()) {
978 std::string mod_type = cci_type.get_string();
979 cci::cci_value_list mod_args = get_module_args(std::string(sc_module::name()) + "." + name);
980 sc_core::sc_module* m = construct_module(mod_type, name.c_str(), mod_args);
981 if (!m) {
983 "ModuleFactory",
984 ("Can't automatically handle argument list for module: " + mod_type).c_str());
985 }
986
987 m_allModules.push_back(m);
988 if (!m_local_pass) {
989 m_local_pass = dynamic_cast<transaction_forwarder_if<PASS>*>(m);
990 }
991 } else {
992 SCP_WARN(()) << "moduletype parameter is not a string for " << name;
993 }
994 }
995 }
996 }
997
998 for (auto mod : m_allModules) {
999 name_bind(mod);
1000 }
1001 SCP_DEBUG(())("ModulesConstruct complete");
1002 }
1003
1004 using tlm_initiator_socket_type = tlm_utils::simple_initiator_socket_b<
1005 ContainerBase, DEFAULT_TLM_BUSWIDTH, tlm::tlm_base_protocol_types, sc_core::SC_ZERO_OR_MORE_BOUND>;
1006 using tlm_target_socket_type = tlm_utils::simple_target_socket_tagged_b<
1007 ContainerBase, DEFAULT_TLM_BUSWIDTH, tlm::tlm_base_protocol_types, sc_core::SC_ZERO_OR_MORE_BOUND>;
1008
1009private:
1010 bool m_defer_modules_construct;
1011 std::list<sc_core::sc_module*> m_allModules;
1012 std::list<std::shared_ptr<sc_core::sc_module>> m_constructedModules;
1013
1014 std::set<qemu::LibraryLoaderIface::LibraryIfacePtr> m_dls;
1015 qemu::LibraryLoaderIface& m_library_loader = qemu::get_default_lib_loader();
1016
1017public:
1018 cci::cci_broker_handle m_broker;
1019 cci::cci_param<std::string> moduletype; // for consistency
1020 cci::cci_param<uint32_t> p_tlm_initiator_ports_num;
1021 cci::cci_param<uint32_t> p_tlm_target_ports_num;
1022 cci::cci_param<uint32_t> p_initiator_signals_num;
1023 cci::cci_param<uint32_t> p_target_signals_num;
1024 sc_core::sc_vector<tlm_initiator_socket_type> initiator_sockets;
1025 sc_core::sc_vector<tlm_target_socket_type> target_sockets;
1026 sc_core::sc_vector<InitiatorSignalSocket<bool>> initiator_signal_sockets;
1027 sc_core::sc_vector<TargetSignalSocket<bool>> target_signal_sockets;
1028 TargetSignalSocket<bool> container_self_reset;
1029 transaction_forwarder_if<PASS>* m_local_pass;
1030
1031 std::vector<cci::cci_param<gs::cci_constructor_vl>*> registered_mods;
1032 sc_core::sc_object* container_mod_arg;
1033
1034 virtual ~ContainerBase()
1035 {
1036 m_constructedModules.reverse();
1037 m_constructedModules.clear();
1038 }
1039
1040 std::shared_ptr<sc_core::sc_module> find_module_by_name(const std::string& mod_name)
1041 {
1042 auto ret = std::find_if(m_constructedModules.begin(), m_constructedModules.end(),
1043 [&](auto mod) { return (mod && std::string(mod->name()) == mod_name); });
1044 if (ret == m_constructedModules.end()) {
1045 return nullptr;
1046 }
1047 return *ret;
1048 }
1049
1050 template <typename T>
1051 std::shared_ptr<sc_core::sc_module> find_module_by_cci_param(const std::string& cci_param_name, const T& cmp_value)
1052 {
1053 T ret_val;
1054 auto ret = std::find_if(m_constructedModules.begin(), m_constructedModules.end(), [&](auto mod) {
1055 return (mod && m_broker.has_preset_value(std::string(mod->name()) + "." + cci_param_name) &&
1056 m_broker.get_preset_cci_value(std::string(mod->name()) + "." + cci_param_name)
1057 .template try_get<T>(ret_val) &&
1058 (ret_val == cmp_value));
1059 });
1060 if (ret == m_constructedModules.end()) {
1061 return nullptr;
1062 }
1063 return *ret;
1064 }
1065
1072 ContainerBase(const sc_core::sc_module_name _n, bool defer_modules_construct,
1073 sc_core::sc_object* p_container_mod_arg = nullptr)
1074 : m_defer_modules_construct(defer_modules_construct)
1075 , m_broker(cci::cci_get_broker())
1076 , moduletype("moduletype", "", "Module type for the TLM container, must be \"Container\"")
1077 , p_tlm_initiator_ports_num("tlm_initiator_ports_num", 0, "number of tlm initiator ports")
1078 , p_tlm_target_ports_num("tlm_target_ports_num", 0, "number of tlm target ports")
1079 , p_initiator_signals_num("initiator_signals_num", 0, "number of initiator signals")
1080 , p_target_signals_num("target_signals_num", 0, "number of target signals")
1081 , initiator_sockets("initiator_socket")
1082 , target_sockets("target_socket")
1083 , initiator_signal_sockets("initiator_signal_socket")
1084 , target_signal_sockets("target_signal_socket")
1085 , container_self_reset("container_self_reset")
1086 , m_local_pass(nullptr)
1087 , container_mod_arg(p_container_mod_arg)
1088 {
1089 SCP_DEBUG(()) << "ContainerBase Constructor";
1090
1091 initiator_sockets.init(p_tlm_initiator_ports_num.get_value(),
1092 [this](const char* n, int i) { return new tlm_initiator_socket_type(n); });
1093 target_sockets.init(p_tlm_target_ports_num.get_value(),
1094 [this](const char* n, int i) { return new tlm_target_socket_type(n); });
1095 initiator_signal_sockets.init(p_initiator_signals_num.get_value(),
1096 [this](const char* n, int i) { return new InitiatorSignalSocket<bool>(n); });
1097 target_signal_sockets.init(p_target_signals_num.get_value(),
1098 [this](const char* n, int i) { return new TargetSignalSocket<bool>(n); });
1099
1100 for (int i = 0; i < p_tlm_target_ports_num.get_value(); i++) {
1101 target_sockets[i].register_b_transport(this, &ContainerBase::b_transport, i);
1102 target_sockets[i].register_transport_dbg(this, &ContainerBase::transport_dbg, i);
1103 target_sockets[i].register_get_direct_mem_ptr(this, &ContainerBase::get_direct_mem_ptr, i);
1104 }
1105
1106 for (int i = 0; i < p_tlm_initiator_ports_num.get_value(); i++) {
1107 initiator_sockets[i].register_invalidate_direct_mem_ptr(this, &ContainerBase::invalidate_direct_mem_ptr);
1108 }
1109
1110 for (int i = 0; i < p_target_signals_num.get_value(); i++) {
1111 target_signal_sockets[i].register_value_changed_cb([&, i](bool value) {
1112 if (m_local_pass) m_local_pass->fw_handle_signal(i, value);
1113 });
1114 }
1115
1116 container_self_reset.register_value_changed_cb([this](bool value) { do_reset(value); });
1117
1118 auto mods = gs::ModuleFactory::GetAvailableModuleList();
1119
1120 while (mods->size()) {
1121 registered_mods.push_back((mods->back())());
1122 mods->pop_back();
1123 }
1124
1125 if (!m_defer_modules_construct) ModulesConstruct();
1126 }
1127
1128 void fw_b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) override
1129 {
1130 SCP_DEBUG(()) << "calling b_transport on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
1131 initiator_sockets[id]->b_transport(trans, delay);
1132 SCP_DEBUG(()) << "return from b_transport on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
1133 }
1134
1135 unsigned int fw_transport_dbg(int id, tlm::tlm_generic_payload& trans) override
1136 {
1137 SCP_DEBUG(()) << "calling transport_dbg on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
1138 unsigned int ret = initiator_sockets[id]->transport_dbg(trans);
1139 SCP_DEBUG(()) << "return from transport_dbg on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
1140 return ret;
1141 }
1142
1143 bool fw_get_direct_mem_ptr(int id, tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data) override
1144 {
1145 SCP_DEBUG(()) << "calling get_direct_mem_ptr on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
1146 bool ret = initiator_sockets[id]->get_direct_mem_ptr(trans, dmi_data);
1147 SCP_DEBUG(()) << "return from get_direct_mem_ptr on initiator_socket_" << id << " "
1148 << " RET: " << std::boolalpha << ret << " " << scp::scp_txn_tostring(trans)
1149 << " IS_READ_ALLOWED: " << std::boolalpha << dmi_data.is_read_allowed() << " "
1150 << " IS_WRITE_ALLOWED: " << std::boolalpha << dmi_data.is_write_allowed();
1151 return ret;
1152 }
1153
1154 void fw_invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) override
1155 {
1156 SCP_DEBUG(()) << " " << name() << " invalidate_direct_mem_ptr " << " start address 0x" << std::hex << start
1157 << " end address 0x" << std::hex << end;
1158 for (int i = 0; i < target_sockets.size(); i++) {
1159 target_sockets[i]->invalidate_direct_mem_ptr(start, end);
1160 }
1161 }
1162
1163 void fw_handle_signal(int id, bool value) override
1164 {
1165 SCP_DEBUG(()) << "calling handle_signal on initiator_signal_socket_" << id << " value: " << std::boolalpha
1166 << value;
1167 initiator_signal_sockets[id]->write(value);
1168 }
1169
1170private:
1171 void b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
1172 {
1173 if (m_local_pass) {
1174 m_local_pass->fw_b_transport(id, trans, delay);
1175 }
1176 }
1177
1178 unsigned int transport_dbg(int id, tlm::tlm_generic_payload& trans)
1179 {
1180 if (m_local_pass) {
1181 return m_local_pass->fw_transport_dbg(id, trans);
1182 }
1183 return 0;
1184 }
1185
1186 bool get_direct_mem_ptr(int id, tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data)
1187 {
1188 if (m_local_pass) {
1189 return m_local_pass->fw_get_direct_mem_ptr(id, trans, dmi_data);
1190 }
1191 return false;
1192 }
1193
1194 void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end)
1195 {
1196 if (m_local_pass) {
1197 m_local_pass->fw_invalidate_direct_mem_ptr(start, end);
1198 }
1199 }
1200
1201 std::vector<std::string> parse_order_str(const std::string& reset_order)
1202 {
1203 std::vector<std::string> ret;
1204 if (reset_order.empty()) {
1205 return ret;
1206 }
1207 std::string reset_order_tr = reset_order;
1208 reset_order_tr.erase(
1209 std::remove_if(reset_order_tr.begin(), reset_order_tr.end(), [](char c) { return std::isspace(c); }),
1210 reset_order_tr.end());
1211 size_t sig_count = std::count_if(reset_order_tr.begin(), reset_order_tr.end(), [](char c) { return c == ';'; });
1212 ret.resize(sig_count + 1);
1213 const std::regex separator(R"(;)");
1214 std::copy(std::sregex_token_iterator(reset_order_tr.begin(), reset_order_tr.end(), separator, -1),
1215 std::sregex_token_iterator(), ret.begin());
1216 return ret;
1217 }
1218
1219 void do_binding(sc_core::sc_module* module_obj, const std::string& initiator_name, const std::string& target_name)
1220 {
1221 sc_core::sc_object* i_obj = nullptr;
1222 sc_core::sc_object* t_obj = nullptr;
1223 /* find the initiator object */
1224
1225 i_obj = find_sc_obj(nullptr, initiator_name);
1226
1227 /* find the target object which must be inside this object */
1229
1230 // actually you could probably just cast everything to (tlm::tlm_target_socket<>*), but
1231 // we will dynamic cast to be sure.
1233 SCP_FATAL(())("No bind found for: {} to {}", i_obj->name(), t_obj->name());
1234 }
1235 }
1236
1237 void order_bind(sc_core::sc_module* module_obj, const std::string& target_order_str,
1238 const std::string& initiator_name)
1239 {
1240 if (!target_order_str.empty()) {
1241 std::vector<std::string> target_vec = parse_order_str(target_order_str);
1242 for (const auto& target : target_vec) {
1243 std::string target_name = target;
1244 if (target_name.at(0) != '&') continue;
1245 target_name.erase(0, 1);
1247 target_name = std::string(name()) + "." + target_name;
1248 }
1249 SCP_TRACE(())("Bind {} to {}", target_name, initiator_name);
1251 }
1252 }
1253 }
1254
1255 virtual void do_reset(bool value)
1256 {
1257 if (value) SCP_WARN(()) << "Reset";
1258 }
1259};
1260
1265{
1266public:
1267 SCP_LOGGER(());
1268 Container(const sc_core::sc_module_name& n): ContainerBase(n, false, nullptr)
1269 {
1270 SCP_DEBUG(()) << "Container constructor";
1271 std::string moduletype_param = std::string(name()) + ".moduletype";
1272 if (!m_broker.has_preset_value(moduletype_param)) {
1273 m_broker.set_preset_cci_value(moduletype_param, cci::cci_value("Container"));
1274 }
1275 }
1276
1277 virtual ~Container() = default;
1278};
1284{
1285public:
1286 SCP_LOGGER(());
1287 ContainerWithArgs(const sc_core::sc_module_name& n, sc_core::sc_object* p_container_mod_arg)
1289 {
1290 SCP_DEBUG(()) << "ContainerWithArgs constructor";
1291 std::string moduletype_param = std::string(name()) + ".moduletype";
1292 if (!m_broker.has_preset_value(moduletype_param)) {
1293 m_broker.set_preset_cci_value(moduletype_param, cci::cci_value("ContainerWithArgs"));
1294 }
1295 }
1296
1297 virtual ~ContainerWithArgs() = default;
1298};
1304{
1305public:
1306 SCP_LOGGER(());
1307 ContainerDeferModulesConstruct(const sc_core::sc_module_name& n): ContainerBase(n, true, nullptr)
1308 {
1309 SCP_DEBUG(()) << "ContainerDeferModulesConstruct constructor";
1310 std::string moduletype_param = std::string(name()) + ".moduletype";
1311 if (!m_broker.has_preset_value(moduletype_param)) {
1312 m_broker.set_preset_cci_value(moduletype_param, cci::cci_value("ContainerDeferModulesConstruct"));
1313 }
1314 }
1315
1316 virtual ~ContainerDeferModulesConstruct() = default;
1317};
1318
1319} // namespace ModuleFactory
1320} // namespace gs
1321
1325#endif
A QEMU output GPIO exposed as a InitiatorSignalSocket<bool>
Definition qemu-initiator-signal-socket.h:40
A QEMU input GPIO exposed as a TargetSignalSocket<bool>
Definition qemu-target-signal-socket.h:29
Definition target.h:160
Definition module_factory_container.h:51
bool is_absolute_path(const std::string &name)
Check if a name refers to an absolute path (outside this container)
Definition module_factory_container.h:124
sc_core::sc_module * construct_module(std::string moduletype, sc_core::sc_module_name name)
Helper to construct a module that takes no arguments.
Definition module_factory_container.h:107
void get_nested_dependencies(const std::string &container_name, std::set< std::string > &dependencies)
Get all EXTERNAL nested dependencies from a container's children (excludes dependencies that are inte...
Definition module_factory_container.h:398
void name_bind(sc_core::sc_module *m)
Bind all known port types.
Definition module_factory_container.h:259
sc_core::sc_module * construct_module(std::string moduletype, sc_core::sc_module_name name, cci::cci_value_list args)
Definition module_factory_container.h:77
ContainerBase(const sc_core::sc_module_name _n, bool defer_modules_construct, sc_core::sc_object *p_container_mod_arg=nullptr)
construct a Container, and all modules within it, and perform binding
Definition module_factory_container.h:1072
cci::cci_value_list get_module_args(std::string modulename)
Get the module args helper to find argument list for a module constructor.
Definition module_factory_container.h:185
bool is_container_type(const std::string &name)
Check if a module is a container type.
Definition module_factory_container.h:363
bool try_bind_all(sc_core::sc_object *i_obj, sc_core::sc_object *t_obj)
Definition module_factory_container.h:305
Definition module_factory_container.h:1304
Definition module_factory_container.h:1284
Definition module_factory_container.h:1265
sc_module constructor container for CCI This uses the CCI Function container, and the FactoryMaker in...
Definition cciutils.h:59
Definition pass.h:26
Definition transaction_forwarder_if.h:23
Definition dynlib_loader.h:23
Tool which reads a Lua configuration file and sets parameters.
Definition biflow.cc:10
std::list< std::string > sc_cci_children(sc_core::sc_module_name name)
return a list of 'unconsumed' children from the given module name, can be used inside or outside the ...
Definition cciutils.cc:63
sc_core::sc_object * find_sc_obj(sc_core::sc_object *m, std::string name, bool test=false)
Helper function to find a sc_object by fully qualified name throws SC_ERROR if nothing found.
Definition cciutils.cc:18