cvw/pipelined/src/privileged/csrc.sv

165 lines
9.2 KiB
Systemverilog
Raw Normal View History

///////////////////////////////////////////
// csrc.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Counter CSRs
// See RISC-V Privileged Mode Specification 20190608 3.1.10-11
//
2023-01-14 03:44:38 +00:00
// Documentation: RISC-V System on Chip Design Chapter 5
2023-01-14 05:25:55 +00:00
// MHPMEVENT is not supported
2023-01-14 03:44:38 +00:00
//
2023-01-11 23:15:08 +00:00
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// 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
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
`include "wally-config.vh"
module csrc #(parameter
MHPMCOUNTERBASE = 12'hB00,
MHPMCOUNTERHBASE = 12'hB80,
MHPMEVENTBASE = 12'h320,
HPMCOUNTERBASE = 12'hC00,
2021-12-31 06:40:21 +00:00
HPMCOUNTERHBASE = 12'hC80,
TIME = 12'hC01,
TIMEH = 12'hC81
) (
2023-01-14 05:09:29 +00:00
input logic clk, reset,
input logic StallE, StallM,
input logic FlushM,
input logic InstrValidNotFlushedM, LoadStallD, CSRMWriteM,
input logic DirPredictionWrongM,
input logic BTBPredPCWrongM,
input logic RASPredPCWrongM,
input logic PredictionInstrClassWrongM,
input logic BPPredWrongM, // branch predictor is wrong
2023-01-14 05:09:29 +00:00
input logic [3:0] InstrClassM,
input logic JumpOrTakenBranchM, // actual instruction class
2023-01-14 05:09:29 +00:00
input logic DCacheMiss,
input logic DCacheAccess,
input logic ICacheMiss,
input logic ICacheAccess,
input logic [11:0] CSRAdrM,
input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] CSRWriteValM,
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
input logic [63:0] MTIME_CLINT,
output logic [`XLEN-1:0] CSRCReadValM,
output logic IllegalCSRCAccessM
2023-01-14 04:49:34 +00:00
);
2023-01-14 05:25:55 +00:00
logic [4:0] CounterNumM;
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
2023-01-14 05:25:55 +00:00
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
logic LoadStallE, LoadStallM;
logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
logic [`COUNTERS-1:0] CounterEvent;
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0];
2023-01-14 05:09:29 +00:00
genvar i;
2023-01-14 05:09:29 +00:00
// Interface signals
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall.
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
// Determine when to increment each counter
2023-01-14 05:25:55 +00:00
assign CounterEvent[0] = 1'b1; // MCYCLE always increments
assign CounterEvent[1] = 1'b0; // Counter 1 doesn't exist
assign CounterEvent[2] = InstrValidNotFlushedM; // MINSTRET instructions retired
2023-01-14 05:09:29 +00:00
if(`QEMU) begin: cevent // No other performance counters in QEMU
assign CounterEvent[`COUNTERS-1:3] = 0;
2023-01-14 05:25:55 +00:00
end else begin: cevent // User-defined counters
assign CounterEvent[3] = LoadStallM; // Load Stalls. don't want to suppress on flush as this only happens if flushed.
assign CounterEvent[4] = DirPredictionWrongM & InstrValidNotFlushedM; // Branch predictor wrong direction
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM; // branch instruction
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM; // branch predictor wrong target
assign CounterEvent[7] = JumpOrTakenBranchM & InstrValidNotFlushedM; // jump or taken branch instructions
2023-01-14 05:25:55 +00:00
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address
assign CounterEvent[9] = InstrClassM[2] & InstrValidNotFlushedM; // return instructions
assign CounterEvent[10] = PredictionInstrClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong
assign CounterEvent[11] = DCacheAccess; // data cache access
assign CounterEvent[12] = DCacheMiss; // data cache miss
assign CounterEvent[13] = ICacheAccess; // instruction cache access
assign CounterEvent[14] = ICacheMiss; // instruction cache miss
2023-01-28 23:56:56 +00:00
assign CounterEvent[15] = BPPredWrongM & InstrValidNotFlushedM; // branch predictor wrong
assign CounterEvent[`COUNTERS-1:16] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
2023-01-14 05:09:29 +00:00
end
// Counter update and write logic
for (i = 0; i < `COUNTERS; i = i+1) begin:cntr
assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i);
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0;
else HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
2023-01-14 05:09:29 +00:00
if (`XLEN==32) begin // write high and low separately
logic [`COUNTERS-1:0] WriteHPMCOUNTERHM;
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0];
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
assign WriteHPMCOUNTERHM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERHBASE + i);
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
always_ff @(posedge clk) //, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0;
else HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
end else begin // XLEN=64; write entire register
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
end
end
2023-01-14 05:09:29 +00:00
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
always_comb
if (PrivilegeModeW == `M_MODE |
MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0;
if (`XLEN==64) begin // 64-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=64
/* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else begin
2022-01-05 14:35:25 +00:00
CSRCReadValM = 0;
2023-01-14 05:09:29 +00:00
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
end
2023-01-14 05:09:29 +00:00
end else begin // 32-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=32
/* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
end
2022-01-05 14:35:25 +00:00
end
2023-01-14 05:09:29 +00:00
end else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // no privileges for this csr
end
endmodule
// mounteren should only exist if u-mode exists