17 #ifndef _SYSC_ROUTER_H_
18 #define _SYSC_ROUTER_H_
21 #include <scc/utilities.h>
22 #include <sysc/utils/sc_vector.h>
24 #include <tlm/scc/initiator_mixin.h>
25 #include <tlm/scc/scv/tlm_rec_initiator_socket.h>
26 #include <tlm/scc/scv/tlm_rec_target_socket.h>
27 #include <tlm/scc/target_mixin.h>
28 #include <unordered_map>
29 #include <util/range_lut.h>
40 template <
unsigned BUSWIDTH = LT>
class router : sc_core::sc_module {
45 sc_core::sc_vector<target_sckt>
target;
56 router(
const sc_core::sc_module_name& nm,
unsigned slave_cnt = 1,
unsigned master_cnt = 1);
70 template <
typename TYPE>
void bind_target(TYPE& socket,
size_t idx, uint64_t base, uint64_t size,
bool remap =
true) {
83 template <
typename TYPE>
void bind_target(TYPE& socket,
size_t idx, std::string name) {
114 void set_target_name(
size_t idx, std::string name) { target_name_lut.insert(std::make_pair(name, idx)); }
124 void add_target_range(std::string name, uint64_t base, uint64_t size,
bool remap =
true);
134 void set_target_range(
size_t idx, uint64_t base, uint64_t size,
bool remap =
true);
143 void b_transport(
int i, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay);
153 bool get_direct_mem_ptr(
int i, tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data);
161 unsigned transport_dbg(
int i, tlm::tlm_generic_payload& trans);
177 size_t default_idx = std::numeric_limits<size_t>::max();
178 std::vector<uint64_t> ibases;
179 std::vector<range_entry> tranges;
180 std::vector<sc_core::sc_mutex> mutexes;
182 std::unordered_map<std::string, size_t> target_name_lut;
185 template <
unsigned BUSWIDTH>
188 , target(
"target", master_cnt)
193 , addr_decoder(std::numeric_limits<unsigned>::max()) {
194 for(
size_t i = 0; i <
target.size(); ++i) {
195 target[i].register_b_transport(
196 [=](tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) ->
void { this->
b_transport(i, trans, delay); });
197 target[i].register_get_direct_mem_ptr(
198 [=](tlm::tlm_generic_payload& trans, tlm::tlm_dmi& dmi_data) ->
bool {
return this->
get_direct_mem_ptr(i, trans, dmi_data); });
199 target[i].register_transport_dbg([=](tlm::tlm_generic_payload& trans) ->
unsigned {
return this->
transport_dbg(i, trans); });
202 for(
size_t i = 0; i <
initiator.size(); ++i) {
203 initiator[i].register_invalidate_direct_mem_ptr([=](::sc_dt::uint64 start_range, ::sc_dt::uint64 end_range) ->
void {
206 tranges[i].base = 0ULL;
207 tranges[i].size = 0ULL;
208 tranges[i].remap =
false;
213 tranges[idx].base = base;
214 tranges[idx].size = size;
215 tranges[idx].remap = remap;
216 addr_decoder.addEntry(idx, base, size);
220 auto it = target_name_lut.find(name);
222 #if(SYSTEMC_VERSION >= 20171012)
223 if(it == target_name_lut.end()) {
224 std::stringstream ss;
225 ss <<
"No target index entry for '" << name <<
"' found ";
226 ::sc_core::sc_assertion_failed(ss.str().c_str(), __FILE__, __LINE__);
229 sc_assert(it != target_name_lut.end());
232 auto idx = it->second;
233 tranges[idx].base = base;
234 tranges[idx].size = size;
235 tranges[idx].remap = remap;
236 addr_decoder.addEntry(idx, base, size);
240 ::sc_dt::uint64 address = trans.get_address();
242 address += ibases[i];
243 trans.set_address(address);
245 size_t idx = addr_decoder.getEntry(address);
246 if(idx == addr_decoder.null_entry) {
247 if(default_idx == std::numeric_limits<size_t>::max()) {
248 trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
254 trans.set_address(address - (tranges[idx].remap ? tranges[idx].base : 0));
258 initiator[idx]->b_transport(trans, delay);
259 mutexes[idx].unlock();
262 ::sc_dt::uint64 address = trans.get_address();
264 address += ibases[i];
265 trans.set_address(address);
267 size_t idx = addr_decoder.getEntry(address);
268 if(idx == addr_decoder.null_entry) {
269 if(default_idx == std::numeric_limits<size_t>::max()) {
270 trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
276 trans.set_address(address - (tranges[idx].remap ? tranges[idx].base : 0));
278 bool status =
initiator[idx]->get_direct_mem_ptr(trans, dmi_data);
280 auto offset = tranges[idx].remap ? tranges[idx].base : 0;
281 dmi_data.set_start_address(dmi_data.get_start_address() - ibases[i] + offset);
282 dmi_data.set_end_address(dmi_data.get_end_address() - ibases[i] + offset);
286 ::sc_dt::uint64 address = trans.get_address();
288 address += ibases[i];
289 trans.set_address(address);
291 size_t idx = addr_decoder.getEntry(address);
292 if(idx == addr_decoder.null_entry) {
293 if(default_idx == std::numeric_limits<size_t>::max()) {
294 trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
300 trans.set_address(address - (tranges[idx].remap ? tranges[idx].base : 0));
303 return initiator[idx]->transport_dbg(trans);
305 template <
unsigned BUSWIDTH>
308 ::sc_dt::uint64 bw_start_range = start_range;
309 if(tranges[
id].remap)
310 bw_start_range += tranges[id].base;
311 ::sc_dt::uint64 bw_end_range = end_range;
312 if(tranges[
id].remap)
313 bw_end_range += tranges[id].base;
314 for(
size_t i = 0; i < target.size(); ++i) {
315 target[i]->invalidate_direct_mem_ptr(bw_start_range - ibases[i], bw_end_range - ibases[i]);
initiator ID recording TLM extension
a TLM2.0 router for loosly-timed (LT) models
void set_target_name(size_t idx, std::string name)
establish a mapping between socket name and socket index
void set_default_target(size_t idx)
define the default target socket
bool get_direct_mem_ptr(int i, tlm::tlm_generic_payload &trans, tlm::tlm_dmi &dmi_data)
tagged forward DMI method
router(const sc_core::sc_module_name &nm, unsigned slave_cnt=1, unsigned master_cnt=1)
constructs a router
unsigned transport_dbg(int i, tlm::tlm_generic_payload &trans)
tagged debug transaction method
sc_core::sc_vector< target_sckt > target
the array of target sockets
void set_initiator_base(size_t idx, uint64_t base)
define a base address of a socket
void set_target_range(size_t idx, uint64_t base, uint64_t size, bool remap=true)
establish a mapping between a socket and a target address range
void bind_target(TYPE &socket, size_t idx, uint64_t base, uint64_t size, bool remap=true)
bind the initiator socket of the router to some target giving a base and size
void add_target_range(std::string name, uint64_t base, uint64_t size, bool remap=true)
establish a mapping between a named socket and a target address range
sc_core::sc_vector< intor_sckt > initiator
the array of initiator sockets
void bind_target(TYPE &socket, size_t idx, std::string name)
bind the initiator socket of the router to some target and name it
void b_transport(int i, tlm::tlm_generic_payload &trans, sc_core::sc_time &delay)
tagged blocking transport method
void invalidate_direct_mem_ptr(int id, ::sc_dt::uint64 start_range, ::sc_dt::uint64 end_range)
tagged backward DMI method