From 3b294d9da0832addf62589d7f1e3adcbe0b75e6a Mon Sep 17 00:00:00 2001
From: Eyck Jentzsch <eyck@minres.com>
Date: Sun, 16 Mar 2025 12:29:03 +0100
Subject: [PATCH] fixes sc_core_adapter wrt refactored memory hierarchy

---
 src/iss/arch/riscv_hart_common.h | 21 +++++------
 src/iss/mem/memory_if.cpp        | 15 ++++----
 src/iss/mem/memory_if.h          |  1 -
 src/sysc/core_complex.cpp        |  2 +-
 src/sysc/sc_core_adapter.h       | 63 ++++++++++++++++----------------
 5 files changed, 50 insertions(+), 52 deletions(-)

diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h
index a4035d2..30b8c3c 100644
--- a/src/iss/arch/riscv_hart_common.h
+++ b/src/iss/arch/riscv_hart_common.h
@@ -365,6 +365,7 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
             csr_wr_cb[minstreth] = MK_CSR_WR_CB(write_instret);
         csr_rd_cb[mhartid] = MK_CSR_RD_CB(read_hartid);
     };
+
     ~riscv_hart_common() {
         if(io_buf.str().length()) {
             CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
@@ -427,14 +428,12 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
 #endif
                     }
                 }
-                try {
-                    tohost = symbol_table.at("tohost");
-                } catch(std::out_of_range& e) {
-                }
-                try {
-                    fromhost = symbol_table.at("fromhost");
-                } catch(std::out_of_range& e) {
-                }
+                auto to_it = symbol_table.find("tohost");
+                if(to_it!=std::end(symbol_table))
+                    tohost = to_it->second;
+                auto from_it = symbol_table.find("tohost");
+                if(from_it!=std::end(symbol_table))
+                    tohost = from_it->second;
             }
             return true;
         }
@@ -743,12 +742,12 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
 
     mem::memory_hierarchy memories;
 
-    virtual mem::memory_if get_mem_if() override {
-        assert(false || "This function should nevver be called");
+    mem::memory_if get_mem_if() override {
+        assert(false || "This function should never be called");
         return mem::memory_if{};
     }
 
-    virtual void set_next(mem::memory_if mem_if) { memory = mem_if; };
+    void set_next(mem::memory_if mem_if) override { memory = mem_if; };
 
     void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
 
diff --git a/src/iss/mem/memory_if.cpp b/src/iss/mem/memory_if.cpp
index 2beedf8..76f5bd2 100644
--- a/src/iss/mem/memory_if.cpp
+++ b/src/iss/mem/memory_if.cpp
@@ -22,15 +22,18 @@ void memory_hierarchy::append(memory_elem& e) {
 void memory_hierarchy::insert_before(memory_elem&) {}
 void memory_hierarchy::insert_after(memory_elem&) {}
 void memory_hierarchy::replace_last(memory_elem& e) {
+    auto old = hierarchy.back();
+    auto it  = std::find_if(std::begin(owned_elems), std::end(owned_elems), [old](std::unique_ptr<memory_elem> const& p) {return p.get()==old;});
     hierarchy.pop_back();
+    if(it!=std::end(owned_elems))
+        owned_elems.erase(it);
     hierarchy.push_back(&e);
+    update_chain();
 }
 void memory_hierarchy::update_chain() {
     bool tail = false;
-    for(size_t i = 0; i < hierarchy.size(); ++i) {
-        hierarchy[i]->register_csrs();
-        if(i)
-            hierarchy[i - 1]->set_next(hierarchy[i]->get_mem_if());
+    for(size_t i = 1; i < hierarchy.size(); ++i) {
+        hierarchy[i - 1]->set_next(hierarchy[i]->get_mem_if());
     }
 }
 
@@ -55,11 +58,7 @@ void memory_hierarchy::insert_after(std::unique_ptr<memory_elem>&& p) {
 }
 
 void memory_hierarchy::replace_last(std::unique_ptr<memory_elem>&& p) {
-    auto e = hierarchy.back();
     replace_last(*p);
-    auto it  = std::find_if(std::begin(owned_elems), std::end(owned_elems), [e](std::unique_ptr<memory_elem> const& p) {return p.get()==e;});
-    if(it!=std::end(owned_elems))
-        owned_elems.erase(it);
     owned_elems.push_back(std::move(p));
 }
 
diff --git a/src/iss/mem/memory_if.h b/src/iss/mem/memory_if.h
index 14e042c..2b5d946 100644
--- a/src/iss/mem/memory_if.h
+++ b/src/iss/mem/memory_if.h
@@ -58,7 +58,6 @@ struct memory_elem {
     virtual ~memory_elem() = default;
     virtual memory_if get_mem_if() = 0;
     virtual void set_next(memory_if) = 0;
-    virtual void register_csrs() {}
     virtual std::tuple<uint64_t, uint64_t> get_range() { return {0, std::numeric_limits<uint64_t>::max()}; }
 };
 
diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp
index dfe61ef..f738aa4 100644
--- a/src/sysc/core_complex.cpp
+++ b/src/sysc/core_complex.cpp
@@ -419,7 +419,7 @@ template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::read_mem(uint64_t
             gp.set_extension(preExt);
         }
         auto pre_delay = delay;
-        dbus->b_transport(gp, delay);
+        sckt->b_transport(gp, delay);
         if(pre_delay > delay) {
             quantum_keeper.reset();
         } else {
diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h
index d654800..384e008 100644
--- a/src/sysc/sc_core_adapter.h
+++ b/src/sysc/sc_core_adapter.h
@@ -14,15 +14,21 @@
 #include <iss/vm_types.h>
 #include <scc/report.h>
 #include <util/ities.h>
+#include <iss/mem/memory_if.h>
 
 namespace sysc {
 template <typename PLAT> class sc_core_adapter : public PLAT, public sc_core_adapter_if {
 public:
+    using this_class = sc_core_adapter<PLAT>;
     using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t;
     using phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t;
-    using heart_state_t = typename PLAT::hart_state_type;
     sc_core_adapter(sysc::tgfs::core_complex_if* owner)
-    : owner(owner) {}
+    : owner(owner) {
+        this->csr_rd_cb[iss::arch::time] = MK_CSR_RD_CB(read_time);
+        if(sizeof(reg_t) == 4)
+            this->csr_rd_cb[iss::arch::timeh] = MK_CSR_RD_CB(read_time);
+        this->memories.replace_last(*this);
+    }
 
     iss::arch_if* get_arch_if() override { return this; }
 
@@ -60,18 +66,24 @@ public:
         }
     };
 
-    iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data) override {
-        if(addr.access && iss::access_type::DEBUG)
-            return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
+    iss::mem::memory_if get_mem_if() override {
+        return iss::mem::memory_if{
+            .rd_mem{util::delegate<iss::mem::rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
+            .wr_mem{util::delegate<iss::mem::wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
+    }
+
+    iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
+        if(access && iss::access_type::DEBUG)
+            return owner->read_mem_dbg(addr, length, data) ? iss::Ok : iss::Err;
         else {
-            return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? iss::Ok : iss::Err;
+            return owner->read_mem(addr, length, data, is_fetch(access)) ? iss::Ok : iss::Err;
         }
     }
 
-    iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data) override {
-        if(addr.access && iss::access_type::DEBUG)
-            return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
-        if(addr.val == this->tohost) {
+    iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
+        if(access && iss::access_type::DEBUG)
+            return owner->write_mem_dbg(addr, length, data) ? iss::Ok : iss::Err;
+        if(addr == this->tohost) {
             reg_t cur_data = *reinterpret_cast<const reg_t*>(data);
             // Extract Device (bits 63:56)
             uint8_t device = sizeof(reg_t) == 4 ? 0 : (cur_data >> 56) & 0xFF;
@@ -117,31 +129,20 @@ public:
             this->interrupt_sim = payload_addr;
             return iss::Ok;
         }
-        auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err;
-        // clear MTIP on mtimecmp write
-        if(addr.val == 0x2004000) {
-            reg_t val;
-            this->read_csr(iss::arch::mip, val);
-            if(val & (1ULL << 7))
-                this->write_csr(iss::arch::mip, val & ~(1ULL << 7));
-        }
+        auto res = owner->write_mem(addr, length, data) ? iss::Ok : iss::Err;
         return res;
     }
 
-    iss::status read_csr(unsigned addr, reg_t& val) override {
-        if((addr == iss::arch::time || addr == iss::arch::timeh)) {
-            uint64_t time_val = owner->mtime_i.get_interface() ? owner->mtime_i.read() : 0;
-            if(addr == iss::arch::time) {
-                val = static_cast<reg_t>(time_val);
-            } else if(addr == iss::arch::timeh) {
-                if(sizeof(reg_t) != 4)
-                    return iss::Err;
-                val = static_cast<reg_t>(time_val >> 32);
-            }
-            return iss::Ok;
-        } else {
-            return PLAT::read_csr(addr, val);
+    iss::status read_time(unsigned addr, reg_t& val) {
+        uint64_t time_val = owner->mtime_i.get_interface() ? owner->mtime_i.read() : 0;
+        if(addr == iss::arch::time) {
+            val = static_cast<reg_t>(time_val);
+        } else if(addr == iss::arch::timeh) {
+            if(sizeof(reg_t) != 4)
+                return iss::Err;
+            val = static_cast<reg_t>(time_val >> 32);
         }
+        return iss::Ok;
     }
 
     void wait_until(uint64_t flags) override {