blob: 6e53b82f2f631fa885351e1b6bd4bd3766d793db [file]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "mpact/sim/generic/status_register.h"
#include "googlemock/include/gmock/gmock.h"
#include "googletest/include/gtest/gtest.h"
namespace {
using ::mpact::sim::generic::StatusRegister;
using ::mpact::sim::generic::StatusRegisterSourceOperand;
// Using bit number 3 as the bit that's testing in the evaluation functions
// below.
constexpr int kBitNum = 3;
constexpr int kBitValue = 1 << kBitNum;
class StatusRegisterTest : public testing::Test {
protected:
StatusRegisterTest() {
// Create 4 different status registers and their source operands.
status_8_ = new StatusRegister<uint8_t>(nullptr, "status8");
status_16_ = new StatusRegister<uint16_t>(nullptr, "status16");
status_32_ = new StatusRegister<uint32_t>(nullptr, "status32");
status_64_ = new StatusRegister<uint64_t>(nullptr, "status64");
src_op_8_ = new StatusRegisterSourceOperand(status_8_);
src_op_16_ = new StatusRegisterSourceOperand(status_16_);
src_op_32_ = new StatusRegisterSourceOperand(status_32_);
src_op_64_ = new StatusRegisterSourceOperand(status_64_);
}
~StatusRegisterTest() override {
// Cleanup.
delete status_8_;
delete status_16_;
delete status_32_;
delete status_64_;
delete src_op_8_;
delete src_op_16_;
delete src_op_32_;
delete src_op_64_;
}
StatusRegister<uint8_t> *status_8_;
StatusRegister<uint16_t> *status_16_;
StatusRegister<uint32_t> *status_32_;
StatusRegister<uint64_t> *status_64_;
StatusRegisterSourceOperand<uint8_t> *src_op_8_;
StatusRegisterSourceOperand<uint16_t> *src_op_16_;
StatusRegisterSourceOperand<uint32_t> *src_op_32_;
StatusRegisterSourceOperand<uint64_t> *src_op_64_;
};
// Test that initial values are all 0.
TEST_F(StatusRegisterTest, Initial) {
uint8_t value8 = status_8_->Read();
EXPECT_EQ(value8, 0);
uint16_t value16 = status_16_->Read();
EXPECT_EQ(value16, 0);
uint32_t value32 = status_32_->Read();
EXPECT_EQ(value32, 0);
uint64_t value64 = status_64_->Read();
EXPECT_EQ(value64, 0);
}
// Verify that the read function returns the correct value when the function
// evaluates to true.
TEST_F(StatusRegisterTest, Read) {
int value = 0;
status_8_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_16_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_32_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_64_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
EXPECT_EQ(status_8_->Read(), 0);
EXPECT_EQ(status_16_->Read(), 0);
EXPECT_EQ(status_32_->Read(), 0);
EXPECT_EQ(status_64_->Read(), 0);
value = 1;
EXPECT_EQ(status_8_->Read(), kBitValue);
EXPECT_EQ(status_16_->Read(), kBitValue);
EXPECT_EQ(status_32_->Read(), kBitValue);
EXPECT_EQ(status_64_->Read(), kBitValue);
}
// Verify that the value for the 4th bit (index 3), is only returned if that
// bit is set in the bitmask.
TEST_F(StatusRegisterTest, ReadMask) {
int value = 1;
status_8_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_16_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_32_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_64_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
EXPECT_EQ(status_8_->Read(0x0), 0);
EXPECT_EQ(status_16_->Read(0x0), 0);
EXPECT_EQ(status_32_->Read(0x0), 0);
EXPECT_EQ(status_64_->Read(0x0), 0);
value = 1;
EXPECT_EQ(status_8_->Read(0xff), kBitValue);
EXPECT_EQ(status_16_->Read(0xffff), kBitValue);
EXPECT_EQ(status_32_->Read(0xffff'ffff), kBitValue);
EXPECT_EQ(status_64_->Read(0xffff'ffff'ffff'ffff), kBitValue);
EXPECT_EQ(status_8_->Read(0b1000), kBitValue);
EXPECT_EQ(status_16_->Read(0b1000), kBitValue);
EXPECT_EQ(status_32_->Read(0b1000), kBitValue);
EXPECT_EQ(status_64_->Read(0b1000), kBitValue);
}
// Double check that the source operands work as expected.
TEST_F(StatusRegisterTest, SourceOperand) {
EXPECT_EQ(src_op_8_->AsUint16(0), 0);
EXPECT_EQ(src_op_16_->AsUint16(0), 0);
EXPECT_EQ(src_op_32_->AsUint16(0), 0);
EXPECT_EQ(src_op_64_->AsUint16(0), 0);
int value = 1;
status_8_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_16_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_32_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
status_64_->SetEvaluateFunction(kBitNum, [&value]() { return value != 0; });
EXPECT_EQ(src_op_8_->AsUint32(0), kBitValue);
EXPECT_EQ(src_op_16_->AsUint32(0), kBitValue);
EXPECT_EQ(src_op_32_->AsUint32(0), kBitValue);
EXPECT_EQ(src_op_64_->AsUint32(0), kBitValue);
}
} // namespace