Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions gen_input/templates/CORENAME_sysc.cpp.gtl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
#include <sysc/core2sc_adapter.h>
#include <sysc/core_complex.h>
#include <array>
<% if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") { %>
#include <iss/mem/clic.h>
#include <iss/mem/pmp.h>
<%}%>
<%
def array_count = coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e"? 3 : 2;
%>
Expand All @@ -59,8 +63,11 @@ volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
auto* cpu = new core2sc_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_mu_p_clic_pmp:interp", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t {
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_clic_pmp:interp", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t {
auto* cpu = new core2sc_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>>(cc);
cpu->memories.insert_before_last(std::make_unique<iss::mem::pmp<iss::arch::${coreDef.name.toLowerCase()}>>(cpu->get_priv_if()));
iss::mem::clic_config ccfg{.clic_base=0xc0000000, .clic_int_ctl_bits=4, .clic_num_irq=16, .clic_num_trigger=0, .nmode=true};
cpu->memories.insert_before_last(std::make_unique<iss::mem::clic<iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_t>>(cpu->get_priv_if(), ccfg));
return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
Expand All @@ -77,8 +84,11 @@ volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
auto* cpu = new core2sc_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_mu_p_clic_pmp:llvm", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t {
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_clic_pmp:llvm", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t {
auto* cpu = new core2sc_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>>(cc);
cpu->memories.insert_before_last(std::make_unique<iss::mem::pmp<iss::arch::${coreDef.name.toLowerCase()}>>(cpu->get_priv_if()));
iss::mem::clic_config ccfg{.clic_base=0xc0000000, .clic_int_ctl_bits=4, .clic_num_irq=16, .clic_num_trigger=0, .nmode=true};
cpu->memories.insert_before_last(std::make_unique<iss::mem::clic<iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_t>>(cpu->get_priv_if(), ccfg));
return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
Expand All @@ -104,6 +114,9 @@ volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_mu_p_clic_pmp:asmjit", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t {
auto* cpu = new core2sc_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>>(cc);
cpu->memories.insert_before_last(std::make_unique<iss::mem::pmp<iss::arch::${coreDef.name.toLowerCase()}>>(cpu->get_priv_if()));
iss::mem::clic_config ccfg{.clic_base=0xc0000000, .clic_int_ctl_bits=4, .clic_num_irq=16, .clic_num_trigger=0, .nmode=true};
cpu->memories.insert_before_last(std::make_unique<iss::mem::clic<iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_t>>(cpu->get_priv_if(), ccfg));
return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
Expand Down
27 changes: 23 additions & 4 deletions gen_input/templates/interp/CORENAME.cpp.gtl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ if(vector) {%>
#include <functional>
#include <exception>
#include <vector>
#include <sstream>
#include <iss/instruction_decoder.h>


Expand Down Expand Up @@ -453,6 +452,13 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
#include <iss/arch/riscv_hart_mu_p.h>
#include <iss/arch/riscv_hart_msu_vp.h>
#include <iss/factory.h>
<% if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") { %>
#include <iss/mem/clic.h>
#include <iss/mem/pmp.h>
<%}%>
<%
def array_count = coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e"? 3 : 2;
%>
namespace iss {
namespace {
<% if(instructions.find{it.instruction.name.toLowerCase() == "sret"}) {%>
Expand All @@ -466,8 +472,8 @@ volatile std::array<bool, 3> dummy = {
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
}),<% } else { %>
volatile std::array<bool, 2> dummy = {<%}%>
}),<%} else {%>
volatile std::array<bool, ${array_count}> dummy = {<%}%>
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}_m:interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
Expand All @@ -487,7 +493,20 @@ volatile std::array<bool, 2> dummy = {<%}%>
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}_clic_pmp:interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>();
cpu->memories.insert_before_last(std::make_unique<iss::mem::pmp<iss::arch::${coreDef.name.toLowerCase()}>>(cpu->get_priv_if()));
iss::mem::clic_config ccfg{.clic_base=0xc0000000, .clic_int_ctl_bits=4, .clic_num_irq=16, .clic_num_trigger=0, .nmode=true};
cpu->memories.insert_before_last(std::make_unique<iss::mem::clic<iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_t>>(cpu->get_priv_if(), ccfg));
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})<%}%>
};
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/iss/arch/riscv_hart_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,7 @@ template <typename BASE = logging::disass> struct riscv_hart_common : public BAS
this->fault_data = fault_data;
},
.csr_rd_cb{this->csr_rd_cb},
.csr_wr_cb{csr_wr_cb},
.csr_wr_cb{this->csr_wr_cb},
.state{this->state},
.PRIV{this->reg.PRIV},
.PC{this->reg.PC},
Expand Down
117 changes: 38 additions & 79 deletions src/iss/mem/clic.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct clic_config {
unsigned clic_num_trigger{0};
bool nmode{false};
};

namespace {
inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch(offs) {
Expand Down Expand Up @@ -88,20 +88,21 @@ inline void write_reg_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* co
break;
}
}
} // namespace

template <typename WORD_TYPE> struct clic : public memory_elem {
using this_class = clic<WORD_TYPE>;
using reg_t = WORD_TYPE;
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;

clic(arch::priv_if<WORD_TYPE> hart_if, clic_config cfg)
clic(arch::priv_if<WORD_TYPE> hart_if, clic_config const& cfg)
: hart_if(hart_if)
, cfg(cfg) {
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
clic_cfg_reg = 0x30;
clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
hart_if.csr_rd_cb[arch::mtvt] = MK_CSR_RD_CB(read_plain);
hart_if.csr_rd_cb[arch::mtvt] = MK_CSR_RD_CB(read_xtvt); // 0x307
hart_if.csr_wr_cb[arch::mtvt] = MK_CSR_WR_CB(write_xtvt);
// hart_if.csr_rd_cb[mxnti] = MK_CSR_RD_CB(read_plain(a,r);};
// hart_if.csr_wr_cb[mxnti] = MK_CSR_WR_CB(write_plain(a,r);};
Expand All @@ -111,18 +112,18 @@ template <typename WORD_TYPE> struct clic : public memory_elem {
// hart_if.csr_wr_cb[mscratchcsw] = MK_CSR_WR_CB(write_plain(a,r);};
// hart_if.csr_rd_cb[mscratchcswl] = MK_CSR_RD_CB(read_plain(a,r);};
// hart_if.csr_wr_cb[mscratchcswl] = MK_CSR_WR_CB(write_plain(a,r);};
hart_if.csr_rd_cb[arch::mintthresh] = MK_CSR_RD_CB(read_plain);
hart_if.csr_rd_cb[arch::mintthresh] = MK_CSR_RD_CB(read_intthresh);
hart_if.csr_wr_cb[arch::mintthresh] = MK_CSR_WR_CB(write_intthresh);
if(cfg.nmode) {
hart_if.csr_rd_cb[arch::utvt] = MK_CSR_RD_CB(read_plain);
hart_if.csr_rd_cb[arch::utvt] = MK_CSR_RD_CB(read_xtvt); // 0x007
hart_if.csr_wr_cb[arch::utvt] = MK_CSR_WR_CB(write_xtvt);
hart_if.csr_rd_cb[arch::uintstatus] = MK_CSR_RD_CB(read_intstatus);
hart_if.csr_wr_cb[arch::uintstatus] = MK_CSR_WR_CB(write_null);
hart_if.csr_rd_cb[arch::uintthresh] = MK_CSR_RD_CB(read_plain);
hart_if.csr_rd_cb[arch::uintthresh] = MK_CSR_RD_CB(read_intthresh);
hart_if.csr_wr_cb[arch::uintthresh] = MK_CSR_WR_CB(write_intthresh);
}
hart_if.csr[arch::mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
hart_if.csr[arch::uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
clic_intthresh[arch::mintthresh >> 8] = (1 << (cfg.clic_int_ctl_bits)) - 1;
clic_intthresh[arch::uintthresh >> 8] = (1 << (cfg.clic_int_ctl_bits)) - 1;
}

~clic() = default;
Expand All @@ -137,16 +138,16 @@ template <typename WORD_TYPE> struct clic : public memory_elem {
std::tuple<uint64_t, uint64_t> get_range() override { return {cfg.clic_base, cfg.clic_base + 0x7fff}; }

private:
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
if(addr >= cfg.clic_base && (addr + length) < (cfg.clic_base + 0x8000))
return read_clic(addr, length, data);
return down_stream_mem.rd_mem(access, addr, length, data);
iss::status read_mem(addr_t const& addr, unsigned length, uint8_t* data) {
if(addr.space == 0 && addr.val >= cfg.clic_base && (addr.val + length) < (cfg.clic_base + 0x8000))
return read_clic(addr.val, length, data);
return down_stream_mem.rd_mem(addr, length, data);
}

iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
if(addr >= cfg.clic_base && (addr + length) < (cfg.clic_base + 0x8000))
return write_clic(addr, length, data);
return down_stream_mem.wr_mem(access, addr, length, data);
iss::status write_mem(addr_t const& addr, unsigned length, uint8_t const* data) {
if(addr.space == 0 && addr.val >= cfg.clic_base && (addr.val + length) < (cfg.clic_base + 0x8000))
return write_clic(addr.val, length, data);
return down_stream_mem.wr_mem(addr, length, data);
}

iss::status read_clic(uint64_t addr, unsigned length, uint8_t* data);
Expand All @@ -155,21 +156,33 @@ template <typename WORD_TYPE> struct clic : public memory_elem {

iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }

iss::status read_plain(unsigned addr, reg_t& val) {
val = hart_if.csr[addr];
iss::status read_xtvt(unsigned addr, reg_t& val) {
val = clic_xtvt[addr >> 8];
return iss::Ok;
}

iss::status write_xtvt(unsigned addr, reg_t val) {
hart_if.csr[addr] = val & ~0x3fULL;
clic_xtvt[addr >> 8] = val & ~0x3fULL;
return iss::Ok;
}

iss::status read_cause(unsigned addr, reg_t& val);
iss::status write_cause(unsigned addr, reg_t val);
iss::status read_intstatus(unsigned addr, reg_t& val) {
auto mode = (addr >> 8) & 0x3;
val = clic_uact_lvl & 0xff;
if(mode == 0x3)
val += (clic_mact_lvl & 0xff) << 24;
return iss::Ok;
}

iss::status read_intthresh(unsigned addr, reg_t& val) {
val = clic_intthresh[addr >> 8];
return iss::Ok;
}

iss::status read_intstatus(unsigned addr, reg_t& val);
iss::status write_intthresh(unsigned addr, reg_t val);
iss::status write_intthresh(unsigned addr, reg_t val) {
clic_intthresh[addr >> 8] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
return iss::Ok;
}

protected:
arch::priv_if<WORD_TYPE> hart_if;
Expand All @@ -189,6 +202,8 @@ template <typename WORD_TYPE> struct clic : public memory_elem {
std::vector<clic_int_reg_t> clic_int_reg;
uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0};
uint8_t clic_mact_lvl{0}, clic_uact_lvl{0};
std::array<reg_t, 4> clic_intthresh;
std::array<reg_t, 4> clic_xtvt;
};

template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
Expand Down Expand Up @@ -225,61 +240,5 @@ template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_clic(uint64_t a
return iss::Ok;
}

template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_cause(unsigned addr, reg_t& val) {
if((hart_if.csr[arch::mtvec] & 0x3) == 3) {
val = hart_if.csr[addr] & (1UL << (sizeof(reg_t) * 8) | (hart_if.mcause_max_irq - 1) | (0xfUL << 16));
auto mode = (addr >> 8) & 0x3;
switch(mode) {
case 0:
val |= clic_uprev_lvl << 16;
val |= hart_if.state.mstatus.UPIE << 27;
break;
default:
val |= clic_mprev_lvl << 16;
val |= hart_if.state.mstatus.MPIE << 27;
val |= hart_if.state.mstatus.MPP << 28;
break;
}
} else
val = hart_if.csr[addr] & ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1));
return iss::Ok;
}

template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_cause(unsigned addr, reg_t val) {
if((hart_if.csr[arch::mtvec] & 0x3) == 3) {
auto mask = ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1) | (0xfUL << 16));
hart_if.csr[addr] = (val & mask) | (hart_if.csr[addr] & ~mask);
auto mode = (addr >> 8) & 0x3;
switch(mode) {
case 0:
clic_uprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1;
hart_if.state.mstatus.UPIE = (val >> 27) & 0x1;
break;
default:
clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1;
hart_if.state.mstatus.MPIE = (val >> 27) & 0x1;
hart_if.state.mstatus.MPP = (val >> 28) & 0x3;
break;
}
} else {
auto mask = ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1));
hart_if.csr[addr] = (val & mask) | (hart_if.csr[addr] & ~mask);
}
return iss::Ok;
}

template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_intstatus(unsigned addr, reg_t& val) {
auto mode = (addr >> 8) & 0x3;
val = clic_uact_lvl & 0xff;
if(mode == 0x3)
val += (clic_mact_lvl & 0xff) << 24;
return iss::Ok;
}

template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_intthresh(unsigned addr, reg_t val) {
hart_if.csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
return iss::Ok;
}

} // namespace mem
} // namespace iss
18 changes: 12 additions & 6 deletions src/iss/mem/memory_if.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,14 @@ void memory_hierarchy::append(memory_elem& e) {
hierarchy.push_back(&e);
update_chain();
}
void memory_hierarchy::insert_before(memory_elem&) {}
void memory_hierarchy::insert_after(memory_elem&) {}
void memory_hierarchy::insert_before_last(memory_elem& e) {
hierarchy.insert(hierarchy.begin() + hierarchy.size() - 1, &e);
update_chain();
}
void memory_hierarchy::insert_after_first(memory_elem& e) {
hierarchy.insert(hierarchy.begin() + 1, &e);
update_chain();
}
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),
Expand Down Expand Up @@ -82,13 +88,13 @@ void memory_hierarchy::append(std::unique_ptr<memory_elem>&& p) {
owned_elems.push_back(std::move(p));
}

void memory_hierarchy::insert_before(std::unique_ptr<memory_elem>&& p) {
insert_before(*p);
void memory_hierarchy::insert_before_last(std::unique_ptr<memory_elem>&& p) {
insert_before_last(*p);
owned_elems.push_back(std::move(p));
}

void memory_hierarchy::insert_after(std::unique_ptr<memory_elem>&& p) {
insert_after(*p);
void memory_hierarchy::insert_after_first(std::unique_ptr<memory_elem>&& p) {
insert_after_first(*p);
owned_elems.push_back(std::move(p));
}

Expand Down
8 changes: 4 additions & 4 deletions src/iss/mem/memory_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ struct memory_hierarchy {
void root(memory_elem&);
void prepend(memory_elem&);
void append(memory_elem&);
void insert_before(memory_elem&);
void insert_after(memory_elem&);
void insert_before_last(memory_elem&);
void insert_after_first(memory_elem&);
void replace_last(memory_elem&);
void prepend(std::unique_ptr<memory_elem>&&);
void append(std::unique_ptr<memory_elem>&&);
void insert_before(std::unique_ptr<memory_elem>&&);
void insert_after(std::unique_ptr<memory_elem>&&);
void insert_before_last(std::unique_ptr<memory_elem>&&);
void insert_after_first(std::unique_ptr<memory_elem>&&);
void replace_last(std::unique_ptr<memory_elem>&&);

protected:
Expand Down
Loading