-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[vanadis] Implement the missing Zicntr instructions.
Chapter 8 in https://github.com/riscv/riscv-isa-manual/releases/download/riscv-isa-release-f797123-2024-06-27/riscv-unprivileged.pdf details the RISC-V counter interface. There are 3 bespoke counters detailed in the Zicntr extensions in 8.1, and up to 29 more user-programmable counters detailed in the Zihpm extenstion in 8.2. This commit provides space for all 32 counters in the register file, but only currently implements the three Zicntr counters. The implementation consists of a few changes. 1. I have extended the register file structure with 32, 64 bit counters, and `increment` and `get` members in order to update and read those counters. 2. I have added a new instruction, `Zicntr::VanadisReadCounterInstruction` in order to read those counters. This instruction can be tailored for any of the 3 `Zicntr`s (implemented as tag types in `inst/zicntr.h`), XLEN=64 or 32, and with or without the `[H]` extension. 3. I have added decoding to `decoder/vriscv64decoder.h` to handle `RDCYCLE`, `RDTIME`, and `RDINSTRET`. Because the `[H]` and XLEN=32 versions are only available in `riscv32`, the `riscv64` decoder simply injects a decoding failure if those occur. 4. I have extended the core's `tick` to update the three `Zicntr`s. 5. I have added a small misc test example to demonstrate usage. I have not implemented any functionality for programming the 29 `Zihpm` counters, nor have I added any special decoding to read these registers. I have decided that the `Zicntr` instructions will be processed by the arithmetic functional unit. I don't know if this is appropriate, but it should manage any register port contention properly and seemed like the most expedient solution. I have removed the `cycle_count` and the `getCycleCount` from the decoder base class, as it is no longer being used. The current cycle is still passed to the decoder `tick()` even though it is _also_ still unused.
- Loading branch information
Showing
12 changed files
with
192 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
|
||
#ifndef _H_VANADIS_ZICNTR | ||
#define _H_VANADIS_ZICNTR | ||
|
||
#include <utility> | ||
|
||
namespace SST::Vanadis | ||
{ | ||
// Tags to be used to with the regfile and VanadisReadCounterInstruction | ||
namespace Zicntr { | ||
inline constexpr std::integral_constant<uint32_t, 0> CYCLE; | ||
inline constexpr std::integral_constant<uint32_t, 1> TIME; | ||
inline constexpr std::integral_constant<uint32_t, 2> INSTRET; | ||
} | ||
} // namespace Vanadis::SST | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
|
||
#ifndef _H_VANADIS_ZICNTR_READ_COUNTER | ||
#define _H_VANADIS_ZICNTR_READ_COUNTER | ||
|
||
#include "inst/vinst.h" | ||
#include "inst/vzicntr.h" | ||
|
||
namespace SST::Vanadis | ||
{ | ||
namespace Zicntr | ||
{ | ||
template <uint32_t id, size_t XLEN = 64, bool H = false> | ||
class VanadisReadCounterInstruction : public VanadisInstruction | ||
{ | ||
static_assert( id < 3 ); | ||
static_assert( XLEN == 64 or XLEN == 32 ); | ||
static_assert( XLEN != 64 or H == false ); | ||
|
||
public: | ||
VanadisReadCounterInstruction( | ||
const std::integral_constant<uint32_t, id>, | ||
const uint64_t addr, | ||
const uint32_t hw_thr, | ||
const VanadisDecoderOptions* isa_opts, | ||
const uint16_t dest) | ||
: VanadisInstruction(addr, hw_thr, isa_opts, 0, 1, 0, 1, 0, 0, 0, 0) | ||
{ | ||
isa_int_regs_out[0] = dest; | ||
} | ||
|
||
VanadisReadCounterInstruction* clone() override | ||
{ | ||
return new VanadisReadCounterInstruction(*this); | ||
} | ||
|
||
VanadisFunctionalUnitType getInstFuncType() const override | ||
{ | ||
return INST_INT_ARITH; // Is this appropriate? | ||
} | ||
|
||
const char* getInstCode() const override | ||
{ | ||
switch ( id ) { | ||
case Zicntr::CYCLE: return H ? "RDCYCLEH" : "RDCYCLE"; | ||
case Zicntr::TIME: return H ? "RDTIMEH" : "RDTIME"; | ||
case Zicntr::INSTRET: return H ? "RDINSTRETH" : "RDINSTRET"; | ||
} | ||
__builtin_unreachable(); | ||
} | ||
|
||
void printToBuffer(char* const buffer, const size_t buffer_size) override | ||
{ | ||
snprintf( | ||
buffer, buffer_size, | ||
"%s %5" PRIu16 " (phys: %5" PRIu16 ")", | ||
getInstCode(), isa_int_regs_out[0], phys_int_regs_out[0]); | ||
} | ||
|
||
void execute(SST::Output* const output, VanadisRegisterFile* const regFile) override | ||
{ | ||
#ifdef VANADIS_BUILD_DEBUG | ||
if(output->getVerboseLevel() >= 16) { | ||
output->verbose( | ||
CALL_INFO, 16, 0, | ||
"Execute: 0x%" PRI_ADDR " %s phys: out=%" PRIu16 ", isa: out=%" PRIu16 "\n", | ||
getInstructionAddress(), getInstCode(), phys_int_regs_out[0], isa_int_regs_out[0]); | ||
} | ||
#endif | ||
|
||
static constexpr uint64_t mask = 0x00000000'FFFFFFFF; | ||
const uint64_t count64 = regFile->getCounter(id); | ||
const uint32_t count32 = count64 & mask; | ||
const uint32_t count32H = count64 >> 32; | ||
|
||
if constexpr ( XLEN == 64 ) { | ||
regFile->setIntReg(phys_int_regs_out[0], count64); | ||
} | ||
else if constexpr ( XLEN == 32 and H ) { | ||
regFile->setIntReg(phys_int_regs_out[0], count32H); | ||
} | ||
else { | ||
regFile->setIntReg(phys_int_regs_out[0], count32); | ||
} | ||
|
||
markExecuted(); | ||
} | ||
}; | ||
} // namespace Zicntr | ||
} // namespace Vanadis::SST | ||
|
||
#endif |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,6 +55,7 @@ | |
#exe = "uname" | ||
#exe = "mem-test" | ||
#exe = "checkpoint" | ||
#exe = "zicntr" | ||
|
||
physMemSize = "4GiB" | ||
|
||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#include <inttypes.h> | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
|
||
uint64_t read_cycles() { | ||
uint64_t cycles; | ||
asm volatile ("rdcycle %0" : "=r" (cycles)); | ||
return cycles; | ||
} | ||
|
||
uint64_t read_time() { | ||
uint64_t time; | ||
asm volatile ("rdtime %0" : "=r" (time)); | ||
return time; | ||
} | ||
|
||
uint64_t read_instructions() { | ||
uint64_t instructions; | ||
asm volatile ("rdinstret %0" : "=r" (instructions)); | ||
return instructions; | ||
} | ||
|
||
int main() | ||
{ | ||
uint64_t cycles = read_cycles(); | ||
uint64_t time = read_time(); | ||
uint64_t instructions = read_instructions(); | ||
printf("cycles: %" PRIu64 " time: %" PRIu64 " instructions: %" PRIu64 "\n", cycles, time, instructions); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters