quic/qbox
Loading...
Searching...
No Matches
module_factory_container.h
1/*
2 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
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 <dlfcn.h>
19
20#include <scp/report.h>
21#include <scp/helpers.h>
22
23#include <libgsutils.h>
24#include <libgssync.h>
25
26#include <ports/target-signal-socket.h>
27#include <ports/initiator-signal-socket.h>
28
29#ifndef WITHOUT_QEMU
30#include <ports/target.h>
31#include <ports/initiator.h>
32#include <ports/qemu-target-signal-socket.h>
33#include <ports/qemu-initiator-signal-socket.h>
34#endif
35
36#include <ports/biflow-socket.h>
37#include <module_factory_registery.h>
38#include <transaction_forwarder_if.h>
39#include <tlm_sockets_buswidth.h>
40#include <algorithm>
41#include <vector>
42#include <iterator>
43#include <regex>
44#include <cctype>
45
46namespace gs {
47namespace ModuleFactory {
48
49class ContainerBase : public virtual sc_core::sc_module, public transaction_forwarder_if<CONTAINER>
50{
61public:
63
64 sc_core::sc_module* construct_module(std::string moduletype, sc_core::sc_module_name name, cci::cci_value_list args)
65 {
67 cci::cci_value v = cci::cci_value::from_json("\"" + moduletype + "\"");
68 if (!v.try_get<gs::cci_constructor_vl>(m_fac)) {
69 register_module_from_dylib(name);
70 }
71
72 if (v.try_get<gs::cci_constructor_vl>(m_fac)) {
77 sc_core::sc_module* mod = (m_fac)(name, args);
78 if (mod) {
79 m_constructedModules.emplace_back(mod);
80 return mod;
81 } else {
82 SC_REPORT_ERROR("ModuleFactory", ("Null module type: " + moduletype).c_str());
83 }
84 } else {
85 SC_REPORT_ERROR("ModuleFactory", ("Can't find module type: " + moduletype).c_str());
86 }
88 }
89
94 sc_core::sc_module* construct_module(std::string moduletype, sc_core::sc_module_name name)
95 {
96 cci::cci_value_list emptyargs;
97 return construct_module(moduletype, name, emptyargs);
98 }
99
100 std::string get_parent_name(const std::string& module_name)
101 {
102 return module_name.substr(0, module_name.find_last_of("."));
103 }
104
105 bool is_container_arg_mod_name(const std::string& name)
106 {
107 if (!this->container_mod_arg) return false;
108 std::string arg_mod_full_name_str = std::string(this->container_mod_arg->name());
109 std::string arg_mod_name_str = arg_mod_full_name_str.substr(get_parent_name(arg_mod_full_name_str).size() + 1);
110 return name == arg_mod_name_str;
111 }
112
119 cci::cci_value_list get_module_args(std::string modulename)
120 {
121 cci::cci_value_list args;
122 for (int i = 0; cci::cci_get_broker().has_preset_value(modulename + ".args." + std::to_string(i)); i++) {
123 SCP_TRACE(())("Looking for : {}.args.{}", modulename, std::to_string(i));
124
125 gs::cci_clear_unused(m_broker, modulename + ".args." + std::to_string(i));
126 auto arg = cci::cci_get_broker().get_preset_cci_value(modulename + ".args." + std::to_string(i));
127 if (arg.is_string() && std::string(arg.get_string())[0] == '&') {
128 std::string parent = is_container_arg_mod_name(std::string(arg.get_string()).erase(0, 1))
129 ? get_parent_name(std::string(this->container_mod_arg->name()))
130 : get_parent_name(modulename);
131 if (std::string(arg.get_string()).find(parent, 1) == std::string::npos)
132 arg.set_string("&" + parent + "." + std::string(arg.get_string()).erase(0, 1));
133 }
134 args.push_back(arg);
135 }
136 return args;
137 }
138
139 template <typename I, typename T>
140 bool try_bind(sc_core::sc_object* i_obj, sc_core::sc_object* t_obj)
141 {
142 auto i = dynamic_cast<I*>(i_obj);
143 auto t = dynamic_cast<T*>(t_obj);
144 if (i && t) {
145 i->bind(*t);
146 SCP_INFO(())
147 ("Binding initiator socket: {}({}) with the target socket: {}({})", i_obj->name(), typeid(i).name(),
148 t_obj->name(), typeid(t).name());
149 return true;
150 }
151 t = dynamic_cast<T*>(i_obj);
152 i = dynamic_cast<I*>(t_obj);
153 if (i && t) {
154 i->bind(*t);
155 SCP_INFO(())
156 ("Binding initiator socket: {}({}) with the target socket: {}({})", t_obj->name(), typeid(i).name(),
157 i_obj->name(), typeid(t).name());
158 return true;
159 }
160 return false;
161 }
162
163 /* bind all know port types */
171 void name_bind(sc_core::sc_module* m)
172 {
173 for (auto param : sc_cci_children(m->name())) {
174 /* We should have a param like
175 * foo = &a.baa
176 * foo should relate to an object in this model. a.b.bar should relate to an other
177 * object Note that the names are relative to the current module (this).
178 */
179 std::string targetname = std::string(m->name()) + "." + param;
180 gs::cci_clear_unused(m_broker, targetname + ".0");
181 if (m_broker.get_preset_cci_value(targetname + ".0").is_string()) {
182 // deal with an alias
183 std::string src = m_broker.get_preset_cci_value(targetname + ".0").get_string();
184 m_broker.set_preset_cci_value(targetname + ".address", m_broker.get_preset_cci_value(src + ".address"));
185 m_broker.set_preset_cci_value(targetname + ".size", m_broker.get_preset_cci_value(src + ".size"));
186 }
187 std::string bindname = targetname + ".bind";
188 gs::cci_clear_unused(m_broker, bindname);
189 if (!m_broker.get_preset_cci_value(bindname).is_string()) {
190 continue;
191 }
192 std::string initname = m_broker.get_preset_cci_value(bindname).get_string();
193
194 if (initname.at(0) != '&') continue; // all port binds are donated with a '&', so not for us
195
196 if (initname.find(';') != std::string::npos) {
197 order_bind(m, initname, targetname);
198 } else {
199 initname.erase(0, 1); // remove leading '&'
200 initname = std::string(name()) + "." + initname;
201 SCP_TRACE(())("Bind {} to {}", targetname, initname);
202 do_binding(m, initname, targetname);
203 }
204 }
205 }
206
212 template <unsigned int BIND_BUSWIDTH>
213 bool try_bind_all(sc_core::sc_object* i_obj, sc_core::sc_object* t_obj)
214 {
215 if ((try_bind<tlm_utils::multi_init_base<BIND_BUSWIDTH>, tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(i_obj,
216 t_obj)) ||
217 (try_bind<tlm_utils::multi_init_base<BIND_BUSWIDTH>, tlm_utils::multi_target_base<BIND_BUSWIDTH>>(i_obj,
218 t_obj)) ||
219 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH>, tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(
220 i_obj, t_obj)) ||
221 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH>, tlm_utils::multi_target_base<BIND_BUSWIDTH>>(
222 i_obj, t_obj)) ||
223 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH, tlm::tlm_fw_transport_if<>,
224 tlm::tlm_bw_transport_if<>, 1, sc_core::SC_ZERO_OR_MORE_BOUND>,
225 tlm_utils::multi_target_base<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
227 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH, tlm::tlm_fw_transport_if<>,
228 tlm::tlm_bw_transport_if<>, 1, sc_core::SC_ZERO_OR_MORE_BOUND>,
229 tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
230 (try_bind<
231 tlm::tlm_initiator_socket<BIND_BUSWIDTH, tlm::tlm_base_protocol_types, 1,
232 sc_core::SC_ONE_OR_MORE_BOUND>,
233 tlm::tlm_target_socket<BIND_BUSWIDTH, tlm::tlm_base_protocol_types, 1, sc_core::SC_ZERO_OR_MORE_BOUND>>(
234 i_obj, t_obj)) ||
235 (try_bind<
236 tlm_utils::multi_init_base<BIND_BUSWIDTH>,
237 tlm::tlm_target_socket<BIND_BUSWIDTH, tlm::tlm_base_protocol_types, 1, sc_core::SC_ZERO_OR_MORE_BOUND>>(
238 i_obj, t_obj)) ||
239 (try_bind<
240 tlm::tlm_base_initiator_socket<BIND_BUSWIDTH, tlm::tlm_fw_transport_if<>, tlm::tlm_bw_transport_if<>, 1,
241 sc_core::SC_ZERO_OR_MORE_BOUND>,
242 tlm::tlm_target_socket<BIND_BUSWIDTH, tlm::tlm_base_protocol_types, 1, sc_core::SC_ZERO_OR_MORE_BOUND>>(
243 i_obj, t_obj)) ||
244 (try_bind<sc_core::sc_port<sc_core::sc_signal_inout_if<bool>, 0, sc_core::SC_ZERO_OR_MORE_BOUND>,
248 ||
249 (try_bind<QemuInitiatorSocket<BIND_BUSWIDTH>, tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
250 (try_bind<QemuInitiatorSocket<BIND_BUSWIDTH>, tlm_utils::multi_target_base<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
251 (try_bind<tlm_utils::multi_init_base<BIND_BUSWIDTH>, QemuTargetSocket<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
252 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH>, QemuTargetSocket<BIND_BUSWIDTH>>(i_obj, t_obj)) ||
257#endif
258 ) {
259 return true;
260 } else {
261 return false;
262 }
263 }
264
265 std::list<std::string> PriorityConstruct(void)
266 {
267 std::list<std::string> args;
268 std::set<std::string> done;
269 std::list<std::string> todo;
270 std::string module_name = std::string(sc_module::name());
271
272 todo = gs::sc_cci_children(name());
273
274 while (todo.size() > 0) {
275 int i = 0;
276 for (auto it = todo.begin(); it != todo.end();) {
277 int count_args = 0;
278 std::string name = *it;
279 cci::cci_value_list mod_args = get_module_args(module_name + "." + name);
280 for (auto arg : mod_args) {
281 if (arg.is_string()) {
282 std::string a = arg.get_string();
283 if (a.substr(0, module_name.size() + 1) == "&" + module_name) {
284 if (done.count(a.substr(module_name.size() + 2)) == 0) {
285 count_args += 1;
286 break;
287 }
288 }
289 }
290 }
291 if (count_args == 0) {
292 done.insert(name);
293 it = todo.erase(it);
294 i++;
295 args.push_back(name);
296 } else {
297 it++;
298 }
299 }
300 if (i == 0) {
301 // loop dans todo qui n'a pas été construct
302 for (auto t : todo) {
303 SCP_WARN(()) << "Module name which is not constructable: " << t;
304 }
305 SCP_FATAL(()) << "Module Not constructable";
306 }
307 }
308 return args;
309 }
310
311 void register_module_from_dylib(sc_core::sc_module_name name)
312 {
313 std::string libname;
314#ifdef __APPLE__
315 if (m_broker.has_preset_value(std::string(sc_module::name()) + "." + std::string(name) + ".moduletype")) {
316 libname = m_broker
317 .get_preset_cci_value(std::string(sc_module::name()) + "." + std::string(name) +
318 ".moduletype")
319 .get_string();
320 libname += ".dylib";
321 }
322 if (m_broker.has_preset_value(std::string(sc_module::name()) + "." + std::string(name) + ".dylib_path")) {
323 libname = m_broker
324 .get_preset_cci_value(std::string(sc_module::name()) + "." + std::string(name) +
325 ".dylib_path")
326 .get_string();
327 libname += ".dylib";
328 }
329#else
330 if (m_broker.has_preset_value(std::string(sc_module::name()) + "." + std::string(name) + ".moduletype")) {
331 libname = m_broker
332 .get_preset_cci_value(std::string(sc_module::name()) + "." + std::string(name) +
333 ".moduletype")
334 .get_string();
335 libname += ".so";
336 }
337 if (m_broker.has_preset_value(std::string(sc_module::name()) + "." + std::string(name) + ".dylib_path")) {
338 libname = m_broker
339 .get_preset_cci_value(std::string(sc_module::name()) + "." + std::string(name) +
340 ".dylib_path")
341 .get_string();
342 libname += ".so";
343 }
344#endif
345 std::cout << "libname =" << libname << std::endl;
346 void* libraryHandle = dlopen(libname.c_str(), RTLD_NOW | RTLD_GLOBAL);
347 if (!libraryHandle) {
348 SCP_FATAL(()) << "Impossible to load the library check the path in the lua file or if the library "
349 "exist in your system: "
350 << dlerror();
351 }
352 m_dls.insert(libraryHandle);
353 void (*module_register)() = reinterpret_cast<void (*)()>(dlsym(libraryHandle, "module_register"));
354 if (!module_register) {
355 SCP_WARN(()) << "The method module_register has not been found in the class " << name;
356 }
357 module_register();
358 }
359
360 void ModulesConstruct(void)
361 {
362 for (auto name : PriorityConstruct()) {
363 auto mod_type_name = std::string(sc_module::name()) + "." + name + ".moduletype";
364 if (m_broker.has_preset_value(mod_type_name)) {
365 if (m_broker.has_preset_value(std::string(sc_module::name()) + "." + name + ".dont_construct")) {
366 sc_core::sc_object* no_construct_mod_obj = nullptr;
367 std::string no_construct_mod_name = std::string(sc_module::name()) + "." + name;
369 auto no_construct_mod = dynamic_cast<sc_core::sc_module*>(no_construct_mod_obj);
370 if (!no_construct_mod) {
371 SCP_FATAL(()) << "The object " << std::string(sc_module::name()) + "." + name
372 << " is not yet constructed";
373 }
374 m_allModules.push_back(no_construct_mod);
375 } else {
376 gs::cci_clear_unused(m_broker, mod_type_name);
377 cci::cci_value cci_type = gs::cci_get(m_broker, mod_type_name);
378 if (cci_type.is_string()) {
379 std::string mod_type = cci_type.get_string();
380 SCP_INFO(()) << "Adding a " << mod_type << " with name "
381 << std::string(sc_module::name()) + "." + name;
382 cci::cci_value_list mod_args = get_module_args(std::string(sc_module::name()) + "." + name);
383 SCP_INFO(()) << mod_args.size() << " arguments found for " << mod_type;
384 sc_core::sc_module* m = construct_module(mod_type, name.c_str(), mod_args);
385 if (!m) {
387 "ModuleFactory",
388 ("Can't automatically handle argument list for module: " + mod_type).c_str());
389 }
390
391 m_allModules.push_back(m);
392 if (!m_local_pass) {
393 m_local_pass = dynamic_cast<transaction_forwarder_if<PASS>*>(m);
394 }
395 } else {
396 SCP_WARN(()) << "The value of the parameter moduletype of the module " << name
397 << " is not a string";
398 }
399 }
400 } // else it's some other config
401 }
402 // bind everything
403 for (auto mod : m_allModules) {
404 name_bind(mod);
405 }
406 }
407
408 using tlm_initiator_socket_type = tlm_utils::simple_initiator_socket_b<
409 ContainerBase, DEFAULT_TLM_BUSWIDTH, tlm::tlm_base_protocol_types, sc_core::SC_ZERO_OR_MORE_BOUND>;
410 using tlm_target_socket_type = tlm_utils::simple_target_socket_tagged_b<
411 ContainerBase, DEFAULT_TLM_BUSWIDTH, tlm::tlm_base_protocol_types, sc_core::SC_ZERO_OR_MORE_BOUND>;
412
413private:
414 bool m_defer_modules_construct;
415 std::list<sc_core::sc_module*> m_allModules;
416 std::list<std::shared_ptr<sc_core::sc_module>> m_constructedModules;
417
418 std::set<void*> m_dls;
419
420public:
421 cci::cci_broker_handle m_broker;
422 cci::cci_param<std::string> moduletype; // for consistency
423 cci::cci_param<uint32_t> p_tlm_initiator_ports_num;
424 cci::cci_param<uint32_t> p_tlm_target_ports_num;
425 cci::cci_param<uint32_t> p_initiator_signals_num;
426 cci::cci_param<uint32_t> p_target_signals_num;
427 sc_core::sc_vector<tlm_initiator_socket_type> initiator_sockets;
428 sc_core::sc_vector<tlm_target_socket_type> target_sockets;
429 sc_core::sc_vector<InitiatorSignalSocket<bool>> initiator_signal_sockets;
430 sc_core::sc_vector<TargetSignalSocket<bool>> target_signal_sockets;
431 TargetSignalSocket<bool> container_self_reset;
432 transaction_forwarder_if<PASS>* m_local_pass;
433
434 std::vector<cci::cci_param<gs::cci_constructor_vl>*> registered_mods;
435 sc_core::sc_object* container_mod_arg;
436
437 virtual ~ContainerBase()
438 {
439 m_constructedModules.reverse();
440 m_constructedModules.clear();
441 for (auto l : m_dls) {
442 dlclose(l);
443 }
444 }
445
446 std::shared_ptr<sc_core::sc_module> find_module_by_name(const std::string& mod_name)
447 {
448 auto ret = std::find_if(m_constructedModules.begin(), m_constructedModules.end(),
449 [&](auto mod) { return (mod && std::string(mod->name()) == mod_name); });
450 if (ret == m_constructedModules.end()) {
451 return nullptr;
452 }
453 return *ret;
454 }
455
456 template <typename T>
457 std::shared_ptr<sc_core::sc_module> find_module_by_cci_param(const std::string& cci_param_name, const T& cmp_value)
458 {
459 T ret_val;
460 auto ret = std::find_if(m_constructedModules.begin(), m_constructedModules.end(), [&](auto mod) {
461 return (mod && m_broker.has_preset_value(std::string(mod->name()) + "." + cci_param_name) &&
462 m_broker.get_preset_cci_value(std::string(mod->name()) + "." + cci_param_name)
463 .template try_get<T>(ret_val) &&
464 (ret_val == cmp_value));
465 });
466 if (ret == m_constructedModules.end()) {
467 return nullptr;
468 }
469 return *ret;
470 }
471
478 ContainerBase(const sc_core::sc_module_name _n, bool defer_modules_construct,
479 sc_core::sc_object* p_container_mod_arg = nullptr)
480 : m_defer_modules_construct(defer_modules_construct)
481 , m_broker(cci::cci_get_broker())
482 , moduletype("moduletype", "", "Module type for the TLM container, must be \"Container\"")
483 , p_tlm_initiator_ports_num("tlm_initiator_ports_num", 0, "number of tlm initiator ports")
484 , p_tlm_target_ports_num("tlm_target_ports_num", 0, "number of tlm target ports")
485 , p_initiator_signals_num("initiator_signals_num", 0, "number of initiator signals")
486 , p_target_signals_num("target_signals_num", 0, "number of target signals")
487 , initiator_sockets("initiator_socket")
488 , target_sockets("target_socket")
489 , initiator_signal_sockets("initiator_signal_socket")
490 , target_signal_sockets("target_signal_socket")
491 , container_self_reset("container_self_reset")
492 , m_local_pass(nullptr)
493 , container_mod_arg(p_container_mod_arg)
494 {
495 SCP_DEBUG(()) << "ContainerBase Constructor";
496
497 initiator_sockets.init(p_tlm_initiator_ports_num.get_value(),
498 [this](const char* n, int i) { return new tlm_initiator_socket_type(n); });
499 target_sockets.init(p_tlm_target_ports_num.get_value(),
500 [this](const char* n, int i) { return new tlm_target_socket_type(n); });
501 initiator_signal_sockets.init(p_initiator_signals_num.get_value(),
502 [this](const char* n, int i) { return new InitiatorSignalSocket<bool>(n); });
503 target_signal_sockets.init(p_target_signals_num.get_value(),
504 [this](const char* n, int i) { return new TargetSignalSocket<bool>(n); });
505
506 for (int i = 0; i < p_tlm_target_ports_num.get_value(); i++) {
507 target_sockets[i].register_b_transport(this, &ContainerBase::b_transport, i);
508 target_sockets[i].register_transport_dbg(this, &ContainerBase::transport_dbg, i);
509 target_sockets[i].register_get_direct_mem_ptr(this, &ContainerBase::get_direct_mem_ptr, i);
510 }
511
512 for (int i = 0; i < p_tlm_initiator_ports_num.get_value(); i++) {
513 initiator_sockets[i].register_invalidate_direct_mem_ptr(this, &ContainerBase::invalidate_direct_mem_ptr);
514 }
515
516 for (int i = 0; i < p_target_signals_num.get_value(); i++) {
517 target_signal_sockets[i].register_value_changed_cb([&, i](bool value) {
518 if (m_local_pass) m_local_pass->fw_handle_signal(i, value);
519 });
520 }
521
522 container_self_reset.register_value_changed_cb([this](bool value) { do_reset(value); });
523
524 auto mods = gs::ModuleFactory::GetAvailableModuleList();
525
526 while (mods->size()) {
527 registered_mods.push_back((mods->back())());
528 mods->pop_back();
529 }
530
531 if (!m_defer_modules_construct) ModulesConstruct();
532 }
533
534 void fw_b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) override
535 {
536 SCP_DEBUG(()) << "calling b_transport on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
537 initiator_sockets[id]->b_transport(trans, delay);
538 SCP_DEBUG(()) << "return from b_transport on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
539 }
540
541 unsigned int fw_transport_dbg(int id, tlm::tlm_generic_payload& trans) override
542 {
543 SCP_DEBUG(()) << "calling transport_dbg on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
544 unsigned int ret = initiator_sockets[id]->transport_dbg(trans);
545 SCP_DEBUG(()) << "return from transport_dbg on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
546 return ret;
547 }
548
549 bool fw_get_direct_mem_ptr(int id, tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data) override
550 {
551 SCP_DEBUG(()) << "calling get_direct_mem_ptr on initiator_socket_" << id << " " << scp::scp_txn_tostring(trans);
552 bool ret = initiator_sockets[id]->get_direct_mem_ptr(trans, dmi_data);
553 SCP_DEBUG(()) << "return from get_direct_mem_ptr on initiator_socket_" << id << " "
554 << " RET: " << std::boolalpha << ret << " " << scp::scp_txn_tostring(trans)
555 << " IS_READ_ALLOWED: " << std::boolalpha << dmi_data.is_read_allowed() << " "
556 << " IS_WRITE_ALLOWED: " << std::boolalpha << dmi_data.is_write_allowed();
557 return ret;
558 }
559
560 void fw_invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) override
561 {
562 SCP_DEBUG(()) << " " << name() << " invalidate_direct_mem_ptr "
563 << " start address 0x" << std::hex << start << " end address 0x" << std::hex << end;
564 for (int i = 0; i < target_sockets.size(); i++) {
565 target_sockets[i]->invalidate_direct_mem_ptr(start, end);
566 }
567 }
568
569 void fw_handle_signal(int id, bool value) override
570 {
571 SCP_DEBUG(()) << "calling handle_signal on initiator_signal_socket_" << id << " value: " << std::boolalpha
572 << value;
573 initiator_signal_sockets[id]->write(value);
574 }
575
576private:
577 void b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
578 {
579 if (m_local_pass) {
580 m_local_pass->fw_b_transport(id, trans, delay);
581 }
582 }
583
584 unsigned int transport_dbg(int id, tlm::tlm_generic_payload& trans)
585 {
586 if (m_local_pass) {
587 return m_local_pass->fw_transport_dbg(id, trans);
588 }
589 return 0;
590 }
591
592 bool get_direct_mem_ptr(int id, tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data)
593 {
594 if (m_local_pass) {
595 return m_local_pass->fw_get_direct_mem_ptr(id, trans, dmi_data);
596 }
597 return false;
598 }
599
600 void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end)
601 {
602 if (m_local_pass) {
603 m_local_pass->fw_invalidate_direct_mem_ptr(start, end);
604 }
605 }
606
607 std::vector<std::string> parse_order_str(const std::string& reset_order)
608 {
609 std::vector<std::string> ret;
610 if (reset_order.empty()) {
611 return ret;
612 }
613 std::string reset_order_tr = reset_order;
614 reset_order_tr.erase(
615 std::remove_if(reset_order_tr.begin(), reset_order_tr.end(), [](char c) { return std::isspace(c); }),
616 reset_order_tr.end());
617 size_t sig_count = std::count_if(reset_order_tr.begin(), reset_order_tr.end(), [](char c) { return c == ';'; });
618 ret.resize(sig_count + 1);
619 const std::regex separator(R"(;)");
620 std::copy(std::sregex_token_iterator(reset_order_tr.begin(), reset_order_tr.end(), separator, -1),
621 std::sregex_token_iterator(), ret.begin());
622 return ret;
623 }
624
625 void do_binding(sc_core::sc_module* module_obj, const std::string& initiator_name, const std::string& target_name)
626 {
627 sc_core::sc_object* i_obj = nullptr;
628 sc_core::sc_object* t_obj = nullptr;
629 /* find the initiator object */
630
631 i_obj = find_sc_obj(nullptr, initiator_name);
632
633 /* find the target object which must be inside this object */
635
636 // actually you could probably just cast everything to (tlm::tlm_target_socket<>*), but
637 // we will dynamic cast to be sure.
639 SCP_FATAL(())("No bind found for: {} to {}", i_obj->name(), t_obj->name());
640 }
641 }
642
643 void order_bind(sc_core::sc_module* module_obj, const std::string& target_order_str,
644 const std::string& initiator_name)
645 {
646 if (!target_order_str.empty()) {
647 std::vector<std::string> target_vec = parse_order_str(target_order_str);
648 for (const auto& target : target_vec) {
649 std::string target_name = target;
650 if (target_name.at(0) != '&') continue;
651 target_name.erase(0, 1);
652 target_name = std::string(name()) + "." + target_name;
653 SCP_TRACE(())("Bind {} to {}", target_name, initiator_name);
655 }
656 }
657 }
658
659 virtual void do_reset(bool value)
660 {
661 if (value) SCP_WARN(()) << "Reset";
662 }
663};
664
669{
670public:
671 SCP_LOGGER(());
672 Container(const sc_core::sc_module_name& n): ContainerBase(n, false, nullptr)
673 {
674 SCP_DEBUG(()) << "Container constructor";
675 assert(std::string(moduletype.get_value()) == "Container");
676 }
677
678 virtual ~Container() = default;
679};
685{
686public:
687 SCP_LOGGER(());
688 ContainerWithArgs(const sc_core::sc_module_name& n, sc_core::sc_object* p_container_mod_arg)
690 {
691 SCP_DEBUG(()) << "ContainerWithArgs constructor";
692 assert(std::string(moduletype.get_value()) == "ContainerWithArgs");
693 }
694
695 virtual ~ContainerWithArgs() = default;
696};
702{
703public:
704 SCP_LOGGER(());
705 ContainerDeferModulesConstruct(const sc_core::sc_module_name& n): ContainerBase(n, true, nullptr)
706 {
707 SCP_DEBUG(()) << "ContainerDeferModulesConstruct constructor";
708 assert(std::string(moduletype.get_value()) == "ContainerDeferModulesConstruct");
709 }
710
711 virtual ~ContainerDeferModulesConstruct() = default;
712};
713
714} // namespace ModuleFactory
715} // namespace gs
716
720GSC_MODULE_REGISTER(Container);
721GSC_MODULE_REGISTER(ContainerDeferModulesConstruct);
722GSC_MODULE_REGISTER(ContainerWithArgs, sc_core::sc_object*);
723#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:50
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:94
void name_bind(sc_core::sc_module *m)
Bind all known port types.
Definition module_factory_container.h:171
SCP_LOGGER(())
construct a module using the pre-register CCI functor, with typed arguments from a CCI value list....
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:64
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:478
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:119
bool try_bind_all(sc_core::sc_object *i_obj, sc_core::sc_object *t_obj)
Definition module_factory_container.h:213
Definition module_factory_container.h:702
Definition module_factory_container.h:685
Definition module_factory_container.h:669
sc_module constructor container for CCI This uses the CCI Function container, and the FactoryMaker in...
Definition cciutils.h:59
Definition transaction_forwarder_if.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