From f8d5da01b7efae52c356abd14a0791f15af9346a Mon Sep 17 00:00:00 2001 From: Sanghoon Park Date: Mon, 13 Apr 2026 11:36:21 -0700 Subject: [PATCH 1/3] tests: add regression for high-range DMI wrap in router --- tests/memory_subsys/memory_test.cpp | 13 +++++++++++ tests/memory_subsys/testbench.h | 35 ++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/tests/memory_subsys/memory_test.cpp b/tests/memory_subsys/memory_test.cpp index eb31e6cc6..fda36d62f 100644 --- a/tests/memory_subsys/memory_test.cpp +++ b/tests/memory_subsys/memory_test.cpp @@ -104,6 +104,19 @@ TEST_CASE("scattered_access", "[memory][tlm-level]") { f(kPageSize - 2); } +TEST_CASE("dmi_high_range_wrap_regression", "[memory][tlm-level]") { + auto& dut = factory::get(); + tlm::tlm_generic_payload gp; + tlm::tlm_dmi dmi; + + gp.set_address(testbench::high_range_base); + auto res = dut.isck0->get_direct_mem_ptr(gp, dmi); + + REQUIRE(res == true); + REQUIRE(dmi.get_start_address() == testbench::high_range_base); + REQUIRE(dmi.get_end_address() == testbench::high_range_base + dmi_probe_target::window_size - 1); +} + TEST_CASE("page_boundary_check", "[memory][tlm-level]") { auto& dut = factory::get(); constexpr uint64_t kPageSize = dut.mem3.getPageSize(); diff --git a/tests/memory_subsys/testbench.h b/tests/memory_subsys/testbench.h index d0e6fc84a..e956282b4 100644 --- a/tests/memory_subsys/testbench.h +++ b/tests/memory_subsys/testbench.h @@ -1,7 +1,9 @@ #ifndef _TESTBENCH_H_ #define _TESTBENCH_H_ +#include #include +#include #include #include #include @@ -19,22 +21,51 @@ using namespace std; namespace scc { const char* sc_gen_unique_name(const char*, bool preserve_first); +struct dmi_probe_target : public sc_core::sc_module { + static constexpr auto window_size = uint64_t{64}; + tlm::scc::target_mixin> target{"target"}; + std::array storage{}; + + dmi_probe_target() + : dmi_probe_target(sc_core::sc_gen_unique_name("dmi_probe_target", false)) {} + + explicit dmi_probe_target(sc_core::sc_module_name const& nm) + : sc_module(nm) { + target.register_b_transport([](tlm::tlm_generic_payload& gp, sc_core::sc_time&) { gp.set_response_status(tlm::TLM_OK_RESPONSE); }); + target.register_get_direct_mem_ptr([this](tlm::tlm_generic_payload& gp, tlm::tlm_dmi& dmi_data) -> bool { + auto const start = gp.get_address(); + dmi_data.set_start_address(start); + dmi_data.set_end_address(start + window_size - 1); + dmi_data.set_dmi_ptr(storage.data()); + dmi_data.set_granted_access(tlm::tlm_dmi::DMI_ACCESS_READ_WRITE); + dmi_data.set_read_latency(sc_core::SC_ZERO_TIME); + dmi_data.set_write_latency(sc_core::SC_ZERO_TIME); + return true; + }); + } +}; + struct testbench : public sc_core::sc_module { using transaction_type = tlm::tlm_base_protocol_types::tlm_payload_type; using phase_type = tlm::tlm_base_protocol_types::tlm_phase_type; + static constexpr uint64_t high_range_size = 4_kB; + static constexpr uint64_t high_range_base = std::numeric_limits::max() - (high_range_size - 1); + sc_core::sc_signal clk{"clk"}; sc_core::sc_signal rst{"rst"}; tlm::scc::initiator_mixin> isck0{"isck0"}; tlm::scc::initiator_mixin> isck1{"isck1"}; - scc::router router{"router", 6, 2}; + + scc::router router{"router", 7, 2}; scc::memory_tl<1_kB, scc::LT> mem0{"mem0"}; scc::memory_tl<1_kB, scc::LT> mem1{"mem1"}; scc::memory_tl<18_MB, scc::LT> mem2{"mem2"}; scc::memory_tl<24_MB, scc::LT> mem3{"mem3"}; scc::memory_tl<88_MB, scc::LT> mem4{"mem4"}; scc::memory<4_GB> mem5{"mem5"}; + dmi_probe_target dmi_probe{"dmi_probe"}; testbench() : testbench(sc_core::sc_gen_unique_name("testbench", false)) {} @@ -51,6 +82,8 @@ struct testbench : public sc_core::sc_module { router.bind_target(mem4.target, 4, 64_MB, 20_MB, false); router.initiator[5].bind(mem5.target); router.set_default_target(5); + + router.bind_target(dmi_probe.target, 6, high_range_base, high_range_size, false); mem0.clk_i(clk); mem1.clk_i(clk); mem2.clk_i(clk); From 2e64abb778fd66601de729675ba520f3a66cdfc0 Mon Sep 17 00:00:00 2001 From: Sanghoon Park Date: Tue, 14 Apr 2026 03:17:12 -0700 Subject: [PATCH 2/3] router: avoid DMI clamp overflow on wrapped high ranges --- src/components/scc/router.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/scc/router.h b/src/components/scc/router.h index d46bb8846..349c20251 100644 --- a/src/components/scc/router.h +++ b/src/components/scc/router.h @@ -313,8 +313,12 @@ bool router::get_direct_mem_ptr(int i, tlm::tlm_ge trans.set_address(address - offset); bool status = initiator[idx]->get_direct_mem_ptr(trans, dmi_data); // make sure end address does not exceed size - auto remap_end = (tranges[idx].remap ? 0 : tranges[idx].base) + tranges[idx].size; - if(tranges[idx].size && dmi_data.get_end_address() >= remap_end) + using addr_t = decltype(address); + auto const remap_base = tranges[idx].remap ? addr_t{0} : static_cast(tranges[idx].base); + auto const remap_size = static_cast(tranges[idx].size); + auto const remap_end = remap_base + remap_size; + auto const remap_end_overflow = remap_size > (std::numeric_limits::max() - remap_base); + if(remap_size && !remap_end_overflow && dmi_data.get_end_address() >= remap_end) dmi_data.set_end_address(remap_end - 1); // Calculate DMI address of target in system address space dmi_data.set_start_address(dmi_data.get_start_address() - ibases[i] + offset); From d69a53c378c21e5916388931507f5cf8bc0f29ba Mon Sep 17 00:00:00 2001 From: Sanghoon Park Date: Tue, 21 Apr 2026 00:47:21 -0700 Subject: [PATCH 3/3] router: simplify remap overflow detection logic --- src/components/scc/router.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/scc/router.h b/src/components/scc/router.h index 349c20251..fc8d63603 100644 --- a/src/components/scc/router.h +++ b/src/components/scc/router.h @@ -313,11 +313,10 @@ bool router::get_direct_mem_ptr(int i, tlm::tlm_ge trans.set_address(address - offset); bool status = initiator[idx]->get_direct_mem_ptr(trans, dmi_data); // make sure end address does not exceed size - using addr_t = decltype(address); - auto const remap_base = tranges[idx].remap ? addr_t{0} : static_cast(tranges[idx].base); - auto const remap_size = static_cast(tranges[idx].size); + auto const remap_base = tranges[idx].remap ? 0 : tranges[idx].base; + auto const remap_size = tranges[idx].size; auto const remap_end = remap_base + remap_size; - auto const remap_end_overflow = remap_size > (std::numeric_limits::max() - remap_base); + auto const remap_end_overflow = remap_end < remap_base; if(remap_size && !remap_end_overflow && dmi_data.get_end_address() >= remap_end) dmi_data.set_end_address(remap_end - 1); // Calculate DMI address of target in system address space