URL
https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk
Subversion Repositories riscv_vhdl
[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [cpu_sysc_plugin/] [riverlib/] [core/] [csr.cpp] - Rev 2
Go to most recent revision | Compare with Previous | Blame | View Log
/** * @file * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. * @author Sergey Khabarov - sergeykhbr@gmail.com * @brief CSR registers module. */ #include "csr.h" #include "riscv-isa.h" namespace debugger { CsrRegs::CsrRegs(sc_module_name name_) : sc_module(name_) { SC_METHOD(comb); sensitive << i_nrst; sensitive << i_xret; sensitive << i_addr; sensitive << i_wena; sensitive << i_wdata; sensitive << i_break_mode; sensitive << i_breakpoint; sensitive << i_trap_ena; sensitive << i_trap_code; sensitive << i_trap_pc; sensitive << i_dport_ena; sensitive << i_dport_write; sensitive << i_dport_addr; sensitive << i_dport_wdata; sensitive << r.mtvec; sensitive << r.mscratch; sensitive << r.mbadaddr; sensitive << r.mode; sensitive << r.uie; sensitive << r.mie; sensitive << r.mpie; sensitive << r.mpp; sensitive << r.mepc; sensitive << r.trap_irq; sensitive << r.trap_code; SC_METHOD(registers); sensitive << i_clk.pos(); }; void CsrRegs::generateVCD(sc_trace_file *i_vcd, sc_trace_file *o_vcd) { if (o_vcd) { sc_trace(o_vcd, i_xret, "/top/proc0/csr0/i_xret"); sc_trace(o_vcd, i_addr, "/top/proc0/csr0/i_addr"); sc_trace(o_vcd, i_wena, "/top/proc0/csr0/i_wena"); sc_trace(o_vcd, i_wdata, "/top/proc0/csr0/i_wdata"); sc_trace(o_vcd, i_trap_ena, "/top/proc0/csr0/i_trap_ena"); sc_trace(o_vcd, i_trap_code, "/top/proc0/csr0/i_trap_code"); sc_trace(o_vcd, i_trap_pc, "/top/proc0/csr0/i_trap_pc"); sc_trace(o_vcd, o_mode, "/top/proc0/csr0/o_mode"); sc_trace(o_vcd, o_ie, "/top/proc0/csr0/o_ie"); sc_trace(o_vcd, o_rdata, "/top/proc0/csr0/o_rdata"); sc_trace(o_vcd, o_mtvec, "/top/proc0/csr0/o_mtvec"); sc_trace(o_vcd, i_dport_ena, "/top/proc0/csr0/i_dport_ena"); sc_trace(o_vcd, i_dport_write, "/top/proc0/csr0/i_dport_write"); sc_trace(o_vcd, i_dport_addr, "/top/proc0/csr0/i_dport_addr"); sc_trace(o_vcd, i_dport_wdata, "/top/proc0/csr0/i_dport_wdata"); sc_trace(o_vcd, o_dport_rdata, "/top/proc0/csr0/o_dport_rdata"); } } void CsrRegs::procedure_RegAccess(uint64_t iaddr, bool iwena, sc_uint<RISCV_ARCH> iwdata, RegistersType &ir, RegistersType *ov, sc_uint<RISCV_ARCH> *ordata) { *ordata = 0; switch (iaddr) { case CSR_misa: /** Base[XLEN-1:XLEN-2] * 1 = 32 * 2 = 64 * 3 = 128 */ (*ordata)(RISCV_ARCH-1, RISCV_ARCH-2) = 2; /** BitCharacterDescription * 0 A Atomic extension * 1 B Tentatively reserved for Bit operations extension * 2 C Compressed extension3DDouble-precision Foating-point extension * 4 E RV32E base ISA * 5 F Single-precision Foating-point extension * 6 G Additional standard extensions present * 7 H Hypervisor mode implemented * 8 I RV32I/64I/128I base ISA * 9 J Reserved * 10 K Reserved * 11 L Tentatively reserved for Decimal Floating-Point extension * 12 M Integer Multiply/Divide extension * 13 N User-level interrupts supported * 14 O Reserved * 15 P Tentatively reserved for Packed-SIMD extension * 16 Q Quad-precision Foating-point extension * 17 R Reserved * 18 S Supervisor mode implemented * 19 T Tentatively reserved for Transactional Memory extension * 20 U User mode implemented * 21 V Tentatively reserved for Vector extension * 22 W Reserved * 23 X Non-standard extensions present * 24 Y Reserved * 25 Z Reserve */ //(*ordata)['A' - 'A'] = 1; (*ordata)['I' - 'A'] = 1; (*ordata)['M' - 'A'] = 1; (*ordata)['U' - 'A'] = 1; break; case CSR_mvendorid: break; case CSR_marchid: break; case CSR_mimplementationid: break; case CSR_mhartid: break; case CSR_uepc:// - User mode program counter break; case CSR_mstatus:// - Machine mode status register (*ordata)[0] = ir.uie; (*ordata)[3] = ir.mie; (*ordata)[7] = ir.mpie; (*ordata)(12, 11) = ir.mpp; if (iwena) { ov->uie = iwdata[0]; ov->mie = iwdata[3]; ov->mpie = iwdata[7]; ov->mpp = iwdata(12, 11); } break; case CSR_medeleg:// - Machine exception delegation break; case CSR_mideleg:// - Machine itnerrupt delegation break; case CSR_mie:// - Machine interrupt enable bit break; case CSR_mtvec: (*ordata) = ir.mtvec; if (iwena) { ov->mtvec = iwdata; } break; case CSR_mtimecmp:// - Machine wall-clock timer compare value break; case CSR_mscratch:// - Machine scratch register (*ordata) = ir.mscratch; if (iwena) { ov->mscratch = iwdata; } break; case CSR_mepc:// - Machine program counter (*ordata) = ir.mepc; if (iwena) { ov->mepc = iwdata; } break; case CSR_mcause:// - Machine trap cause (*ordata) = 0; (*ordata)[63] = ir.trap_irq; (*ordata)(3, 0) = ir.trap_code; break; case CSR_mbadaddr:// - Machine bad address (*ordata) = ir.mbadaddr; break; case CSR_mip:// - Machine interrupt pending break; default:; } } void CsrRegs::comb() { sc_uint<RISCV_ARCH> wb_rdata = 0; sc_uint<RISCV_ARCH> wb_dport_rdata = 0; bool w_ie; bool w_dport_wena; v = r; w_dport_wena = i_dport_ena & i_dport_write; procedure_RegAccess(i_addr.read(), i_wena.read(), i_wdata.read(), r, &v, &wb_rdata); procedure_RegAccess(i_dport_addr.read(), w_dport_wena, i_dport_wdata.read(), r, &v, &wb_dport_rdata); if (i_addr.read() == CSR_mepc && i_xret.read()) { // Switch to previous mode v.mie = r.mpie; v.mpie = 1; v.mode = r.mpp; v.mpp = PRV_U; } if (i_trap_ena.read() && (i_break_mode.read() || !i_breakpoint.read())) { v.mie = 0; v.mpp = r.mode; v.mepc = i_trap_pc.read(); v.mbadaddr = i_trap_pc.read(); v.trap_code = i_trap_code.read()(3, 0); v.trap_irq = i_trap_code.read()[4]; v.mode = PRV_M; switch (r.mode.read()) { case PRV_U: v.mpie = r.uie; break; case PRV_M: v.mpie = r.mie; break; default:; } } w_ie = 0; if ((r.mode.read() != PRV_M) || r.mie.read()) { w_ie = 1; } if (!i_nrst.read()) { v.mtvec = 0; v.mscratch = 0; v.mbadaddr = 0; v.mode = PRV_M; v.uie = 0; v.mie = 0; v.mpie = 0; v.mpp = 0; v.mepc = 0; v.trap_code = 0; v.trap_irq = 0; } o_rdata = wb_rdata; o_ie = w_ie; o_mode = r.mode; o_mtvec = r.mtvec.read()(BUS_ADDR_WIDTH - 1, 0); o_dport_rdata = wb_dport_rdata; } void CsrRegs::registers() { r = v; } } // namespace debugger
Go to most recent revision | Compare with Previous | Blame | View Log