mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 12:17:19 -04:00
🐛 Fix interrupt registers
This commit is contained in:
parent
ec354b25ab
commit
c9366c4478
3 changed files with 110 additions and 52 deletions
|
@ -124,6 +124,24 @@ package ariane_pkg;
|
|||
|
||||
localparam NR_WB_PORTS = 4;
|
||||
|
||||
// read mask for SSTATUS over MMSTATUS
|
||||
localparam logic [63:0] SMODE_STATUS_MASK = riscv::SSTATUS_UIE
|
||||
| riscv::SSTATUS_SIE
|
||||
| riscv::SSTATUS_SPIE
|
||||
| riscv::SSTATUS_SPP
|
||||
| riscv::SSTATUS_FS
|
||||
| riscv::SSTATUS_XS
|
||||
| riscv::SSTATUS_SUM
|
||||
| riscv::SSTATUS_MXR
|
||||
| riscv::SSTATUS_UPIE
|
||||
| riscv::SSTATUS_SPIE
|
||||
| riscv::SSTATUS_SPP
|
||||
| riscv::SSTATUS_FS
|
||||
| riscv::SSTATUS_XS
|
||||
| riscv::SSTATUS_SUM
|
||||
| riscv::SSTATUS_MXR
|
||||
| riscv::SSTATUS_UXL
|
||||
| riscv::SSTATUS64_SD;
|
||||
// ---------------
|
||||
// Fetch Stage
|
||||
// ---------------
|
||||
|
|
|
@ -96,9 +96,6 @@ package riscv;
|
|||
logic [43:0] ppn;
|
||||
} satp_t;
|
||||
|
||||
// read mask for SSTATUS over MMSTATUS
|
||||
localparam logic [63:0] SMODE_STATUS_MASK = 64'h80000003000DE133;
|
||||
|
||||
// --------------------
|
||||
// Instruction Types
|
||||
// --------------------
|
||||
|
@ -312,12 +309,26 @@ package riscv;
|
|||
localparam logic [63:0] LOAD_PAGE_FAULT = 13; // Load page fault
|
||||
localparam logic [63:0] STORE_PAGE_FAULT = 15; // Store page fault
|
||||
|
||||
localparam logic [63:0] S_SW_INTERRUPT = (1 << 63) | 1;
|
||||
localparam logic [63:0] M_SW_INTERRUPT = (1 << 63) | 3;
|
||||
localparam logic [63:0] S_TIMER_INTERRUPT = (1 << 63) | 5;
|
||||
localparam logic [63:0] M_TIMER_INTERRUPT = (1 << 63) | 7;
|
||||
localparam logic [63:0] S_EXT_INTERRUPT = (1 << 63) | 9;
|
||||
localparam logic [63:0] M_EXT_INTERRUPT = (1 << 63) | 11;
|
||||
localparam int unsigned IRQ_S_SOFT = 1;
|
||||
localparam int unsigned IRQ_M_SOFT = 3;
|
||||
localparam int unsigned IRQ_S_TIMER = 5;
|
||||
localparam int unsigned IRQ_M_TIMER = 7;
|
||||
localparam int unsigned IRQ_S_EXT = 9;
|
||||
localparam int unsigned IRQ_M_EXT = 11;
|
||||
|
||||
localparam logic [63:0] MIP_SSIP = (1 << IRQ_S_SOFT);
|
||||
localparam logic [63:0] MIP_MSIP = (1 << IRQ_M_SOFT);
|
||||
localparam logic [63:0] MIP_STIP = (1 << IRQ_S_TIMER);
|
||||
localparam logic [63:0] MIP_MTIP = (1 << IRQ_M_TIMER);
|
||||
localparam logic [63:0] MIP_SEIP = (1 << IRQ_S_EXT);
|
||||
localparam logic [63:0] MIP_MEIP = (1 << IRQ_M_EXT);
|
||||
|
||||
localparam logic [63:0] S_SW_INTERRUPT = (1 << 63) | IRQ_S_SOFT;
|
||||
localparam logic [63:0] M_SW_INTERRUPT = (1 << 63) | IRQ_M_SOFT;
|
||||
localparam logic [63:0] S_TIMER_INTERRUPT = (1 << 63) | IRQ_S_TIMER;
|
||||
localparam logic [63:0] M_TIMER_INTERRUPT = (1 << 63) | IRQ_M_TIMER;
|
||||
localparam logic [63:0] S_EXT_INTERRUPT = (1 << 63) | IRQ_S_EXT;
|
||||
localparam logic [63:0] M_EXT_INTERRUPT = (1 << 63) | IRQ_M_EXT;
|
||||
|
||||
// -----
|
||||
// CSRs
|
||||
|
@ -393,6 +404,19 @@ package riscv;
|
|||
CSR_MIS_PREDICT = PERF_MIS_PREDICT + 12'hC03
|
||||
} csr_reg_t;
|
||||
|
||||
localparam logic [63:0] SSTATUS_UIE = 64'h00000001;
|
||||
localparam logic [63:0] SSTATUS_SIE = 64'h00000002;
|
||||
localparam logic [63:0] SSTATUS_SPIE = 64'h00000020;
|
||||
localparam logic [63:0] SSTATUS_SPP = 64'h00000100;
|
||||
localparam logic [63:0] SSTATUS_FS = 64'h00006000;
|
||||
localparam logic [63:0] SSTATUS_XS = 64'h00018000;
|
||||
localparam logic [63:0] SSTATUS_SUM = 64'h00040000;
|
||||
localparam logic [63:0] SSTATUS_MXR = 64'h00080000;
|
||||
localparam logic [63:0] SSTATUS_UPIE = 64'h00000010;
|
||||
localparam logic [63:0] SSTATUS_UXL = 64'h0000000300000000;
|
||||
localparam logic [63:0] SSTATUS64_SD = 64'h8000000000000000;
|
||||
localparam logic [63:0] SSTATUS32_SD = 64'h80000000;
|
||||
|
||||
typedef enum logic [2:0] {
|
||||
CSRRW = 3'h1,
|
||||
CSRRS = 3'h2,
|
||||
|
|
|
@ -154,7 +154,7 @@ module csr_regfile #(
|
|||
perf_addr_o = csr_addr.address;
|
||||
|
||||
if (csr_read) begin
|
||||
case (csr_addr.address)
|
||||
unique case (csr_addr.address)
|
||||
riscv::CSR_FFLAGS: begin
|
||||
if (mstatus_q.fs == riscv::Off) begin
|
||||
read_access_exception = 1'b1;
|
||||
|
@ -194,7 +194,7 @@ module csr_regfile #(
|
|||
riscv::CSR_TDATA2:; // not implemented
|
||||
riscv::CSR_TDATA3:; // not implemented
|
||||
// supervisor registers
|
||||
riscv::CSR_SSTATUS: csr_rdata = mstatus_q & riscv::SMODE_STATUS_MASK;
|
||||
riscv::CSR_SSTATUS: csr_rdata = mstatus_q & ariane_pkg::SMODE_STATUS_MASK;
|
||||
riscv::CSR_SIE: csr_rdata = mie_q & mideleg_q;
|
||||
riscv::CSR_SIP: csr_rdata = mip_q & mideleg_q;
|
||||
riscv::CSR_STVEC: csr_rdata = stvec_q;
|
||||
|
@ -257,15 +257,27 @@ module csr_regfile #(
|
|||
// ---------------------------
|
||||
// CSR Write and update logic
|
||||
// ---------------------------
|
||||
logic [63:0] mask;
|
||||
always_comb begin : csr_update
|
||||
automatic riscv::satp_t sapt;
|
||||
automatic logic [63:0] mip;
|
||||
automatic logic [63:0] instret;
|
||||
|
||||
sapt = satp_q;
|
||||
mip = csr_wdata & 64'h33;
|
||||
instret = instret_q;
|
||||
// only FCSR, USIP, SSIP, UTIP, STIP are write-able
|
||||
// --------------------
|
||||
// Counters
|
||||
// --------------------
|
||||
if (!debug_mode_q) begin
|
||||
// just increment the cycle count
|
||||
cycle_d = cycle_q + 1'b1;
|
||||
// increase instruction retired counter
|
||||
for (int i = 0; i < NR_COMMIT_PORTS; i++) begin
|
||||
if (commit_ack_i[i]) begin
|
||||
instret++;
|
||||
end
|
||||
end
|
||||
instret_d = instret;
|
||||
end
|
||||
|
||||
eret_o = 1'b0;
|
||||
flush_o = 1'b0;
|
||||
|
@ -325,7 +337,7 @@ module csr_regfile #(
|
|||
|
||||
// check for correct access rights and that we are writing
|
||||
if (csr_we) begin
|
||||
case (csr_addr.address)
|
||||
unique case (csr_addr.address)
|
||||
// Floating-Point
|
||||
riscv::CSR_FFLAGS: begin
|
||||
if (mstatus_q.fs == riscv::Off) begin
|
||||
|
@ -413,17 +425,14 @@ module csr_regfile #(
|
|||
// even machine mode interrupts can be visible and set-able to supervisor
|
||||
// if the corresponding bit in mideleg is set
|
||||
riscv::CSR_SIE: begin
|
||||
// the mideleg makes sure only delegate-able register (and therefore also only implemented registers)
|
||||
// are written
|
||||
for (int unsigned i = 0; i < 64; i++)
|
||||
if (mideleg_q[i])
|
||||
mie_d[i] = csr_wdata[i];
|
||||
// the mideleg makes sure only delegate-able register (and therefore also only implemented registers) are written
|
||||
mie_d = (mie_q & ~mideleg_q) | (csr_wdata & mideleg_q);
|
||||
end
|
||||
|
||||
riscv::CSR_SIP: begin
|
||||
for (int unsigned i = 0; i < 64; i++)
|
||||
if (mideleg_q[i])
|
||||
mip_d[i] = mip[i];
|
||||
// only the supervisor software interrupt is write-able, iff delegated
|
||||
mask = riscv::MIP_SSIP & mideleg_q;
|
||||
mip_d = (mip_q & ~mask) | (csr_wdata & mask);
|
||||
end
|
||||
|
||||
riscv::CSR_SCOUNTEREN:;
|
||||
|
@ -467,20 +476,32 @@ module csr_regfile #(
|
|||
riscv::CSR_MISA:;
|
||||
// machine exception delegation register
|
||||
// 0 - 15 exceptions supported
|
||||
riscv::CSR_MEDELEG: medeleg_d = csr_wdata & 64'hF7FF;
|
||||
riscv::CSR_MEDELEG: begin
|
||||
mask = (1 << riscv::INSTR_ADDR_MISALIGNED) |
|
||||
(1 << riscv::BREAKPOINT) |
|
||||
(1 << riscv::ENV_CALL_UMODE) |
|
||||
(1 << riscv::INSTR_PAGE_FAULT) |
|
||||
(1 << riscv::LOAD_PAGE_FAULT) |
|
||||
(1 << riscv::STORE_PAGE_FAULT);
|
||||
medeleg_d = (medeleg_q & ~mask) | (csr_wdata & mask);
|
||||
end
|
||||
// machine interrupt delegation register
|
||||
// we do not support user interrupt delegation
|
||||
riscv::CSR_MIDELEG: mideleg_d = csr_wdata & 64'hBBB;
|
||||
|
||||
riscv::CSR_MIDELEG: begin
|
||||
mask = riscv::MIP_SSIP | riscv::MIP_STIP | riscv::MIP_SEIP;
|
||||
mideleg_d = (mideleg_q & ~mask) | (csr_wdata & mask);
|
||||
end
|
||||
// mask the register so that unsupported interrupts can never be set
|
||||
riscv::CSR_MIE: mie_d = csr_wdata & 64'hBBB; // we only support supervisor and m-mode interrupts
|
||||
riscv::CSR_MIE: begin
|
||||
mask = riscv::MIP_SSIP | riscv::MIP_STIP | riscv::MIP_SEIP | riscv::MIP_MSIP | riscv::MIP_MTIP;
|
||||
mie_d = (mie_q & ~mask) | (csr_wdata & mask); // we only support supervisor and M-mode interrupts
|
||||
end
|
||||
|
||||
riscv::CSR_MTVEC: begin
|
||||
mtvec_d = {csr_wdata[63:2], 1'b0, csr_wdata[0]};
|
||||
mtvec_d = {csr_wdata[63:2], 1'b0, csr_wdata[0]};
|
||||
// we are in vector mode, this implementation requires the additional
|
||||
// alignment constraint of 64 * 4 bytes
|
||||
if (csr_wdata[0])
|
||||
mtvec_d = {csr_wdata[63:8], 7'b0, csr_wdata[0]};
|
||||
if (csr_wdata[0]) mtvec_d = {csr_wdata[63:8], 7'b0, csr_wdata[0]};
|
||||
end
|
||||
riscv::CSR_MCOUNTEREN:;
|
||||
|
||||
|
@ -488,7 +509,10 @@ module csr_regfile #(
|
|||
riscv::CSR_MEPC: mepc_d = {csr_wdata[63:1], 1'b0};
|
||||
riscv::CSR_MCAUSE: mcause_d = csr_wdata;
|
||||
riscv::CSR_MTVAL: mtval_d = csr_wdata;
|
||||
riscv::CSR_MIP: mip_d = mip;
|
||||
riscv::CSR_MIP: begin
|
||||
mask = riscv::MIP_SSIP | riscv::MIP_STIP | riscv::MIP_SEIP;
|
||||
mip_d = (mip_q & ~mask) | (csr_wdata & mask);
|
||||
end
|
||||
// Placeholders for M-mode protection
|
||||
riscv::CSR_PMPCFG0: pmpcfg0_d = csr_wdata;
|
||||
riscv::CSR_PMPADDR0: pmpaddr0_d = csr_wdata;
|
||||
|
@ -529,12 +553,13 @@ module csr_regfile #(
|
|||
// External Interrupts
|
||||
// ---------------------
|
||||
// Machine Mode External Interrupt Pending
|
||||
mip_d[11] = mie_q[11] & irq_i[1];
|
||||
mip_d[9] = mie_q[9] & irq_i[0];
|
||||
mip_d[riscv::IRQ_M_EXT] = irq_i[0];
|
||||
// Supervisor Mode External Interrupt Pending
|
||||
mip_d[riscv::IRQ_S_EXT] = mie_q[riscv::IRQ_S_EXT] & irq_i[1];
|
||||
// Machine software interrupt
|
||||
mip_d[3] = mie_q[3] & ipi_i;
|
||||
mip_d[riscv::IRQ_M_SOFT] = ipi_i;
|
||||
// Timer interrupt pending, coming from platform timer
|
||||
mip_d[7] = time_irq_i;
|
||||
mip_d[riscv::IRQ_M_TIMER] = time_irq_i;
|
||||
|
||||
// -----------------------
|
||||
// Manage Exception Stack
|
||||
|
@ -718,21 +743,6 @@ module csr_regfile #(
|
|||
// actually return from debug mode
|
||||
debug_mode_d = 1'b0;
|
||||
end
|
||||
|
||||
// --------------------
|
||||
// Counters
|
||||
// --------------------
|
||||
if (!debug_mode_q) begin
|
||||
// just increment the cycle count
|
||||
cycle_d = cycle_q + 1'b1;
|
||||
// increase instruction retired counter
|
||||
for (int i = 0; i < NR_COMMIT_PORTS; i++) begin
|
||||
if (commit_ack_i[i]) begin
|
||||
instret++;
|
||||
end
|
||||
end
|
||||
instret_d = instret;
|
||||
end
|
||||
end
|
||||
|
||||
// ---------------------------
|
||||
|
@ -809,7 +819,9 @@ module csr_regfile #(
|
|||
if (mie_q[riscv::S_SW_INTERRUPT[5:0]] && mip_q[riscv::S_SW_INTERRUPT[5:0]])
|
||||
interrupt_cause = riscv::S_SW_INTERRUPT;
|
||||
// Supervisor External Interrupt
|
||||
if (mie_q[riscv::S_EXT_INTERRUPT[5:0]] && mip_q[riscv::S_EXT_INTERRUPT[5:0]])
|
||||
// The logical-OR of the software-writable bit and the signal from the external interrupt controller is
|
||||
// used to generate external interrupts to the supervisor
|
||||
if (mie_q[riscv::S_EXT_INTERRUPT[5:0]] && (mip_q[riscv::S_EXT_INTERRUPT[5:0]] | irq_i[1]))
|
||||
interrupt_cause = riscv::S_EXT_INTERRUPT;
|
||||
// Machine Timer Interrupt
|
||||
if (mip_q[riscv::M_TIMER_INTERRUPT[5:0]] && mie_q[riscv::M_TIMER_INTERRUPT[5:0]])
|
||||
|
@ -915,7 +927,11 @@ module csr_regfile #(
|
|||
// -------------------
|
||||
// Output Assignments
|
||||
// -------------------
|
||||
assign csr_rdata_o = csr_rdata;
|
||||
// When the SEIP bit is read with a CSRRW, CSRRS, or CSRRC instruction, the value
|
||||
// returned in the rd destination register contains the logical-OR of the software-writable
|
||||
// bit and the interrupt signal from the interrupt controller.
|
||||
assign csr_rdata_o = (csr_addr.address == riscv::CSR_MIP) ? (csr_rdata | (irq_i[1] << riscv::IRQ_S_EXT))
|
||||
: csr_rdata;
|
||||
// in debug mode we execute with privilege level M
|
||||
assign priv_lvl_o = (debug_mode_q) ? riscv::PRIV_LVL_M : priv_lvl_q;
|
||||
// FPU outputs
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue