blob: 0dc6dc4eb911aaaea6a2602b6f352b195b6377ce [file]
#include "riscv/riscv_counter_csr.h"
#include <cstdint>
#include <limits>
#include "googlemock/include/gmock/gmock.h"
#include "mpact/sim/generic/counters.h"
#include "riscv/riscv_csr.h"
#include "riscv/riscv_state.h"
// This file contains unit tests for counter_csr classes used to implement
// mcycle/mcycleh and minstret/minstreth.
namespace {
using ::mpact::sim::generic::SimpleCounter;
using ::mpact::sim::riscv::RiscVCounterCsr;
using ::mpact::sim::riscv::RiscVCounterCsrHigh;
using ::mpact::sim::riscv::RiscVCsrEnum;
using ::mpact::sim::riscv::RiscVState;
class RiscVMCycleTest : public ::testing::Test {
protected:
RiscVMCycleTest() : counter_("cycles", 0) {};
~RiscVMCycleTest() override = default;
SimpleCounter<uint64_t> counter_;
};
// Verify the operation of 64 bit mcycle with counter increments.
TEST_F(RiscVMCycleTest, GetTest64) {
RiscVCounterCsr<uint64_t, RiscVState> mcycle("mcycle", RiscVCsrEnum::kMCycle,
nullptr);
mcycle.set_counter(&counter_);
// Initial value should be zero.
EXPECT_EQ(mcycle.GetUint32(), 0);
EXPECT_EQ(mcycle.GetUint64(), 0);
counter_.Increment(1);
EXPECT_EQ(mcycle.GetUint32(), 1);
EXPECT_EQ(mcycle.GetUint64(), 1);
mcycle.Write(100u);
EXPECT_EQ(mcycle.GetUint32(), 100);
EXPECT_EQ(mcycle.GetUint64(), 100);
mcycle.Set(static_cast<uint64_t>(1000));
EXPECT_EQ(mcycle.GetUint32(), 1000);
EXPECT_EQ(mcycle.GetUint64(), 1000);
}
// Verify the operation of 32 bit mcycle and mcycleh with counter increments.
TEST_F(RiscVMCycleTest, GetTest32) {
RiscVCounterCsr<uint32_t, RiscVState> mcycle("mcycle", RiscVCsrEnum::kMCycle,
nullptr);
RiscVCounterCsrHigh<RiscVState> mcycleh("mcycleh", RiscVCsrEnum::kMCycleH,
nullptr, &mcycle);
mcycle.set_counter(&counter_);
mcycleh.set_counter(&counter_);
// Initial value should be zero.
EXPECT_EQ(mcycle.GetUint32(), 0);
EXPECT_EQ(mcycle.GetUint64(), 0);
EXPECT_EQ(mcycleh.GetUint32(), 0);
EXPECT_EQ(mcycleh.GetUint64(), 0);
counter_.Increment(1);
// Only low 32 bits should be set.
EXPECT_EQ(mcycle.GetUint32(), 1);
EXPECT_EQ(mcycle.GetUint64(), 1);
EXPECT_EQ(mcycleh.GetUint32(), 0);
EXPECT_EQ(mcycleh.GetUint64(), 0);
// Increment counter by uint32_t max.
counter_.Increment(std::numeric_limits<uint32_t>::max());
// Counters should have wrapped around.
EXPECT_EQ(mcycle.GetUint32(), 0);
EXPECT_EQ(mcycle.GetUint64(), 0);
EXPECT_EQ(mcycleh.GetUint32(), 1);
EXPECT_EQ(mcycleh.GetUint64(), 1);
// Increment counter by 1 again.
counter_.Increment(1);
EXPECT_EQ(mcycle.GetUint32(), 1);
EXPECT_EQ(mcycle.GetUint64(), 1);
EXPECT_EQ(mcycleh.GetUint32(), 1);
EXPECT_EQ(mcycleh.GetUint64(), 1);
}
// Test that write to mcycle is reflected in the value of mcycle.
TEST_F(RiscVMCycleTest, SetTest64) {
RiscVCounterCsr<uint64_t, RiscVState> mcycle("mcycle", RiscVCsrEnum::kMCycle,
nullptr);
mcycle.set_counter(&counter_);
EXPECT_EQ(mcycle.GetUint32(), 0);
EXPECT_EQ(mcycle.GetUint64(), 0);
mcycle.Write(100u);
EXPECT_EQ(mcycle.GetUint32(), 100);
EXPECT_EQ(mcycle.GetUint64(), 100);
counter_.Increment(10);
EXPECT_EQ(mcycle.GetUint32(), 110);
EXPECT_EQ(mcycle.GetUint64(), 110);
}
// Test that write to mcycle and mcycleh is reflected in the value of mcycle and
// mcycleh.
TEST_F(RiscVMCycleTest, SetTest32) {
RiscVCounterCsr<uint32_t, RiscVState> mcycle("mcycle", RiscVCsrEnum::kMCycle,
nullptr);
RiscVCounterCsrHigh<RiscVState> mcycleh("mcycleh", RiscVCsrEnum::kMCycleH,
nullptr, &mcycle);
mcycle.set_counter(&counter_);
mcycleh.set_counter(&counter_);
EXPECT_EQ(mcycle.GetUint32(), 0);
EXPECT_EQ(mcycle.GetUint64(), 0);
EXPECT_EQ(mcycleh.GetUint32(), 0);
EXPECT_EQ(mcycleh.GetUint64(), 0);
mcycle.Write(100u);
mcycleh.Write(200u);
EXPECT_EQ(mcycle.GetUint32(), 100);
EXPECT_EQ(mcycle.GetUint64(), 100);
EXPECT_EQ(mcycleh.GetUint32(), 200);
EXPECT_EQ(mcycleh.GetUint64(), 200);
counter_.Increment(10);
EXPECT_EQ(mcycle.GetUint32(), 110);
EXPECT_EQ(mcycle.GetUint64(), 110);
EXPECT_EQ(mcycleh.GetUint32(), 200);
EXPECT_EQ(mcycleh.GetUint64(), 200);
counter_.Increment(std::numeric_limits<uint32_t>::max());
EXPECT_EQ(mcycle.GetUint32(), 109);
EXPECT_EQ(mcycle.GetUint64(), 109);
EXPECT_EQ(mcycleh.GetUint32(), 201);
EXPECT_EQ(mcycleh.GetUint64(), 201);
}
} // namespace