cvw/src/privileged/csr.sv

313 lines
16 KiB
Systemverilog
Raw Normal View History

2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
// csr.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
// dottolia@hmc.edu 7 April 2021
2021-01-15 04:37:51 +00:00
//
// Purpose: Counter Control and Status Registers
// See RISC-V Privileged Mode Specification 20190608
//
2023-01-14 03:44:38 +00:00
// Documentation: RISC-V System on Chip Design Chapter 5
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
// https://github.com/openhwgroup/cvw
2021-01-15 04:37:51 +00:00
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
2021-01-15 04:37:51 +00:00
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
2021-01-15 04:37:51 +00:00
//
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
2021-01-15 04:37:51 +00:00
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
2021-01-15 04:37:51 +00:00
module csr import cvw::*; #(parameter cvw_t P) (
2023-06-14 04:12:49 +00:00
input logic clk, reset,
input logic FlushM, FlushW,
input logic StallE, StallM, StallW,
input logic [31:0] InstrM, // current instruction
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
2023-12-21 00:18:31 +00:00
input logic [P.XLEN-1:0] PCM, // program counter, next PC going to trap/return logic
2023-06-14 04:12:49 +00:00
input logic [P.XLEN-1:0] SrcAM, IEUAdrM, // SrcA and memory address from IEU
input logic CSRReadM, CSRWriteM, // read or write CSR
input logic TrapM, // trap is occurring
input logic mretM, sretM, // return instruction
2023-06-14 04:12:49 +00:00
input logic InterruptM, // interrupt is occurring
input logic ExceptionM, // interrupt is occurring
input logic MTimerInt, // timer interrupt
input logic MExtInt, SExtInt, // external interrupt (from PLIC)
input logic MSwInt, // software interrupt
input logic [63:0] MTIME_CLINT, // TIME value from CLINT
input logic InstrValidM, // current instruction is valid
input logic FRegWriteM, // writes to floating point registers change STATUS.FS
input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR
input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
input logic [1:0] PrivilegeModeW, // current privilege mode
input logic [3:0] CauseM, // Trap cause
input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode
2023-01-14 04:49:34 +00:00
// inputs for performance counters
2024-01-18 20:43:34 +00:00
input logic LoadStallD, StoreStallD,
2023-06-14 04:12:49 +00:00
input logic ICacheStallF,
input logic DCacheStallM,
input logic BPDirPredWrongM,
input logic BTAWrongM,
input logic RASPredPCWrongM,
input logic IClassWrongM,
input logic BPWrongM, // branch predictor is wrong
input logic [3:0] InstrClassM,
input logic DCacheMiss,
input logic DCacheAccess,
input logic ICacheMiss,
input logic ICacheAccess,
input logic sfencevmaM,
input logic InvalidateICacheM,
input logic DivBusyE, // integer divide busy
input logic FDivBusyE, // floating point divide busy
2023-01-14 04:49:34 +00:00
// outputs from CSRs
2023-06-14 04:12:49 +00:00
output logic [1:0] STATUS_MPP,
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
output logic [15:0] MEDELEG_REGW,
output logic [P.XLEN-1:0] SATP_REGW,
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
output logic STATUS_MIE, STATUS_SIE,
output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_TW,
output logic [1:0] STATUS_FS,
output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0],
output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0],
2023-06-14 04:12:49 +00:00
output logic [2:0] FRM_REGW,
output logic [3:0] ENVCFG_CBE,
output logic ENVCFG_PBMTE, // Page-based memory type enable
2023-12-13 19:49:04 +00:00
output logic ENVCFG_ADUE, // HPTW A/D Update enable
2023-12-21 00:18:31 +00:00
// PC logic output from privileged unit to IFU
output logic [P.XLEN-1:0] EPCM, // Exception Program counter to IFU PC logic
output logic [P.XLEN-1:0] TrapVectorM, // Trap vector, to IFU PC logic
2023-01-14 04:49:34 +00:00
//
2023-06-14 04:12:49 +00:00
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level
output logic BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields
2021-01-15 04:37:51 +00:00
);
localparam MIP = 12'h344;
localparam SIP = 12'h144;
2023-06-14 04:12:49 +00:00
logic [P.XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRCReadValM;
logic [P.XLEN-1:0] CSRReadValM;
logic [P.XLEN-1:0] CSRSrcM;
logic [P.XLEN-1:0] CSRRWM, CSRRSM, CSRRCM;
logic [P.XLEN-1:0] CSRWriteValM;
logic [P.XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, MSTATUSH_REGW;
logic [P.XLEN-1:0] STVEC_REGW, MTVEC_REGW;
logic [P.XLEN-1:0] MEPC_REGW, SEPC_REGW;
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
logic UngatedCSRMWriteM;
logic WriteFRMM, WriteFFLAGSM;
logic [P.XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
logic [4:0] NextCauseM;
logic [11:0] CSRAdrM;
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM;
logic InsufficientCSRPrivilegeM;
logic IllegalCSRMWriteReadonlyM;
logic [P.XLEN-1:0] CSRReadVal2M;
logic [11:0] MIP_REGW_writeable;
2023-12-21 00:18:31 +00:00
logic [P.XLEN-1:0] TVecM,NextFaultMtvalM;
2023-06-14 04:12:49 +00:00
logic MTrapM, STrapM;
logic SelMtvecM;
logic [P.XLEN-1:0] TVecAlignedM;
logic InstrValidNotFlushedM;
logic STimerInt;
logic [63:0] MENVCFG_REGW;
logic [P.XLEN-1:0] SENVCFG_REGW;
logic ENVCFG_STCE; // supervisor timer counter enable
logic ENVCFG_FIOM; // fence implies io (presently not used)
2023-01-14 04:49:34 +00:00
// only valid unflushed instructions can access CSRs
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
2022-05-12 21:50:15 +00:00
///////////////////////////////////////////
2023-01-14 04:49:34 +00:00
// MTVAL: gets value from PC, Instruction, or load/store address
2022-05-12 21:50:15 +00:00
///////////////////////////////////////////
always_comb
if (InterruptM) NextFaultMtvalM = '0;
2022-05-12 23:37:40 +00:00
else case (CauseM)
2022-05-12 21:50:15 +00:00
12, 1, 3: NextFaultMtvalM = PCM; // Instruction page/access faults, breakpoint
2: NextFaultMtvalM = {{(P.XLEN-32){1'b0}}, InstrOrigM}; // Illegal instruction fault
2022-05-12 21:50:15 +00:00
0, 4, 6, 13, 15, 5, 7: NextFaultMtvalM = IEUAdrM; // Instruction misaligned, Load/Store Misaligned/page/access faults
default: NextFaultMtvalM = '0; // Ecall, interrupts
2022-05-12 21:50:15 +00:00
endcase
///////////////////////////////////////////
2023-01-14 05:00:06 +00:00
// Trap Vectoring & Returns; vectored traps must be aligned to 64-byte address boundaries
2022-05-12 21:50:15 +00:00
///////////////////////////////////////////
2022-12-21 00:53:09 +00:00
// Select trap vector from STVEC or MTVEC and word-align
assign SelMtvecM = (NextPrivilegeModeM == P.M_MODE);
mux2 #(P.XLEN) tvecmux(STVEC_REGW, MTVEC_REGW, SelMtvecM, TVecM);
assign TVecAlignedM = {TVecM[P.XLEN-1:2], 2'b00};
2022-05-12 21:50:15 +00:00
2022-12-21 00:53:09 +00:00
// Support vectored interrupts
if(P.VECTORED_INTERRUPTS_SUPPORTED) begin:vec
2022-12-21 00:53:09 +00:00
logic VectoredM;
logic [P.XLEN-1:0] TVecPlusCauseM;
2022-12-21 00:53:09 +00:00
assign VectoredM = InterruptM & (TVecM[1:0] == 2'b01);
assign TVecPlusCauseM = {TVecAlignedM[P.XLEN-1:6], CauseM, 2'b00}; // 64-byte alignment allows concatenation rather than addition
mux2 #(P.XLEN) trapvecmux(TVecAlignedM, TVecPlusCauseM, VectoredM, TrapVectorM);
2022-12-21 00:53:09 +00:00
end else
assign TrapVectorM = TVecAlignedM; // unvectored interrupt handler can be at any word-aligned address. This is called Sstvecd
2022-05-12 21:50:15 +00:00
2022-12-21 00:24:04 +00:00
// Trap Returns
// A trap sets the PC to TrapVector
// A return sets the PC to MEPC or SEPC
2023-12-21 00:18:31 +00:00
mux2 #(P.XLEN) epcmux(SEPC_REGW, MEPC_REGW, mretM, EPCM);
2022-05-12 21:55:50 +00:00
///////////////////////////////////////////
// CSRWriteValM
///////////////////////////////////////////
2023-01-14 05:00:06 +00:00
always_comb begin
// Choose either rs1 or uimm[4:0] as source
CSRSrcM = InstrM[14] ? {{(P.XLEN-5){1'b0}}, InstrM[19:15]} : SrcAM;
2022-04-03 20:18:25 +00:00
// CSR set and clear for MIP/SIP should only touch internal state, not interrupt inputs
if (CSRAdrM == MIP | CSRAdrM == SIP) CSRReadVal2M = {{(P.XLEN-12){1'b0}}, MIP_REGW_writeable};
2022-04-03 20:18:25 +00:00
else CSRReadVal2M = CSRReadValM;
// Compute AND/OR modification
2023-06-14 04:12:49 +00:00
CSRRWM = CSRSrcM;
CSRRSM = CSRReadVal2M | CSRSrcM;
CSRRCM = CSRReadVal2M & ~CSRSrcM;
case (InstrM[13:12])
2023-06-14 04:12:49 +00:00
2'b01: CSRWriteValM = CSRRWM;
2'b10: CSRWriteValM = CSRRSM;
2'b11: CSRWriteValM = CSRRCM;
default: CSRWriteValM = CSRReadValM;
endcase
end
2021-01-15 04:37:51 +00:00
2022-05-12 21:55:50 +00:00
///////////////////////////////////////////
// CSR Write values
///////////////////////////////////////////
2023-01-14 05:00:06 +00:00
assign CSRAdrM = InstrM[31:20];
assign UnalignedNextEPCM = TrapM ? PCM : CSRWriteValM;
assign NextEPCM = P.ZCA_SUPPORTED ? {UnalignedNextEPCM[P.XLEN-1:1], 1'b0} : {UnalignedNextEPCM[P.XLEN-1:2], 2'b00}; // 3.1.15 alignment
assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[P.XLEN-1], CSRWriteValM[3:0]};
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM;
assign UngatedCSRMWriteM = CSRWriteM & (PrivilegeModeW == P.M_MODE);
assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM;
assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW) & InstrValidNotFlushedM;
assign CSRUWriteM = CSRWriteM & InstrValidNotFlushedM;
assign MTrapM = TrapM & (NextPrivilegeModeM == P.M_MODE);
assign STrapM = TrapM & (NextPrivilegeModeM == P.S_MODE) & P.S_SUPPORTED;
2021-01-15 04:37:51 +00:00
2022-05-12 21:55:50 +00:00
///////////////////////////////////////////
// CSRs
///////////////////////////////////////////
csri #(P) csri(.clk, .reset,
2023-01-14 05:09:29 +00:00
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt,
.MIDELEG_REGW, .ENVCFG_STCE, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
2023-01-14 06:12:06 +00:00
csrsr #(P) csrsr(.clk, .reset, .StallW,
2023-01-14 05:09:29 +00:00
.WriteMSTATUSM, .WriteMSTATUSHM, .WriteSSTATUSM,
.TrapM, .FRegWriteM, .NextPrivilegeModeM, .PrivilegeModeW,
.mretM, .sretM, .WriteFRMM, .WriteFFLAGSM, .CSRWriteValM, .SelHPTW,
.MSTATUS_REGW, .SSTATUS_REGW, .MSTATUSH_REGW,
.STATUS_MPP, .STATUS_SPP, .STATUS_TSR, .STATUS_TW,
.STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TVM,
.STATUS_FS, .BigEndianM);
2023-01-14 06:12:06 +00:00
csrm #(P) csrm(.clk, .reset,
.UngatedCSRMWriteM, .CSRMWriteM, .MTrapM, .CSRAdrM,
2023-01-14 05:09:29 +00:00
.NextEPCM, .NextCauseM, .NextMtvalM, .MSTATUS_REGW, .MSTATUSH_REGW,
.CSRWriteValM, .CSRMReadValM, .MTVEC_REGW,
.MEPC_REGW, .MCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW,
.MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM,
2023-06-14 04:12:49 +00:00
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM,
.MENVCFG_REGW);
2023-01-14 06:12:06 +00:00
if (P.S_SUPPORTED) begin:csrs
logic STCE;
assign STCE = P.SSTC_SUPPORTED & (PrivilegeModeW == P.M_MODE | (MCOUNTEREN_REGW[1] & ENVCFG_STCE));
csrs #(P) csrs(.clk, .reset,
2023-01-14 06:12:06 +00:00
.CSRSWriteM, .STrapM, .CSRAdrM,
.NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW,
.STATUS_TVM,
.CSRWriteValM, .PrivilegeModeW,
2023-01-14 06:12:06 +00:00
.CSRSReadValM, .STVEC_REGW, .SEPC_REGW,
.SCOUNTEREN_REGW,
.SATP_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MTIME_CLINT, .STCE,
.WriteSSTATUSM, .IllegalCSRSAccessM, .STimerInt, .SENVCFG_REGW);
2023-01-14 06:12:06 +00:00
end else begin
assign WriteSSTATUSM = 1'b0;
assign CSRSReadValM = '0;
assign SEPC_REGW = '0;
assign STVEC_REGW = '0;
assign SCOUNTEREN_REGW = '0;
assign SATP_REGW = '0;
assign IllegalCSRSAccessM = 1'b1;
2023-01-14 06:12:06 +00:00
end
// Floating Point CSRs in User Mode only needed if Floating Point is supported
if (P.F_SUPPORTED | P.D_SUPPORTED) begin:csru
csru #(P) csru(.clk, .reset, .InstrValidNotFlushedM,
2023-01-14 06:12:06 +00:00
.CSRUWriteM, .CSRAdrM, .CSRWriteValM, .STATUS_FS, .CSRUReadValM,
.SetFflagsM, .FRM_REGW, .WriteFRMM, .WriteFFLAGSM,
.IllegalCSRUAccessM);
end else begin
assign FRM_REGW = '0;
assign CSRUReadValM = '0;
assign IllegalCSRUAccessM = 1'b1;
2023-01-14 06:12:06 +00:00
end
2023-06-14 04:12:49 +00:00
if (P.ZICNTR_SUPPORTED) begin:counters
csrc #(P) counters(.clk, .reset, .StallE, .StallM, .FlushM,
2024-01-18 20:43:34 +00:00
.InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM,
2023-03-03 06:18:34 +00:00
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM,
.InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .sfencevmaM,
.InterruptM, .ExceptionM, .InvalidateICacheM, .ICacheStallF, .DCacheStallM, .DivBusyE, .FDivBusyE,
2023-01-14 05:09:29 +00:00
.CSRAdrM, .PrivilegeModeW, .CSRWriteValM,
.MCOUNTINHIBIT_REGW, .MCOUNTEREN_REGW, .SCOUNTEREN_REGW,
.MTIME_CLINT, .CSRCReadValM, .IllegalCSRCAccessM);
end else begin
assign CSRCReadValM = '0;
assign IllegalCSRCAccessM = 1'b1; // counters aren't enabled
2023-01-14 05:09:29 +00:00
end
2021-01-15 04:37:51 +00:00
// Broadcast appropriate environment configuration based on privilege mode
assign ENVCFG_STCE = MENVCFG_REGW[63]; // supervisor timer counter enable
assign ENVCFG_PBMTE = MENVCFG_REGW[62]; // page-based memory types enable
2023-12-13 19:49:04 +00:00
assign ENVCFG_ADUE = MENVCFG_REGW[61]; // Hardware A/D Update enable
assign ENVCFG_CBE = (PrivilegeModeW == P.M_MODE) ? 4'b1111 :
(PrivilegeModeW == P.S_MODE | !P.S_SUPPORTED) ? MENVCFG_REGW[7:4] :
2023-07-02 09:01:40 +00:00
(MENVCFG_REGW[7:4] & SENVCFG_REGW[7:4]);
// FIOM presently doesn't do anything because Wally fences don't do anything
assign ENVCFG_FIOM = (PrivilegeModeW == P.M_MODE) ? 1'b1 :
(PrivilegeModeW == P.S_MODE | !P.S_SUPPORTED) ? MENVCFG_REGW[0] :
(MENVCFG_REGW[0] & SENVCFG_REGW[0]);
// merge CSR Reads
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM;
flopenrc #(P.XLEN) CSRValWReg(clk, reset, FlushW, ~StallW, CSRReadValM, CSRReadValW);
2021-01-15 04:37:51 +00:00
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 & PrivilegeModeW != P.M_MODE) |
(CSRAdrM[9:8] == 2'b01 & PrivilegeModeW == P.U_MODE);
assign IllegalCSRAccessM = ((IllegalCSRCAccessM & IllegalCSRMAccessM &
IllegalCSRSAccessM & IllegalCSRUAccessM |
InsufficientCSRPrivilegeM) & CSRReadM) | IllegalCSRMWriteReadonlyM;
2021-01-15 04:37:51 +00:00
endmodule