fixes sc_core_adapter wrt refactored memory hierarchy
This commit is contained in:
parent
54233b448d
commit
3b294d9da0
@ -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_wr_cb[minstreth] = MK_CSR_WR_CB(write_instret);
|
||||||
csr_rd_cb[mhartid] = MK_CSR_RD_CB(read_hartid);
|
csr_rd_cb[mhartid] = MK_CSR_RD_CB(read_hartid);
|
||||||
};
|
};
|
||||||
|
|
||||||
~riscv_hart_common() {
|
~riscv_hart_common() {
|
||||||
if(io_buf.str().length()) {
|
if(io_buf.str().length()) {
|
||||||
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
|
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
|
||||||
@ -427,14 +428,12 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
auto to_it = symbol_table.find("tohost");
|
||||||
tohost = symbol_table.at("tohost");
|
if(to_it!=std::end(symbol_table))
|
||||||
} catch(std::out_of_range& e) {
|
tohost = to_it->second;
|
||||||
}
|
auto from_it = symbol_table.find("tohost");
|
||||||
try {
|
if(from_it!=std::end(symbol_table))
|
||||||
fromhost = symbol_table.at("fromhost");
|
tohost = from_it->second;
|
||||||
} catch(std::out_of_range& e) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -743,12 +742,12 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
|
|||||||
|
|
||||||
mem::memory_hierarchy memories;
|
mem::memory_hierarchy memories;
|
||||||
|
|
||||||
virtual mem::memory_if get_mem_if() override {
|
mem::memory_if get_mem_if() override {
|
||||||
assert(false || "This function should nevver be called");
|
assert(false || "This function should never be called");
|
||||||
return mem::memory_if{};
|
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); }
|
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||||
|
|
||||||
|
@ -22,15 +22,18 @@ void memory_hierarchy::append(memory_elem& e) {
|
|||||||
void memory_hierarchy::insert_before(memory_elem&) {}
|
void memory_hierarchy::insert_before(memory_elem&) {}
|
||||||
void memory_hierarchy::insert_after(memory_elem&) {}
|
void memory_hierarchy::insert_after(memory_elem&) {}
|
||||||
void memory_hierarchy::replace_last(memory_elem& e) {
|
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();
|
hierarchy.pop_back();
|
||||||
|
if(it!=std::end(owned_elems))
|
||||||
|
owned_elems.erase(it);
|
||||||
hierarchy.push_back(&e);
|
hierarchy.push_back(&e);
|
||||||
|
update_chain();
|
||||||
}
|
}
|
||||||
void memory_hierarchy::update_chain() {
|
void memory_hierarchy::update_chain() {
|
||||||
bool tail = false;
|
bool tail = false;
|
||||||
for(size_t i = 0; i < hierarchy.size(); ++i) {
|
for(size_t i = 1; i < hierarchy.size(); ++i) {
|
||||||
hierarchy[i]->register_csrs();
|
hierarchy[i - 1]->set_next(hierarchy[i]->get_mem_if());
|
||||||
if(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) {
|
void memory_hierarchy::replace_last(std::unique_ptr<memory_elem>&& p) {
|
||||||
auto e = hierarchy.back();
|
|
||||||
replace_last(*p);
|
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));
|
owned_elems.push_back(std::move(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ struct memory_elem {
|
|||||||
virtual ~memory_elem() = default;
|
virtual ~memory_elem() = default;
|
||||||
virtual memory_if get_mem_if() = 0;
|
virtual memory_if get_mem_if() = 0;
|
||||||
virtual void set_next(memory_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()}; }
|
virtual std::tuple<uint64_t, uint64_t> get_range() { return {0, std::numeric_limits<uint64_t>::max()}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::read_mem(uint64_t
|
|||||||
gp.set_extension(preExt);
|
gp.set_extension(preExt);
|
||||||
}
|
}
|
||||||
auto pre_delay = delay;
|
auto pre_delay = delay;
|
||||||
dbus->b_transport(gp, delay);
|
sckt->b_transport(gp, delay);
|
||||||
if(pre_delay > delay) {
|
if(pre_delay > delay) {
|
||||||
quantum_keeper.reset();
|
quantum_keeper.reset();
|
||||||
} else {
|
} else {
|
||||||
|
@ -14,15 +14,21 @@
|
|||||||
#include <iss/vm_types.h>
|
#include <iss/vm_types.h>
|
||||||
#include <scc/report.h>
|
#include <scc/report.h>
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
|
#include <iss/mem/memory_if.h>
|
||||||
|
|
||||||
namespace sysc {
|
namespace sysc {
|
||||||
template <typename PLAT> class sc_core_adapter : public PLAT, public sc_core_adapter_if {
|
template <typename PLAT> class sc_core_adapter : public PLAT, public sc_core_adapter_if {
|
||||||
public:
|
public:
|
||||||
|
using this_class = sc_core_adapter<PLAT>;
|
||||||
using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t;
|
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 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)
|
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; }
|
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 {
|
iss::mem::memory_if get_mem_if() override {
|
||||||
if(addr.access && iss::access_type::DEBUG)
|
return iss::mem::memory_if{
|
||||||
return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
|
.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 {
|
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 {
|
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
|
||||||
if(addr.access && iss::access_type::DEBUG)
|
if(access && iss::access_type::DEBUG)
|
||||||
return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err;
|
return owner->write_mem_dbg(addr, length, data) ? iss::Ok : iss::Err;
|
||||||
if(addr.val == this->tohost) {
|
if(addr == this->tohost) {
|
||||||
reg_t cur_data = *reinterpret_cast<const reg_t*>(data);
|
reg_t cur_data = *reinterpret_cast<const reg_t*>(data);
|
||||||
// Extract Device (bits 63:56)
|
// Extract Device (bits 63:56)
|
||||||
uint8_t device = sizeof(reg_t) == 4 ? 0 : (cur_data >> 56) & 0xFF;
|
uint8_t device = sizeof(reg_t) == 4 ? 0 : (cur_data >> 56) & 0xFF;
|
||||||
@ -117,31 +129,20 @@ public:
|
|||||||
this->interrupt_sim = payload_addr;
|
this->interrupt_sim = payload_addr;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err;
|
auto res = owner->write_mem(addr, 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));
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
iss::status read_csr(unsigned addr, reg_t& val) override {
|
iss::status read_time(unsigned addr, reg_t& val) {
|
||||||
if((addr == iss::arch::time || addr == iss::arch::timeh)) {
|
uint64_t time_val = owner->mtime_i.get_interface() ? owner->mtime_i.read() : 0;
|
||||||
uint64_t time_val = owner->mtime_i.get_interface() ? owner->mtime_i.read() : 0;
|
if(addr == iss::arch::time) {
|
||||||
if(addr == iss::arch::time) {
|
val = static_cast<reg_t>(time_val);
|
||||||
val = static_cast<reg_t>(time_val);
|
} else if(addr == iss::arch::timeh) {
|
||||||
} else if(addr == iss::arch::timeh) {
|
if(sizeof(reg_t) != 4)
|
||||||
if(sizeof(reg_t) != 4)
|
return iss::Err;
|
||||||
return iss::Err;
|
val = static_cast<reg_t>(time_val >> 32);
|
||||||
val = static_cast<reg_t>(time_val >> 32);
|
|
||||||
}
|
|
||||||
return iss::Ok;
|
|
||||||
} else {
|
|
||||||
return PLAT::read_csr(addr, val);
|
|
||||||
}
|
}
|
||||||
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait_until(uint64_t flags) override {
|
void wait_until(uint64_t flags) override {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user