1
0
mirror of https://github.com/olofk/serv.git synced 2026-03-01 09:20:58 +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));

View File

@@ -135,7 +135,9 @@ servant_arbiter servant_arbiter
.o_wb_rdt (wb_mem_rdt),
.o_wb_ack (wb_mem_ack));
servant_timer timer
servant_timer
#(.WIDTH (32))
timer
(.i_clk (wb_clk),
.i_rst (wb_rst),
.o_irq (timer_irq),

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff