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>>>
68 mutable std::map<std::string, std::vector<std::pair<std::string, cci::cci_value>>>
69 m_moduletype_params_cache;
70 mutable std::map<std::string, std::set<std::string>>
71 m_per_pass_nested_deps_cache;
72 mutable std::map<std::string, bool> m_is_container_type_cache;
77 sc_core::sc_module*
construct_module(std::string moduletype, sc_core::sc_module_name name, cci::cci_value_list args)
80 cci::cci_value
v = cci::cci_value::from_json(
"\"" + moduletype +
"\"");
82 register_module_from_dylib(name);
90 sc_core::sc_module* mod = (
m_fac)(name, args);
92 m_constructedModules.emplace_back(mod);
113 std::string get_parent_name(
const std::string&
module_name)
127 auto it = m_is_absolute_path_cache.find(name);
128 if (
it != m_is_absolute_path_cache.end()) {
139 }
else if (name.find(
'.') != std::string::npos) {
153 if (
obj !=
nullptr) {
167 m_is_absolute_path_cache[name] =
result;
171 bool is_container_arg_mod_name(
const std::string& name)
173 if (!this->container_mod_arg)
return false;
189 if (
cache_it != m_module_args_cache.end()) {
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++) {
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);
205 std::string parent = is_container_arg_mod_name(
arg_path)
206 ? get_parent_name(std::string(this->container_mod_arg->name()))
209 if (
arg_path.find(parent) == std::string::npos) {
227 template <
typename I,
typename T>
228 bool try_bind(sc_core::sc_object*
i_obj, sc_core::sc_object*
t_obj)
230 auto i =
dynamic_cast<I*
>(
i_obj);
231 auto t =
dynamic_cast<T*
>(
t_obj);
235 (
"Binding initiator socket: {}({}) with the target socket: {}({})",
i_obj->name(),
typeid(
i).name(),
236 t_obj->name(),
typeid(
t).name());
244 (
"Binding initiator socket: {}({}) with the target socket: {}({})",
t_obj->name(),
typeid(
i).name(),
245 i_obj->name(),
typeid(
t).name());
268 gs::cci_clear_unused(m_broker,
targetname +
".0");
269 if (m_broker.get_preset_cci_value(
targetname +
".0").is_string()) {
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"));
276 gs::cci_clear_unused(m_broker,
bindname);
277 if (!m_broker.get_preset_cci_value(
bindname).is_string()) {
280 std::string
initname = m_broker.get_preset_cci_value(
bindname).get_string();
282 if (
initname.at(0) !=
'&')
continue;
284 if (
initname.find(
';') != std::string::npos) {
304 template <
unsigned int BIND_BUSWIDTH>
307 if ((try_bind<tlm_utils::multi_init_base<BIND_BUSWIDTH>, tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(
i_obj,
309 (try_bind<tlm_utils::multi_init_base<BIND_BUSWIDTH>, tlm_utils::multi_target_base<BIND_BUSWIDTH>>(
i_obj,
311 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH>, tlm::tlm_base_target_socket<BIND_BUSWIDTH>>(
313 (try_bind<tlm::tlm_base_initiator_socket<BIND_BUSWIDTH>, tlm_utils::multi_target_base<BIND_BUSWIDTH>>(
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)) ||
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>>(
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>>(
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>>(
336 (try_bind<sc_core::sc_port<sc_core::sc_signal_inout_if<bool>, 0, sc_core::SC_ZERO_OR_MORE_BOUND>,
366 auto cache_it = m_is_container_type_cache.find(name);
367 if (
cache_it != m_is_container_type_cache.end()) {
371 std::string
module_name = std::string(sc_module::name());
380 mod_type ==
"ContainerDeferModulesConstruct" ||
mod_type ==
"container_builder");
385 m_is_container_type_cache[name] =
result;
401 if (
cache_it != m_per_pass_nested_deps_cache.end()) {
406 std::string
module_name = std::string(sc_module::name());
410 std::vector<std::pair<std::string, cci::cci_value>>
all_params;
415 auto params_range = m_broker.get_unconsumed_preset_values(
418 iv.first.find(
".moduletype") != std::string::npos &&
419 iv.first.find(
".moduletype") ==
iv.first.length() - 11;
439 if (
dot_pos != std::string::npos) {
446 if (
child_path.find(
"config.") == 0)
continue;
450 if (
dot_pos != std::string::npos) {
470 for (
int i = 0; m_broker.has_preset_value(
child_config_name +
".args." + std::to_string(
i));
i++) {
478 if (
arg.is_string()) {
479 std::string
a =
arg.get_string();
480 if (
a.length() > 0 &&
a[0] ==
'&') {
505 if (
mt.is_string()) {
506 std::string moduletype =
mt.get_string();
507 child_is_container = (moduletype ==
"Container" || moduletype ==
"container_builder");
515 auto child_params = m_broker.get_unconsumed_preset_values(
518 iv.first.find(
".bind") != std::string::npos;
522 if (
param.second.is_string()) {
528 if (end == std::string::npos) end =
bind_value.length();
532 size_t start =
single_bind.find_first_not_of(
" \t\n\r");
533 if (start != std::string::npos) {
568 param_name.find(
".config.") == std::string::npos &&
569 param_name.find(
".bind") != std::string::npos;
573 if (
param.second.is_string()) {
579 if (end == std::string::npos) end =
bind_value.length();
583 size_t start =
single_bind.find_first_not_of(
" \t\n\r");
584 if (start != std::string::npos) {
615 bool are_dependencies_available(
const std::string& name,
const std::set<std::string>& done)
617 std::string
module_name = std::string(sc_module::name());
622 if (
arg.is_string()) {
623 std::string
a =
arg.get_string();
624 if (
a.length() > 0 &&
a[0] ==
'&') {
642 if (
dot_pos != std::string::npos) {
659 std::set<std::string> get_bind_references_to_module(
const std::string&
module_name,
679 auto mod_params = m_broker.get_unconsumed_preset_values(
710 int get_construction_priority(
const std::string& name)
712 std::string
module_name = std::string(sc_module::name());
726 std::list<std::string> PriorityConstruct(
void)
728 std::list<std::string> args;
729 std::set<std::string> done;
731 std::string
module_name = std::string(sc_module::name());
746 int priority = get_construction_priority(mod);
760 m_per_pass_nested_deps_cache.clear();
781 auto mod_params = m_broker.get_unconsumed_preset_values(
804 if (
dot_pos != std::string::npos) {
819 for (
const auto& mod :
todo) {
823 if (
arg.is_string()) {
824 std::string
a =
arg.get_string();
825 if (
a.length() > 0 &&
a[0] ==
'&') {
843 if (
dot_pos != std::string::npos) {
861 std::string name = *
it;
884 args.push_back(name);
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);
902 if (
arg.is_string()) {
903 std::string
a =
arg.get_string();
904 if (
a.length() > 0 &&
a[0] ==
'&') {
922 SCP_FATAL(())(
"Unresolvable module dependencies");
930 void register_module_from_dylib(sc_core::sc_module_name name)
933 std::vector<std::string>
lib_types = {
".moduletype",
".dylib_path" };
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());
943 qemu::LibraryLoaderIface::LibraryIfacePtr
libraryHandle = m_library_loader.load_library(
libname);
945 SCP_FATAL(())(
"Failed to load library {}: {}",
libname, m_library_loader.get_last_error());
950 void (*module_register)() =
nullptr;
952 module_register =
reinterpret_cast<void (*)()
>(
libraryHandle->get_symbol(
"module_register"));
959 void ModulesConstruct(
void)
961 for (
auto name : PriorityConstruct()) {
962 auto mod_type_name = std::string(sc_module::name()) +
"." + name +
".moduletype";
964 if (m_broker.has_preset_value(std::string(sc_module::name()) +
"." + name +
".dont_construct")) {
970 SCP_FATAL(()) <<
"The object " << std::string(sc_module::name()) +
"." + name
971 <<
" is not yet constructed";
984 (
"Can't automatically handle argument list for module: " +
mod_type).
c_str());
987 m_allModules.push_back(
m);
992 SCP_WARN(()) <<
"moduletype parameter is not a string for " << name;
998 for (
auto mod : m_allModules) {
1001 SCP_DEBUG(())(
"ModulesConstruct complete");
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>;
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;
1014 std::set<qemu::LibraryLoaderIface::LibraryIfacePtr> m_dls;
1018 cci::cci_broker_handle m_broker;
1019 cci::cci_param<std::string> moduletype;
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;
1031 std::vector<cci::cci_param<gs::cci_constructor_vl>*> registered_mods;
1032 sc_core::sc_object* container_mod_arg;
1034 virtual ~ContainerBase()
1036 m_constructedModules.reverse();
1037 m_constructedModules.clear();
1040 std::shared_ptr<sc_core::sc_module> find_module_by_name(
const std::string&
mod_name)
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()) {
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)
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));
1060 if (
ret == m_constructedModules.end()) {
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")
1089 SCP_DEBUG(()) <<
"ContainerBase Constructor";
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); });
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);
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);
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);
1116 container_self_reset.register_value_changed_cb([
this](
bool value) { do_reset(value); });
1118 auto mods = gs::ModuleFactory::GetAvailableModuleList();
1120 while (
mods->size()) {
1121 registered_mods.push_back((
mods->back())());
1125 if (!m_defer_modules_construct) ModulesConstruct();
1128 void fw_b_transport(
int id, tlm::tlm_generic_payload&
trans, sc_core::sc_time& delay)
override
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);
1135 unsigned int fw_transport_dbg(
int id, tlm::tlm_generic_payload&
trans)
override
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);
1143 bool fw_get_direct_mem_ptr(
int id, tlm::tlm_generic_payload&
trans, tlm::tlm_dmi& dmi_data)
override
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();
1154 void fw_invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end)
override
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);
1163 void fw_handle_signal(
int id,
bool value)
override
1165 SCP_DEBUG(()) <<
"calling handle_signal on initiator_signal_socket_" <<
id <<
" value: " << std::boolalpha
1167 initiator_signal_sockets[id]->write(value);
1171 void b_transport(
int id, tlm::tlm_generic_payload&
trans, sc_core::sc_time& delay)
1174 m_local_pass->fw_b_transport(
id,
trans, delay);
1178 unsigned int transport_dbg(
int id, tlm::tlm_generic_payload&
trans)
1181 return m_local_pass->fw_transport_dbg(
id,
trans);
1186 bool get_direct_mem_ptr(
int id, tlm::tlm_generic_payload&
trans, tlm::tlm_dmi& dmi_data)
1189 return m_local_pass->fw_get_direct_mem_ptr(
id,
trans, dmi_data);
1194 void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end)
1197 m_local_pass->fw_invalidate_direct_mem_ptr(start, end);
1201 std::vector<std::string> parse_order_str(
const std::string&
reset_order)
1203 std::vector<std::string>
ret;
1215 std::sregex_token_iterator(), ret.begin());
1221 sc_core::sc_object*
i_obj =
nullptr;
1222 sc_core::sc_object*
t_obj =
nullptr;
1255 virtual void do_reset(
bool value)
1257 if (value)
SCP_WARN(()) <<
"Reset";