Make illegal instruction exceptions work again

This commit is contained in:
Andreas Traber 2015-09-11 13:14:56 +02:00
parent e41c7b96be
commit 0608b98440
5 changed files with 42 additions and 45 deletions

View file

@ -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

View file

@ -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

View file

@ -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 ),

View file

@ -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;

View file

@ -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 ),