From 5b370bdc0f64ce8e2b0a64e23bc6f5335bfaeb60 Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 16 Feb 2023 07:37:12 -0800 Subject: [PATCH] Added SSTC support for supervisor timer compare, but presently disable support. Reenable for rv32gc and rv64gc after tests pass. --- config/buildroot/wally-config.vh | 3 +- config/fpga/wally-config.vh | 1 + config/rv32e/wally-config.vh | 1 + config/rv32gc/wally-config.vh | 1 + config/rv32i/wally-config.vh | 1 + config/rv32imc/wally-config.vh | 1 + config/rv64fpquad/wally-config.vh | 1 + config/rv64gc/wally-config.vh | 1 + config/rv64i/wally-config.vh | 1 + src/privileged/csr.sv | 10 +++--- src/privileged/csri.sv | 18 +++++++--- src/privileged/csrs.sv | 57 ++++++++++++++++++++++++------- src/privileged/csrsr.sv | 2 +- 13 files changed, 76 insertions(+), 22 deletions(-) diff --git a/config/buildroot/wally-config.vh b/config/buildroot/wally-config.vh index 783b9d91b..f10e11f99 100644 --- a/config/buildroot/wally-config.vh +++ b/config/buildroot/wally-config.vh @@ -40,8 +40,9 @@ `define ZICSR_SUPPORTED 1 `define ZIFENCEI_SUPPORTED 1 `define ZICOUNTERS_SUPPORTED 1 -`define ZFH_SUPPORTED 0 `define COUNTERS 32 +`define ZFH_SUPPORTED 0 +`define SSTC_SUPPORTED 1 // LSU microarchitectural Features `define BUS_SUPPORTED 1 diff --git a/config/fpga/wally-config.vh b/config/fpga/wally-config.vh index c4d9cf629..d0299c4e3 100644 --- a/config/fpga/wally-config.vh +++ b/config/fpga/wally-config.vh @@ -43,6 +43,7 @@ `define ZICOUNTERS_SUPPORTED 1 `define ZFH_SUPPORTED 0 `define COUNTERS 32 +`define SSTC_SUPPORTED 1 // LSU microarchitectural Features `define BUS_SUPPORTED 1 diff --git a/config/rv32e/wally-config.vh b/config/rv32e/wally-config.vh index 24242b384..8cd9ca3f4 100644 --- a/config/rv32e/wally-config.vh +++ b/config/rv32e/wally-config.vh @@ -44,6 +44,7 @@ `define COUNTERS 0 `define ZICOUNTERS_SUPPORTED 0 `define ZFH_SUPPORTED 0 +`define SSTC_SUPPORTED 0 // LSU microarchitectural Features `define BUS_SUPPORTED 1 diff --git a/config/rv32gc/wally-config.vh b/config/rv32gc/wally-config.vh index 089a9ada4..e45c2b093 100644 --- a/config/rv32gc/wally-config.vh +++ b/config/rv32gc/wally-config.vh @@ -43,6 +43,7 @@ `define COUNTERS 32 `define ZICOUNTERS_SUPPORTED 1 `define ZFH_SUPPORTED 0 +`define SSTC_SUPPORTED 0 // LSU microarchitectural Features `define BUS_SUPPORTED 1 diff --git a/config/rv32i/wally-config.vh b/config/rv32i/wally-config.vh index 0a081b415..d400cebe9 100644 --- a/config/rv32i/wally-config.vh +++ b/config/rv32i/wally-config.vh @@ -44,6 +44,7 @@ `define COUNTERS 32 `define ZICOUNTERS_SUPPORTED 0 `define ZFH_SUPPORTED 0 +`define SSTC_SUPPORTED 0 // LSU microarchitectural Features `define BUS_SUPPORTED 0 diff --git a/config/rv32imc/wally-config.vh b/config/rv32imc/wally-config.vh index b4293dcc6..010b6599f 100644 --- a/config/rv32imc/wally-config.vh +++ b/config/rv32imc/wally-config.vh @@ -43,6 +43,7 @@ `define COUNTERS 32 `define ZICOUNTERS_SUPPORTED 1 `define ZFH_SUPPORTED 0 +`define SSTC_SUPPORTED 0 // LSU microarchitectural Features `define BUS_SUPPORTED 1 diff --git a/config/rv64fpquad/wally-config.vh b/config/rv64fpquad/wally-config.vh index 3757175a3..23a9aa05e 100644 --- a/config/rv64fpquad/wally-config.vh +++ b/config/rv64fpquad/wally-config.vh @@ -44,6 +44,7 @@ `define COUNTERS 32 `define ZICOUNTERS_SUPPORTED 1 `define ZFH_SUPPORTED 1 +`define SSTC_SUPPORTED 0 // LSU microarchitectural Features `define BUS_SUPPORTED 1 diff --git a/config/rv64gc/wally-config.vh b/config/rv64gc/wally-config.vh index c3dd87295..0b8a932d6 100644 --- a/config/rv64gc/wally-config.vh +++ b/config/rv64gc/wally-config.vh @@ -44,6 +44,7 @@ `define COUNTERS 32 `define ZICOUNTERS_SUPPORTED 1 `define ZFH_SUPPORTED 0 +`define SSTC_SUPPORTED 0 // LSU microarchitectural Features `define BUS_SUPPORTED 1 diff --git a/config/rv64i/wally-config.vh b/config/rv64i/wally-config.vh index 90d7b4045..627cac8f7 100644 --- a/config/rv64i/wally-config.vh +++ b/config/rv64i/wally-config.vh @@ -44,6 +44,7 @@ `define COUNTERS 32 `define ZICOUNTERS_SUPPORTED 0 `define ZFH_SUPPORTED 0 +`define SSTC_SUPPORTED 0 // LSU microarchitectural Features `define BUS_SUPPORTED 0 diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index ef4d73cb2..7b765bae0 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -113,6 +113,7 @@ module csr #(parameter logic SelMtvecM; logic [`XLEN-1:0] TVecAlignedM; logic InstrValidNotFlushedM; + logic STimerInt; // only valid unflushed instructions can access CSRs assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW; @@ -201,7 +202,7 @@ module csr #(parameter csri csri(.clk, .reset, .InstrValidNotFlushedM, .CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM, - .MExtInt, .SExtInt, .MTimerInt, .MSwInt, + .MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable); csrsr csrsr(.clk, .reset, .StallW, @@ -227,11 +228,12 @@ module csr #(parameter csrs csrs(.clk, .reset, .InstrValidNotFlushedM, .CSRSWriteM, .STrapM, .CSRAdrM, .NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW, - .STATUS_TVM, .CSRWriteValM, .PrivilegeModeW, + .STATUS_TVM, .MCOUNTEREN_TM(MCOUNTEREN_REGW[1]), + .CSRWriteValM, .PrivilegeModeW, .CSRSReadValM, .STVEC_REGW, .SEPC_REGW, .SCOUNTEREN_REGW, - .SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, - .WriteSSTATUSM, .IllegalCSRSAccessM); + .SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, + .WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt); end else begin assign WriteSSTATUSM = 0; assign CSRSReadValM = 0; diff --git a/src/privileged/csri.sv b/src/privileged/csri.sv index 0de65beed..bdbb0f591 100644 --- a/src/privileged/csri.sv +++ b/src/privileged/csri.sv @@ -39,13 +39,14 @@ module csri #(parameter input logic CSRMWriteM, CSRSWriteM, input logic [`XLEN-1:0] CSRWriteValM, input logic [11:0] CSRAdrM, - input logic MExtInt, SExtInt, MTimerInt, MSwInt, + input logic MExtInt, SExtInt, MTimerInt, STimerInt, MSwInt, output logic [11:0] MIP_REGW, MIE_REGW, - output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0 + output logic [11:0] MIP_REGW_writeable // only SEIP, STIP, SSIP are actually writeable; the rest are hardwired to 0 ); logic [11:0] MIP_WRITE_MASK, SIP_WRITE_MASK, MIE_WRITE_MASK; logic WriteMIPM, WriteMIEM, WriteSIPM, WriteSIEM; + logic STIP; // Interrupt Write Enables assign WriteMIPM = CSRMWriteM & (CSRAdrM == MIP) & InstrValidNotFlushedM; @@ -58,7 +59,13 @@ module csri #(parameter // SEIP, STIP, SSIP is writable in MIP if S mode exists // SSIP is writable in SIP if S mode exists if (`S_SUPPORTED) begin:mask - assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9) + if (`SSTC_SUPPORTED) begin + assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec) + assign STIP = STimerInt; + end else begin + assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9) + assign STIP = MIP_REGW_writeable[5]; + end assign SIP_WRITE_MASK = 12'h002; // SSIP is writeable in SIP (privileged 20210108-draft 4.1.3) assign MIE_WRITE_MASK = 12'hAAA; end else begin:mask @@ -75,5 +82,8 @@ module csri #(parameter else if (WriteMIEM) MIE_REGW <= (CSRWriteValM[11:0] & MIE_WRITE_MASK); // MIE controls M and S fields else if (WriteSIEM) MIE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (MIE_REGW & 12'h888); // only S fields - assign MIP_REGW = {MExtInt,1'b0,SExtInt|MIP_REGW_writeable[9],1'b0,MTimerInt,1'b0,MIP_REGW_writeable[5],1'b0,MSwInt,1'b0,MIP_REGW_writeable[1],1'b0}; + + assign MIP_REGW = {MExtInt, 1'b0, SExtInt|MIP_REGW_writeable[9], 1'b0, + MTimerInt, 1'b0, STIP, 1'b0, + MSwInt, 1'b0, MIP_REGW_writeable[1], 1'b0}; endmodule diff --git a/src/privileged/csrs.sv b/src/privileged/csrs.sv index 3dfb2cbea..99c56ad1b 100644 --- a/src/privileged/csrs.sv +++ b/src/privileged/csrs.sv @@ -41,22 +41,27 @@ module csrs #(parameter SCAUSE = 12'h142, STVAL = 12'h143, SIP= 12'h144, + STIMECMP = 12'h14D, + STIMECMPH = 12'h15D, SATP = 12'h180) ( - input logic clk, reset, - input logic InstrValidNotFlushedM, - input logic CSRSWriteM, STrapM, - input logic [11:0] CSRAdrM, - input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW, - input logic STATUS_TVM, - input logic [`XLEN-1:0] CSRWriteValM, - input logic [1:0] PrivilegeModeW, + input logic clk, reset, + input logic InstrValidNotFlushedM, + input logic CSRSWriteM, STrapM, + input logic [11:0] CSRAdrM, + input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW, + input logic STATUS_TVM, + input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear + input logic [`XLEN-1:0] CSRWriteValM, + input logic [1:0] PrivilegeModeW, output logic [`XLEN-1:0] CSRSReadValM, STVEC_REGW, output logic [`XLEN-1:0] SEPC_REGW, output logic [31:0] SCOUNTEREN_REGW, output logic [`XLEN-1:0] SATP_REGW, - input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, - output logic WriteSSTATUSM, - output logic IllegalCSRSAccessM + input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, + input logic [63:0] MTIME_CLINT, + output logic WriteSSTATUSM, + output logic IllegalCSRSAccessM, + output logic STimerInt ); // Constants @@ -66,10 +71,13 @@ module csrs #(parameter logic WriteSTVECM; logic WriteSSCRATCHM, WriteSEPCM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; + logic WriteSTIMECMPM, WriteSTIMECMPHM; logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW; logic [`XLEN-1:0] SCAUSE_REGW; + logic [63:0] STIMECMP_REGW; // write enables + // *** can InstrValidNotFlushed be factored out of all these writes into CSRWriteM? assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & InstrValidNotFlushedM; assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & InstrValidNotFlushedM; assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & InstrValidNotFlushedM; @@ -78,6 +86,8 @@ module csrs #(parameter assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & InstrValidNotFlushedM; assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & InstrValidNotFlushedM; assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & InstrValidNotFlushedM; + assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & MCOUNTEREN_TM & InstrValidNotFlushedM; + assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & MCOUNTEREN_TM & (`XLEN == 32) & InstrValidNotFlushedM; // CSRs flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); @@ -90,7 +100,20 @@ module csrs #(parameter else assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); + if (`XLEN == 64) + flopenr #(`XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, STIMECMP_REGW); + else begin + flopenr #(`XLEN) STIMECMPreg(clk, reset, WriteSTIMECMPM, CSRWriteValM, STIMECMP_REGW[31:0]); + flopenr #(`XLEN) STIMECMPHreg(clk, reset, WriteSTIMECMPHM, CSRWriteValM, STIMECMP_REGW[63:32]); + end + // Supervisor timer interrupt logic + // Spec is a bit peculiar - Machine timer interrupts are produced in CLINT, while Supervisor timer interrupts are in CSRs + if (`SSTC_SUPPORTED) + assign STimerInt = ({1'b0, MTIME_CLINT} >= {1'b0, STIMECMP_REGW}); // unsigned comparison + else + assign STimerInt = 0; + // CSR Reads always_comb begin:csrr IllegalCSRSAccessM = 0; @@ -109,10 +132,20 @@ module csrs #(parameter if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1; end SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW}; + STIMECMP: if (MCOUNTEREN_TM) CSRSReadValM = STIMECMP_REGW[`XLEN-1:0]; + else begin + CSRSReadValM = 0; + IllegalCSRSAccessM = 1; + end + STIMECMPH: if (MCOUNTEREN_TM & (`XLEN == 32)) CSRSReadValM[31:0] = STIMECMP_REGW[63:32]; + else begin // not supported for RV64 + CSRSReadValM = 0; + IllegalCSRSAccessM = 1; + end default: begin CSRSReadValM = 0; IllegalCSRSAccessM = 1; - end + end endcase end endmodule diff --git a/src/privileged/csrsr.sv b/src/privileged/csrsr.sv index 1fa1fe8e7..a92aca3be 100644 --- a/src/privileged/csrsr.sv +++ b/src/privileged/csrsr.sv @@ -68,7 +68,7 @@ module csrsr ( STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, STATUS_SPP, /*STATUS_MPIE*/ 1'b0, STATUS_UBE, STATUS_SPIE, /*1'b0, STATUS_MIE, 1'b0*/ 3'b0, STATUS_SIE, 1'b0}; - assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be. + assign MSTATUSH_REGW = '0; // *** does not exist when XLEN=64, but don't want it to have an undefined value. Spec is not clear what it should be. end else begin: csrsr32 // RV32 assign MSTATUS_REGW = {STATUS_SD, 8'b0, STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,