mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Make illegal instruction exceptions work again
This commit is contained in:
parent
e41c7b96be
commit
0608b98440
5 changed files with 42 additions and 45 deletions
|
@ -46,6 +46,7 @@ module controller
|
|||
input logic instr_ack_i, // Acknow from instr memory or cache (means that data is available)
|
||||
|
||||
output logic [2:0] pc_mux_sel_o, // Selector in the Fetch stage to select the rigth PC (normal, jump ...)
|
||||
output logic pc_set_o, // jump to address set by pc_mux_sel
|
||||
|
||||
// ALU signals
|
||||
output logic [`ALU_OP_WIDTH-1:0] alu_operator_o, // Operator in the Ex stage for the ALU block
|
||||
|
@ -99,6 +100,7 @@ module controller
|
|||
input logic irq_present_i, // there is an IRQ, so if we are sleeping we should wake up now
|
||||
|
||||
// Exception Controller Signals
|
||||
input logic exc_pc_sel_i, // exception execution requested
|
||||
input logic illegal_c_insn_i, // compressed instruction decode failed
|
||||
output logic illegal_insn_o, // illegal instruction encountered
|
||||
output logic trap_insn_o, // trap instruction encountered
|
||||
|
@ -142,7 +144,7 @@ module controller
|
|||
);
|
||||
|
||||
// FSM state encoding
|
||||
enum logic [3:0] { RESET, BOOT_SET, SLEEP, FIRST_FETCH, DECODE, BRANCH, BRANCH_DELAY,
|
||||
enum logic [3:0] { RESET, BOOT_SET, SLEEP, FIRST_FETCH, DECODE, BRANCH,
|
||||
FLUSH_EX, FLUSH_WB,
|
||||
DBG_FLUSH_EX, DBG_FLUSH_WB, DBG_SIGNAL, DBG_WAIT } ctrl_fsm_cs, ctrl_fsm_ns;
|
||||
|
||||
|
@ -166,6 +168,7 @@ module controller
|
|||
|
||||
logic pipe_flush;
|
||||
logic trap_insn;
|
||||
logic eret_insn;
|
||||
|
||||
logic [1:0] jump_in_id;
|
||||
|
||||
|
@ -243,6 +246,7 @@ module controller
|
|||
|
||||
illegal_insn_int = 1'b0;
|
||||
trap_insn = 1'b0;
|
||||
eret_insn = 1'b0;
|
||||
pipe_flush = 1'b0;
|
||||
|
||||
rega_used = 1'b0;
|
||||
|
@ -789,8 +793,7 @@ module controller
|
|||
|
||||
32'h10_00_00_73: // ERET
|
||||
begin
|
||||
// TODO: Handle in controller
|
||||
//pc_mux_sel = `PC_ERET;
|
||||
eret_insn = 1'b1;
|
||||
clear_isr_running_o = 1'b1;
|
||||
end
|
||||
|
||||
|
@ -960,6 +963,7 @@ module controller
|
|||
instr_req_o = 1'b1;
|
||||
|
||||
pc_mux_sel_o = `PC_BOOT;
|
||||
pc_set_o = 1'b0;
|
||||
|
||||
ctrl_fsm_ns = ctrl_fsm_cs;
|
||||
|
||||
|
@ -987,6 +991,7 @@ module controller
|
|||
begin
|
||||
instr_req_o = 1'b1;
|
||||
pc_mux_sel_o = `PC_BOOT;
|
||||
pc_set_o = 1'b1;
|
||||
|
||||
ctrl_fsm_ns = FIRST_FETCH;
|
||||
end
|
||||
|
@ -1015,8 +1020,10 @@ module controller
|
|||
|
||||
// hwloop detected, jump to start address!
|
||||
// Attention: This has to be done in the DECODE and the FIRST_FETCH states
|
||||
if (hwloop_jump_i == 1'b1)
|
||||
if (hwloop_jump_i == 1'b1) begin
|
||||
pc_mux_sel_o = `PC_HWLOOP;
|
||||
pc_set_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
DECODE:
|
||||
|
@ -1035,8 +1042,9 @@ module controller
|
|||
if (jump_in_id == `BRANCH_JALR || jump_in_id == `BRANCH_JAL) begin
|
||||
pc_mux_sel_o = `PC_JUMP;
|
||||
|
||||
if (~stall_id_o)
|
||||
ctrl_fsm_ns = DECODE;
|
||||
// we don't have to change our current state here as the prefetch
|
||||
// buffer is automatically invalidated, thus the next instruction
|
||||
// that is served to the ID stage is the one of the jump target
|
||||
end
|
||||
|
||||
// handle hwloops
|
||||
|
@ -1049,6 +1057,21 @@ module controller
|
|||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
||||
if (exc_pc_sel_i) begin
|
||||
pc_mux_sel_o = `PC_EXCEPTION;
|
||||
pc_set_o = 1'b1;
|
||||
|
||||
// we don't have to change our current state here as the prefetch
|
||||
// buffer is automatically invalidated, thus the next instruction
|
||||
// that is served to the ID stage is the one of the jump to the
|
||||
// exception handler
|
||||
end
|
||||
|
||||
if (eret_insn) begin
|
||||
pc_mux_sel_o = `PC_ERET;
|
||||
pc_set_o = 1'b1;
|
||||
end
|
||||
|
||||
// handle WFI instruction, flush pipeline and (potentially) go to
|
||||
// sleep
|
||||
if (pipe_flush || exc_pipe_flush_i)
|
||||
|
@ -1107,25 +1130,6 @@ module controller
|
|||
end
|
||||
end
|
||||
|
||||
// "delay slot" of jump and branch
|
||||
// inserts a nop by not decoding the instruction
|
||||
BRANCH_DELAY:
|
||||
begin
|
||||
// if we want to debug, flush the pipeline
|
||||
// the current_pc_if will take the value of the next instruction to
|
||||
// be executed (NPC)
|
||||
if (trap_hit_i)
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
halt_id = 1'b1;
|
||||
|
||||
ctrl_fsm_ns = DBG_FLUSH_EX;
|
||||
end else begin
|
||||
if (~stall_id_o)
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
end
|
||||
|
||||
DBG_FLUSH_EX:
|
||||
begin
|
||||
halt_if = 1'b1;
|
||||
|
@ -1161,6 +1165,7 @@ module controller
|
|||
if(dbg_set_npc_i == 1'b1) begin
|
||||
halt_id = 1'b0;
|
||||
pc_mux_sel_o = `PC_DBG_NPC;
|
||||
pc_set_o = 1'b1;
|
||||
ctrl_fsm_ns = DBG_WAIT;
|
||||
end
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ module exc_controller
|
|||
// to IF stage
|
||||
output logic exc_pc_sel_o, // influences next PC, if set exception PC is used
|
||||
output logic [1:0] exc_pc_mux_o, // Selector in the Fetch stage to select the rigth exception PC
|
||||
output logic force_nop_o, // Force a Nop (Bubble) in the Fetch stage
|
||||
|
||||
// hwloop signals
|
||||
output logic hwloop_enable_o, // '1' if pc is valid (interrupt related signal)
|
||||
|
@ -78,7 +77,7 @@ module exc_controller
|
|||
logic clear_exc_reason;
|
||||
|
||||
// disable hardware loops when nops are inserted or the controller is not active
|
||||
assign hwloop_enable_o = (~force_nop_o) | (~core_busy_i);
|
||||
assign hwloop_enable_o = (~core_busy_i);
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// ____ _ //
|
||||
|
@ -162,7 +161,6 @@ module exc_controller
|
|||
clear_exc_reason = 1'b0;
|
||||
save_pc_if_o = 1'b0;
|
||||
save_pc_id_o = 1'b0;
|
||||
force_nop_o = 1'b0;
|
||||
pc_valid_o = 1'b1;
|
||||
exc_pc_sel_o = 1'b0;
|
||||
exc_pc_mux_o = `EXC_PC_NO_INCR;
|
||||
|
@ -179,7 +177,6 @@ module exc_controller
|
|||
ExcIR: begin
|
||||
if (jump_in_id_i == 2'b00)
|
||||
begin // no delay slot
|
||||
force_nop_o = 1'b1;
|
||||
exc_pc_sel_o = 1'b1;
|
||||
save_pc_if_o = 1'b1; // save current PC
|
||||
|
||||
|
@ -201,7 +198,6 @@ module exc_controller
|
|||
// Illegal instruction encountered, we directly jump to
|
||||
// the ISR without flushing the pipeline
|
||||
ExcIllegalInsn: begin
|
||||
force_nop_o = 1'b1;
|
||||
exc_pc_sel_o = 1'b1;
|
||||
exc_pc_mux_o = `EXC_PC_ILLINSN;
|
||||
save_pc_id_o = 1'b1; // save current PC
|
||||
|
@ -217,7 +213,6 @@ module exc_controller
|
|||
// Execute delay slot for IR
|
||||
NopDelayIR:
|
||||
begin
|
||||
force_nop_o = 1'b1;
|
||||
exc_pc_sel_o = 1'b1;
|
||||
save_pc_if_o = 1'b1; // save current PC
|
||||
|
||||
|
|
11
id_stage.sv
11
id_stage.sv
|
@ -55,9 +55,9 @@ module id_stage
|
|||
output logic [31:0] jump_target_o,
|
||||
|
||||
// IF and ID stage signals
|
||||
output logic pc_set_o,
|
||||
output logic [2:0] pc_mux_sel_o,
|
||||
output logic [1:0] exc_pc_mux_o,
|
||||
output logic force_nop_o,
|
||||
|
||||
input logic illegal_c_insn_i,
|
||||
|
||||
|
@ -169,8 +169,6 @@ module id_stage
|
|||
logic exc_pc_sel;
|
||||
logic [2:0] pc_mux_sel_int; // selects next PC in if stage
|
||||
|
||||
logic force_nop_exc;
|
||||
|
||||
logic irq_present;
|
||||
|
||||
// Signals running between controller and exception controller
|
||||
|
@ -267,8 +265,7 @@ module id_stage
|
|||
logic [31:0] operand_c;
|
||||
|
||||
|
||||
assign force_nop_o = force_nop_exc;
|
||||
assign pc_mux_sel_o = (exc_pc_sel == 1'b1) ? `PC_EXCEPTION : pc_mux_sel_int;
|
||||
assign pc_mux_sel_o = pc_mux_sel_int;
|
||||
|
||||
|
||||
assign instr = instr_rdata_i;
|
||||
|
@ -538,6 +535,8 @@ module id_stage
|
|||
.instr_req_o ( instr_req_o ),
|
||||
.instr_gnt_i ( instr_gnt_i ),
|
||||
.instr_ack_i ( instr_ack_i ),
|
||||
|
||||
.pc_set_o ( pc_set_o ),
|
||||
.pc_mux_sel_o ( pc_mux_sel_int ),
|
||||
|
||||
// Alu signals
|
||||
|
@ -592,6 +591,7 @@ module id_stage
|
|||
.irq_present_i ( irq_present ),
|
||||
|
||||
// Exception Controller Signals
|
||||
.exc_pc_sel_i ( exc_pc_sel ),
|
||||
.illegal_c_insn_i ( illegal_c_insn_i ),
|
||||
.illegal_insn_o ( illegal_insn ),
|
||||
.trap_insn_o ( trap_insn ),
|
||||
|
@ -662,7 +662,6 @@ module id_stage
|
|||
// to IF stage
|
||||
.exc_pc_sel_o ( exc_pc_sel ),
|
||||
.exc_pc_mux_o ( exc_pc_mux_o ),
|
||||
.force_nop_o ( force_nop_exc ),
|
||||
|
||||
// hwloop signals
|
||||
.hwloop_enable_o ( hwloop_enable ),
|
||||
|
|
|
@ -60,7 +60,7 @@ module if_stage
|
|||
output logic [31:0] current_pc_id_o,
|
||||
|
||||
// Forwarding ports - control signals
|
||||
input logic force_nop_i, // insert a NOP in the pipe
|
||||
input logic pc_set_i, // set the program counter to a new value
|
||||
input logic [31:0] exception_pc_reg_i, // address used to restore PC when the interrupt/exception is served
|
||||
input logic [2:0] pc_mux_sel_i, // sel for pc multiplexer
|
||||
input logic [1:0] exc_pc_mux_i, // select which exception to execute
|
||||
|
@ -78,7 +78,6 @@ module if_stage
|
|||
|
||||
// from debug unit
|
||||
input logic [31:0] dbg_npc_i,
|
||||
input logic dbg_set_npc_i,
|
||||
|
||||
// pipeline stall
|
||||
input logic stall_if_i,
|
||||
|
@ -320,7 +319,7 @@ module if_stage
|
|||
end
|
||||
|
||||
end else if (jump_in_id_i == `BRANCH_JAL || jump_in_id_i == `BRANCH_JALR
|
||||
|| dbg_set_npc_i
|
||||
|| pc_set_i
|
||||
|| hwloop_jump_i) begin
|
||||
valid_o = 1'b0;
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ module riscv_core
|
|||
logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage
|
||||
logic [31:0] current_pc_if; // Current Program counter
|
||||
logic [31:0] current_pc_id; // Current Program counter
|
||||
logic force_nop_id;
|
||||
logic pc_set;
|
||||
logic [2:0] pc_mux_sel_id; // Mux selector for next PC
|
||||
logic [1:0] exc_pc_mux_id; // Mux selector for exception PC
|
||||
|
||||
|
@ -248,8 +248,8 @@ module riscv_core
|
|||
.current_pc_if_o ( current_pc_if ), // current pc in IF stage
|
||||
.current_pc_id_o ( current_pc_id ), // current pc in ID stage
|
||||
|
||||
// Forwrding ports - control signals
|
||||
.force_nop_i ( force_nop_id ), // select incoming instr or NOP
|
||||
// control signals
|
||||
.pc_set_i ( pc_set ),
|
||||
.exception_pc_reg_i ( epcr ), // Exception PC register
|
||||
.pc_mux_sel_i ( pc_mux_sel_id ), // sel for pc multiplexer
|
||||
.exc_pc_mux_i ( exc_pc_mux_id ), // selector for exception multiplexer
|
||||
|
@ -260,7 +260,6 @@ module riscv_core
|
|||
|
||||
// from debug unit
|
||||
.dbg_npc_i ( dbg_npc ),
|
||||
.dbg_set_npc_i ( dbg_set_npc ),
|
||||
|
||||
// Jump and branch target and decision
|
||||
.jump_in_id_i ( jump_in_id ),
|
||||
|
@ -308,9 +307,9 @@ module riscv_core
|
|||
.instr_gnt_i ( instr_grant_i ),
|
||||
.instr_ack_i ( instr_ack_int ),
|
||||
|
||||
.pc_set_o ( pc_set ),
|
||||
.pc_mux_sel_o ( pc_mux_sel_id ),
|
||||
.exc_pc_mux_o ( exc_pc_mux_id ),
|
||||
.force_nop_o ( force_nop_id ),
|
||||
|
||||
.illegal_c_insn_i ( illegal_c_insn_id ),
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue