2021-06-10 13:41:26 +00:00
///////////////////////////////////////////
// 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
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include " wally-config.vh "
2021-06-17 16:09:10 +00:00
// Ben 06/17/21: I brought in MTIME, MTIMECMP from CLINT. *** this probably isn't perfect though because it doesn't yet provide the ability to change these through CSR writes; overall this whole thing might need some rethinking
2021-06-10 13:41:26 +00:00
module csrc # ( parameter
MCYCLE = 12 'hB00 ,
2021-06-18 11:53:49 +00:00
MTIME = 12 'hB01 , // address not specified in privileged spec. Consider moving to CLINT to match SiFive
MTIMECMP = 12 'hB21 , // not specified in privileged spec. Move to CLINT
2021-06-10 13:41:26 +00:00
MINSTRET = 12 'hB02 ,
MHPMCOUNTERBASE = 12 'hB00 ,
//MHPMCOUNTER3 = 12'hB03,
//MHPMCOUNTER4 = 12'hB04,
// ... more counters
//MHPMCOUNTER31 = 12'hB1F,
MCYCLEH = 12 'hB80 ,
2021-06-18 11:53:49 +00:00
MTIMEH = 12 'hB81 , // address not specified in privileged spec. Consider moving to CLINT to match SiFive
MTIMECMPH = 12 'hBA1 , // not specified in privileged spec. Move to CLINT
2021-06-10 13:41:26 +00:00
MINSTRETH = 12 'hB82 ,
MHPMCOUNTERHBASE = 12 'hB80 ,
//MHPMCOUNTER3H = 12'hB83,
//MHPMCOUNTER4H = 12'hB84,
// ... more counters
//MHPMCOUNTER31H = 12'hB9F,
MCOUNTERINHIBIT = 12 'h320 ,
MHPMEVENTBASE = 12 'h320 ,
//MHPMEVENT3 = 12'h323,
//MHPMEVENT4 = 12'h324,
// ... more counters
//MHPMEVENT31 = 12'h33F,
CYCLE = 12 'hC00 ,
2021-06-17 12:38:30 +00:00
TIME = 12 'hC01 ,
2021-06-10 13:41:26 +00:00
INSTRET = 12 'hC02 ,
HPMCOUNTERBASE = 12 'hC00 ,
//HPMCOUNTER3 = 12'hC03,
//HPMCOUNTER4 = 12'hC04,
// ...more counters
//HPMCOUNTER31 = 12'hC1F,
CYCLEH = 12 'hC80 ,
2021-06-17 12:38:30 +00:00
TIMEH = 12 'hC81 , // not specified
2021-06-10 13:41:26 +00:00
INSTRETH = 12 'hC82 ,
HPMCOUNTERHBASE = 12 'hC80
//HPMCOUNTER3H = 12'hC83,
//HPMCOUNTER4H = 12'hC84,
// ... more counters
//HPMCOUNTER31H = 12'hC9F
) (
2021-09-29 03:17:58 +00:00
input logic clk , reset ,
input logic StallD , StallE , StallM , StallW ,
2021-08-23 17:24:03 +00:00
input logic FlushD , FlushE , FlushM , FlushW ,
2021-09-29 03:17:58 +00:00
input logic InstrValidM , LoadStallD , CSRMWriteM ,
input logic BPPredDirWrongM ,
input logic BTBPredPCWrongM ,
input logic RASPredPCWrongM ,
input logic BPPredClassNonCFIWrongM ,
input logic [ 4 : 0 ] InstrClassM ,
input logic DCacheMiss ,
input logic DCacheAccess ,
input logic [ 11 : 0 ] CSRAdrM ,
input logic [ 1 : 0 ] PrivilegeModeW ,
2021-08-23 17:24:03 +00:00
input logic [ `XLEN - 1 : 0 ] CSRWriteValM ,
2021-09-29 03:17:58 +00:00
input logic [ 31 : 0 ] MCOUNTINHIBIT_REGW , MCOUNTEREN_REGW , SCOUNTEREN_REGW ,
input logic [ 63 : 0 ] MTIME_CLINT , MTIMECMP_CLINT ,
2021-06-10 13:41:26 +00:00
output logic [ `XLEN - 1 : 0 ] CSRCReadValM ,
2021-09-29 03:17:58 +00:00
output logic IllegalCSRCAccessM
2021-06-10 13:41:26 +00:00
) ;
2021-07-04 22:52:16 +00:00
generate
2021-09-15 17:14:00 +00:00
if ( `ZICOUNTERS_SUPPORTED ) begin
2021-06-10 13:41:26 +00:00
// logic [63:0] TIME_REGW, TIMECMP_REGW;
logic [ 63 : 0 ] CYCLE_REGW , INSTRET_REGW ;
logic [ 63 : 0 ] HPMCOUNTER3_REGW , HPMCOUNTER4_REGW ; // add more performance counters here if desired
logic [ 63 : 0 ] CYCLEPlusM , INSTRETPlusM ;
logic [ 63 : 0 ] HPMCOUNTER3PlusM , HPMCOUNTER4PlusM ;
2021-09-29 03:17:58 +00:00
// logic [`XLEN-1:0] NextTIMEM;
2021-06-10 13:41:26 +00:00
logic [ `XLEN - 1 : 0 ] NextCYCLEM , NextINSTRETM ;
logic [ `XLEN - 1 : 0 ] NextHPMCOUNTER3M , NextHPMCOUNTER4M ;
logic WriteCYCLEM , WriteINSTRETM ;
logic WriteHPMCOUNTER3M , WriteHPMCOUNTER4M ;
logic [ 4 : 0 ] CounterNumM ;
logic [ `COUNTERS - 1 : 3 ] [ `XLEN - 1 : 0 ] HPMCOUNTER_REGW , HPMCOUNTERH_REGW ;
2021-09-29 03:17:58 +00:00
var [ `COUNTERS - 1 : 3 ] [ `XLEN - 1 : 0 ] initHPMCOUNTER ;
logic InstrValidNotFlushedM ;
initial
`ifdef CHECKPOINT
$readmemh ( { `LINUX_CHECKPOINT , " checkpoint-HPMCOUNTER.txt " } , initHPMCOUNTER ) ;
`else
initHPMCOUNTER = { ( `COUNTERS - 3 ) { `XLEN 'b0 } } ;
`endif
2021-08-23 17:24:03 +00:00
assign InstrValidNotFlushedM = InstrValidM & ~ StallW & ~ FlushW ;
2021-06-10 13:41:26 +00:00
//logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTERH_REGW;
// Write enables
// assign WriteTIMEM = CSRMWriteM && (CSRAdrM == MTIME);
// assign WriteTIMECMPM = CSRMWriteM && (CSRAdrM == MTIMECMP);
assign WriteCYCLEM = CSRMWriteM & & ( CSRAdrM = = MCYCLE ) ;
assign WriteINSTRETM = CSRMWriteM & & ( CSRAdrM = = MINSTRET ) ;
//assign WriteHPMCOUNTER3M = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3);
//assign WriteHPMCOUNTER4M = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4);
// Counter adders with inhibits for power savings
assign CYCLEPlusM = CYCLE_REGW + { 63 'b0 , ~ MCOUNTINHIBIT_REGW [ 0 ] } ;
2021-06-17 12:38:30 +00:00
//assign TIMEPlusM = TIME_REGW + 1; // can't be inhibited
2021-08-23 17:24:03 +00:00
assign INSTRETPlusM = INSTRET_REGW + { 63 'b0 , InstrValidNotFlushedM & ~ MCOUNTINHIBIT_REGW [ 2 ] } ;
2021-06-10 13:41:26 +00:00
//assign HPMCOUNTER3PlusM = HPMCOUNTER3_REGW + {63'b0, LoadStallD & ~MCOUNTINHIBIT_REGW[3]}; // count load stalls
2021-06-17 12:38:30 +00:00
//assign HPMCOUNTER4PlusM = HPMCOUNTER4_REGW + {63'b0, 1'b0 & ~MCOUNTINHIBIT_REGW[4]}; // change to count signals
2021-06-10 13:41:26 +00:00
assign NextCYCLEM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM [ `XLEN - 1 : 0 ] ;
2021-06-17 12:38:30 +00:00
//assign NextTIMEM = WriteTIMEM ? CSRWriteValM : TIMEPlusM[`XLEN-1:0];
2021-06-10 13:41:26 +00:00
assign NextINSTRETM = WriteINSTRETM ? CSRWriteValM : INSTRETPlusM [ `XLEN - 1 : 0 ] ;
//assign NextHPMCOUNTER3M = WriteHPMCOUNTER3M ? CSRWriteValM : HPMCOUNTER3PlusM[`XLEN-1:0];
//assign NextHPMCOUNTER4M = WriteHPMCOUNTER4M ? CSRWriteValM : HPMCOUNTER4PlusM[`XLEN-1:0];
2021-09-29 03:17:58 +00:00
// parameterized number of additional counters
if ( `COUNTERS > 3 ) begin
2021-06-10 15:18:58 +00:00
logic [ `COUNTERS - 1 : 3 ] WriteHPMCOUNTERM ;
logic [ `COUNTERS - 1 : 0 ] CounterEvent ;
2021-06-10 13:41:26 +00:00
logic [ 63 : 0 ] /*HPMCOUNTER_REGW[`COUNTERS-1:3], */ HPMCOUNTERPlusM [ `COUNTERS - 1 : 3 ] ;
logic [ `XLEN - 1 : 0 ] NextHPMCOUNTERM [ `COUNTERS - 1 : 3 ] ;
genvar i ;
2021-06-10 15:18:58 +00:00
// could replace special counters 0-2 with this loop for all counters
assign CounterEvent [ 0 ] = 1 'b1 ;
assign CounterEvent [ 1 ] = 1 'b0 ;
2021-09-29 03:17:58 +00:00
if ( `QEMU ) assign CounterEvent [ `COUNTERS - 1 : 2 ] = 0 ;
else begin
logic LoadStallE , LoadStallM ;
flopenrc # ( 1 ) LoadStallEReg ( . clk , . reset , . clear ( FlushE ) , . en ( ~ StallE ) , . d ( LoadStallD ) , . q ( LoadStallE ) ) ;
flopenrc # ( 1 ) LoadStallMReg ( . clk , . reset , . clear ( FlushM ) , . en ( ~ StallM ) , . d ( LoadStallE ) , . q ( LoadStallM ) ) ;
assign CounterEvent [ 2 ] = InstrValidNotFlushedM ;
assign CounterEvent [ 3 ] = LoadStallM & InstrValidNotFlushedM ;
assign CounterEvent [ 4 ] = BPPredDirWrongM & InstrValidNotFlushedM ;
assign CounterEvent [ 5 ] = InstrClassM [ 0 ] & InstrValidNotFlushedM ;
assign CounterEvent [ 6 ] = BTBPredPCWrongM & InstrValidNotFlushedM ;
assign CounterEvent [ 7 ] = ( InstrClassM [ 4 ] | InstrClassM [ 2 ] | InstrClassM [ 1 ] ) & InstrValidNotFlushedM ;
assign CounterEvent [ 8 ] = RASPredPCWrongM & InstrValidNotFlushedM ;
assign CounterEvent [ 9 ] = InstrClassM [ 3 ] & InstrValidNotFlushedM ;
assign CounterEvent [ 10 ] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM ;
assign CounterEvent [ 11 ] = DCacheAccess & InstrValidNotFlushedM ;
assign CounterEvent [ 12 ] = DCacheMiss & InstrValidNotFlushedM ;
assign CounterEvent [ `COUNTERS - 1 : 13 ] = 0 ; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
end
2021-06-10 13:41:26 +00:00
for ( i = 3 ; i < `COUNTERS ; i = i + 1 ) begin
2021-09-29 03:17:58 +00:00
assign WriteHPMCOUNTERM [ i ] = CSRMWriteM & & ( CSRAdrM = = MHPMCOUNTERBASE + i ) ;
assign NextHPMCOUNTERM [ i ] [ `XLEN - 1 : 0 ] = WriteHPMCOUNTERM [ i ] ? CSRWriteValM : HPMCOUNTERPlusM [ i ] [ `XLEN - 1 : 0 ] ;
always @ ( posedge clk , posedge reset ) // ModelSim doesn't like syntax of passing array element to flop
if ( reset ) HPMCOUNTER_REGW [ i ] [ `XLEN - 1 : 0 ] < = # 1 initHPMCOUNTER [ i ] ;
else if ( ~ StallW ) HPMCOUNTER_REGW [ i ] [ `XLEN - 1 : 0 ] < = # 1 NextHPMCOUNTERM [ i ] ;
//flopr #(`XLEN) HPMCOUNTERreg[i](clk, reset, NextHPMCOUNTERM[i], HPMCOUNTER_REGW[i]);
2021-06-10 13:41:26 +00:00
2021-09-29 03:17:58 +00:00
if ( `XLEN = = 32 ) begin
logic [ `COUNTERS - 1 : 3 ] WriteHPMCOUNTERHM ;
logic [ `XLEN - 1 : 0 ] NextHPMCOUNTERHM [ `COUNTERS - 1 : 3 ] ;
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 @ ( 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 if ( ~ StallW ) HPMCOUNTERH_REGW [ i ] [ `XLEN - 1 : 0 ] < = # 1 NextHPMCOUNTERHM [ i ] ;
//flopr #(`XLEN) HPMCOUNTERHreg[i](clk, reset, NextHPMCOUNTERHM[i], HPMCOUNTER_REGW[i][63:32]);
end else begin
assign HPMCOUNTERPlusM [ i ] = HPMCOUNTER_REGW [ i ] + { 63 'b0 , CounterEvent [ i ] & ~ MCOUNTINHIBIT_REGW [ i ] } ;
end
2021-06-10 13:41:26 +00:00
end
2021-09-29 03:17:58 +00:00
end
2021-06-10 13:41:26 +00:00
// Write / update counters
// Only the Machine mode versions of the counter CSRs are writable
2021-09-29 03:17:58 +00:00
if ( `XLEN = = 64 ) begin // 64-bit counters
// flopr #(64) TIMEreg(clk, reset, WriteTIMEM ? CSRWriteValM : TIME_REGW + 1, TIME_REGW); // may count off a different clock***
// flopenr #(64) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW);
flopr # ( 64 ) CYCLEreg ( clk , reset , NextCYCLEM , CYCLE_REGW ) ;
flopr # ( 64 ) INSTRETreg ( clk , reset , NextINSTRETM , INSTRET_REGW ) ;
//flopr #(64) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW);
//flopr #(64) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW);
end else begin // 32-bit low and high counters
logic WriteTIMEHM , WriteTIMECMPHM , WriteCYCLEHM , WriteINSTRETHM ;
//logic WriteHPMCOUNTER3HM, WriteHPMCOUNTER4HM;
logic [ `XLEN - 1 : 0 ] NextCYCLEHM , NextTIMEHM , NextINSTRETHM ;
//logic [`XLEN-1:0] NextHPMCOUNTER3HM, NextHPMCOUNTER4HM;
2021-06-10 13:41:26 +00:00
2021-09-29 03:17:58 +00:00
// Write Enables
// assign WriteTIMEHM = CSRMWriteM && (CSRAdrM == MTIMEH);
// assign WriteTIMECMPHM = CSRMWriteM && (CSRAdrM == MTIMECMPH);
assign WriteCYCLEHM = CSRMWriteM & & ( CSRAdrM = = MCYCLEH ) ;
assign WriteINSTRETHM = CSRMWriteM & & ( CSRAdrM = = MINSTRETH ) ;
//assign WriteHPMCOUNTER3HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3H);
//assign WriteHPMCOUNTER4HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4H);
assign NextCYCLEHM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM [ 63 : 32 ] ;
// assign NextTIMEHM = WriteTIMEHM ? CSRWriteValM : TIMEPlusM[63:32];
assign NextINSTRETHM = WriteINSTRETHM ? CSRWriteValM : INSTRETPlusM [ 63 : 32 ] ;
//assign NextHPMCOUNTER3HM = WriteHPMCOUNTER3HM ? CSRWriteValM : HPMCOUNTER3PlusM[63:32];
//assign NextHPMCOUNTER4HM = WriteHPMCOUNTER4HM ? CSRWriteValM : HPMCOUNTER4PlusM[63:32];
2021-06-10 13:41:26 +00:00
2021-09-29 03:17:58 +00:00
// Counter CSRs
// flopr #(32) TIMEreg(clk, reset, NextTIMEM, TIME_REGW); // may count off a different clock***
// flopenr #(32) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW[31:0]);
flopr # ( 32 ) CYCLEreg ( clk , reset , NextCYCLEM , CYCLE_REGW [ 31 : 0 ] ) ;
flopr # ( 32 ) INSTRETreg ( clk , reset , NextINSTRETM , INSTRET_REGW [ 31 : 0 ] ) ;
// flopr #(32) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW[31:0]);
// flopr #(32) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]);
// flopr #(32) TIMEHreg(clk, reset, NextTIMEHM, TIME_REGW); // may count off a different clock***
// flopenr #(32) TIMECMPHreg(clk, reset, WriteTIMECMPHM, CSRWriteValM, TIMECMP_REGW[63:32]);
flopr # ( 32 ) CYCLEHreg ( clk , reset , NextCYCLEHM , CYCLE_REGW [ 63 : 32 ] ) ;
flopr # ( 32 ) INSTRETHreg ( clk , reset , NextINSTRETHM , INSTRET_REGW [ 63 : 32 ] ) ;
//flopr #(32) HPMCOUNTER3Hreg(clk, reset, NextHPMCOUNTER3HM, HPMCOUNTER3_REGW[63:32]);
//flopr #(32) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]);
end
2021-06-10 13:41:26 +00:00
2021-09-29 03:17:58 +00:00
// eventually move TIME and TIMECMP to the CLINT -- Ben 06/17/21: sure let's give that a shot!
// run TIME off asynchronous reference clock
// synchronize write enable to TIME
// four phase handshake to synchronize reads from TIME
2021-06-10 13:41:26 +00:00
2021-09-29 03:17:58 +00:00
// interrupt on timer compare
// ability to disable optional CSRs
2021-06-10 13:41:26 +00:00
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM [ 4 : 0 ] ; // which counter to read?
if ( `XLEN = = 64 ) // 64-bit counter reads
always_comb
2021-09-29 03:17:58 +00:00
if ( PrivilegeModeW = = `M_MODE | | MCOUNTEREN_REGW [ CounterNumM ] & & ( PrivilegeModeW = = `S_MODE | | SCOUNTEREN_REGW [ CounterNumM ] ) ) begin
2021-06-10 13:41:26 +00:00
IllegalCSRCAccessM = 0 ;
if ( CSRAdrM > = MHPMCOUNTERBASE + 3 & & CSRAdrM < MHPMCOUNTERBASE + `COUNTERS ) CSRCReadValM = HPMCOUNTER_REGW [ CSRAdrM - MHPMCOUNTERBASE ] ;
else if ( CSRAdrM > = HPMCOUNTERBASE + 3 & & CSRAdrM < HPMCOUNTERBASE + `COUNTERS ) CSRCReadValM = HPMCOUNTER_REGW [ CSRAdrM - HPMCOUNTERBASE ] ;
else case ( CSRAdrM )
2021-06-18 11:53:49 +00:00
MTIME: CSRCReadValM = MTIME_CLINT ;
MTIMECMP: CSRCReadValM = MTIMECMP_CLINT ;
2021-06-10 13:41:26 +00:00
MCYCLE: CSRCReadValM = CYCLE_REGW ;
MINSTRET: CSRCReadValM = INSTRET_REGW ;
//MHPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW;
//MHPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW;
2021-06-18 11:53:49 +00:00
TIME: CSRCReadValM = MTIME_CLINT ;
2021-06-10 13:41:26 +00:00
CYCLE: CSRCReadValM = CYCLE_REGW ;
INSTRET: CSRCReadValM = INSTRET_REGW ;
//HPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW;
//HPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW;
default : begin
CSRCReadValM = 0 ;
IllegalCSRCAccessM = 1 ;
end
endcase
end else begin
IllegalCSRCAccessM = 1 ; // no privileges for this csr
CSRCReadValM = 0 ;
end
else // 32-bit counter reads
always_comb
if ( PrivilegeModeW = = `M_MODE | | MCOUNTEREN_REGW [ CounterNumM ] & & ( PrivilegeModeW = = `S_MODE | | SCOUNTEREN_REGW [ CounterNumM ] ) ) begin
IllegalCSRCAccessM = 0 ;
if ( CSRAdrM > = MHPMCOUNTERBASE + 3 & & CSRAdrM < MHPMCOUNTERBASE + `COUNTERS ) CSRCReadValM = HPMCOUNTER_REGW [ CSRAdrM - MHPMCOUNTERBASE ] ;
else if ( CSRAdrM > = HPMCOUNTERBASE + 3 & & CSRAdrM < HPMCOUNTERBASE + `COUNTERS ) CSRCReadValM = HPMCOUNTER_REGW [ CSRAdrM - HPMCOUNTERBASE ] ;
else if ( CSRAdrM > = MHPMCOUNTERHBASE + 3 & & CSRAdrM < MHPMCOUNTERHBASE + `COUNTERS ) CSRCReadValM = HPMCOUNTERH_REGW [ CSRAdrM - MHPMCOUNTERHBASE ] ;
else if ( CSRAdrM > = HPMCOUNTERHBASE + 3 & & CSRAdrM < HPMCOUNTERHBASE + `COUNTERS ) CSRCReadValM = HPMCOUNTERH_REGW [ CSRAdrM - HPMCOUNTERHBASE ] ;
else case ( CSRAdrM )
2021-06-18 11:53:49 +00:00
MTIME: CSRCReadValM = MTIME_CLINT [ 31 : 0 ] ;
MTIMECMP: CSRCReadValM = MTIMECMP_CLINT [ 31 : 0 ] ;
2021-06-10 13:41:26 +00:00
MCYCLE: CSRCReadValM = CYCLE_REGW [ 31 : 0 ] ;
MINSTRET: CSRCReadValM = INSTRET_REGW [ 31 : 0 ] ;
//MHPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW[31:0];
//MHPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW[31:0];
2021-06-18 11:53:49 +00:00
TIME: CSRCReadValM = MTIME_CLINT [ 31 : 0 ] ;
2021-06-10 13:41:26 +00:00
CYCLE: CSRCReadValM = CYCLE_REGW [ 31 : 0 ] ;
INSTRET: CSRCReadValM = INSTRET_REGW [ 31 : 0 ] ;
//HPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW[31:0];
//HPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW[31:0];
2021-06-18 11:53:49 +00:00
MTIMEH: CSRCReadValM = MTIME_CLINT [ 63 : 32 ] ;
MTIMECMPH: CSRCReadValM = MTIMECMP_CLINT [ 63 : 32 ] ;
2021-06-10 13:41:26 +00:00
MCYCLEH: CSRCReadValM = CYCLE_REGW [ 63 : 32 ] ;
MINSTRETH: CSRCReadValM = INSTRET_REGW [ 63 : 32 ] ;
//MHPMCOUNTER3H: CSRCReadValM = HPMCOUNTER3_REGW[63:32];
//MHPMCOUNTER4H: CSRCReadValM = HPMCOUNTER4_REGW[63:32];
2021-06-18 11:53:49 +00:00
TIMEH: CSRCReadValM = MTIME_CLINT [ 63 : 32 ] ;
2021-06-10 13:41:26 +00:00
CYCLEH: CSRCReadValM = CYCLE_REGW [ 63 : 32 ] ;
INSTRETH: CSRCReadValM = INSTRET_REGW [ 63 : 32 ] ;
//HPMCOUNTER3H: CSRCReadValM = HPMCOUNTER3_REGW[63:32];
//HPMCOUNTER4H: CSRCReadValM = HPMCOUNTER4_REGW[63:32];
default : begin
CSRCReadValM = 0 ;
IllegalCSRCAccessM = 1 ;
end
endcase
end else begin
IllegalCSRCAccessM = 1 ; // no privileges for this csr
CSRCReadValM = 0 ;
end
2021-09-29 03:17:58 +00:00
end else begin // not `ZICOUNTERS_SUPPORTED
2021-06-10 13:41:26 +00:00
assign CSRCReadValM = 0 ;
assign IllegalCSRCAccessM = 1 ;
end
endgenerate
endmodule
/ * Bad code from class
2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
// csrc.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
2021-03-04 16:40:18 +00:00
// Modified:ssanghai@hmc.edu 2nd March
// Added a configurable number of counters
2021-04-20 21:57:56 +00:00
// dottolia@hmc.edu 20 April 2021
// Make counters synthesizable
2021-01-15 04:37:51 +00:00
//
// Purpose: Counter CSRs
// See RISC-V Privileged Mode Specification 20190608 3.1.10-11
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
2021-01-23 15:48:12 +00:00
`include " wally-config.vh "
2021-01-15 04:37:51 +00:00
2021-06-10 13:41:26 +00:00
module csrc # ( parameter
// counters
MHPMCOUNTERBASE = 12 'hB00 ,
MHPMCOUNTERHBASE = 12 'hB80 ,
MPHMEVENTBASE = 12 'h320 ,
HPMCOUNTERBASE = 12 'hC00 ,
HPMCOUNTERHBASE = 12 'hC80 ,
2021-09-29 03:17:58 +00:00
) ( input logic clk , reset ,
input logic StallD , StallE , StallM , StallW ,
input logic InstrValidM , LoadStallD , CSRMWriteM ,
input logic BPPredDirWrongM ,
input logic BTBPredPCWrongM ,
input logic RASPredPCWrongM ,
input logic BPPredClassNonCFIWrongM ,
input logic [ 4 : 0 ] InstrClassM ,
input logic [ 11 : 0 ] CSRAdrM ,
input logic [ 1 : 0 ] PrivilegeModeW ,
2021-03-31 16:54:02 +00:00
input logic [ `XLEN - 1 : 0 ] CSRWriteValM ,
2021-09-29 03:17:58 +00:00
input logic [ 31 : 0 ] MCOUNTINHIBIT_REGW , MCOUNTEREN_REGW , SCOUNTEREN_REGW ,
2021-01-23 15:48:12 +00:00
output logic [ `XLEN - 1 : 0 ] CSRCReadValM ,
2021-09-29 03:17:58 +00:00
output logic IllegalCSRCAccessM ) ;
2021-01-15 04:37:51 +00:00
2021-06-10 13:41:26 +00:00
// counters
2021-03-04 16:40:18 +00:00
// create Counter arrays to store address of each counter
integer MHPMCOUNTER [ `COUNTERS : 0 ] ;
integer MHPMCOUNTERH [ `COUNTERS : 0 ] ;
integer HPMCOUNTER [ `COUNTERS : 0 ] ;
integer HPMCOUNTERH [ `COUNTERS : 0 ] ;
integer MHPEVENT [ `COUNTERS : 0 ] ;
2021-01-15 04:37:51 +00:00
2021-04-20 21:57:56 +00:00
genvar i ;
2021-06-10 00:58:20 +00:00
// *** this is totally incorrect. Fix parameterized counters dh 6/9/21
2021-04-20 21:57:56 +00:00
generate
for ( i = 0 ; i < = `COUNTERS ; i = i + 1 ) begin
if ( i ! = 1 ) begin
always @ ( posedge reset ) begin
MHPMCOUNTER [ i ] = 12 'hB00 + i ; // not sure this addition is legit
MHPMCOUNTERH [ i ] = 12 'hB80 + i ;
HPMCOUNTER [ i ] = 12 'hC00 + i ;
HPMCOUNTERH [ i ] = 12 'hC80 + i ;
MHPEVENT [ i ] = 12 'h320 + i ; // MHPEVENT[0] = MCOUNTERINHIBIT
end
2021-03-04 16:40:18 +00:00
end
end //end for loop
2021-04-20 21:57:56 +00:00
endgenerate
2021-01-15 04:37:51 +00:00
2021-03-04 16:40:18 +00:00
logic [ `COUNTERS : 0 ] MCOUNTEN ;
assign MCOUNTEN [ 0 ] = 1 'b1 ;
assign MCOUNTEN [ 1 ] = 1 'b0 ;
2021-07-13 17:19:13 +00:00
assign MCOUNTEN [ 2 ] = InstrValidM & ~ StallW ;
2021-03-24 20:56:55 +00:00
assign MCOUNTEN [ 3 ] = LoadStallD & ~ StallD ;
2021-03-31 16:54:02 +00:00
assign MCOUNTEN [ 4 ] = BPPredDirWrongM & ~ StallM ;
2021-03-24 20:56:55 +00:00
assign MCOUNTEN [ 5 ] = InstrClassM [ 0 ] & ~ StallM ;
2021-03-31 16:54:02 +00:00
assign MCOUNTEN [ 6 ] = BTBPredPCWrongM & ~ StallM ;
assign MCOUNTEN [ 7 ] = ( InstrClassM [ 4 ] | InstrClassM [ 2 ] | InstrClassM [ 1 ] ) & ~ StallM ;
assign MCOUNTEN [ 8 ] = RASPredPCWrongM & ~ StallM ;
assign MCOUNTEN [ 9 ] = InstrClassM [ 3 ] & ~ StallM ;
assign MCOUNTEN [ 10 ] = BPPredClassNonCFIWrongM & ~ StallM ;
assign MCOUNTEN [ `COUNTERS : 11 ] = 0 ;
2021-01-15 04:37:51 +00:00
2021-03-04 16:40:18 +00:00
genvar j ;
generate
2021-09-15 17:14:00 +00:00
if ( `ZICOUNTERS_SUPPORTED ) begin
2021-03-04 16:40:18 +00:00
logic [ `COUNTERS : 0 ] [ 63 : 0 ] HPMCOUNTER_REGW ;
logic [ `COUNTERS : 0 ] [ 63 : 0 ] HPMCOUNTERPlusM ;
logic [ `COUNTERS : 0 ] [ `XLEN - 1 : 0 ] NextHPMCOUNTERM ;
logic [ `COUNTERS : 0 ] WriteHPMCOUNTERM ;
logic [ 4 : 0 ] CounterNumM ;
2021-01-15 04:37:51 +00:00
2021-03-04 17:59:45 +00:00
assign CounterNumM = CSRAdrM [ 4 : 0 ] ; // which counter to read? ***
2021-03-04 16:40:18 +00:00
for ( j = 0 ; j < = `COUNTERS ; j = j + 1 ) begin
// Write enables
2021-04-13 16:27:12 +00:00
if ( j ! = 1 ) begin
2021-03-04 16:40:18 +00:00
assign WriteHPMCOUNTERM [ j ] = CSRMWriteM & & ( CSRAdrM = = MHPMCOUNTER [ j ] ) ;
// Count Signals
assign HPMCOUNTERPlusM [ j ] = HPMCOUNTER_REGW [ j ] + { 63 'b0 , MCOUNTEN [ j ] & ~ MCOUNTINHIBIT_REGW [ j ] } ;
assign NextHPMCOUNTERM [ j ] = WriteHPMCOUNTERM [ j ] ? CSRWriteValM : HPMCOUNTERPlusM [ j ] [ `XLEN - 1 : 0 ] ;
end
2021-01-15 04:37:51 +00:00
2021-03-04 16:40:18 +00:00
// Write / update counters
// Only the Machine mode versions of the counter CSRs are writable
if ( `XLEN = = 64 ) begin // 64-bit counters
2021-03-24 20:56:55 +00:00
flopenr # ( 64 ) HPMCOUNTERreg_j ( clk , reset , ~ StallW , NextHPMCOUNTERM [ j ] , HPMCOUNTER_REGW [ j ] ) ;
2021-03-04 16:40:18 +00:00
end
else begin // 32-bit low and high counters
logic [ `COUNTERS : 0 ] WriteHPMCOUNTERHM ;
logic [ `COUNTERS : 0 ] [ `XLEN - 1 : 0 ] NextHPMCOUNTERHM ;
2021-01-15 04:37:51 +00:00
2021-03-04 16:40:18 +00:00
// Write Enables
assign WriteHPMCOUNTERHM [ j ] = CSRMWriteM & & ( CSRAdrM = = MHPMCOUNTERH [ j ] ) ;
assign NextHPMCOUNTERHM [ j ] = WriteHPMCOUNTERHM [ j ] ? CSRWriteValM : HPMCOUNTERPlusM [ j ] [ 63 : 32 ] ;
2021-01-15 04:37:51 +00:00
2021-03-04 16:40:18 +00:00
// Counter CSRs
2021-03-24 20:56:55 +00:00
flopenr # ( 32 ) HPMCOUNTERreg_j ( clk , reset , ~ StallW , NextHPMCOUNTERM [ j ] , HPMCOUNTER_REGW [ j ] [ 31 : 0 ] ) ;
flopenr # ( 32 ) HPMCOUNTERHreg_j ( clk , reset , ~ StallW , NextHPMCOUNTERHM [ j ] , HPMCOUNTER_REGW [ j ] [ 63 : 32 ] ) ;
2021-01-15 04:37:51 +00:00
end
2021-03-04 17:59:45 +00:00
end // end for
// eventually move TIME and TIMECMP to the CLINT
// run TIME off asynchronous reference clock
// synchronize write enable to TIME
// four phase handshake to synchronize reads from TIME
// interrupt on timer compare
// ability to disable optional CSRs
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
if ( `XLEN = = 64 ) begin // 64-bit counter reads
always_comb
if ( PrivilegeModeW = = `M_MODE | |
MCOUNTEREN_REGW [ CounterNumM ] & & ( PrivilegeModeW = = `S_MODE | | SCOUNTEREN_REGW [ CounterNumM ] ) ) begin
2021-03-04 16:40:18 +00:00
2021-03-04 17:59:45 +00:00
if ( CSRAdrM [ 11 : 5 ] = = MHPMCOUNTER [ 0 ] [ 11 : 5 ] | | CSRAdrM [ 11 : 5 ] = = HPMCOUNTER [ 0 ] [ 11 : 5 ] ) begin
CSRCReadValM = HPMCOUNTER_REGW [ CSRAdrM [ 4 : 0 ] ] ;
IllegalCSRCAccessM = 0 ;
2021-03-04 16:40:18 +00:00
end
2021-03-04 17:59:45 +00:00
// //case (CSRAdrM)
// MHPMCOUNTER[j]: CSRCReadValM = HPMCOUNTER_REGW[j];
// HPMCOUNTER[j]: CSRCReadValM = HPMCOUNTER_REGW[j];
// default: begin
// CSRCReadValM = 0;
// IllegalCSRCAccessM = 1;
// end
// endcase
// end
2021-03-04 16:40:18 +00:00
else begin
IllegalCSRCAccessM = 1 ; // no privileges for this csr
CSRCReadValM = 0 ;
2021-03-04 17:59:45 +00:00
end
end
else begin
IllegalCSRCAccessM = 1 ; // no privileges for this csr
CSRCReadValM = 0 ;
2021-01-15 04:37:51 +00:00
end
2021-03-04 17:59:45 +00:00
end
else begin // 32-bit counter reads
always_comb
if ( PrivilegeModeW = = `M_MODE | |
MCOUNTEREN_REGW [ CounterNumM ] & & ( PrivilegeModeW = = `S_MODE | | SCOUNTEREN_REGW [ CounterNumM ] ) ) begin
if ( CSRAdrM [ 11 : 5 ] = = MHPMCOUNTER [ 0 ] [ 11 : 5 ] | | CSRAdrM [ 11 : 5 ] = = HPMCOUNTER [ 0 ] [ 11 : 5 ] | |
CSRAdrM [ 11 : 5 ] = = MHPMCOUNTERH [ 0 ] [ 11 : 5 ] | | CSRAdrM [ 11 : 5 ] = = HPMCOUNTERH [ 0 ] [ 11 : 5 ] ) begin
CSRCReadValM = HPMCOUNTER_REGW [ CSRAdrM [ 4 : 0 ] ] ;
IllegalCSRCAccessM = 0 ;
2021-03-04 16:40:18 +00:00
end
2021-03-04 17:59:45 +00:00
2021-03-04 16:40:18 +00:00
else begin
IllegalCSRCAccessM = 1 ; // no privileges for this csr
CSRCReadValM = 0 ;
2021-03-04 17:59:45 +00:00
end
// IllegalCSRCAccessM = 0;
// case (CSRAdrM)
// MHPMCOUNTER[j]: CSRCReadValM = HPMCOUNTER_REGW[j][31:0];
// HPMCOUNTER[j]: CSRCReadValM = HPMCOUNTER_REGW[j][31:0];
// MHPMCOUNTERH[j]: CSRCReadValM = HPMCOUNTER_REGW[j][63:32];
// HPMCOUNTERH[j]: CSRCReadValM = HPMCOUNTER_REGW[j][63:32];
// default: begin
// CSRCReadValM = 0;
// IllegalCSRCAccessM = 1;
// end
// endcase
end
else begin
IllegalCSRCAccessM = 1 ; // no privileges for this csr
CSRCReadValM = 0 ;
end
end // 32-bit counter end
end // end for big if
2021-03-04 16:40:18 +00:00
else begin
2021-03-04 17:59:45 +00:00
assign CSRCReadValM = 0 ;
assign IllegalCSRCAccessM = 1 ;
2021-03-04 16:40:18 +00:00
end // end for else
endgenerate
2021-01-15 04:37:51 +00:00
endmodule
2021-07-20 03:12:20 +00:00
*/