David Black Posted December 27, 2018 Report Share Posted December 27, 2018 (edited) Note: This is somewhat of an expert question. I am considering how best to probe a SystemC design to determine connectivity. My goal is to be able to automatically determine how ports are connected at end-of-elaboration or later. My first inclination was to do something like: std::cout << "Connection from " << myport.name() << " to " << myport->name() << std::endl; Just to be clear, myport.name() provides the path to the port itself; whereas, myport->name() should provide the path to the channel that the port is connected to. However the above requires all channels and interfaces to implement the method name(), which is not currently the case. The implementation would simply be: const char* Channel::name( void ) const { return sc_object::name(); } I am first looking to see if anybody has a current solution that does not require modification of the standard. I don't think it exists, but I could be overlooking something. Edited December 27, 2018 by David Black Clarification Quote Link to comment Share on other sites More sharing options...
Roman Popov Posted December 27, 2018 Report Share Posted December 27, 2018 I think you have answered your question yourself 🙂 Quote However the above requires all channels and interfaces to implement the method name(), which is not currently the case. In practice however most channels inherit sc_object, so they have method name(). So you can do something like this (print_connections method): #include <systemc.h> struct void_if : sc_interface { }; struct test : sc_module , void_if { struct submodule : sc_module , void_if { sc_export<void_if> SC_NAMED(void_export); SC_CTOR(submodule) { void_export.bind(*this); } } SC_NAMED(sub); struct not_sc_object : void_if { } non_sc_obj; sc_vector<sc_port<void_if>> SC_NAMED(ports, 3); SC_CTOR(test) { ports[0].bind(*this); ports[1].bind(sub.void_export); ports[2].bind(non_sc_obj); } void print_connections(const sc_object * cur, std::string padding ) const { cout << padding << cur->name(); const sc_interface * binded_iface = nullptr; if (auto exp = dynamic_cast<const sc_export_base*>(cur)) { cout << " (export) "; binded_iface = exp->get_interface(); } else if (auto port = dynamic_cast<const sc_port_base*>(cur)) { cout << " (port) "; binded_iface = port->get_interface(); } if (binded_iface) { cout << " bound to "; if (auto binded_obj = dynamic_cast<const sc_object*>(binded_iface)) { cout << binded_obj->name(); } else { cout << "not an sc_object"; } } cout << "\n"; for (auto *child : cur->get_child_objects()) { print_connections(child, padding + " "); } } void start_of_simulation() override { for (auto * obj : sc_get_top_level_objects()) { print_connections ( obj , ""); } } }; int sc_main(int, char**) { test test_inst{"test_inst"}; sc_start(); return 0; } Will print: test_inst test_inst.sub test_inst.sub.void_export (export) bound to test_inst.sub test_inst.ports test_inst.ports_0 (port) bound to test_inst test_inst.ports_1 (port) bound to test_inst.sub test_inst.ports_2 (port) bound to not an sc_object Sometimes you also want to print hierarchical port-to-port connections (instead of port-to-interface) . This I think is not possible. For our internal uses we had modified Accellera SystemC kernel to preserve information about hierarchical connections. Quote Link to comment Share on other sites More sharing options...
David Black Posted December 29, 2018 Author Report Share Posted December 29, 2018 Actually, I was very close to the solution you provided, and it provides some of the solution. The hierarchical is not a problem for my needs. I am having problems getting my TLM sockets to report properly. I only need the initiator sockets. Thank you. Quote Link to comment Share on other sites More sharing options...
Roman Popov Posted December 31, 2018 Report Share Posted December 31, 2018 On 12/29/2018 at 2:10 AM, David Black said: I am having problems getting my TLM sockets to report properly. Yes, with TLM sockets this won't work well: for example classes implementing TLM interfaces inside tlm_utils::* sockets do not inherit from sc_object. So you will have "not an sc_object" reported if you call print_connections function on some generic TLM model. In general such a problem is a subset of "serialization" problem, which is not possible to solve in standard C++. Because C++ wants to be "zero cost" and does not provide dynamic introspection capabilities. You can solve the problem radically by utilizing C++ compiler internals. By doing so you can implement whatever functionality you want (usually people want the same features they have in Verilog/VHDL tools). I'm not sure, but probably you can have this feature of dumping connectivity from commercial SystemC tools. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.