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