[WIP] first working version
This commit is contained in:
parent
e483887c43
commit
15f4c059e6
|
@ -6,7 +6,7 @@ import "RVC.core_desc"
|
||||||
import "RVF.core_desc"
|
import "RVF.core_desc"
|
||||||
import "RVD.core_desc"
|
import "RVD.core_desc"
|
||||||
|
|
||||||
Core MNRV32 provides RV32I/*, RV32IC */ {
|
Core MNRV32 provides RV32I, RV32IC {
|
||||||
constants {
|
constants {
|
||||||
XLEN:=32;
|
XLEN:=32;
|
||||||
PCLEN:=32;
|
PCLEN:=32;
|
||||||
|
@ -17,7 +17,7 @@ Core MNRV32 provides RV32I/*, RV32IC */ {
|
||||||
PGMASK := 0xfff; //PGSIZE-1
|
PGMASK := 0xfff; //PGSIZE-1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
Core RV32IMAC provides RV32I, RV32M, RV32A, RV32IC {
|
Core RV32IMAC provides RV32I, RV32M, RV32A, RV32IC {
|
||||||
constants {
|
constants {
|
||||||
XLEN:=32;
|
XLEN:=32;
|
||||||
|
@ -67,4 +67,4 @@ Core RV64GC provides RV64I, RV64M, RV64A, RV64F, RV64D, RV64IC, RV32FC, RV32DC {
|
||||||
PGMASK := 0xfff; //PGSIZE-1
|
PGMASK := 0xfff; //PGSIZE-1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -83,8 +83,7 @@ protected:
|
||||||
|
|
||||||
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
|
||||||
|
|
||||||
|
virt_addr_t execute_inst(virt_addr_t start, std::function<bool(void)> pred) override;
|
||||||
virt_addr_t execute_single_inst(virt_addr_t pc) override;
|
|
||||||
|
|
||||||
// some compile time constants
|
// some compile time constants
|
||||||
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
|
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
|
||||||
|
@ -97,9 +96,9 @@ protected:
|
||||||
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
|
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
|
||||||
std::array<compile_func, LUT_SIZE> lut_11;
|
std::array<compile_func, LUT_SIZE> lut_11;
|
||||||
|
|
||||||
std::array<compile_func *, 4> qlut;
|
std::array<compile_func *, 4> qlut;
|
||||||
|
|
||||||
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
|
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
|
||||||
|
|
||||||
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
|
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
|
||||||
compile_func f) {
|
compile_func f) {
|
||||||
|
@ -138,6 +137,24 @@ protected:
|
||||||
return lut_val;
|
return lut_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void raise_trap(uint16_t trap_id, uint16_t cause){
|
||||||
|
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
||||||
|
this->template get_reg<uint32_t>(arch::traits<ARCH>::TRAP_STATE) = trap_val;
|
||||||
|
this->template get_reg<uint32_t>(arch::traits<ARCH>::NEXT_PC) = std::numeric_limits<uint32_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
void leave_trap(unsigned lvl){
|
||||||
|
this->core.leave_trap(lvl);
|
||||||
|
auto pc_val = super::template read_mem<reg_t>(traits<ARCH>::CSR, (lvl << 8) + 0x41);
|
||||||
|
this->template get_reg<reg_t>(arch::traits<ARCH>::NEXT_PC) = pc_val;
|
||||||
|
this->template get_reg<uint32_t>(arch::traits<ARCH>::LAST_BRANCH) = std::numeric_limits<uint32_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait(unsigned type){
|
||||||
|
this->core.wait_until(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
|
@ -158,7 +175,7 @@ private:
|
||||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* instruction ${idx}: ${instr.name} */
|
||||||
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){<%instr.code.eachLine{%>
|
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){<%instr.code.eachLine{%>
|
||||||
${it}<%}%>
|
${it}<%}%>
|
||||||
}
|
}
|
||||||
<%}%>
|
<%}%>
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -191,32 +208,30 @@ vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_single_inst(virt_addr_t pc) {
|
typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(virt_addr_t start, std::function<bool(void)> pred) {
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t insn = 0;
|
|
||||||
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
|
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
|
||||||
phys_addr_t paddr(pc);
|
code_word_t insn = 0;
|
||||||
auto *const data = (uint8_t *)&insn;
|
auto *const data = (uint8_t *)&insn;
|
||||||
paddr = this->core.v2p(pc);
|
auto pc=start;
|
||||||
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
while(pred){
|
||||||
auto res = this->core.read(paddr, 2, data);
|
auto paddr = this->core.v2p(pc);
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
||||||
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
if (this->core.read(paddr, 2, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||||
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
if ((insn & 0x3) == 0x3) // this is a 32bit instruction
|
||||||
|
if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||||
|
} else {
|
||||||
|
if (this->core.read(paddr, 4, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
||||||
}
|
}
|
||||||
} else {
|
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto lut_val = extract_fields(insn);
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
auto f = qlut[insn & 0x3][lut_val];
|
||||||
|
if (!f)
|
||||||
|
f = &this_class::illegal_intruction;
|
||||||
|
pc = (this->*f)(pc, insn);
|
||||||
}
|
}
|
||||||
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
return pc;
|
||||||
// curr pc on stack
|
|
||||||
auto lut_val = extract_fields(insn);
|
|
||||||
auto f = qlut[insn & 0x3][lut_val];
|
|
||||||
if (f == nullptr) {
|
|
||||||
f = &this_class::illegal_intruction;
|
|
||||||
}
|
|
||||||
return (this->*f)(pc, insn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mnrv32
|
} // namespace mnrv32
|
||||||
|
|
|
@ -657,9 +657,9 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
||||||
const uint64_t addr, const unsigned length, uint8_t *const data) {
|
const uint64_t addr, const unsigned length, uint8_t *const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (access && iss::access_type::DEBUG) {
|
if (access && iss::access_type::DEBUG) {
|
||||||
LOG(TRACE) << "debug read of " << length << " bytes @addr " << addr;
|
LOG(TRACE) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr;
|
||||||
} else {
|
} else {
|
||||||
LOG(TRACE) << "read of " << length << " bytes @addr " << addr;
|
LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
|
@ -738,19 +738,19 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
||||||
switch (length) {
|
switch (length) {
|
||||||
case 8:
|
case 8:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
|
||||||
<< ") @addr " << addr;
|
<< ") @addr 0x" << std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
|
||||||
<< ") @addr " << addr;
|
<< ") @addr 0x" << std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
|
||||||
<< ") @addr " << addr;
|
<< ") @addr 0x" << std::hex << addr;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
|
LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
|
||||||
<< ") @addr " << addr;
|
<< ") @addr 0x" << std::hex << addr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
||||||
|
|
|
@ -105,7 +105,7 @@ int main(int argc, char *argv[]) {
|
||||||
std::unique_ptr<iss::arch_if> cpu{nullptr};
|
std::unique_ptr<iss::arch_if> cpu{nullptr};
|
||||||
std::string isa_opt(clim["isa"].as<std::string>());
|
std::string isa_opt(clim["isa"].as<std::string>());
|
||||||
iss::arch::mnrv32* lcpu = new iss::arch::riscv_hart_msu_vp<iss::arch::mnrv32>();
|
iss::arch::mnrv32* lcpu = new iss::arch::riscv_hart_msu_vp<iss::arch::mnrv32>();
|
||||||
vm = iss::llvm::create(lcpu, clim["gdb-port"].as<unsigned>());
|
vm = iss::interp::create(lcpu, clim["gdb-port"].as<unsigned>()); //iss::llvm::create(lcpu, clim["gdb-port"].as<unsigned>());
|
||||||
cpu.reset(lcpu);
|
cpu.reset(lcpu);
|
||||||
if (clim.count("plugin")) {
|
if (clim.count("plugin")) {
|
||||||
for (std::string opt_val : clim["plugin"].as<std::vector<std::string>>()) {
|
for (std::string opt_val : clim["plugin"].as<std::vector<std::string>>()) {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue