quic/qbox
Loading...
Searching...
No Matches
component_constructor.h
1/*
2 * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef __GS_COMPONENT_CONSTRUCTOR__
8#define __GS_COMPONENT_CONSTRUCTOR__
9
10#include <cci_configuration>
11#include <systemc>
12#include <tlm>
13#include <scp/report.h>
14#include <module_factory_registery.h>
15#include <cciutils.h>
16#include <sstream>
17#include <functional>
18#include "fss_utils.h"
19#include "fss_interfaces.h"
20#include <dlfcn.h>
21
22namespace gs {
23
24class component_constructor : public sc_core::sc_module
25{
26 SCP_LOGGER();
27 typedef fssBindIFHandle (*CreateNodeFnPtr)(fssString, fssConfigIfHandle);
28 typedef fssRetStatus (*DestroyNodeFnPtr)(fssBindIFHandle);
29
30public:
31 component_constructor(const sc_core::sc_module_name& nm)
32 : sc_core::sc_module(nm)
33 , m_broker(cci::cci_get_broker())
34 , p_node_exe_path("node_exe_path", "", "path of the node binary executable or .so")
35 , p_node_name("node_name", "", "unique name of the spawned node")
36 , events_binder("events_binder")
37 , time_sync_binder("time_sync_binder")
38 , data_binder("data_binder")
39 , control_binder("control_binder")
40 {
41 SCP_TRACE(()) << "component_constructor constructor";
42 if (p_node_exe_path.get_value().empty()) {
43 SCP_FATAL(()) << "node_exe_path CCI parameter is not set!";
44 }
45 if (p_node_name.get_value().empty()) {
46 SCP_FATAL(()) << "node_name CCI parameter is not set!";
47 }
48 m_config_handle.version = (1ULL << 32);
49 m_config_handle.getConfigs = &component_constructor::get_configs;
50 CreateNode = get_shared_lib_function_ptr<CreateNodeFnPtr>("fssCreateNode");
51 DestroyNode = get_shared_lib_function_ptr<DestroyNodeFnPtr>("fssDestroyNode");
52 create_node();
53 init_binders();
54 }
55
57
59 {
61 _config_if_handle, &component_constructor::m_config_handle);
62 return cmp->get_node_config(name);
63 }
64
65 fssBindIFHandle get_node_bind_handle() { return m_node_handle; }
66
67private:
68 void create_node()
69 {
70 m_node_handle = CreateNode(p_node_name.get_value().c_str(), &m_config_handle);
71 if (!m_node_handle) {
72 SCP_FATAL(()) << "Couldn't create node: " << p_node_name.get_value();
73 }
74 }
75
76 void init_binders()
77 {
78 for (const auto& param : m_broker.get_unconsumed_preset_values()) {
79 auto curr_param_name = param.first;
80 auto curr_param_val = param.second.to_json();
81 if ((curr_param_name.rfind(".name") + std::string(".name").size()) == curr_param_name.size()) {
82 if (curr_param_name.find(events_binder.name()) != std::string::npos) {
83 events_binder.emplace_back(curr_param_val.c_str(), get_node_bind_handle());
84 } else if (curr_param_name.find(time_sync_binder.name()) != std::string::npos) {
85 time_sync_binder.emplace_back(curr_param_val.c_str(), get_node_bind_handle());
86 } else if (curr_param_name.find(data_binder.name()) != std::string::npos) {
87 data_binder.emplace_back(curr_param_val.c_str(), get_node_bind_handle());
88 } else if (curr_param_name.find(control_binder.name()) != std::string::npos) {
89 control_binder.emplace_back(curr_param_val.c_str(), get_node_bind_handle());
90 } else {
91 continue;
92 }
93 }
94 }
95 }
96
97 const char* get_node_config(const std::string& _name)
98 {
99 std::string module_name = std::string(name());
100 std::stringstream configs;
101 for (const auto& param : m_broker.get_unconsumed_preset_values()) {
102 auto param_name = param.first;
103 auto key = param.first;
104 auto value = param.second.to_json();
105 std::string config_marker = module_name + ".node_configs";
106 if (key.find(config_marker) == 0) {
107 key = key.substr(config_marker.length() + 1);
108 m_broker.ignore_unconsumed_preset_values(
109 [param_name](const std::pair<std::string, cci::cci_value>& iv) -> bool {
110 return iv.first == param_name;
111 });
112 if (!_name.empty() && (_name != key)) continue;
113 configs << key << "=" << value << ";";
114 }
115 }
116 if (!_name.empty() && configs.str().empty()) {
117 SCP_FATAL(()) << "Requested configuration: " << _name << " was not found!";
118 }
119 return configs.str().c_str();
120 }
121
122 template <typename T>
123 T get_shared_lib_function_ptr(const char* function_name)
124 {
125 if (!m_lib_handle) {
126 m_lib_handle = dlopen(p_node_exe_path.get_value().c_str(), RTLD_NOW | RTLD_GLOBAL);
127 }
128 if (!m_lib_handle) {
129 SCP_FATAL(()) << "Failed to load: " << p_node_exe_path.get_value() << " Error: " << dlerror();
130 }
131 T fn = reinterpret_cast<T>(dlsym(m_lib_handle, function_name));
132 if (!fn) {
133 SCP_FATAL(()) << "function: " << function_name
134 << "is not found in the library: " << p_node_exe_path.get_value().c_str();
135 }
136 return fn;
137 }
138
139 void end_of_simulation() { DestroyNode(m_node_handle); }
140
141private:
142 cci::cci_broker_handle m_broker;
143 cci::cci_param<std::string> p_node_exe_path;
144 cci::cci_param<std::string> p_node_name;
145 void* m_lib_handle;
146 fssBindIFHandle m_node_handle;
147 fssConfigIf m_config_handle;
148 CreateNodeFnPtr CreateNode;
149 DestroyNodeFnPtr DestroyNode;
150
151public:
152 sc_core::sc_vector<fss_events_binder> events_binder;
153 sc_core::sc_vector<fss_time_sync_binder> time_sync_binder;
154 sc_core::sc_vector<fss_data_binder> data_binder;
155 sc_core::sc_vector<fss_control_binder> control_binder;
156};
157} // namespace gs
158extern "C" void module_register();
159#endif
Definition target.h:160
Definition component_constructor.h:25
Tool which reads a Lua configuration file and sets parameters.
Definition biflow.cc:10
Bind interface encapsulates the functions to bind different interfaces.
Definition fss_interfaces.h:368
Configuration interface encapsulates the function to get configurations.
Definition fss_interfaces.h:336