Add mcycle / mcycleh to Kelvin sim PiperOrigin-RevId: 597650959
diff --git a/WORKSPACE b/WORKSPACE index 3e2833e..54b618f 100644 --- a/WORKSPACE +++ b/WORKSPACE
@@ -6,9 +6,9 @@ # MPACT-RiscV repo http_archive( name = "com_google_mpact-riscv", - sha256 = "2f51e0d90f6adf639fe6b23bee6dd86283326d86f8952e60cb26abeccc1e939b", - strip_prefix = "mpact-riscv-641f0748c6b17aa8789d455e82fb8f1296f79d26", - url = "https://github.com/google/mpact-riscv/archive/641f0748c6b17aa8789d455e82fb8f1296f79d26.tar.gz", + sha256 = "68c65bae71654ce59f3bd047af9083840b4b463aee7a17ba7d75c84322534347", + strip_prefix = "mpact-riscv-a4c534a97b107f3734e04c8e32d182e49d400ac3", + url = "https://github.com/google/mpact-riscv/archive/a4c534a97b107f3734e04c8e32d182e49d400ac3.tar.gz", ) # MPACT-Sim repo
diff --git a/sim/kelvin_state.cc b/sim/kelvin_state.cc index 62b92f2..0c82a23 100644 --- a/sim/kelvin_state.cc +++ b/sim/kelvin_state.cc
@@ -47,7 +47,9 @@ mpact::sim::util::MemoryInterface *memory, mpact::sim::util::AtomicMemoryOpInterface *atomic_memory) : mpact::sim::riscv::RiscVState(id, xlen, memory, atomic_memory), - kisa_("kisa", static_cast<RiscVCsrEnum>(KelvinCsrEnum::kKIsa), this) { + kisa_("kisa", static_cast<RiscVCsrEnum>(KelvinCsrEnum::kKIsa), this), + mcycle_("mcycle", RiscVCsrEnum::kMCycle, this), + mcycleh_("mcycleh", RiscVCsrEnum::kMCycleH, this) { set_vector_register_width(kVectorRegisterWidth); for (int i = 0; i < acc_register_.size(); ++i) { acc_register_[i].fill(0); @@ -62,6 +64,13 @@ } auto *misa = *result; misa->Set(kKelvinMisaVal); + + if (!csr_set()->AddCsr(&mcycle_).ok()) { + LOG(FATAL) << "Failed to register mcycle"; + } + if (!csr_set()->AddCsr(&mcycleh_).ok()) { + LOG(FATAL) << "Failed to register mcycleh"; + } } KelvinState::KelvinState(absl::string_view id, @@ -129,4 +138,11 @@ log_args_.clear(); } +void KelvinState::IncrementMCycle(uint64_t value) { + uint64_t new_cycle = + (mcycle_.GetUint64() | (mcycleh_.GetUint64() << 32)) + value; + mcycle_.Set(new_cycle & 0xFFFFFFFF); + mcycleh_.Set(new_cycle >> 32); +} + } // namespace kelvin::sim
diff --git a/sim/kelvin_state.h b/sim/kelvin_state.h index 5c66649..ffcfd84 100644 --- a/sim/kelvin_state.h +++ b/sim/kelvin_state.h
@@ -97,6 +97,8 @@ on_mpause_.emplace_back(std::move(handler)); } + void IncrementMCycle(uint64_t value); + private: uint32_t vector_length_{kVectorLengthInBits}; @@ -114,6 +116,10 @@ // Kelvin-specific CSR, contains information about the Kelvin ISA version. mpact::sim::riscv::RiscV32SimpleCsr kisa_; + + // mcycle/mcycleh CSR. + mpact::sim::riscv::RiscV32SimpleCsr mcycle_; + mpact::sim::riscv::RiscV32SimpleCsr mcycleh_; }; } // namespace kelvin::sim
diff --git a/sim/kelvin_top.cc b/sim/kelvin_top.cc index 26e2391..3b49bd2 100644 --- a/sim/kelvin_top.cc +++ b/sim/kelvin_top.cc
@@ -252,7 +252,7 @@ bool executed = false; do { executed = ExecuteInstruction(real_inst); - counter_num_cycles_.Increment(1); + IncrementCycleCount(1); state_->AdvanceDelayLines(); } while (!executed); // Increment counter. @@ -309,7 +309,7 @@ bool executed = false; do { executed = ExecuteInstruction(inst); - counter_num_cycles_.Increment(1); + IncrementCycleCount(1); state_->AdvanceDelayLines(); } while (!executed); count++; @@ -406,7 +406,7 @@ trace_entry->set_disasm(inst->AsString()); } } - counter_num_cycles_.Increment(1); + IncrementCycleCount(1); state_->AdvanceDelayLines(); } while (!executed); // Update counters. @@ -725,4 +725,9 @@ } } +void KelvinTop::IncrementCycleCount(uint64_t value) { + counter_num_cycles_.Increment(value); + state_->IncrementMCycle(value); +} + } // namespace kelvin::sim
diff --git a/sim/kelvin_top.h b/sim/kelvin_top.h index 1aa0637..5bab3d1 100644 --- a/sim/kelvin_top.h +++ b/sim/kelvin_top.h
@@ -121,6 +121,8 @@ absl::Status StepPastBreakpoint(); // Set the pc value. void SetPc(uint64_t value); + // Increment the cycle count. + void IncrementCycleCount(uint64_t value); // The DB factory is used to manage data buffers for memory read/writes. mpact::sim::generic::DataBufferFactory db_factory_;
diff --git a/sim/test/BUILD b/sim/test/BUILD index a965726..b634ef2 100644 --- a/sim/test/BUILD +++ b/sim/test/BUILD
@@ -20,6 +20,7 @@ "testfiles/hello_world_mpause.elf", "testfiles/hello_world_rv32imf.elf", "testfiles/kelvin_ebreak.elf", + "testfiles/kelvin_perf_counters.elf", "testfiles/kelvin_vldvst.elf", "testfiles/rv32i.elf", "testfiles/rv32m.elf", @@ -80,6 +81,7 @@ "testfiles/hello_world_mpause.elf", "testfiles/hello_world_rv32imf.elf", "testfiles/kelvin_ebreak.elf", + "testfiles/kelvin_perf_counters.elf", "testfiles/kelvin_vldvst.elf", "testfiles/rv32i.elf", "testfiles/rv32m.elf",
diff --git a/sim/test/kelvin_top_test.cc b/sim/test/kelvin_top_test.cc index b4883d7..3d9a956 100644 --- a/sim/test/kelvin_top_test.cc +++ b/sim/test/kelvin_top_test.cc
@@ -51,6 +51,7 @@ constexpr char kRV32SoftFloatElfFileName[] = "rv32soft_fp.elf"; constexpr char kRV32fElfFileName[] = "rv32uf_fadd.elf"; constexpr char kKelvinVldVstFileName[] = "kelvin_vldvst.elf"; +constexpr char kKelvinPerfCountersFileName[] = "kelvin_perf_counters.elf"; // The depot path to the test directory. constexpr char kDepotPath[] = "sim/test/"; @@ -474,6 +475,17 @@ EXPECT_THAT(stdout_str, testing::HasSubstr("vld_vst test passed!")); } +TEST_F(KelvinTopTest, RunKelvinPerfCountersProgram) { + LoadFile(kKelvinPerfCountersFileName); + EXPECT_OK(kelvin_top_->WriteRegister("pc", entry_point_)); + EXPECT_OK(kelvin_top_->Run()); + EXPECT_OK(kelvin_top_->Wait()); + auto halt_result = kelvin_top_->GetLastHaltReason(); + CHECK_OK(halt_result); + EXPECT_EQ(static_cast<int>(halt_result.value()), + static_cast<int>(HaltReason::kUserRequest)); +} + constexpr int kMemoryBlockSize = 256 * 1024; // 256KB // Default max memory address is 4MB - 1. Round up to find the number of memory // blocks.
diff --git a/sim/test/testfiles/kelvin_perf_counters.elf b/sim/test/testfiles/kelvin_perf_counters.elf new file mode 100755 index 0000000..6037860 --- /dev/null +++ b/sim/test/testfiles/kelvin_perf_counters.elf Binary files differ