X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=riscv%2Fprocessor.cc;h=8c267f4964456e64ad5e4a9b944a8f81219e2aa7;hb=5daafcde73f448a702356e049911b5677a1811c2;hp=b932034e9a6415ba8079490565a78ccff2c9be1d;hpb=a9c5b05eca6a46a0c8722b26b741fc7f1de22405;p=riscv-isa-sim.git diff --git a/riscv/processor.cc b/riscv/processor.cc index b932034..8c267f4 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -5,8 +5,9 @@ #include "common.h" #include "config.h" #include "sim.h" -#include "htif.h" +#include "mmu.h" #include "disasm.h" +#include "gdbserver.h" #include #include #include @@ -19,18 +20,17 @@ #undef STATE #define STATE state -processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id) - : sim(sim), ext(NULL), disassembler(new disassembler_t), - id(id), run(false), debug(false) +processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id, + bool halt_on_reset) + : debug(false), sim(sim), ext(NULL), id(id), halt_on_reset(halt_on_reset) { parse_isa_string(isa); + register_base_instructions(); - mmu = new mmu_t(sim->mem, sim->memsz); - mmu->set_processor(this); - - reset(true); + mmu = new mmu_t(sim, this); + disassembler = new disassembler_t(max_xlen); - register_base_instructions(); + reset(); } processor_t::~processor_t() @@ -84,6 +84,7 @@ void processor_t::parse_isa_string(const char* str) isa_string = "rv" + std::to_string(max_xlen) + p; isa |= 1L << ('s' - 'a'); // advertise support for supervisor mode + isa |= 1L << ('u' - 'a'); // advertise support for user mode while (*p) { isa |= 1L << (*p - 'a'); @@ -115,6 +116,7 @@ void state_t::reset() memset(this, 0, sizeof(*this)); prv = PRV_M; pc = DEFAULT_RSTVEC; + mtvec = DEFAULT_MTVEC; load_reservation = -1; } @@ -136,13 +138,11 @@ void processor_t::set_histogram(bool value) #endif } -void processor_t::reset(bool value) +void processor_t::reset() { - if (run == !value) - return; - run = !value; - state.reset(); + state.dcsr.halt = halt_on_reset; + halt_on_reset = false; set_csr(CSR_MSTATUS, state.mstatus); if (ext) @@ -191,11 +191,39 @@ void processor_t::set_privilege(reg_t prv) state.prv = prv; } +void processor_t::enter_debug_mode(uint8_t cause) +{ + state.dcsr.cause = cause; + state.dcsr.prv = state.prv; + set_privilege(PRV_M); + state.dpc = state.pc; + state.pc = DEBUG_ROM_START; + //debug = true; // TODO +} + void processor_t::take_trap(trap_t& t, reg_t epc) { - if (debug) + if (debug) { fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n", id, t.name(), epc); + if (t.has_badaddr()) + fprintf(stderr, "core %3d: badaddr 0x%016" PRIx64 "\n", id, + t.get_badaddr()); + } + + if (t.cause() == CAUSE_BREAKPOINT && ( + (state.prv == PRV_M && state.dcsr.ebreakm) || + (state.prv == PRV_H && state.dcsr.ebreakh) || + (state.prv == PRV_S && state.dcsr.ebreaks) || + (state.prv == PRV_U && state.dcsr.ebreaku))) { + enter_debug_mode(DCSR_CAUSE_SWBP); + return; + } + + if (state.dcsr.cause) { + state.pc = DEBUG_ROM_EXCEPTION; + return; + } // by default, trap to M-mode, unless delegated to S-mode reg_t bit = t.cause(); @@ -217,9 +245,9 @@ void processor_t::take_trap(trap_t& t, reg_t epc) set_csr(CSR_MSTATUS, s); set_privilege(PRV_S); } else { - state.pc = DEFAULT_MTVEC; - state.mcause = t.cause(); + state.pc = state.mtvec; state.mepc = epc; + state.mcause = t.cause(); if (t.has_badaddr()) state.mbadaddr = t.get_badaddr(); @@ -250,10 +278,16 @@ static bool validate_vm(int max_xlen, reg_t vm) return vm == VM_MBARE; } +int processor_t::paddr_bits() +{ + assert(xlen == max_xlen); + return max_xlen == 64 ? 50 : 34; +} + void processor_t::set_csr(int which, reg_t val) { val = zext_xlen(val); - reg_t delegable_ints = MIP_SSIP | MIP_STIP | (1 << IRQ_HOST) | (1 << IRQ_COP); + reg_t delegable_ints = MIP_SSIP | MIP_STIP | MIP_SEIP | (1 << IRQ_COP); reg_t all_ints = delegable_ints | MIP_MSIP | MIP_MTIP; switch (which) { @@ -272,12 +306,12 @@ void processor_t::set_csr(int which, reg_t val) break; case CSR_MSTATUS: { if ((val ^ state.mstatus) & - (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_PUM)) + (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_PUM | MSTATUS_MXR)) mmu->flush_tlb(); reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_PUM - | (ext ? MSTATUS_XS : 0); + | MSTATUS_MXR | (ext ? MSTATUS_XS : 0); if (validate_vm(max_xlen, get_field(val, MSTATUS_VM))) mask |= MSTATUS_VM; @@ -299,13 +333,10 @@ void processor_t::set_csr(int which, reg_t val) break; } case CSR_MIP: { - reg_t mask = MIP_SSIP | MIP_STIP | MIP_MSIP; + reg_t mask = MIP_SSIP | MIP_STIP; state.mip = (state.mip & ~mask) | (val & mask); break; } - case CSR_MIPI: - state.mip = set_field(state.mip, MIP_MSIP, val & 1); - break; case CSR_MIE: state.mie = (state.mie & ~all_ints) | (val & all_ints); break; @@ -337,23 +368,36 @@ void processor_t::set_csr(int which, reg_t val) case CSR_SIE: return set_csr(CSR_MIE, (state.mie & ~state.mideleg) | (val & state.mideleg)); + case CSR_SPTBR: { + // upper bits of sptbr are the ASID; we only support ASID = 0 + state.sptbr = val & (((reg_t)1 << (paddr_bits() - PGSHIFT)) - 1); + break; + } case CSR_SEPC: state.sepc = val; break; case CSR_STVEC: state.stvec = val >> 2 << 2; break; - case CSR_SPTBR: state.sptbr = val; break; case CSR_SSCRATCH: state.sscratch = val; break; case CSR_SCAUSE: state.scause = val; break; case CSR_SBADADDR: state.sbadaddr = val; break; case CSR_MEPC: state.mepc = val; break; + case CSR_MTVEC: state.mtvec = val >> 2 << 2; break; case CSR_MSCRATCH: state.mscratch = val; break; case CSR_MCAUSE: state.mcause = val; break; case CSR_MBADADDR: state.mbadaddr = val; break; - case CSR_MTOHOST: - if (state.tohost == 0) - state.tohost = val; + case CSR_DCSR: + state.dcsr.prv = get_field(val, DCSR_PRV); + state.dcsr.step = get_field(val, DCSR_STEP); + // TODO: ndreset and fullreset + state.dcsr.ebreakm = get_field(val, DCSR_EBREAKM); + state.dcsr.ebreakh = get_field(val, DCSR_EBREAKH); + state.dcsr.ebreaks = get_field(val, DCSR_EBREAKS); + state.dcsr.ebreaku = get_field(val, DCSR_EBREAKU); + state.dcsr.halt = get_field(val, DCSR_HALT); + break; + case CSR_DPC: + state.dpc = val; break; - case CSR_MFROMHOST: - state.mip = (state.mip & ~(1 << IRQ_HOST)) | (val ? (1 << IRQ_HOST) : 0); - state.fromhost = val; + case CSR_DSCRATCH: + state.dscratch = val; break; } } @@ -426,11 +470,9 @@ reg_t processor_t::get_csr(int which) return state.scause | ((state.scause >> (max_xlen-1)) << (xlen-1)); return state.scause; case CSR_SPTBR: return state.sptbr; - case CSR_SASID: return 0; case CSR_SSCRATCH: return state.sscratch; case CSR_MSTATUS: return state.mstatus; case CSR_MIP: return state.mip; - case CSR_MIPI: return 0; case CSR_MIE: return state.mie; case CSR_MEPC: return state.mepc; case CSR_MSCRATCH: return state.mscratch; @@ -441,16 +483,34 @@ reg_t processor_t::get_csr(int which) case CSR_MIMPID: return 0; case CSR_MVENDORID: return 0; case CSR_MHARTID: return id; - case CSR_MTVEC: return DEFAULT_MTVEC; + case CSR_MTVEC: return state.mtvec; case CSR_MEDELEG: return state.medeleg; case CSR_MIDELEG: return state.mideleg; - case CSR_MTOHOST: - sim->get_htif()->tick(); // not necessary, but faster - return state.tohost; - case CSR_MFROMHOST: - sim->get_htif()->tick(); // not necessary, but faster - return state.fromhost; - case CSR_MCFGADDR: return sim->config_string_addr; + case CSR_TDRSELECT: return 0; + case CSR_DCSR: + { + uint32_t v = 0; + v = set_field(v, DCSR_XDEBUGVER, 1); + v = set_field(v, DCSR_HWBPCOUNT, 0); + v = set_field(v, DCSR_NDRESET, 0); + v = set_field(v, DCSR_FULLRESET, 0); + v = set_field(v, DCSR_PRV, state.dcsr.prv); + v = set_field(v, DCSR_STEP, state.dcsr.step); + v = set_field(v, DCSR_DEBUGINT, sim->debug_module.get_interrupt(id)); + v = set_field(v, DCSR_STOPCYCLE, 0); + v = set_field(v, DCSR_STOPTIME, 0); + v = set_field(v, DCSR_EBREAKM, state.dcsr.ebreakm); + v = set_field(v, DCSR_EBREAKH, state.dcsr.ebreakh); + v = set_field(v, DCSR_EBREAKS, state.dcsr.ebreaks); + v = set_field(v, DCSR_EBREAKU, state.dcsr.ebreaku); + v = set_field(v, DCSR_HALT, state.dcsr.halt); + v = set_field(v, DCSR_CAUSE, state.dcsr.cause); + return v; + } + case CSR_DPC: + return state.dpc; + case CSR_DSCRATCH: + return state.dscratch; } throw trap_illegal_instruction(); } @@ -506,7 +566,7 @@ void processor_t::build_opcode_map() std::sort(instructions.begin(), instructions.end(), cmp()); for (size_t i = 0; i < OPCODE_CACHE_SIZE; i++) - opcode_cache[i] = {1, 0, &illegal_instruction, &illegal_instruction}; + opcode_cache[i] = {0, 0, &illegal_instruction, &illegal_instruction}; } void processor_t::register_extension(extension_t* x) @@ -540,23 +600,20 @@ void processor_t::register_base_instructions() bool processor_t::load(reg_t addr, size_t len, uint8_t* bytes) { - try { - auto res = get_csr(addr / (max_xlen / 8)); - memcpy(bytes, &res, len); - return true; - } catch (trap_illegal_instruction& t) { - return false; - } + return false; } bool processor_t::store(reg_t addr, size_t len, const uint8_t* bytes) { - try { - reg_t value = 0; - memcpy(&value, bytes, len); - set_csr(addr / (max_xlen / 8), value); - return true; - } catch (trap_illegal_instruction& t) { - return false; + switch (addr) + { + case 0: + state.mip &= ~MIP_MSIP; + if (bytes[0] & 1) + state.mip |= MIP_MSIP; + return true; + + default: + return false; } }