36    SCP_LOGGER((
DMI), 
"dmi");
 
   43    void register_boundto(std::string s)
 
   48        ti.index = bound_targets.size();
 
   49        SCP_DEBUG(()) << 
"Connecting : " << ti.name;
 
   52        for (
i = 0; 
i < s.length(); 
i++)
 
   53            if (s[
i] != 
tmp[
i]) 
break;
 
   54        ti.shortname = s.substr(
i);
 
   55        bound_targets.push_back(ti);
 
   59    void b_transport(
int id, tlm::tlm_generic_payload& 
trans, sc_core::sc_time& delay)
 
   63        auto ti = decode_address(
trans);
 
   66            SCP_WARN(())(
"Attempt to access unknown location in register memory at offset 0x{:x}", 
addr);
 
   67            trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
 
   71#ifdef ENABLE_MODULE_NAME_DBG_INFO 
   76            SCP_DEBUG(()) << 
"b_transport: " << txn_command_str(
trans) << 
" to Register at address: 0x" << std::hex
 
   77                          << 
trans.get_address() << 
" which belongs to Module: [" << 
mod_name << 
"]";
 
   82        if (
trans.get_response_status() >= tlm::TLM_INCOMPLETE_RESPONSE) {
 
   84            if (ti->use_offset) 
trans.set_address(
addr - ti->address);
 
   85            initiator_socket[ti->index]->b_transport(
trans, delay);
 
   86            if (ti->use_offset) 
trans.set_address(
addr);
 
   89        if (
trans.get_response_status() >= tlm::TLM_OK_RESPONSE) {
 
   90            do_callbacks(
trans, delay);
 
   92        if (cb_targets.size() > 0) {
 
   93            trans.set_dmi_allowed(
false);
 
   97    unsigned int transport_dbg(
int id, tlm::tlm_generic_payload& 
trans)
 
  101        auto ti = decode_address(
trans);
 
  104            SCP_WARN(())(
"transport_dbg: Attempt to access unknown location in register memory at offset 0x{:x}", 
addr);
 
  105            trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
 
  109#ifdef ENABLE_MODULE_NAME_DBG_INFO 
  114            SCP_DEBUG(()) << 
"transport_dbg: " << txn_command_str(
trans) << 
" to Register at address: 0x" << std::hex
 
  115                          << 
trans.get_address() << 
" which belongs to Module: [" << 
mod_name << 
"]";
 
  119        if (ti->use_offset) 
trans.set_address(
addr - ti->address);
 
  120        SCP_TRACEALL(()) << 
"[REG-MEM] call transport_dbg [txn]: " << scp::scp_txn_tostring(
trans);
 
  121        unsigned int ret = initiator_socket[ti->index]->transport_dbg(
trans);
 
  122        if (ti->use_offset) 
trans.set_address(
addr);
 
  126    bool get_direct_mem_ptr(
int id, tlm::tlm_generic_payload& 
trans, tlm::tlm_dmi& dmi_data)
 
  128        SCP_TRACE(()) << 
"[REG-MEM] call get_direct_mem_ptr (not allowed) [txn]: " << scp::scp_txn_tostring(
trans);
 
  132    std::string txn_to_str(tlm::tlm_generic_payload& 
trans, 
bool is_callback = 
false, 
bool found_callback = 
false)
 
  134        std::stringstream 
ss;
 
  135        std::string cmd = txn_command_str(
trans);
 
  137            if (cmd != 
"IGNORE" && cmd != 
"UNKNOWN") {
 
  138                if ((
trans.get_response_status() == tlm::TLM_INCOMPLETE_RESPONSE))
 
  139                    ss << 
"[PRE-" << cmd << 
"] Register callbacks [txn]: ";
 
  140                else if ((
trans.get_response_status() == tlm::TLM_OK_RESPONSE))
 
  141                    ss << 
"[POST-" << cmd << 
"] Register callbacks [txn]: ";
 
  144            ss << 
"[REG-MEM] (" << cmd << 
" TO REG-MEM BEFORE " << cmd << 
" CB) [txn]: ";
 
  146            ss << 
"[REG-MEM] (NO CB FOUND) [txn]: ";
 
  149        ss << scp::scp_txn_tostring(
trans);
 
  153    std::string txn_command_str(
const tlm::tlm_generic_payload& 
trans)
 
  156        switch (
trans.get_command()) {
 
  157        case tlm::TLM_READ_COMMAND:
 
  160        case tlm::TLM_WRITE_COMMAND:
 
  163        case tlm::TLM_IGNORE_COMMAND:
 
  173#ifdef ENABLE_MODULE_NAME_DBG_INFO 
  176        if (mod_addr_name_map.empty()) {
 
  180        auto search = mod_addr_name_map.equal_range(
addr);
 
  181        if (
search.first != mod_addr_name_map.end() && 
search.first->first == 
addr) {
 
  185                return search.first->second.second;
 
  187        } 
else if (
search.second != mod_addr_name_map.begin()) {
 
  203    bool do_callbacks(tlm::tlm_generic_payload& 
trans, sc_core::sc_time& delay)
 
  205        if (cb_targets.empty()) {
 
  209        sc_dt::uint64 
addr = 
trans.get_address();
 
  210        sc_dt::uint64 
len = 
trans.get_data_length();
 
  216                ti = 
search.first->second;
 
  218        } 
else if (
search.second != cb_targets.begin()) {
 
  229        if (ti->use_offset) 
trans.set_address(
addr - ti->address);
 
  230        initiator_socket[ti->index]->b_transport(
trans, delay);
 
  231        if (ti->use_offset) 
trans.set_address(
addr);
 
  233        if (
trans.get_response_status() <= tlm::TLM_GENERIC_ERROR_RESPONSE) {
 
  234            SCP_WARN(()) << 
"Accesing register callback at addr: " << std::hex << 
addr 
  235                         << 
" returned with: " << 
trans.get_response_string();
 
  244        sc_dt::uint64 
addr = 
trans.get_address();
 
  245        sc_dt::uint64 
len = 
trans.get_data_length();
 
  247        for (
auto ti : mem_targets) {
 
  248            if (
addr >= ti->address && (
addr - ti->address) < ti->size) {
 
  256    virtual void before_end_of_elaboration()
 
  258        if (!lazy_init) lazy_initialize();
 
  262    void lazy_initialize()
 
  264        if (initialized) 
return;
 
  267        for (
auto& ti : bound_targets) {
 
  268            std::string name = ti.name;
 
  271            ti.address = gs::cci_get<uint64_t>(m_broker, name + 
".address");
 
  272            ti.size = gs::cci_get<uint64_t>(m_broker, name + 
".size");
 
  273            ti.use_offset = gs::cci_get_d<bool>(m_broker, name + 
".relative_addresses", 
true);
 
  274            ti.is_callback = gs::cci_get_d<bool>(m_broker, name + 
".is_callback", 
false);
 
  276            SCP_INFO(()) << 
"Address map " << ti.name + 
" at" 
  278                         << 
"0x" << std::hex << ti.address << 
" size " 
  279                         << 
"0x" << std::hex << ti.size << (ti.use_offset ? 
" (with relative address) " : 
"")
 
  280                         << (ti.is_callback ? 
" (callback) " : 
"");
 
  282            if (ti.is_callback) {
 
  283                auto insertion_pair = cb_targets.insert(std::make_pair(ti.address, &ti));
 
  285                    SCP_FATAL(()) << 
"a CB register with the same adress: 0x" << std::hex << ti.address
 
  286                                  << 
" was already bound!";
 
  288                if (!mem_targets.empty()) {
 
  289                    for (
const auto& 
mem : mem_targets) {
 
  290                        if (((ti.address >= 
mem->address) && ((ti.address - 
mem->address) < 
mem->size)) ||
 
  291                            ((ti.address < 
mem->address) && ((ti.address + ti.size) > 
mem->address))) {
 
  292                            SCP_WARN(()) << ti.name << 
" overlaps with " << 
mem->name;
 
  296                mem_targets.push_back(&ti);
 
  303        const sc_core::sc_module_name& 
nm,
 
  305            std::map<
uint64_t, std::pair<uint64_t, const char*>>(),
 
  307        cci::cci_broker_handle 
broker = cci::cci_get_broker())
 
  308        : sc_core::sc_module(
nm)
 
  309        , initiator_socket(
"initiator_socket", [&](std::string s) -> 
void { register_boundto(s); })
 
  310        , target_socket(
"target_socket")
 
  312        , lazy_init(
"lazy_init", 
false, 
"Initialize the reg_router lazily (eg. during simulation rather than BEOL)")
 
  316        SCP_DEBUG(()) << 
"reg_router constructed";
 
  318        target_socket.register_b_transport(
this, ®_router::b_transport);
 
  319        target_socket.register_transport_dbg(
this, ®_router::transport_dbg);
 
  320        target_socket.register_get_direct_mem_ptr(
this, ®_router::get_direct_mem_ptr);
 
  322        SCP_DEBUG((
DMI)) << 
"reg_router Initializing DMI SCP reporting";
 
  333    initiator_socket_type initiator_socket;
 
  334    tlm_utils::multi_passthrough_target_socket<reg_router<BUSWIDTH>, 
BUSWIDTH> target_socket;
 
  335    cci::cci_broker_handle m_broker;
 
  336    cci::cci_param<bool> lazy_init;
 
  339    std::vector<target_info*> mem_targets;
 
  340    std::map<sc_dt::uint64, target_info*> cb_targets;
 
  341    std::map<uint64_t, std::pair<uint64_t, const char*>> mod_addr_name_map;
 
  342    std::function<
void(
bool, 
uint64_t)> m_pre_b_transport_callback;
 
  343    bool initialized = 
false;