X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=riscv%2Fprocessor.h;h=3e67215b46df9e29493b050c2d59e5cd586507cf;hb=1da69b975beeda193d5fa47950be5883ca20ad13;hp=41d778e589263a1cbfb43ad51fb0263c65e0343f;hpb=bc49f60710d95c577079a9d8f0c7ccc8c5f2c98c;p=riscv-isa-sim.git diff --git a/riscv/processor.h b/riscv/processor.h index 41d778e..3e67215 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -5,14 +5,16 @@ #include "decode.h" #include "config.h" #include "devices.h" +#include "trap.h" #include #include #include +#include "debug_rom_defines.h" class processor_t; class mmu_t; typedef reg_t (*insn_func_t)(processor_t*, insn_t, reg_t); -class sim_t; +class simif_t; class trap_t; class extension_t; class disassembler_t; @@ -28,7 +30,7 @@ struct insn_desc_t struct commit_log_reg_t { reg_t addr; - reg_t data; + freg_t data; }; typedef struct @@ -65,8 +67,10 @@ typedef enum typedef struct { uint8_t type; + bool dmode; uint8_t maskmax; bool select; + bool timing; mcontrol_action_t action; bool chain; mcontrol_match_t match; @@ -82,7 +86,7 @@ typedef struct // architectural state of a RISC-V hart struct state_t { - void reset(); + void reset(reg_t max_isa); static const int num_triggers = 4; @@ -92,9 +96,10 @@ struct state_t // control and status registers reg_t prv; // TODO: Can this be an enum instead? + reg_t misa; reg_t mstatus; reg_t mepc; - reg_t mbadaddr; + reg_t mtval; reg_t mscratch; reg_t mtvec; reg_t mcause; @@ -103,20 +108,20 @@ struct state_t reg_t mip; reg_t medeleg; reg_t mideleg; - reg_t mucounteren; - reg_t mscounteren; + uint32_t mcounteren; + uint32_t scounteren; reg_t sepc; - reg_t sbadaddr; + reg_t stval; reg_t sscratch; reg_t stvec; - reg_t sptbr; + reg_t satp; reg_t scause; reg_t dpc; reg_t dscratch; dcsr_t dcsr; reg_t tselect; mcontrol_t mcontrol[num_triggers]; - reg_t tdata1[num_triggers]; + reg_t tdata2[num_triggers]; uint32_t fflags; uint32_t frm; @@ -135,6 +140,8 @@ struct state_t #ifdef RISCV_ENABLE_COMMITLOG commit_log_reg_t log_reg_write; reg_t last_inst_priv; + int last_inst_xlen; + int last_inst_flen; #endif }; @@ -157,7 +164,7 @@ static int cto(reg_t val) class processor_t : public abstract_device_t { public: - processor_t(const char* isa, sim_t* sim, uint32_t id, bool halt_on_reset=false); + processor_t(const char* isa, simif_t* sim, uint32_t id, bool halt_on_reset=false); ~processor_t(); void set_debug(bool value); @@ -165,15 +172,30 @@ public: void reset(); void step(size_t n); // run for n cycles void set_csr(int which, reg_t val); - void raise_interrupt(reg_t which); reg_t get_csr(int which); mmu_t* get_mmu() { return mmu; } state_t* get_state() { return &state; } + unsigned get_xlen() { return xlen; } + unsigned get_max_xlen() { return max_xlen; } + std::string get_isa_string() { return isa_string; } + unsigned get_flen() { + return supports_extension('Q') ? 128 : + supports_extension('D') ? 64 : + supports_extension('F') ? 32 : 0; + } extension_t* get_extension() { return ext; } bool supports_extension(unsigned char ext) { if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a'; - return ext >= 'A' && ext <= 'Z' && ((isa >> (ext - 'A')) & 1); + return ext >= 'A' && ext <= 'Z' && ((state.misa >> (ext - 'A')) & 1); + } + reg_t pc_alignment_mask() { + return ~(reg_t)(supports_extension('C') ? 0 : 2); } + void check_pc_alignment(reg_t pc) { + if (unlikely(pc & ~pc_alignment_mask())) + throw trap_instruction_address_misaligned(pc); + } + reg_t legalize_privilege(reg_t); void set_privilege(reg_t); void yield_load_reservation() { state.load_reservation = (reg_t)-1; } void update_histogram(reg_t pc); @@ -190,6 +212,8 @@ public: bool debug; // When true, take the slow simulation path. bool slow_path(); + bool halted() { return state.dcsr.cause ? true : false; } + bool halt_request; // Return the index of a trigger that matched, or -1. inline int trigger_match(trigger_operation_t operation, reg_t address, reg_t data) @@ -209,7 +233,6 @@ public: (operation == OPERATION_STORE && !state.mcontrol[i].store) || (operation == OPERATION_LOAD && !state.mcontrol[i].load) || (state.prv == PRV_M && !state.mcontrol[i].m) || - (state.prv == PRV_H && !state.mcontrol[i].h) || (state.prv == PRV_S && !state.mcontrol[i].s) || (state.prv == PRV_U && !state.mcontrol[i].u)) { continue; @@ -230,42 +253,43 @@ public: switch (state.mcontrol[i].match) { case MATCH_EQUAL: - if (value != state.tdata1[i]) + if (value != state.tdata2[i]) continue; break; case MATCH_NAPOT: { - reg_t mask = ~((1 << cto(state.tdata1[i])) - 1); - if ((value & mask) != (state.tdata1[i] & mask)) + reg_t mask = ~((1 << cto(state.tdata2[i])) - 1); + if ((value & mask) != (state.tdata2[i] & mask)) continue; } break; case MATCH_GE: - if (value < state.tdata1[i]) + if (value < state.tdata2[i]) continue; break; case MATCH_LT: - if (value >= state.tdata1[i]) + if (value >= state.tdata2[i]) continue; break; case MATCH_MASK_LOW: { - reg_t mask = state.tdata1[i] >> (xlen/2); - if ((value & mask) != (state.tdata1[i] & mask)) + reg_t mask = state.tdata2[i] >> (xlen/2); + if ((value & mask) != (state.tdata2[i] & mask)) continue; } break; case MATCH_MASK_HIGH: { - reg_t mask = state.tdata1[i] >> (xlen/2); - if (((value >> (xlen/2)) & mask) != (state.tdata1[i] & mask)) + reg_t mask = state.tdata2[i] >> (xlen/2); + if (((value >> (xlen/2)) & mask) != (state.tdata2[i] & mask)) continue; } break; } - if (!state.mcontrol[i].chain) + if (!state.mcontrol[i].chain) { return i; + } chain_ok = true; } return -1; @@ -274,7 +298,7 @@ public: void trigger_updated(); private: - sim_t* sim; + simif_t* sim; mmu_t* mmu; // main memory is always accessed via the mmu extension_t* ext; disassembler_t* disassembler; @@ -282,7 +306,7 @@ private: uint32_t id; unsigned max_xlen; unsigned xlen; - reg_t isa; + reg_t max_isa; std::string isa_string; bool histogram_enabled; bool halt_on_reset; @@ -293,23 +317,25 @@ private: static const size_t OPCODE_CACHE_SIZE = 8191; insn_desc_t opcode_cache[OPCODE_CACHE_SIZE]; - void check_timer(); - void take_interrupt(); // take a trap if any interrupts are pending + void take_pending_interrupt() { take_interrupt(state.mip & state.mie); } + void take_interrupt(reg_t mask); // take first enabled interrupt in mask void take_trap(trap_t& t, reg_t epc); // take an exception void disasm(insn_t insn); // disassemble and print an instruction int paddr_bits(); void enter_debug_mode(uint8_t cause); - friend class sim_t; friend class mmu_t; - friend class rtc_t; + friend class clint_t; friend class extension_t; void parse_isa_string(const char* isa); void build_opcode_map(); void register_base_instructions(); insn_func_t decode_insn(insn_t insn); + + // Track repeated executions for processor_t::disasm() + uint64_t last_pc, last_bits, executions; }; reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc);