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;