1
0
mirror of https://github.com/olofk/serv.git synced 2026-01-11 23:42:50 +00:00

Optimize trap handling

This commit is contained in:
Olof Kindgren 2021-01-23 22:33:55 +01:00
parent 8d5dd77a26
commit 6fbdea58d6
4 changed files with 37 additions and 51 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -3,6 +3,7 @@ module serv_csr
(
input wire i_clk,
//State
input wire i_init,
input wire i_en,
input wire i_cnt0to3,
input wire i_cnt3,
@ -11,8 +12,7 @@ module serv_csr
input wire i_mem_op,
input wire i_mtip,
input wire i_trap,
input wire i_pending_irq,
output wire o_new_irq,
output reg o_new_irq,
//Control
input wire i_e_op,
input wire i_ebreak,
@ -71,15 +71,15 @@ module serv_csr
assign o_csr_in = csr_in;
assign o_new_irq = !timer_irq_r & timer_irq;
always @(posedge i_clk) begin
if (!i_init & i_cnt_done) begin
timer_irq_r <= timer_irq;
o_new_irq <= timer_irq & !timer_irq_r;
end
if (i_mie_en & i_cnt7)
mie_mtie <= csr_in;
timer_irq_r <= timer_irq;
/*
The mie bit in mstatus gets updated under three conditions
@ -124,12 +124,12 @@ module serv_csr
*/
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]);
mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & mcause3_0[3]);
mcause3_0[1] <= o_new_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & mcause3_0[2]);
mcause3_0[0] <= o_new_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;
mcause31 <= i_trap ? o_new_irq : csr_in;
end
endmodule

View File

@ -5,7 +5,6 @@ module serv_state
input wire i_clk,
input wire i_rst,
input wire i_new_irq,
output reg o_pending_irq,
input wire i_dbus_ack,
output wire o_ibus_cyc,
input wire i_ibus_ack,
@ -49,6 +48,7 @@ module serv_state
reg stage_two_req;
reg init_done;
reg misalign_trap_sync;
reg [4:2] o_cnt;
reg [3:0] o_cnt_r;
@ -70,7 +70,7 @@ module serv_state
assign cnt4 = (o_cnt[4:2] == 3'd1) & o_cnt_r[0];
assign o_cnt7 = (o_cnt[4:2] == 3'd1) & o_cnt_r[3];
assign o_alu_shamt_en = o_cnt0to3 | cnt4 | !o_init;
//Take branch for jump or branch instructions (opcode == 1x0xx) if
@ -86,14 +86,16 @@ 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_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)
assign o_rf_rreq = i_ibus_ack | (stage_two_req & trap_pending);
assign o_rf_rreq = i_ibus_ack | (stage_two_req & misalign_trap_sync);
//Prepare RF for writes when everything is ready to enter stage two
assign o_rf_wreq = ((i_shift_op & (i_alu_sh_done | !i_sh_right) & init_done) | (i_mem_op & i_dbus_ack) | (stage_two_req & (i_slt_op | i_branch_op))) & !trap_pending;
// and the first stage didn't cause a misalign exception
assign o_rf_wreq = !misalign_trap_sync &
((i_shift_op & (i_alu_sh_done | !i_sh_right) & init_done) |
(i_mem_op & i_dbus_ack) |
(stage_two_req & (i_slt_op | i_branch_op)));
assign o_rf_rd_en = i_rd_op & o_cnt_en & !o_init;
@ -112,7 +114,7 @@ module serv_state
assign o_ibus_cyc = ibus_cyc & !i_rst;
assign o_init = two_stage_op & !o_pending_irq & !init_done;
assign o_init = two_stage_op & !i_new_irq & !init_done;
always @(posedge i_clk) begin
//ibus_cyc changes on three conditions.
@ -170,38 +172,24 @@ module serv_state
end
end
assign o_ctrl_trap = WITH_CSR & (i_e_op | i_new_irq | misalign_trap_sync);
generate
if (WITH_CSR) begin
reg irq_sync;
reg misalign_trap_sync;
//trap_pending is only guaranteed to have correct value during the
// last cycle of the init stage
wire trap_pending = WITH_CSR & ((take_branch & i_ctrl_misalign) |
(i_mem_op & i_mem_misalign));
assign o_ctrl_trap = i_e_op | o_pending_irq | misalign_trap_sync;
always @(posedge i_clk) begin
if (i_ibus_ack)
irq_sync <= 1'b0;
if (i_new_irq)
irq_sync <= 1'b1;
if (i_ibus_ack)
o_pending_irq <= irq_sync;
if (stage_two_req)
misalign_trap_sync <= trap_pending;
if (o_cnt_done)
misalign_trap_sync <= 1'b0;
if (i_rst)
if (RESET_STRATEGY != "NONE") begin
misalign_trap_sync <= 1'b0;
irq_sync <= 1'b0;
o_pending_irq <= 1'b0;
end
end // always @ (posedge i_clk)
end else begin
assign o_ctrl_trap = 0;
always @(*)
o_pending_irq = 1'b0;
end
always @(posedge i_clk) begin
if (o_cnt_done)
misalign_trap_sync <= trap_pending & o_init;
if (i_rst)
if (RESET_STRATEGY != "NONE")
misalign_trap_sync <= 1'b0;
end
end else
always @(*)
misalign_trap_sync = 1'b0;
endgenerate
endmodule

View File

@ -149,7 +149,6 @@ module serv_top
wire rf_csr_out;
wire new_irq;
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_pending_irq (pending_irq),
.i_alu_cmp (alu_cmp),
.o_init (init),
.o_cnt_en (cnt_en),
@ -428,6 +426,7 @@ module serv_top
(
.i_clk (clk),
//State
.i_init (init),
.i_en (cnt_en),
.i_cnt0to3 (cnt0to3),
.i_cnt3 (cnt3),
@ -436,7 +435,6 @@ module serv_top
.i_mem_op (mem_op),
.i_mtip (i_timer_irq),
.i_trap (trap),
.i_pending_irq (pending_irq),
.o_new_irq (new_irq),
//Control
.i_e_op (e_op),