[WIP] first working version

This commit is contained in:
Eyck Jentzsch 2020-01-12 18:19:48 +01:00
parent e483887c43
commit 15f4c059e6
5 changed files with 2505 additions and 71 deletions

View File

@ -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
} }
} }
*/

View File

@ -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

View File

@ -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;

View File

@ -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