mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-24 22:27:21 -04:00
removed mtinst CSR since it is not ratified by the official RISC-V specs yet
This commit is contained in:
parent
16636c4353
commit
d38509fc92
6 changed files with 30 additions and 42 deletions
|
@ -142,7 +142,7 @@ The CPU is compliant to the [official RISC-V specifications](https://raw.githubu
|
|||
* CSR access instructions: `CSRRW` `CSRRS` `CSRRC` `CSRRWI` `CSRRSI` `CSRRCI`
|
||||
* System instructions: `ECALL` `EBREAK` `MRET` `WFI`
|
||||
* Counter CSRs: `cycle` `cycleh` `time` `timeh` `instret` `instreth` `mcycle` `mcycleh` `minstret` `minstreth`
|
||||
* Machine CSRs: `mstatus` `misa` `mie` `mtvec` `mscratch` `mepc` `mcause` `mtval` `mip` `mtinst` `mimpid` `mhartid`
|
||||
* Machine CSRs: `mstatus` `misa` `mie` `mtvec` `mscratch` `mepc` `mcause` `mtval` `mip` `mimpid` `mhartid`
|
||||
* Custom CSRs: `mfeatures` `mclock` `mispacebase` `mdspacebase` `mispacesize` `mdspacesize`
|
||||
* Supported exceptions and interrupts:
|
||||
* Misaligned instruction address
|
||||
|
|
BIN
docs/NEORV32.pdf
BIN
docs/NEORV32.pdf
Binary file not shown.
|
@ -192,7 +192,6 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
|
|||
irq_ack_nxt : std_ulogic_vector(interrupt_width_c-1 downto 0);
|
||||
cause : std_ulogic_vector(data_width_c-1 downto 0); -- trap ID (for "mcause")
|
||||
cause_nxt : std_ulogic_vector(data_width_c-1 downto 0);
|
||||
instr : std_ulogic_vector(31 downto 0); -- faulting instruction
|
||||
exc_src : std_ulogic_vector(exception_width_c-1 downto 0);
|
||||
--
|
||||
env_start : std_ulogic; -- start trap handler env
|
||||
|
@ -232,7 +231,6 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
|
|||
mtvec : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W)
|
||||
mtval : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/-)
|
||||
mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
|
||||
mtinst : std_ulogic_vector(data_width_c-1 downto 0); -- mtinst: machine trap instruction (transformed) (R/-)
|
||||
cycle : std_ulogic_vector(32 downto 0); -- cycle, mtime (R/-), plus carry bit
|
||||
instret : std_ulogic_vector(32 downto 0); -- instret (R/-), plus carry bit
|
||||
cycleh : std_ulogic_vector(31 downto 0); -- cycleh, mtimeh (R/-)
|
||||
|
@ -1044,7 +1042,6 @@ begin
|
|||
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause
|
||||
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval
|
||||
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip
|
||||
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"34a") or -- mtinst
|
||||
--
|
||||
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycle
|
||||
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- time
|
||||
|
@ -1121,7 +1118,6 @@ begin
|
|||
trap_ctrl.exc_ack <= '0';
|
||||
trap_ctrl.irq_ack <= (others => '0');
|
||||
trap_ctrl.cause <= (others => '0');
|
||||
trap_ctrl.instr <= (others => '0');
|
||||
trap_ctrl.exc_src <= (others => '0');
|
||||
trap_ctrl.env_start <= '0';
|
||||
elsif rising_edge(clk_i) then
|
||||
|
@ -1147,13 +1143,11 @@ begin
|
|||
if (trap_ctrl.env_start = '0') then -- no started trap handler
|
||||
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and
|
||||
((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- exception/IRQ detected!
|
||||
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture source ID for program
|
||||
trap_ctrl.instr <= execute_engine.i_reg; -- FIXME mtinst transformation not fully implemented yet!
|
||||
trap_ctrl.instr(1) <= not execute_engine.is_ci; -- bit is set for uncompressed instruction
|
||||
trap_ctrl.exc_src <= trap_ctrl.exc_buf; -- capture exception source for hardware
|
||||
trap_ctrl.exc_ack <= '1'; -- clear execption
|
||||
trap_ctrl.irq_ack <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
|
||||
trap_ctrl.env_start <= '1'; -- now we want to start the trap handler
|
||||
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture source ID for program
|
||||
trap_ctrl.exc_src <= trap_ctrl.exc_buf; -- capture exception source for hardware
|
||||
trap_ctrl.exc_ack <= '1'; -- clear execption
|
||||
trap_ctrl.irq_ack <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
|
||||
trap_ctrl.env_start <= '1'; -- now we want to start the trap handler
|
||||
end if;
|
||||
else -- trap waiting to get started
|
||||
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
|
||||
|
@ -1175,7 +1169,6 @@ begin
|
|||
|
||||
-- exception/interrupt/status ID visible for program --
|
||||
csr.mcause <= trap_ctrl.cause;
|
||||
csr.mtinst <= trap_ctrl.instr;
|
||||
|
||||
|
||||
-- Trap Priority Detector -----------------------------------------------------------------
|
||||
|
@ -1412,8 +1405,6 @@ begin
|
|||
csr_rdata_o(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
|
||||
csr_rdata_o(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
|
||||
csr_rdata_o(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
|
||||
when x"34a" => -- R/-: mtinst - machine trap instruction (transformed)
|
||||
csr_rdata_o <= csr.mtinst;
|
||||
-- counter and timers --
|
||||
when x"c00" | x"c01" | x"b00" => -- R/-: cycle/time/mcycle: Cycle counter LOW / Timer LOW
|
||||
csr_rdata_o <= csr.cycle(31 downto 0);
|
||||
|
|
|
@ -42,9 +42,6 @@
|
|||
.global _start
|
||||
|
||||
|
||||
// standard CSRs
|
||||
.set mtinst, 0x34a
|
||||
|
||||
// custom CSRs
|
||||
.set CSR_MISPACEBASE, 0xfc4 // CUSTOM (r/-): Base address of instruction memory space (via MEM_ISPACE_BASE generic) */
|
||||
.set CSR_MDSPACEBASE, 0xfc5 // CUSTOM (r/-): Base address of data memory space (via MEM_DSPACE_BASE generic) */
|
||||
|
@ -295,12 +292,16 @@ __crt0_neorv32_rte:
|
|||
// --------------------------------------------
|
||||
__crt0_neorv32_rte_is_exc:
|
||||
|
||||
// is faulting instruction compressed?
|
||||
csrr t0, mtinst
|
||||
andi t0, t0, 2 // get compression flag (bit #1): 0=compressed, 1=uncompressed
|
||||
// check if faulting instruction is compressed and adjust return address
|
||||
|
||||
lh t0, 0(ra) // get compressed instruction or lower 16 bits of uncompressed instruction that caused exception
|
||||
addi t2, zero, 3 // mask
|
||||
and t0, t0, t2 // isolate lowest 2 opcode bits (= 11 for uncompressed instructions)
|
||||
|
||||
addi ra, ra, +2 // only this for compressed instructions
|
||||
add ra, ra, t0 // add another 2 (making +4) for uncompressed instructions
|
||||
bne t0, t2, __crt0_neorv32_rte_execute // jump if compressed instruction
|
||||
|
||||
addi ra, ra, +2 // add another 2 (making +4) for uncompressed instructions
|
||||
j __crt0_neorv32_rte_execute
|
||||
|
||||
|
||||
|
|
|
@ -70,7 +70,6 @@ enum NEORV32_CPU_CSRS_enum {
|
|||
CSR_MCAUSE = 0x342, /**< 0x342 - mcause (r/-): Machine trap cause */
|
||||
CSR_MTVAL = 0x343, /**< 0x343 - mtval (r/-): Machine bad address or instruction */
|
||||
CSR_MIP = 0x344, /**< 0x344 - mip (r/w): Machine interrupt pending register */
|
||||
CSR_MTINST = 0x34a, /**< 0x34a - mtinst (r/-): Machine trap instruction (transformed) */
|
||||
|
||||
CSR_MCYCLE = 0xb00, /**< 0xb00 - mcycle (r/-): Machine cycle counter low word */
|
||||
CSR_MINSTRET = 0xb02, /**< 0xb02 - minstret (r/-): Machine instructions-retired counter low word */
|
||||
|
|
|
@ -157,26 +157,29 @@ static void __neorv32_rte_debug_exc_handler(void) {
|
|||
|
||||
neorv32_uart_printf("System time: 0x%x_%x\n", neorv32_cpu_csr_read(CSR_TIMEH), neorv32_cpu_csr_read(CSR_TIME));
|
||||
|
||||
register uint32_t exc_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
|
||||
register uint32_t return_addr = neorv32_cpu_csr_read(CSR_MEPC);
|
||||
register uint32_t trans_cmd = neorv32_cpu_csr_read(CSR_MTINST);
|
||||
register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE);
|
||||
register uint32_t trap_addr = neorv32_cpu_csr_read(CSR_MEPC);
|
||||
register uint32_t trap_inst;
|
||||
|
||||
if (exc_cause & 0x80000000) {
|
||||
// get faulting instruction
|
||||
asm volatile ("lh %[result], 0(%[input_i])" : [result] "=r" (trap_inst) : [input_i] "r" (trap_addr));
|
||||
|
||||
if (trap_cause & 0x80000000) {
|
||||
neorv32_uart_printf("INTERRUPT");
|
||||
}
|
||||
else {
|
||||
neorv32_uart_printf("EXCEPTION");
|
||||
if ((trans_cmd & (1 << 1)) == 0) {
|
||||
return_addr -= 4;
|
||||
if ((trap_inst & 3) == 3) {
|
||||
trap_addr -= 4;
|
||||
}
|
||||
else {
|
||||
return_addr -= 2;
|
||||
trap_addr -= 2;
|
||||
}
|
||||
}
|
||||
neorv32_uart_printf(" at instruction address: 0x%x\n", return_addr);
|
||||
neorv32_uart_printf(" at instruction address: 0x%x\n", trap_addr);
|
||||
|
||||
neorv32_uart_printf("Cause: ");
|
||||
switch (exc_cause) {
|
||||
switch (trap_cause) {
|
||||
case 0x00000000: neorv32_uart_printf("Instruction address misaligned"); break;
|
||||
case 0x00000001: neorv32_uart_printf("Instruction access fault"); break;
|
||||
case 0x00000002: neorv32_uart_printf("Illegal instruction"); break;
|
||||
|
@ -189,20 +192,14 @@ static void __neorv32_rte_debug_exc_handler(void) {
|
|||
case 0x80000003: neorv32_uart_printf("Machine software interrupt"); break;
|
||||
case 0x80000007: neorv32_uart_printf("Machine timer interrupt (via MTIME)"); break;
|
||||
case 0x8000000B: neorv32_uart_printf("Machine external interrupt (via CLIC)"); break;
|
||||
default: neorv32_uart_printf("Unknown (0x%x)", exc_cause); break;
|
||||
default: neorv32_uart_printf("Unknown (0x%x)", trap_cause); break;
|
||||
}
|
||||
|
||||
// fault address
|
||||
if (exc_cause == 0x00000002) {
|
||||
neorv32_uart_printf("\nFaulting instruction");
|
||||
}
|
||||
else {
|
||||
neorv32_uart_printf("\nFaulting address");
|
||||
}
|
||||
neorv32_uart_printf(": 0x%x\n", neorv32_cpu_csr_read(CSR_MTVAL));
|
||||
neorv32_uart_printf("Transf. instruction: 0x%x ", trans_cmd);
|
||||
neorv32_uart_printf("\nFaulting instruction: 0x%x\n", trap_inst);
|
||||
neorv32_uart_printf("MTVAL: 0x%x\n", neorv32_cpu_csr_read(CSR_MTVAL));
|
||||
|
||||
if ((trans_cmd & (1 << 1)) == 0) {
|
||||
if ((trap_inst & 3) != 3) {
|
||||
neorv32_uart_printf("(decompressed)\n");
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue