Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions src/components/scc/router.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <limits>
#include <scc/utilities.h>
#include <scc/report.h>
#include <sysc/utils/sc_vector.h>
#include <tlm.h>
#include <tlm/scc/initiator_mixin.h>
Expand Down Expand Up @@ -51,8 +52,9 @@ template <unsigned BUSWIDTH = LT, typename TARGET_SOCKET_TYPE = tlm::tlm_target_
* @param nm the component name
* @param slave_cnt number of slaves to be connected
* @param master_cnt number of masters to be connected
* @param check_overlap_on_add_target if true this enables validation of overlaps when adding or setting the target range.
*/
router(const sc_core::sc_module_name& nm, size_t slave_cnt = 1, size_t master_cnt = 1);
router(const sc_core::sc_module_name& nm, size_t slave_cnt = 1, size_t master_cnt = 1, bool check_overlap_on_add_target = false);

~router() = default;
/**
Expand All @@ -68,7 +70,6 @@ template <unsigned BUSWIDTH = LT, typename TARGET_SOCKET_TYPE = tlm::tlm_target_
*/
template <typename TYPE> void bind_target(TYPE& socket, size_t idx, uint64_t base, uint64_t size, bool remap = true) {
set_target_range(idx, base, size, remap);
set_target_name(idx, socket.basename());
Copy link
Contributor

@eyck eyck Nov 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this line breaks add_target_range(std::string name, uint64_t base, uint64_t size, bool remap)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use set_target_name(idx, socket.get_base_export().basename()); instead of set_target_name(idx, socket.basename()); ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to use the name of the export?

Copy link
Contributor

@eyck eyck Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to use the name of the export? If the socket to bind is a tlm::tlm_target_socket it maps to the same than tlm::tlm_target_socket::basename. In case of hierachical binding (binding to tlm::tlm_initiator_socket), the export gets a generated name which is the port name with a '_export' appended. And this is not what a user expects.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are passing tlm::tlm_base_target_socket_b as the socket type. Based on my understanding, this class does not provide the basename() function because it is an abstract interface and does not inherit from sc_object. This causes a build issue when code tries to call basename() on it.
so maybe we can use socket.get_base_export().basename(), since the export object is derived from sc_object and supports basename().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As described above this breaks the semantic if doing hierarchical binding to an initiator socket since the basename of the export '<socket_name>_export'.
Lets remove the call to set_target_name() entirely and move the responsibility to the caller.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 3b94a23

initiator[idx].bind(socket);
}
/**
Expand All @@ -81,7 +82,6 @@ template <unsigned BUSWIDTH = LT, typename TARGET_SOCKET_TYPE = tlm::tlm_target_
* @param name of the binding
*/
template <typename TYPE> void bind_target(TYPE& socket, size_t idx, std::string name) {
set_target_name(idx, name);
initiator[idx].bind(socket);
}
/**
Expand Down Expand Up @@ -132,6 +132,13 @@ template <unsigned BUSWIDTH = LT, typename TARGET_SOCKET_TYPE = tlm::tlm_target_
* @param remap if true address will be rewritten in accesses to be 0-based at the target
*/
void set_target_range(size_t idx, uint64_t base, uint64_t size, bool remap = true);
/**
* @fn void set_warn_on_address_error(bool)
* @brief enable warning message on address not found error
*
* @param enable if true enable warning message
*/
void set_warn_on_address_error(bool enable) { warn_on_address_error = enable; }
/**
* @fn void b_transport(int, tlm::tlm_generic_payload&, sc_core::sc_time&)
* @brief tagged blocking transport method
Expand Down Expand Up @@ -169,6 +176,12 @@ template <unsigned BUSWIDTH = LT, typename TARGET_SOCKET_TYPE = tlm::tlm_target_
*/
void invalidate_direct_mem_ptr(int id, ::sc_dt::uint64 start_range, ::sc_dt::uint64 end_range);

/**
* @fn void end_of_elaboration()
* @brief tagged end of elaboration callback.
*/
void end_of_elaboration() override;

protected:
struct range_entry {
uint64_t base, size;
Expand All @@ -180,17 +193,20 @@ template <unsigned BUSWIDTH = LT, typename TARGET_SOCKET_TYPE = tlm::tlm_target_
std::vector<sc_core::sc_mutex> mutexes;
util::range_lut<unsigned> addr_decoder;
std::unordered_map<std::string, size_t> target_name_lut;
bool check_overlap_on_add_target;
bool warn_on_address_error{false};
};

template <unsigned BUSWIDTH, typename TARGET_SOCKET_TYPE>
router<BUSWIDTH, TARGET_SOCKET_TYPE>::router(const sc_core::sc_module_name& nm, size_t slave_cnt, size_t master_cnt)
router<BUSWIDTH, TARGET_SOCKET_TYPE>::router(const sc_core::sc_module_name& nm, size_t slave_cnt, size_t master_cnt, bool check_overlap_on_add_target)
: sc_module(nm)
, target("target", master_cnt)
, initiator("intor", slave_cnt)
, ibases(master_cnt)
, tranges(slave_cnt)
, mutexes(slave_cnt)
, addr_decoder(std::numeric_limits<unsigned>::max()) {
, addr_decoder(std::numeric_limits<unsigned>::max())
, check_overlap_on_add_target(check_overlap_on_add_target) {
for(size_t i = 0; i < target.size(); ++i) {
target[i].register_b_transport(
[this, i](tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) -> void { this->b_transport(i, trans, delay); });
Expand All @@ -216,6 +232,8 @@ void router<BUSWIDTH, TARGET_SOCKET_TYPE>::set_target_range(size_t idx, uint64_t
tranges[idx].size = size;
tranges[idx].remap = remap;
addr_decoder.addEntry(idx, base, size);
if(check_overlap_on_add_target)
addr_decoder.validate();
}

template <unsigned BUSWIDTH, typename TARGET_SOCKET_TYPE>
Expand All @@ -237,6 +255,8 @@ void router<BUSWIDTH, TARGET_SOCKET_TYPE>::add_target_range(std::string name, ui
tranges[idx].size = size;
tranges[idx].remap = remap;
addr_decoder.addEntry(idx, base, size);
if(check_overlap_on_add_target)
addr_decoder.validate();
}

template <unsigned BUSWIDTH, typename TARGET_SOCKET_TYPE>
Expand All @@ -249,6 +269,9 @@ void router<BUSWIDTH, TARGET_SOCKET_TYPE>::b_transport(int i, tlm::tlm_generic_p
size_t idx = addr_decoder.getEntry(address);
if(idx == addr_decoder.null_entry) {
if(default_idx == std::numeric_limits<size_t>::max()) {
if(warn_on_address_error) {
SCCWARN(SCMOD) << "target address=0x" << std::hex << address << " not found for " << (trans.get_command() == tlm::TLM_READ_COMMAND ? "read" : "write") << " transaction.";
}
trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
return;
}
Expand All @@ -272,6 +295,9 @@ bool router<BUSWIDTH, TARGET_SOCKET_TYPE>::get_direct_mem_ptr(int i, tlm::tlm_ge
size_t idx = addr_decoder.getEntry(address);
if(idx == addr_decoder.null_entry) {
if(default_idx == std::numeric_limits<size_t>::max()) {
if(warn_on_address_error) {
SCCWARN(SCMOD) << "target address=0x" << std::hex << address << " not found for " << (trans.get_command() == tlm::TLM_READ_COMMAND ? "read" : "write") << " transaction.";
}
trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
return false;
}
Expand Down Expand Up @@ -300,6 +326,9 @@ unsigned router<BUSWIDTH, TARGET_SOCKET_TYPE>::transport_dbg(int i, tlm::tlm_gen
size_t idx = addr_decoder.getEntry(address);
if(idx == addr_decoder.null_entry) {
if(default_idx == std::numeric_limits<size_t>::max()) {
if(warn_on_address_error) {
SCCWARN(SCMOD) << "target address=0x" << std::hex << address << " not found for " << (trans.get_command() == tlm::TLM_READ_COMMAND ? "read" : "write") << " transaction.";
}
trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
return 0;
}
Expand All @@ -324,6 +353,10 @@ void router<BUSWIDTH, TARGET_SOCKET_TYPE>::invalidate_direct_mem_ptr(int id, ::s
target[i]->invalidate_direct_mem_ptr(bw_start_range - ibases[i], bw_end_range - ibases[i]);
}
}
template <unsigned BUSWIDTH, typename TARGET_SOCKET_TYPE>
void router<BUSWIDTH, TARGET_SOCKET_TYPE>::end_of_elaboration() {
addr_decoder.validate();
}

} // namespace scc

Expand Down