blob: 8badee86a785ba238da9bb012b632b13a735c22b [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/register.h"
#include <cstdint>
#include <memory>
#include "absl/memory/memory.h"
#include "googlemock/include/gmock/gmock.h"
#include "googletest/include/gtest/gtest.h"
#include "mpact/sim/generic/simple_resource.h"
namespace mpact {
namespace sim {
namespace generic {
namespace {
constexpr int kVectorLength = 8;
constexpr int kMatrixRows = 8;
constexpr int kMatrixCols = 16;
static constexpr char kTestPoolName[] = "TestPool";
static constexpr int kTestPoolSize = 35;
using testing::StrEq;
using ScalarRegister = Register<uint32_t>;
using Vector8Register = VectorRegister<uint32_t, kVectorLength>;
using Matrix8By16Register = MatrixRegister<uint32_t, kMatrixRows, kMatrixCols>;
using ScalarReservedRegister = ReservedRegister<uint32_t>;
// Test fixture that instantiates the factory class for DataBuffers.
class RegisterTest : public testing::Test {
protected:
RegisterTest() {
db_factory_ = new DataBufferFactory();
pool_ = new SimpleResourcePool(kTestPoolName, kTestPoolSize);
}
~RegisterTest() override {
delete db_factory_;
delete pool_;
}
DataBufferFactory *db_factory_;
SimpleResourcePool *pool_;
};
// Create scalar register and verify attributes.
TEST_F(RegisterTest, ScalarCreate) {
auto scalar_reg = std::make_unique<ScalarRegister>(nullptr, "R0");
EXPECT_THAT(scalar_reg->name(), StrEq("R0"));
EXPECT_EQ(scalar_reg->shape().size(), 1);
EXPECT_EQ(scalar_reg->size(), sizeof(uint32_t));
}
// Create vector register and verify attributes.
TEST_F(RegisterTest, VectorCreate) {
auto vector_reg = std::make_unique<Vector8Register>(nullptr, "V0");
EXPECT_THAT(vector_reg->name(), StrEq("V0"));
EXPECT_EQ(vector_reg->shape()[0], kVectorLength);
EXPECT_EQ(vector_reg->size(), kVectorLength * sizeof(uint32_t));
}
// Create matrix register and verify attirbutes.
TEST_F(RegisterTest, MatrixCreate) {
auto matrix_reg = std::make_unique<Matrix8By16Register>(nullptr, "M0");
EXPECT_THAT(matrix_reg->name(), StrEq("M0"));
EXPECT_EQ(matrix_reg->shape()[0], kMatrixRows);
EXPECT_EQ(matrix_reg->shape()[1], kMatrixCols);
EXPECT_EQ(matrix_reg->size(), kMatrixRows * kMatrixCols * sizeof(uint32_t));
}
// Create reserved register and verify that it releases the resource when
// SetDataBuffer is called.
TEST_F(RegisterTest, ScalarReservedCreate) {
ASSERT_TRUE(pool_->AddResource("S0").ok());
auto scalar_reserved_reg = std::make_unique<ScalarReservedRegister>(
nullptr, "S0", pool_->GetResource("S0"));
pool_->GetResource("S0")->Acquire();
EXPECT_FALSE(pool_->GetResource("S0")->IsFree());
auto *db = db_factory_->Allocate(scalar_reserved_reg->size());
scalar_reserved_reg->SetDataBuffer(db);
EXPECT_TRUE(pool_->GetResource("S0")->IsFree());
db->DecRef();
}
// Verify scalar databuffer api.
TEST_F(RegisterTest, ScalarDataBuffer) {
// Allocate register and make sure data_buffer is nullptr.
auto scalar_reg = std::make_unique<ScalarRegister>(nullptr, "R0");
EXPECT_EQ(scalar_reg->data_buffer(), nullptr);
// Allocate a data buffer of the right byte size and bind it to the register.
DataBuffer *db = db_factory_->Allocate(scalar_reg->size());
scalar_reg->SetDataBuffer(db);
// Verify reference count is 2, then DecRef.
EXPECT_EQ(db->ref_count(), 2);
db->DecRef();
EXPECT_EQ(scalar_reg->data_buffer(), db);
}
// Verify vector databuffer api.
TEST_F(RegisterTest, VectorDataBuffer) {
// Allocate register and make sure data_buffer is nullptr.
auto vector_reg = std::make_unique<Vector8Register>(nullptr, "V0");
EXPECT_EQ(vector_reg->data_buffer(), nullptr);
// Allocate a data buffer of the right byte size and bind it to the register.
DataBuffer *db = db_factory_->Allocate(vector_reg->size());
vector_reg->SetDataBuffer(db);
// Verify reference count is 2, then DecRef.
EXPECT_EQ(db->ref_count(), 2);
db->DecRef();
EXPECT_EQ(vector_reg->data_buffer(), db);
}
// Verify matrix databuffer api.
TEST_F(RegisterTest, MatrixDataBuffer) {
// Allocate register and make sure data_buffer is nullptr.
auto matrix_reg = std::make_unique<Matrix8By16Register>(nullptr, "M0");
EXPECT_EQ(matrix_reg->data_buffer(), nullptr);
// Allocate a data buffer of the right byte size and bind it to the register.
DataBuffer *db = db_factory_->Allocate(matrix_reg->size());
matrix_reg->SetDataBuffer(db);
// Verify reference count is 2, then DecRef.
EXPECT_EQ(db->ref_count(), 2);
db->DecRef();
EXPECT_EQ(matrix_reg->data_buffer(), db);
}
} // namespace
} // namespace generic
} // namespace sim
} // namespace mpact