Skip to content

Commit ab2d590

Browse files
committed
🐛 Fix wrong interrupt stack behaviour
1 parent 1b1b4a4 commit ab2d590

File tree

2 files changed

+74
-52
lines changed

2 files changed

+74
-52
lines changed

include/ariane_pkg.sv

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,25 @@ package ariane_pkg;
6868
localparam logic INVALIDATE_ON_FLUSH = 1'b1;
6969

7070
// read mask for SSTATUS over MMSTATUS
71-
localparam logic [63:0] SMODE_STATUS_MASK = riscv::SSTATUS_UIE
72-
| riscv::SSTATUS_SIE
73-
| riscv::SSTATUS_SPIE
74-
| riscv::SSTATUS_SPP
75-
| riscv::SSTATUS_FS
76-
| riscv::SSTATUS_XS
77-
| riscv::SSTATUS_SUM
78-
| riscv::SSTATUS_MXR
79-
| riscv::SSTATUS_UPIE
80-
| riscv::SSTATUS_SPIE
81-
| riscv::SSTATUS_SPP
82-
| riscv::SSTATUS_FS
83-
| riscv::SSTATUS_XS
84-
| riscv::SSTATUS_SUM
85-
| riscv::SSTATUS_MXR
86-
| riscv::SSTATUS_UXL
87-
| riscv::SSTATUS64_SD;
71+
localparam logic [63:0] SMODE_STATUS_READ_MASK = riscv::SSTATUS_UIE
72+
| riscv::SSTATUS_SIE
73+
| riscv::SSTATUS_SPIE
74+
| riscv::SSTATUS_SPP
75+
| riscv::SSTATUS_FS
76+
| riscv::SSTATUS_XS
77+
| riscv::SSTATUS_SUM
78+
| riscv::SSTATUS_MXR
79+
| riscv::SSTATUS_UPIE
80+
| riscv::SSTATUS_SPIE
81+
| riscv::SSTATUS_UXL
82+
| riscv::SSTATUS64_SD;
83+
84+
localparam logic [63:0] SMODE_STATUS_WRITE_MASK = riscv::SSTATUS_SIE
85+
| riscv::SSTATUS_SPIE
86+
| riscv::SSTATUS_SPP
87+
| riscv::SSTATUS_FS
88+
| riscv::SSTATUS_SUM
89+
| riscv::SSTATUS_MXR;
8890
// ---------------
8991
// Fetch Stage
9092
// ---------------

src/csr_regfile.sv

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import ariane_pkg::*;
1717
module csr_regfile #(
1818
parameter int ASID_WIDTH = 1,
1919
parameter int unsigned NR_COMMIT_PORTS = 2
20-
)(
20+
) (
2121
input logic clk_i, // Clock
2222
input logic rst_ni, // Asynchronous reset active low
2323
input logic time_irq_i, // Timer threw a interrupt
@@ -156,7 +156,9 @@ module csr_regfile #(
156156
riscv::CSR_TDATA2:; // not implemented
157157
riscv::CSR_TDATA3:; // not implemented
158158
// supervisor registers
159-
riscv::CSR_SSTATUS: csr_rdata = mstatus_q & ariane_pkg::SMODE_STATUS_MASK;
159+
riscv::CSR_SSTATUS: begin
160+
csr_rdata = mstatus_q & ariane_pkg::SMODE_STATUS_READ_MASK;
161+
end
160162
riscv::CSR_SIE: csr_rdata = mie_q & mideleg_q;
161163
riscv::CSR_SIP: csr_rdata = mip_q & mideleg_q;
162164
riscv::CSR_STVEC: csr_rdata = stvec_q;
@@ -312,24 +314,8 @@ module csr_regfile #(
312314
riscv::CSR_TDATA3:; // not implemented
313315
// sstatus is a subset of mstatus - mask it accordingly
314316
riscv::CSR_SSTATUS: begin
315-
mstatus_d = csr_wdata;
316-
// also hardwire the registers for sstatus
317-
mstatus_d.sxl = riscv::XLEN_64;
318-
mstatus_d.uxl = riscv::XLEN_64;
319-
// hardwired zero registers
320-
mstatus_d.sd = 1'b0;
321-
mstatus_d.xs = 2'b0;
322-
mstatus_d.fs = 2'b0;
323-
mstatus_d.upie = 1'b0;
324-
mstatus_d.uie = 1'b0;
325-
// not all fields of mstatus can be written
326-
mstatus_d.mie = mstatus_q.mie;
327-
mstatus_d.mpie = mstatus_q.mpie;
328-
mstatus_d.mpp = mstatus_q.mpp;
329-
mstatus_d.mprv = mstatus_q.mprv;
330-
mstatus_d.tsr = mstatus_q.tsr;
331-
mstatus_d.tw = mstatus_q.tw;
332-
mstatus_d.tvm = mstatus_q.tvm;
317+
mask = ariane_pkg::SMODE_STATUS_WRITE_MASK;
318+
mstatus_d = (mstatus_q & ~mask) | (csr_wdata & mask);
333319
// this instruction has side-effects
334320
flush_o = 1'b1;
335321
end
@@ -453,8 +439,6 @@ module csr_regfile #(
453439
// ---------------------
454440
// Machine Mode External Interrupt Pending
455441
mip_d[riscv::IRQ_M_EXT] = irq_i[0];
456-
// Supervisor Mode External Interrupt Pending
457-
mip_d[riscv::IRQ_S_EXT] = mie_q[riscv::IRQ_S_EXT];
458442
// Machine software interrupt
459443
mip_d[riscv::IRQ_M_SOFT] = ipi_i;
460444
// Timer interrupt pending, coming from platform timer
@@ -488,7 +472,7 @@ module csr_regfile #(
488472
mstatus_d.sie = 1'b0;
489473
mstatus_d.spie = mstatus_q.sie;
490474
// this can either be user or supervisor mode
491-
mstatus_d.spp = logic'(priv_lvl_q);
475+
mstatus_d.spp = priv_lvl_q[0];
492476
// set cause
493477
scause_d = ex_i.cause;
494478
// set epc
@@ -510,7 +494,6 @@ module csr_regfile #(
510494
end
511495

512496
priv_lvl_d = trap_to_priv_lvl;
513-
514497
end
515498

516499
// ------------------------------
@@ -623,11 +606,11 @@ module csr_regfile #(
623606
// return from exception, IF doesn't care from where we are returning
624607
eret_o = 1'b1;
625608
// return the previous supervisor interrupt enable flag
626-
mstatus_d.sie = mstatus_d.spie;
609+
mstatus_d.sie = mstatus_q.spie;
627610
// restore the previous privilege level
628-
priv_lvl_d = riscv::priv_lvl_t'({1'b0, mstatus_d.spp});
611+
priv_lvl_d = riscv::priv_lvl_t'({1'b0, mstatus_q.spp});
629612
// set spp to user mode
630-
mstatus_d.spp = logic'(riscv::PRIV_LVL_U);
613+
mstatus_d.spp = 1'b0;
631614
// set spie to 1
632615
mstatus_d.spie = 1'b1;
633616
end
@@ -783,9 +766,10 @@ module csr_regfile #(
783766
// -------------------
784767
// if there is any interrupt pending un-stall the core
785768
// also un-stall if we want to enter debug mode
786-
if (|mip_q || debug_req_i) begin
769+
if (|mip_q || debug_req_i || irq_i[1]) begin
787770
wfi_d = 1'b0;
788-
// or alternatively if there is no exception pending and we are not in debug mode wait here for the interrupt
771+
// or alternatively if there is no exception pending and we are not in debug mode wait here
772+
// for the interrupt
789773
end else if (!debug_mode_q && csr_op_i == WFI && !ex_i.valid) begin
790774
wfi_d = 1'b1;
791775
end
@@ -822,22 +806,58 @@ module csr_regfile #(
822806
end
823807
end
824808

809+
ila_0 i_ila_0 (
810+
.clk(clk_i), // input wire clk
811+
.probe0(commit_instr_i[0].pc), // input wire [63:0] probe0
812+
.probe1(commit_instr_i[1].pc), // input wire [63:0] probe1
813+
.probe2(commit_ack_i[0]), // input wire [0:0] probe2
814+
.probe3(commit_ack_i[1]), // input wire [0:0] probe3
815+
.probe4(mstatus_q.mie), // input wire [0:0] probe4
816+
.probe5(mstatus_q.mpp), // input wire [1:0] probe5
817+
.probe6(mstatus_q.mpie), // input wire [0:0] probe6
818+
.probe7(mstatus_q.sie), // input wire [0:0] probe7
819+
.probe8(mstatus_q.spp), // input wire [0:0] probe8
820+
.probe9(mstatus_q.spie), // input wire [0:0] probe9
821+
.probe10(mip_q[riscv::IRQ_S_SOFT]), // input wire [0:0] probe10
822+
.probe11(mip_q[riscv::IRQ_M_SOFT]), // input wire [0:0] probe11
823+
.probe12(mip_q[riscv::IRQ_S_TIMER]), // input wire [0:0] probe12
824+
.probe13(mip_q[riscv::IRQ_M_TIMER]), // input wire [0:0] probe13
825+
.probe14(mie_q[riscv::IRQ_S_SOFT]), // input wire [0:0] probe14
826+
.probe15(mie_q[riscv::IRQ_M_SOFT]), // input wire [0:0] probe15
827+
.probe16(mie_q[riscv::IRQ_S_TIMER]), // input wire [0:0] probe16
828+
.probe17(mie_q[riscv::IRQ_M_TIMER]), // input wire [0:0] probe17
829+
.probe18(priv_lvl_o) // input wire [1:0] probe18
830+
);
831+
825832
// -------------------
826833
// Output Assignments
827834
// -------------------
828-
// When the SEIP bit is read with a CSRRW, CSRRS, or CSRRC instruction, the value
829-
// returned in the rd destination register contains the logical-OR of the software-writable
830-
// bit and the interrupt signal from the interrupt controller.
831-
assign csr_rdata_o = (csr_addr.address == riscv::CSR_MIP) ? (csr_rdata | (irq_i[1] << riscv::IRQ_S_EXT))
832-
: csr_rdata;
835+
always_comb begin
836+
// When the SEIP bit is read with a CSRRW, CSRRS, or CSRRC instruction, the value
837+
// returned in the rd destination register contains the logical-OR of the software-writable
838+
// bit and the interrupt signal from the interrupt controller.
839+
csr_rdata_o = csr_rdata;
840+
841+
unique case (csr_addr.address)
842+
riscv::CSR_MIP: csr_rdata_o = csr_rdata | (irq_i[1] << riscv::IRQ_S_EXT);
843+
// in supervisor mode we also need to check whether we delegated this bit
844+
riscv::CSR_SIP: begin
845+
csr_rdata_o = csr_rdata
846+
| ((irq_i[1] & mideleg_q[riscv::IRQ_S_EXT]) << riscv::IRQ_S_EXT);
847+
end
848+
default:;
849+
endcase
850+
end
833851
// in debug mode we execute with privilege level M
834852
assign priv_lvl_o = (debug_mode_q) ? riscv::PRIV_LVL_M : priv_lvl_q;
835853
// MMU outputs
836854
assign satp_ppn_o = satp_q.ppn;
837855
assign asid_o = satp_q.asid[ASID_WIDTH-1:0];
838856
assign sum_o = mstatus_q.sum;
839857
// we support bare memory addressing and SV39
840-
assign en_translation_o = (satp_q.mode == 4'h8 && priv_lvl_o != riscv::PRIV_LVL_M) ? 1'b1 : 1'b0;
858+
assign en_translation_o = (satp_q.mode == 4'h8 && priv_lvl_o != riscv::PRIV_LVL_M)
859+
? 1'b1
860+
: 1'b0;
841861
assign mxr_o = mstatus_q.mxr;
842862
assign tvm_o = mstatus_q.tvm;
843863
assign tw_o = mstatus_q.tw;

0 commit comments

Comments
 (0)