X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=riscv%2Fprocessor.h;h=1b94b1f710e0c69d22e276318331a8e004d6e3cf;hb=12714e371e9b8ce2efcf0e77347ed1b33c8de27b;hp=3f8c4def59b4e71be280bc1d0a8629cbe74beacc;hpb=c8149cb261631aadfe6d984cb9b40b88bfb31408;p=riscv-isa-sim.git diff --git a/riscv/processor.h b/riscv/processor.h index 3f8c4de..1b94b1f 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -8,6 +8,7 @@ #include #include #include +#include "debug_rom/debug_rom_defines.h" class processor_t; class mmu_t; @@ -28,7 +29,7 @@ struct insn_desc_t struct commit_log_reg_t { reg_t addr; - reg_t data; + freg_t data; }; typedef struct @@ -45,7 +46,6 @@ typedef struct typedef enum { - ACTION_NONE = MCONTROL_ACTION_NONE, ACTION_DEBUG_EXCEPTION = MCONTROL_ACTION_DEBUG_EXCEPTION, ACTION_DEBUG_MODE = MCONTROL_ACTION_DEBUG_MODE, ACTION_TRACE_START = MCONTROL_ACTION_TRACE_START, @@ -66,8 +66,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; @@ -95,7 +97,7 @@ struct state_t reg_t prv; // TODO: Can this be an enum instead? reg_t mstatus; reg_t mepc; - reg_t mbadaddr; + reg_t mtval; reg_t mscratch; reg_t mtvec; reg_t mcause; @@ -104,20 +106,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; @@ -136,6 +138,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 }; @@ -166,15 +170,21 @@ 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_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); } + 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); @@ -191,6 +201,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) @@ -198,18 +210,21 @@ public: if (state.dcsr.cause) return -1; - bool chain_ok = false; + bool chain_ok = true; for (unsigned int i = 0; i < state.num_triggers; i++) { - if (state.mcontrol[i].action == ACTION_NONE || - (operation == OPERATION_EXECUTE && !state.mcontrol[i].execute) || + if (!chain_ok) { + chain_ok |= !state.mcontrol[i].chain; + continue; + } + + if ((operation == OPERATION_EXECUTE && !state.mcontrol[i].execute) || (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)) { - goto next; + continue; } reg_t value; @@ -227,55 +242,44 @@ public: switch (state.mcontrol[i].match) { case MATCH_EQUAL: - if (value != state.tdata1[i]) - goto next; + 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)) - goto next; + 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]) - goto next; + if (value < state.tdata2[i]) + continue; break; case MATCH_LT: - if (value >= state.tdata1[i]) - goto next; + 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)) - goto next; + 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)) - goto next; + reg_t mask = state.tdata2[i] >> (xlen/2); + if (((value >> (xlen/2)) & mask) != (state.tdata2[i] & mask)) + continue; } break; } - if (state.mcontrol[i].chain && !chain_ok) { - goto next; - } - - // We got here, so this trigger matches. But if the next trigger has - // chain set, then we can't perform the action. - if (i+1 < state.num_triggers && state.mcontrol[i+1].chain) { - chain_ok = true; - continue; - } else { + if (!state.mcontrol[i].chain) { return i; } - -next: - chain_ok = false; + chain_ok = true; } return -1; } @@ -292,6 +296,7 @@ private: unsigned max_xlen; unsigned xlen; reg_t isa; + reg_t max_isa; std::string isa_string; bool histogram_enabled; bool halt_on_reset; @@ -302,8 +307,8 @@ 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(); @@ -312,13 +317,16 @@ private: 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);