Skip to content

Commit 1590af2

Browse files
authored
Merge pull request #297 from tactcomplabs/refactor_perf_counters
Refactor the performance counters code
2 parents 5511c14 + 4b71c79 commit 1590af2

File tree

2 files changed

+66
-76
lines changed

2 files changed

+66
-76
lines changed

include/RevRegFile.h

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,6 @@ class RevRegFile {
209209
/// Invoke the MarkLoadComplete function
210210
void MarkLoadComplete( const MemReq& req ) const { MarkLoadCompleteFunc( req ); }
211211

212-
/// Get the number of instructions retired
213-
uint64_t GetInstRet() const { return InstRet; }
214-
215212
/// Capture the PC of current instruction which raised exception
216213
void SetSEPC() {
217214
if( IsRV32 ) {
@@ -338,16 +335,70 @@ class RevRegFile {
338335
}
339336
}
340337

338+
private:
339+
// Performance counters
340+
341+
// Template is used to break circular dependencies between RevCore and RevRegFile
342+
template<typename CORE>
343+
uint64_t rdcycle( CORE* core ) const {
344+
return core->GetCycles();
345+
}
346+
347+
template<typename CORE>
348+
uint64_t rdtime( CORE* core ) const {
349+
return core->GetCurrentSimCycle();
350+
}
351+
352+
template<typename CORE>
353+
uint64_t rdinstret( CORE* ) const {
354+
return InstRet;
355+
}
356+
357+
enum class Half { Lo, Hi };
358+
359+
/// Performance Counter template
360+
// Passed a function which gets the 64-bit value of a performance counter
361+
template<typename T, Half HALF, uint64_t ( RevRegFile::*COUNTER )( RevCore* ) const>
362+
T GetPerfCounter() const {
363+
if constexpr( sizeof( T ) == sizeof( uint32_t ) ) {
364+
// clang-format off
365+
if constexpr( HALF == Half::Lo ) {
366+
return static_cast<T>( ( this->*COUNTER )( Core ) & 0xffffffff );
367+
} else {
368+
return static_cast<T>( ( this->*COUNTER )( Core ) >> 32 );
369+
}
370+
// clang-format on
371+
} else {
372+
if constexpr( HALF == Half::Lo ) {
373+
return ( this->*COUNTER )( Core );
374+
} else {
375+
return 0; // Hi half is not available on RV64
376+
}
377+
}
378+
}
379+
380+
public:
341381
/// Get a CSR register
342382
template<typename T>
343383
T GetCSR( size_t csr ) const {
344-
// We store fcsr separately from the global CSR
384+
// clang-format off
345385
switch( csr ) {
346-
case 1: return static_cast<uint32_t>( fcsr ) >> 0 & 0b00011111u; break;
347-
case 2: return static_cast<uint32_t>( fcsr ) >> 5 & 0b00000111u; break;
348-
case 3: return static_cast<uint32_t>( fcsr ) >> 0 & 0b11111111u; break;
349386
default: return static_cast<T>( CSR[csr] );
387+
388+
// We store fcsr separately from the global CSR
389+
case 1: return static_cast<uint32_t>( fcsr ) >> 0 & 0b00011111u;
390+
case 2: return static_cast<uint32_t>( fcsr ) >> 5 & 0b00000111u;
391+
case 3: return static_cast<uint32_t>( fcsr ) >> 0 & 0b11111111u;
392+
393+
// Performance Counters
394+
case 0xc00: return GetPerfCounter<T, Half::Lo, &RevRegFile::rdcycle>();
395+
case 0xc80: return GetPerfCounter<T, Half::Hi, &RevRegFile::rdcycle>();
396+
case 0xc01: return GetPerfCounter<T, Half::Lo, &RevRegFile::rdtime>();
397+
case 0xc81: return GetPerfCounter<T, Half::Hi, &RevRegFile::rdtime>();
398+
case 0xc02: return GetPerfCounter<T, Half::Lo, &RevRegFile::rdinstret>();
399+
case 0xc82: return GetPerfCounter<T, Half::Hi, &RevRegFile::rdinstret>();
350400
}
401+
// clang-format on
351402
}
352403

353404
/// Set a CSR register

include/insns/Zicsr.h

Lines changed: 8 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,7 @@ class Zicsr : public RevExt {
2323
/// Modify a CSR Register according to CSRRW, CSRRS, or CSRRC
2424
// Because CSR has a 32/64-bit width, this function is templatized
2525
template<typename XLEN, OpKind OPKIND, CSROp OP>
26-
static bool ModCSRImpl( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
27-
28-
// Alternative forms of rdcycle[h], rdtime[h], rdinstret[h] which use an immediate 0 or csrrc
29-
// Canonical forms of rdcycle[h], rdtime[h], rdinstret[h] use csrrs with register x0
30-
if( OP != CSROp::Write && Inst.rs1 == 0 ) {
31-
switch( Inst.imm ) {
32-
case 0xc00: return rdcycle( F, R, M, Inst );
33-
case 0xc80: return rdcycleh( F, R, M, Inst );
34-
case 0xc01: return rdtime( F, R, M, Inst );
35-
case 0xc81: return rdtimeh( F, R, M, Inst );
36-
case 0xc02: return rdinstret( F, R, M, Inst );
37-
case 0xc82: return rdinstreth( F, R, M, Inst );
38-
}
39-
}
40-
26+
static bool ModCSRImpl( RevRegFile* R, const RevInst& Inst ) {
4127
XLEN old = 0;
4228

4329
// CSRRW with rd == zero does not read CSR
@@ -81,7 +67,7 @@ class Zicsr : public RevExt {
8167
// This calls the 32/64-bit ModCSR depending on the current XLEN
8268
template<OpKind OPKIND, CSROp OP>
8369
static bool ModCSR( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
84-
return R->IsRV32 ? ModCSRImpl<uint32_t, OPKIND, OP>( F, R, M, Inst ) : ModCSRImpl<uint64_t, OPKIND, OP>( F, R, M, Inst );
70+
return R->IsRV32 ? ModCSRImpl<uint32_t, OPKIND, OP>( R, Inst ) : ModCSRImpl<uint64_t, OPKIND, OP>( R, Inst );
8571
}
8672

8773
static constexpr auto& csrrw = ModCSR<OpKind::Reg, CSROp::Write>;
@@ -91,53 +77,6 @@ class Zicsr : public RevExt {
9177
static constexpr auto& csrrsi = ModCSR<OpKind::Imm, CSROp::Set>;
9278
static constexpr auto& csrrci = ModCSR<OpKind::Imm, CSROp::Clear>;
9379

94-
// Performance counters
95-
// TODO: These should be moved to a separate Zicntr extension, but right now the
96-
// spec is unclear on what order Zicntr should appear in an architecture string
97-
98-
// template is used to break circular dependencies and allow for an incomplete RevCore type now
99-
template<typename T, typename = std::enable_if_t<std::is_same_v<T, RevRegFile>>>
100-
static uint64_t rdcycleImpl( RevFeature* F, T* R, RevMem* M, const RevInst& Inst ) {
101-
return R->Core->GetCycles();
102-
}
103-
104-
template<typename T, typename = std::enable_if_t<std::is_same_v<T, RevRegFile>>>
105-
static uint64_t rdtimeImpl( RevFeature* F, T* R, RevMem* M, const RevInst& Inst ) {
106-
return R->Core->GetCurrentSimCycle();
107-
}
108-
109-
static uint64_t rdinstretImpl( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) { return R->GetInstRet(); }
110-
111-
enum Half { Lo, Hi };
112-
113-
/// Performance Counter template
114-
// Passed a function which gets the 64-bit value of a performance counter
115-
template<Half HALF, uint64_t COUNTER( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst )>
116-
static bool perfCounter( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst ) {
117-
if( R->IsRV32 ) {
118-
if constexpr( HALF == Lo ) {
119-
R->SetX( Inst.rd, static_cast<uint32_t>( COUNTER( F, R, M, Inst ) & 0xffffffff ) );
120-
} else {
121-
R->SetX( Inst.rd, static_cast<uint32_t>( COUNTER( F, R, M, Inst ) >> 32 ) );
122-
}
123-
} else {
124-
if constexpr( HALF == Lo ) {
125-
R->SetX( Inst.rd, COUNTER( F, R, M, Inst ) );
126-
} else {
127-
return false; // Hi half is not available on RV64
128-
}
129-
}
130-
R->AdvancePC( Inst );
131-
return true;
132-
}
133-
134-
static constexpr auto& rdcycle = perfCounter<Lo, rdcycleImpl>;
135-
static constexpr auto& rdcycleh = perfCounter<Hi, rdcycleImpl>;
136-
static constexpr auto& rdtime = perfCounter<Lo, rdtimeImpl>;
137-
static constexpr auto& rdtimeh = perfCounter<Hi, rdtimeImpl>;
138-
static constexpr auto& rdinstret = perfCounter<Lo, rdinstretImpl>;
139-
static constexpr auto& rdinstreth = perfCounter<Hi, rdinstretImpl>;
140-
14180
// ----------------------------------------------------------------------
14281
//
14382
// RISC-V CSR Instructions
@@ -178,12 +117,12 @@ class Zicsr : public RevExt {
178117
{ RevZicsrInstDefaults().SetMnemonic( "csrrci %rd, %csr, $imm" ).SetFunct3( 0b111 ).SetImplFunc( csrrci ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) != 0; } ) },
179118
{ RevZicsrInstDefaults().SetMnemonic( "csrci %csr, $imm" ).SetFunct3( 0b111 ).SetImplFunc( csrrci ).SetPredicate( []( uint32_t Inst ){ return DECODE_RD( Inst ) == 0; } ) },
180119

181-
{ RevZicsrInstDefaults().SetMnemonic( "rdcycle %rd" ).SetFunct3( 0b010 ).SetImplFunc( rdcycle ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc00; } ) },
182-
{ RevZicsrInstDefaults().SetMnemonic( "rdcycleh %rd" ).SetFunct3( 0b010 ).SetImplFunc( rdcycleh ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc80; } ) },
183-
{ RevZicsrInstDefaults().SetMnemonic( "rdtime %rd" ).SetFunct3( 0b010 ).SetImplFunc( rdtime ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc01; } ) },
184-
{ RevZicsrInstDefaults().SetMnemonic( "rdtimeh %rd" ).SetFunct3( 0b010 ).SetImplFunc( rdtimeh ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc81; } ) },
185-
{ RevZicsrInstDefaults().SetMnemonic( "rdinstret %rd" ).SetFunct3( 0b010 ).SetImplFunc( rdinstret ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc02; } ) },
186-
{ RevZicsrInstDefaults().SetMnemonic( "rdinstreth %rd" ).SetFunct3( 0b010 ).SetImplFunc( rdinstreth ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc82; } ) },
120+
{ RevZicsrInstDefaults().SetMnemonic( "rdcycle %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc00; } ) },
121+
{ RevZicsrInstDefaults().SetMnemonic( "rdcycleh %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc80; } ) },
122+
{ RevZicsrInstDefaults().SetMnemonic( "rdtime %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc01; } ) },
123+
{ RevZicsrInstDefaults().SetMnemonic( "rdtimeh %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc81; } ) },
124+
{ RevZicsrInstDefaults().SetMnemonic( "rdinstret %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc02; } ) },
125+
{ RevZicsrInstDefaults().SetMnemonic( "rdinstreth %rd" ).SetFunct3( 0b010 ).SetImplFunc( csrrs ).SetPredicate( []( uint32_t Inst ){ return DECODE_RS1( Inst ) == 0 && DECODE_IMM12( Inst ) == 0xc82; } ) },
187126
};
188127
// clang-format on
189128

0 commit comments

Comments
 (0)