A design that actually passes one performance monitor trace from
TestRig. The example counted redirections, which happend to match between Flute and Toooba for this example.
This commit is contained in:
@@ -59,6 +59,10 @@ import TlbTypes::*;
|
||||
import SynthParam::*;
|
||||
import VerificationPacket::*;
|
||||
import Performance::*;
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
import PerformanceMonitor::*;
|
||||
import SpecialWires::*;
|
||||
`endif
|
||||
import HasSpecBits::*;
|
||||
import Exec::*;
|
||||
import FetchStage::*;
|
||||
@@ -157,6 +161,48 @@ interface CoreRenameDebug;
|
||||
interface Get#(RenameErrInfo) renameErr;
|
||||
endinterface
|
||||
|
||||
// ================================================================
|
||||
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
typedef struct {
|
||||
Bool evt_REDIRECT;
|
||||
Bool evt_TLB_EXC; // TODO: Misleading name
|
||||
Bool evt_BRANCH;
|
||||
Bool evt_JAL;
|
||||
Bool evt_JALR;
|
||||
Bool evt_AUIPC;
|
||||
Bool evt_LOAD;
|
||||
Bool evt_STORE;
|
||||
Bool evt_LR;
|
||||
Bool evt_SC;
|
||||
Bool evt_AMO;
|
||||
Bool evt_SERIAL_SHIFT;
|
||||
Bool evt_INT_MUL_DIV_REM;
|
||||
Bool evt_FP;
|
||||
Bool evt_SC_SUCCESS;
|
||||
Bool evt_LOAD_WAIT;
|
||||
Bool evt_STORE_WAIT;
|
||||
Bool evt_FENCE;
|
||||
Bool evt_F_BUSY_NO_CONSUME;
|
||||
Bool evt_D_BUSY_NO_CONSUME;
|
||||
Bool evt_1_BUSY_NO_CONSUME;
|
||||
Bool evt_2_BUSY_NO_CONSUME;
|
||||
Bool evt_3_BUSY_NO_CONSUME;
|
||||
Bool evt_IMPRECISE_SETBOUND;
|
||||
Bool evt_UNREPRESENTABLE_CAP;
|
||||
Bool evt_MEM_CAP_LOAD;
|
||||
Bool evt_MEM_CAP_STORE;
|
||||
Bool evt_MEM_CAP_LOAD_TAG_SET;
|
||||
Bool evt_MEM_CAP_STORE_TAG_SET;
|
||||
} EventsCore deriving (Bits, FShow);
|
||||
|
||||
instance BitVectorable #(EventsCore, 1, m) provisos (Bits #(EventsCore, m));
|
||||
function to_vector = struct_to_vector;
|
||||
endinstance
|
||||
`endif
|
||||
|
||||
// ================================================================
|
||||
|
||||
interface Core;
|
||||
// core request & indication
|
||||
interface CoreReq coreReq;
|
||||
@@ -258,6 +304,14 @@ module mkCore#(CoreId coreId)(Core);
|
||||
Vector #(SupSize, FIFOF #(Trace_Data2)) v_f_to_TV <- replicateM (mkFIFOF);
|
||||
`endif
|
||||
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
Array #(Wire #(EventsCore)) aw_events <- mkDWireOR (5, unpack (0));
|
||||
Reg #(EventsCore) aw_events_reg <- mkConfigReg(unpack(0));
|
||||
rule update_aw_events_reg;
|
||||
aw_events_reg <= aw_events[0];
|
||||
endrule
|
||||
`endif
|
||||
|
||||
// ================================================================
|
||||
|
||||
// front end
|
||||
@@ -400,6 +454,11 @@ module mkCore#(CoreId coreId)(Core);
|
||||
`endif
|
||||
);
|
||||
globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag);
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
EventsCore events = unpack (0);
|
||||
events.evt_REDIRECT = True;
|
||||
aw_events[1] <= events;
|
||||
`endif
|
||||
endmethod
|
||||
method correctSpec = globalSpecUpdate.correctSpec[finishAluCorrectSpecPort(i)].put;
|
||||
method doStats = doStatsReg._read;
|
||||
@@ -1075,6 +1134,27 @@ module mkCore#(CoreId coreId)(Core);
|
||||
endrule
|
||||
`endif
|
||||
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
// ================================================================
|
||||
// Performance counters
|
||||
|
||||
Vector #(1, Bit #(Counter_Width)) null_evt = replicate (0);
|
||||
Vector #(31, Bit #(Counter_Width)) core_evts_vec = to_large_vector (aw_events_reg);
|
||||
Vector #(16, Bit #(Counter_Width)) imem_evts_vec = replicate (0);//to_large_vector (near_mem.imem.events);
|
||||
Vector #(16, Bit #(Counter_Width)) dmem_evts_vec = replicate (0);//to_large_vector (near_mem.dmem.events);
|
||||
Vector #(32, Bit #(Counter_Width)) external_evts_vec = replicate (0);//to_large_vector (w_external_evts);
|
||||
|
||||
let events = append (null_evt, core_evts_vec);
|
||||
events = append (events, imem_evts_vec);
|
||||
events = append (events, dmem_evts_vec);
|
||||
events = append (events, external_evts_vec);
|
||||
|
||||
(* fire_when_enabled, no_implicit_conditions *)
|
||||
rule rl_send_perf_evts;
|
||||
csrf.send_performance_events (events);
|
||||
endrule
|
||||
`endif
|
||||
|
||||
`ifdef INCLUDE_GDB_CONTROL
|
||||
// ================================================================
|
||||
// DEBUG MODULE INTERFACE
|
||||
|
||||
@@ -58,6 +58,10 @@ import ISA_Decls_CHERI::*;
|
||||
|
||||
import Cur_Cycle :: *;
|
||||
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
import PerformanceMonitor :: *;
|
||||
`endif
|
||||
|
||||
// ================================================================
|
||||
// Project imports from Toooba
|
||||
|
||||
@@ -179,6 +183,10 @@ interface CsrFile;
|
||||
method Action dcsr_cause_write (Bit #(3) dcsr_cause);
|
||||
|
||||
`endif
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
(* always_ready, always_enabled *)
|
||||
method Action send_performance_events (Vector #(No_Of_Evts, Bit #(Counter_Width)) evts);
|
||||
`endif
|
||||
endinterface
|
||||
|
||||
// Fancy Reg functions
|
||||
@@ -233,6 +241,38 @@ function Reg#(t) addWriteSideEffect(Reg#(t) r, Action a);
|
||||
endinterface);
|
||||
endfunction
|
||||
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
interface PerfCountersVec;
|
||||
interface Vector#(No_Of_Ctrs, Reg#(Data)) counter_vec;
|
||||
interface Vector#(No_Of_Ctrs, Reg#(Data)) event_vec;
|
||||
interface Reg#(Data) inhibit;
|
||||
method Action send_performance_events (Vector #(No_Of_Evts, Bit#(Counter_Width)) evts);
|
||||
endinterface
|
||||
(* synthesize *)
|
||||
module mkPerfCountersToooba (PerfCountersVec);
|
||||
PerfCounters_IFC #(No_Of_Ctrs, Counter_Width, No_Of_Evts) perf_counters <- mkPerfCounters;
|
||||
Vector#(No_Of_Ctrs, Reg#(Data)) counters = ?;
|
||||
for (Bit#(TLog#(No_Of_Ctrs)) i = 0; i < 29; i = i + 1) counters[i] =
|
||||
interface Reg;
|
||||
method Action _write(Data x) = perf_counters.write_counter(i,x);
|
||||
method Data _read = perf_counters.read_counters[i];
|
||||
endinterface;
|
||||
Vector#(No_Of_Ctrs, Reg#(Data)) events = ?;
|
||||
for (Bit#(TLog#(No_Of_Ctrs)) i = 0; i < 29; i = i + 1) events[i] =
|
||||
interface Reg;
|
||||
method Action _write(Data x) = perf_counters.write_ctr_sel(i,truncate(x));
|
||||
method Data _read = zeroExtend(perf_counters.read_ctr_sels[i]);
|
||||
endinterface;
|
||||
interface counter_vec = counters;
|
||||
interface event_vec = events;
|
||||
interface inhibit = interface Reg;
|
||||
method Action _write(Data x) = perf_counters.write_ctr_inhibit(truncate(x));
|
||||
method Data _read = zeroExtend(perf_counters.read_ctr_inhibit);
|
||||
endinterface;
|
||||
method send_performance_events = perf_counters.send_performance_events;
|
||||
endmodule
|
||||
`endif
|
||||
|
||||
function Bool has_csr_permission(CSR csr, Bit#(2) prv, Bool write);
|
||||
Bit#(12) csr_index = pack(csr);
|
||||
return ((prv >= csr_index[9:8]) && (!write || (csr_index[11:10] != 2'b11)));
|
||||
@@ -682,6 +722,16 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
Reg #(Data) rg_dscratch1 <- mkConfigRegU;
|
||||
`endif
|
||||
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
PerfCountersVec perf_counters <- mkPerfCountersToooba;
|
||||
|
||||
//Reg #(Bit #(2)) rg_ctr_inhib_lsb <- mkReg (0);
|
||||
//Wire #(Bit #(2)) w_ctr_inhib_lsb <- mkWire;
|
||||
//Bit #(3) ctr_inhibit_lsb = { rg_ctr_inhib_lsb [1], 0, rg_ctr_inhib_lsb [0] };
|
||||
//Word ctr_inhibit = zeroExtend ({ perf_counters.read_ctr_inhibit, ctr_inhibit_lsb });
|
||||
//CSR_Addr no_of_ctrs = fromInteger (valueOf (No_Of_Ctrs));
|
||||
`endif
|
||||
|
||||
`ifdef SECURITY
|
||||
// sanctum machine CSRs
|
||||
|
||||
@@ -756,6 +806,14 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
|
||||
// Function for getting a csr given an index
|
||||
function Reg#(Data) get_csr(CSR csr);
|
||||
Reg#(Data) ret = readOnlyReg(64'b0);
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
let c = csr.addr;
|
||||
if ((csrAddrMHPMCNT3.addr <= c) && (c <= csrAddrMHPMCNT31.addr))
|
||||
ret = perf_counters.counter_vec[c-csrAddrMHPMCNT3.addr];
|
||||
if ((csrAddrMHPMEVENT3.addr <= c) && (c <= csrAddrMHPMEVENT31.addr))
|
||||
ret = perf_counters.event_vec[c - csrAddrMHPMEVENT3.addr];
|
||||
`endif
|
||||
return (case (csr)
|
||||
// User CSRs
|
||||
csrAddrFFLAGS: fflags_csr;
|
||||
@@ -810,20 +868,19 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
csrAddrMSPEC: mspec_csr;
|
||||
csrAddrTRNG: trng_csr;
|
||||
`endif
|
||||
|
||||
csrAddrTSELECT: rg_tselect;
|
||||
csrAddrTDATA1: rg_tdata1;
|
||||
csrAddrTDATA2: rg_tdata2;
|
||||
csrAddrTDATA3: rg_tdata3;
|
||||
csrAddrTSELECT: rg_tselect;
|
||||
csrAddrTDATA1: rg_tdata1;
|
||||
csrAddrTDATA2: rg_tdata2;
|
||||
csrAddrTDATA3: rg_tdata3;
|
||||
|
||||
`ifdef INCLUDE_GDB_CONTROL
|
||||
csrAddrDCSR: rg_dcsr; // TODO: take NMI into account (cf. Piccolo/Flute)
|
||||
csrAddrDPC: scrToCsr(rg_dpc);
|
||||
csrAddrDSCRATCH0: rg_dscratch0;
|
||||
csrAddrDSCRATCH1: rg_dscratch1;
|
||||
csrAddrDCSR: rg_dcsr; // TODO: take NMI into account (cf. Piccolo/Flute)
|
||||
csrAddrDPC: scrToCsr(rg_dpc);
|
||||
csrAddrDSCRATCH0: rg_dscratch0;
|
||||
csrAddrDSCRATCH1: rg_dscratch1;
|
||||
`endif
|
||||
|
||||
default: readOnlyReg(64'b0);
|
||||
default: ret;
|
||||
endcase);
|
||||
endfunction
|
||||
|
||||
@@ -1341,4 +1398,7 @@ module mkCsrFile #(Data hartid)(CsrFile);
|
||||
|
||||
`endif
|
||||
|
||||
`ifdef PERFORMANCE_MONITORING
|
||||
method send_performance_events = perf_counters.send_performance_events;
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user