From dae8acb8a3c5b8d4db34b8fc6d50136780ed0eae Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 6 Mar 2021 07:17:42 +0000 Subject: [PATCH] checkpoint before refactor --- gen_input/CoreDSL-Instruction-Set-Description | 2 +- incl/iss/arch/riscv_hart_m_p.h | 27 +++++++++---- incl/iss/arch/tgf_c.h | 9 +++-- src/iss/tgf_c.cpp | 2 +- src/sysc/core_complex.cpp | 4 +- src/vm/interp/vm_tgf_c.cpp | 40 ++++++++++++------- 6 files changed, 55 insertions(+), 29 deletions(-) diff --git a/gen_input/CoreDSL-Instruction-Set-Description b/gen_input/CoreDSL-Instruction-Set-Description index 37b66a3..3db52dd 160000 --- a/gen_input/CoreDSL-Instruction-Set-Description +++ b/gen_input/CoreDSL-Instruction-Set-Description @@ -1 +1 @@ -Subproject commit 37b66a36d40c499bfb3348b9a5e077b70445260e +Subproject commit 3db52dddcc002f9407d2170f22b8255d93869573 diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 7d11c71..2f7de9b 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -344,7 +345,15 @@ public: }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - + + void setMemReadCb(std::function const& memReadCb) { + mem_read_cb = memReadCb; + } + + void setMemWriteCb(std::function const& memWriteCb) { + mem_write_cb = memWriteCb; + } + protected: struct riscv_instrumentation_if : public iss::instrumentation_if { @@ -407,6 +416,8 @@ private: iss::status read_hartid(unsigned addr, reg_t &val); reg_t mhartid_reg{0xF}; + std::functionmem_read_cb; + std::function mem_write_cb; protected: void check_interrupt(); @@ -653,7 +664,7 @@ iss::status riscv_hart_m_p::write(const address_type type, const access_ty template iss::status riscv_hart_m_p::read_csr(unsigned addr, reg_t &val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); + if (this->reg.PRIV < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); auto it = csr_rd_cb.find(addr); if (it == csr_rd_cb.end()) { val = csr[addr & csr.page_addr_mask]; @@ -667,7 +678,7 @@ template iss::status riscv_hart_m_p::read_csr(unsigned add template iss::status riscv_hart_m_p::write_csr(unsigned addr, reg_t val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.machine_state < req_priv_lvl) + if (this->reg.PRIV < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); if((addr&0xc00)==0xc00) throw illegal_instruction_fault(this->fault_data); @@ -749,6 +760,7 @@ template iss::status riscv_hart_m_p::write_ip(unsigned add template iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { if ((paddr.val + length) > mem.size()) return iss::Err; + if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg if (sizeof(reg_t) < length) return iss::Err; @@ -774,6 +786,7 @@ iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, u template iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { if ((paddr.val + length) > mem.size()) return iss::Err; + if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg @@ -861,7 +874,7 @@ template void riscv_hart_m_p::check_interrupt() { auto ena_irq = csr[mip] & csr[mie]; bool mie = state.mstatus.MIE; - auto m_enabled = this->reg.machine_state < PRIV_M || (this->reg.machine_state == PRIV_M && mie); + auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie); auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; if (enabled_interrupts != 0) { @@ -906,7 +919,7 @@ template uint64_t riscv_hart_m_p::enter_trap(uint64_t flag this->reg.NEXT_PC = ivec & ~0x1UL; if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; // reset trap state - this->reg.machine_state = PRIV_M; + this->reg.PRIV = PRIV_M; this->reg.trap_state = 0; std::array buffer; sprintf(buffer.data(), "0x%016lx", addr); @@ -918,14 +931,14 @@ template uint64_t riscv_hart_m_p::enter_trap(uint64_t flag } template uint64_t riscv_hart_m_p::leave_trap(uint64_t flags) { - auto cur_priv = this->reg.machine_state; + auto cur_priv = this->reg.PRIV; auto inst_priv = flags & 0x3; auto status = state.mstatus; // pop the relevant lower-privilege interrupt enable and privilege mode stack // clear respective yIE if (inst_priv == PRIV_M) { - this->reg.machine_state = state.mstatus.MPP; + this->reg.PRIV = state.mstatus.MPP; state.mstatus.MPP = 0; // clear mpp to U mode state.mstatus.MIE = state.mstatus.MPIE; } else { diff --git a/incl/iss/arch/tgf_c.h b/incl/iss/arch/tgf_c.h index 4e20d11..4d3a334 100644 --- a/incl/iss/arch/tgf_c.h +++ b/incl/iss/arch/tgf_c.h @@ -78,7 +78,8 @@ template <> struct traits { {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,64}}; static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145}}; + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124, + 128,132,136,137,141,145}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -222,6 +223,7 @@ struct tgf_c: public arch_if { inline uint32_t get_last_branch() { return reg.last_branch; } protected: +#pragma pack(push, 1) struct TGF_C_regs { uint32_t X0 = 0; uint32_t X1 = 0; @@ -258,10 +260,11 @@ protected: uint32_t PC = 0; uint32_t NEXT_PC = 0; uint8_t PRIV = 0; - uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; + uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; + uint32_t last_branch; } reg; - +#pragma pack(pop) std::array addr_mode; uint64_t interrupt_sim=0; diff --git a/src/iss/tgf_c.cpp b/src/iss/tgf_c.cpp index 97a437e..68f8cb7 100644 --- a/src/iss/tgf_c.cpp +++ b/src/iss/tgf_c.cpp @@ -54,8 +54,8 @@ void tgf_c::reset(uint64_t address) { for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits::reg_t),0)); reg.PC=address; reg.NEXT_PC=reg.PC; + reg.PRIV=0x3; reg.trap_state=0; - reg.machine_state=0x3; reg.icount=0; } diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 2a93efc..297fdbf 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -96,7 +96,7 @@ public: core_wrapper(core_complex *owner) : owner(owner) { } - uint32_t get_mode() { return this->reg.machine_state; } + uint32_t get_mode() { return this->reg.PRIV; } inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; } @@ -113,7 +113,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { if (INFO <= Log>::reporting_level() && Output2FILE::stream()) { std::stringstream s; - s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') + s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]"; Log>().get(INFO, "disass") << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) diff --git a/src/vm/interp/vm_tgf_c.cpp b/src/vm/interp/vm_tgf_c.cpp index 455e5aa..9497faa 100644 --- a/src/vm/interp/vm_tgf_c.cpp +++ b/src/vm/interp/vm_tgf_c.cpp @@ -914,12 +914,12 @@ private: writeSpace2(traits::MEM, *(X+rs1) + (int16_t)imm, (int16_t)*(X+rs2)); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 16); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1610,7 +1610,7 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {pred}, {succ}, {rs1}, {rd}", fmt::arg("mnemonic", "fence"), - fmt::arg("pred", name(pred)), fmt::arg("succ", name(succ)), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); this->core.disass_output(pc.val, mnemonic); } @@ -1643,7 +1643,7 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), - fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", name(imm))); + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -3341,6 +3341,19 @@ private: pc = pc + ((instr & 3) == 3 ? 4 : 2); return pc; } + + static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; + iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ + auto phys_pc = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; + if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction + if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; + } else { + if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; + } + return iss::Ok; + } }; template void debug_fn(CODE_WORD insn) { @@ -3367,18 +3380,15 @@ template typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - const typename traits::addr_t upper_bits = ~traits::PGMASK; code_word_t insn = 0; auto *const data = (uint8_t *)&insn; auto pc=start; - while(pred){ - auto paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - if (this->core.read(paddr, 2, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); - 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); + while(pred()){ + auto res = fetch_ins(pc, data); + if(res!=iss::Ok){ + auto new_pc = super::core.enter_trap(TRAP_ID, pc.val); + res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); + if(res!=iss::Ok) throw simulation_stopped(0); } if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto lut_val = extract_fields(insn);