1
0
mirror of https://github.com/olofk/serv.git synced 2026-04-27 04:38:43 +00:00
This contains a lot of fixes as IRQ support was broken on both
RTL and zephyr side

* Interrupts are now synced to instruction lifetimes
* Interrupts are disabled on traps and mie is pushed to mpie
* Zephyr applications regenerated from rewritten Zephyr port
* Timer is 32-bit to avoid wrapping around too often
* MEPC was not read properly from CSR storage
This commit is contained in:
Olof Kindgren
2019-11-17 22:40:53 +01:00
parent 603c168d9b
commit 40000cbeb9
8 changed files with 7292 additions and 7256 deletions

View File

@@ -15,12 +15,14 @@ module serv_csr
output wire o_csr_in,
//Stuff
input wire i_mtip,
output reg o_new_irq,
output wire o_new_irq,
input wire i_pending_irq,
input wire i_trap_taken,
input wire i_mstatus_en,
input wire i_mie_en,
input wire i_mcause_en,
input wire [1:0] i_csr_source,
input wire i_trap,
input wire i_mret,
input wire i_d,
output wire o_q);
@@ -28,6 +30,7 @@ module serv_csr
reg mstatus;
reg mstatus_mie;
reg mstatus_mpie;
reg mie_mtie;
reg mcause31;
@@ -37,6 +40,8 @@ module serv_csr
wire csr_in;
wire csr_out;
reg timer_irq_r;
assign csr_in = (i_csr_source == CSR_SOURCE_EXT) ? i_d :
(i_csr_source == CSR_SOURCE_SET) ? csr_out | i_d :
(i_csr_source == CSR_SOURCE_CLR) ? csr_out & ~i_d :
@@ -57,9 +62,14 @@ module serv_csr
assign o_csr_in = csr_in;
reg mtip_r;
assign o_new_irq = !timer_irq_r & timer_irq;
always @(posedge i_clk) begin
/*
Note: To save resources mstatus_mpie (mstatus bit 7) is not
readable or writable from sw
*/
if (i_mstatus_en & (i_cnt[4:2] == 3'd0) & i_cnt_r[3])
mstatus_mie <= csr_in;
@@ -68,12 +78,17 @@ module serv_csr
mstatus <= (i_cnt[4:2] == 0) & i_cnt_r[2] & mstatus_mie;
mtip_r <= i_mtip;
o_new_irq <= !mtip_r & timer_irq;
timer_irq_r <= timer_irq;
if (i_trap) begin
mcause31 <= timer_irq;
mcause3_0 <= timer_irq ? 4'd7 :
if (i_mret) begin
mstatus_mie <= mstatus_mpie;
end
if (i_trap_taken) begin
mstatus_mpie <= mstatus_mie;
mstatus_mie <= 1'b0;
mcause31 <= i_pending_irq;
mcause3_0 <= i_pending_irq ? 4'd7 :
i_e_op ? {!i_ebreak, 3'b011} :
i_mem_misalign ? {2'b01, i_mem_cmd, 1'b0} :
4'd0;

View File

@@ -3,6 +3,8 @@ 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,
input wire i_ibus_ack,
output wire o_rf_rreq,
@@ -49,7 +51,7 @@ module serv_state
assign o_cnt_done = cnt_done;
//Update PC in RUN or TRAP states
assign o_ctrl_pc_en = running | o_ctrl_trap;
assign o_ctrl_pc_en = running | (state == TRAP);
assign o_csr_imm = (o_cnt < 5) ? i_rs1_addr[o_cnt[2:0]] : 1'b0;
assign o_alu_shamt_en = (o_cnt < 5) & (state == INIT);
@@ -64,14 +66,13 @@ module serv_state
assign running = (state == RUN);
assign o_run = running;
assign o_ctrl_trap = (state == TRAP);
//slt*, branch/jump, shift, load/store
wire two_stage_op = i_slt_op | i_mem_op | i_branch_op | i_shift_op;
reg stage_two_pending;
reg pending_irq;
reg irq_sync;
reg misalign_trap_sync;
assign o_dbus_cyc = (state == IDLE) & stage_two_pending & i_mem_op & !i_mem_misalign;
@@ -87,6 +88,10 @@ module serv_state
//Shift operations require bufreg to hold for one cycle between INIT and RUN before shifting
assign o_bufreg_hold = !cnt_en & (stage_two_req | ~i_shift_op);
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 (cnt_done)
o_ctrl_jump <= (state == INIT) & i_take_branch;
@@ -94,14 +99,24 @@ module serv_state
if (cnt_en)
stage_two_pending <= o_init;
if (i_ibus_ack)
irq_sync <= 1'b0;
if (i_new_irq)
pending_irq <= 1'b1;
irq_sync <= 1'b1;
if (i_ibus_ack)
o_pending_irq <= irq_sync;
cnt_done <= (o_cnt[4:2] == 3'b111) & o_cnt_r[2];
//Need a strobe for the first cycle in the IDLE state after INIT
stage_two_req <= cnt_done & (state == INIT);
if (stage_two_req)
misalign_trap_sync <= trap_pending;
if (i_ibus_ack)
misalign_trap_sync <= 1'b0;
case (state)
IDLE : begin
if (stage_two_pending) begin
@@ -111,7 +126,7 @@ module serv_state
state <= TRAP;
end else begin
if (i_rf_ready)
if (i_e_op | pending_irq)
if (i_e_op | o_pending_irq)
state <= TRAP;
else if (two_stage_op)
state <= INIT;
@@ -124,7 +139,6 @@ module serv_state
RUN : begin
end
TRAP : begin
pending_irq <= 1'b0;
end
default : state <= IDLE;
endcase
@@ -138,7 +152,6 @@ module serv_state
if (i_rst) begin
state <= IDLE;
o_cnt <= 5'd0;
pending_irq <= 1'b0;
stage_two_pending <= 1'b0;
o_ctrl_jump <= 1'b0;
o_cnt_r <= 4'b0001;

View File

@@ -128,6 +128,8 @@ module serv_top
parameter RESET_PC = 32'd8;
wire new_irq;
wire trap_taken;
wire pending_irq;
wire [1:0] lsb;
wire [31:0] bufreg_out;
@@ -137,6 +139,8 @@ module serv_top
.i_clk (clk),
.i_rst (i_rst),
.i_new_irq (new_irq),
.o_trap_taken (trap_taken),
.o_pending_irq (pending_irq),
.i_dbus_ack (i_dbus_ack),
.i_ibus_ack (i_ibus_ack),
.o_rf_rreq (rf_rreq),
@@ -375,11 +379,13 @@ module serv_top
.o_csr_in (csr_in),
.i_mtip (i_timer_irq),
.o_new_irq (new_irq),
.i_trap_taken (trap_taken),
.i_pending_irq (pending_irq),
.i_mstatus_en (csr_mstatus_en),
.i_mie_en (csr_mie_en ),
.i_mcause_en (csr_mcause_en ),
.i_csr_source (csr_source),
.i_trap (trap),
.i_mret (mret),
.i_d (csr_d_sel ? csr_imm : rs1),
.o_q (csr_rd));