Simplify and document trap handling

This commit is contained in:
Olof Kindgren 2021-01-16 16:39:33 +01:00
parent 4a5c5bd588
commit d5febe8f63
7 changed files with 33 additions and 36 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Before After
Before After

View file

@ -8,9 +8,9 @@ module serv_csr
input wire i_cnt3,
input wire i_cnt7,
input wire i_cnt_done,
input wire i_mem_misalign,
input wire i_mem_op,
input wire i_mtip,
input wire i_trap_taken,
input wire i_trap,
input wire i_pending_irq,
output wire o_new_irq,
//Control
@ -90,14 +90,14 @@ module serv_csr
These conditions are all mutually exclusibe
*/
if (i_trap_taken | i_mstatus_en & i_cnt3 | i_mret)
mstatus_mie <= !i_trap_taken & (i_mret ? mstatus_mpie : csr_in);
if ((i_trap & i_cnt_done) | i_mstatus_en & i_cnt3 | i_mret)
mstatus_mie <= !i_trap & (i_mret ? mstatus_mpie : csr_in);
/*
Note: To save resources mstatus_mpie (mstatus bit 7) is not
readable or writable from sw
*/
if (i_trap_taken)
if (i_trap & i_cnt_done)
mstatus_mpie <= mstatus_mie;
/*
@ -115,16 +115,21 @@ module serv_csr
if it was caused by an ebreak instruction (3),
ecall instruction (11), misaligned load (4), misaligned store (6)
or misaligned jump (0)
*/
if (i_mcause_en & i_en & i_cnt0to3 | i_trap_taken)
mcause3_0 <= !i_trap_taken ? {csr_in, mcause3_0[3:1]} :
i_pending_irq ? 4'd7 :
i_e_op ? {!i_ebreak, 3'b011} :
i_mem_misalign ? {2'b01, i_mem_cmd, 1'b0} :
4'd0;
if (i_mcause_en & i_cnt_done | i_trap_taken)
mcause31 <= i_trap_taken ? i_pending_irq : csr_in;
The expressions below are derived from the following truth table
irq => 0111 (timer=7)
e_op => x011 (ebreak=3, ecall=11)
mem => 01x0 (store=6, load=4)
ctrl => 0000 (jump=0)
*/
if (i_mcause_en & i_en & i_cnt0to3 | (i_trap & i_cnt_done)) begin
mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & csr_in);
mcause3_0[2] <= i_pending_irq | i_mem_op | (!i_trap & mcause3_0[3]);
mcause3_0[1] <= i_pending_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & mcause3_0[2]);
mcause3_0[0] <= i_pending_irq | i_e_op | (!i_trap & mcause3_0[1]);
end
if (i_mcause_en & i_cnt_done | i_trap)
mcause31 <= i_trap ? i_pending_irq : csr_in;
end
endmodule

View file

@ -59,15 +59,12 @@ module serv_mem_if
if (dat_valid)
signbit <= dat_cur;
end
generate
if (WITH_CSR) begin
reg misalign;
always @(posedge i_clk)
misalign <= (i_lsb[0] & (i_word | i_half)) | (i_lsb[1] & i_word);
assign o_misalign = misalign & i_mem_op;
end else begin
assign o_misalign = 1'b0;
end
endgenerate
/*
mem_misalign is checked after the init stage to decide whether to do a data
bus transaction or go to the trap state. It is only guaranteed to be correct
at this time
*/
assign o_misalign = WITH_CSR & ((i_lsb[0] & (i_word | i_half)) | (i_lsb[1] & i_word));
endmodule

View file

@ -17,7 +17,7 @@ module serv_rf_if
input wire i_trap,
input wire i_mret,
input wire i_mepc,
input wire i_mem_misalign,
input wire i_mem_op,
input wire i_bufreg_q,
input wire i_bad_pc,
output wire o_csr_pc,
@ -59,7 +59,7 @@ module serv_rf_if
(i_csr_rd & i_rd_csr_en) |
(i_mem_rd);
wire mtval = i_mem_misalign ? i_bufreg_q : i_bad_pc;
wire mtval = i_mem_op ? i_bufreg_q : i_bad_pc;
assign o_wdata0 = i_trap ? mtval : rd;
assign o_wdata1 = i_trap ? i_mepc : i_csr;

View file

@ -5,7 +5,6 @@ module serv_state
input wire i_clk,
input wire i_rst,
input wire i_new_irq,
output wire o_trap_taken,
output reg o_pending_irq,
input wire i_dbus_ack,
output wire o_ibus_cyc,
@ -83,7 +82,7 @@ module serv_state
assign o_dbus_cyc = !o_cnt_en & init_done & i_mem_op & !i_mem_misalign;
wire trap_pending = WITH_CSR & ((o_ctrl_jump & i_ctrl_misalign) | i_mem_misalign);
wire trap_pending = WITH_CSR & ((o_ctrl_jump & i_ctrl_misalign) | (i_mem_op & i_mem_misalign));
//Prepare RF for reads when a new instruction is fetched
// or when stage one caused an exception (rreq implies a write request too)
@ -174,7 +173,6 @@ module serv_state
reg misalign_trap_sync;
assign o_ctrl_trap = i_e_op | o_pending_irq | misalign_trap_sync;
assign o_trap_taken = i_ibus_ack & o_ctrl_trap;
always @(posedge i_clk) begin
if (i_ibus_ack)
@ -187,7 +185,7 @@ module serv_state
if (stage_two_req)
misalign_trap_sync <= trap_pending;
if (i_ibus_ack)
if (o_cnt_done)
misalign_trap_sync <= 1'b0;
if (i_rst)
if (RESET_STRATEGY != "NONE") begin
@ -198,7 +196,6 @@ module serv_state
end // always @ (posedge i_clk)
end else begin
assign o_trap_taken = 0;
assign o_ctrl_trap = 0;
always @(*)
o_pending_irq = 1'b0;

View file

@ -148,7 +148,6 @@ module serv_top
wire rf_csr_out;
wire new_irq;
wire trap_taken;
wire pending_irq;
wire [1:0] lsb;
@ -162,7 +161,6 @@ module serv_top
.i_rst (i_rst),
//State
.i_new_irq (new_irq),
.o_trap_taken (trap_taken),
.o_pending_irq (pending_irq),
.i_alu_cmp (alu_cmp),
.o_init (init),
@ -371,7 +369,7 @@ module serv_top
.i_trap (trap),
.i_mret (mret),
.i_mepc (o_ibus_adr[0]),
.i_mem_misalign (mem_misalign),
.i_mem_op (mem_op),
.i_bufreg_q (bufreg_q),
.i_bad_pc (bad_pc),
.o_csr_pc (csr_pc),
@ -434,9 +432,9 @@ module serv_top
.i_cnt3 (cnt3),
.i_cnt7 (cnt7),
.i_cnt_done (cnt_done),
.i_mem_misalign (mem_misalign),
.i_mem_op (mem_op),
.i_mtip (i_timer_irq),
.i_trap_taken (trap_taken),
.i_trap (trap),
.i_pending_irq (pending_irq),
.o_new_irq (new_irq),
//Control