blob: 5c927739dfecc7855de1fdc659ae53e64bd69df9 [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/literal_operand.h"
#include <memory>
#include "absl/memory/memory.h"
#include "googlemock/include/gmock/gmock.h"
#include "googletest/include/gtest/gtest.h"
namespace {
using ::mpact::sim::generic::BoolLiteralOperand;
using ::mpact::sim::generic::BoolLiteralPredicateOperand;
using ::mpact::sim::generic::IntLiteralOperand;
// Test BoolLiteralPredicateOperand<true>.
TEST(LiteralOperandTest, TrueBoolPredicateLiteral) {
BoolLiteralPredicateOperand<true> pred;
EXPECT_TRUE(pred.Value());
}
// Test BoolLiteralPredciateOperand<false>.
TEST(LiteralOperandTest, FalseBoolPredicateLiteral) {
BoolLiteralPredicateOperand<false> pred;
EXPECT_FALSE(pred.Value());
}
// Test BoolLiteralOperand<true> created from the default constructor.
TEST(LiteralOperandTest, TrueBoolLiteral) {
auto operand = std::make_unique<BoolLiteralOperand<true>>();
EXPECT_EQ(operand->shape().size(), 0);
EXPECT_EQ(operand->GetObject().has_value(), false);
EXPECT_EQ(operand->AsBool(0), true);
EXPECT_EQ(operand->AsInt8(0), 1);
EXPECT_EQ(operand->AsUint8(0), 1);
EXPECT_EQ(operand->AsInt16(0), 1);
EXPECT_EQ(operand->AsUint16(0), 1);
EXPECT_EQ(operand->AsInt32(0), 1);
EXPECT_EQ(operand->AsUint32(0), 1);
EXPECT_EQ(operand->AsInt64(0), 1);
EXPECT_EQ(operand->AsUint64(0), 1);
}
// Test BoolLiteralOperand<false> created from the simple constructor.
TEST(LiteralOperandTest, FalseBoolLiteral) {
auto operand = std::make_unique<BoolLiteralOperand<false>>();
EXPECT_EQ(operand->shape().size(), 0);
EXPECT_EQ(operand->GetObject().has_value(), false);
EXPECT_EQ(operand->AsBool(0), false);
EXPECT_EQ(operand->AsInt8(0), 0);
EXPECT_EQ(operand->AsUint8(0), 0);
EXPECT_EQ(operand->AsInt16(0), 0);
EXPECT_EQ(operand->AsUint16(0), 0);
EXPECT_EQ(operand->AsInt32(0), 0);
EXPECT_EQ(operand->AsUint32(0), 0);
EXPECT_EQ(operand->AsInt64(0), 0);
EXPECT_EQ(operand->AsUint64(0), 0);
}
// Test a "vector" immediate where shape is also given.
TEST(LiteralOperandTest, VectorBoolLiteral) {
auto operand =
std::make_unique<BoolLiteralOperand<true>>(std::vector<int>{128});
EXPECT_EQ(operand->shape().size(), 1);
EXPECT_THAT(operand->shape(), testing::ElementsAre(128));
EXPECT_EQ(operand->GetObject().has_value(), false);
for (int index = 0; index < 128; index += 16) {
EXPECT_EQ(operand->AsBool(index), true);
EXPECT_EQ(operand->AsInt8(index), 1);
EXPECT_EQ(operand->AsUint8(index), 1);
EXPECT_EQ(operand->AsInt16(index), 1);
EXPECT_EQ(operand->AsUint16(index), 1);
EXPECT_EQ(operand->AsInt32(index), 1);
EXPECT_EQ(operand->AsUint32(index), 1);
EXPECT_EQ(operand->AsInt64(index), 1);
EXPECT_EQ(operand->AsUint64(index), 1);
}
}
// Test LiteralOperand created from the simple constructor (scalar).
TEST(LiteralOperandTest, IntLiteral) {
auto operand = std::make_unique<IntLiteralOperand<-123>>();
EXPECT_EQ(operand->shape().size(), 0);
EXPECT_EQ(operand->GetObject().has_value(), false);
EXPECT_EQ(operand->AsBool(0), true);
EXPECT_EQ(operand->AsInt8(0), -123);
EXPECT_EQ(operand->AsUint8(0), 133); // 2^8 - 123
EXPECT_EQ(operand->AsInt16(0), -123);
EXPECT_EQ(operand->AsUint16(0), 65413); // 2^16 - 123
EXPECT_EQ(operand->AsInt32(0), -123);
EXPECT_EQ(operand->AsUint32(0), 4294967173); // 2^32 - 123
EXPECT_EQ(operand->AsInt64(0), -123);
EXPECT_EQ(operand->AsUint64(0), 18446744073709551493U); // 2^64 - 123
}
// Test that it always returns the same value even if index is outside
// that expected by the shape.
TEST(LiteralOperandTest, IntLiteralNonZeroIndex) {
auto operand = std::make_unique<IntLiteralOperand<123>>();
// The index doesn't matter.
EXPECT_EQ(operand->AsBool(4), true);
EXPECT_EQ(operand->AsInt8(4), 123);
EXPECT_EQ(operand->AsUint8(4), 123);
EXPECT_EQ(operand->AsInt16(4), 123);
EXPECT_EQ(operand->AsUint16(4), 123);
EXPECT_EQ(operand->AsInt32(4), 123);
EXPECT_EQ(operand->AsUint32(4), 123);
EXPECT_EQ(operand->AsInt64(4), 123);
EXPECT_EQ(operand->AsUint64(4), 123);
}
// Test a "vector" literal where shape is also given.
TEST(LiteralOperandTest, VectorLiteral) {
auto operand =
std::make_unique<IntLiteralOperand<123>>(std::vector<int>{128});
EXPECT_EQ(operand->shape().size(), 1);
EXPECT_THAT(operand->shape(), testing::ElementsAre(128));
EXPECT_EQ(operand->GetObject().has_value(), false);
for (int index = 0; index < 128; index += 16) {
EXPECT_EQ(operand->AsBool(index), true);
EXPECT_EQ(operand->AsInt8(index), 123);
EXPECT_EQ(operand->AsUint8(index), 123);
EXPECT_EQ(operand->AsInt16(index), 123);
EXPECT_EQ(operand->AsUint16(index), 123);
EXPECT_EQ(operand->AsInt32(index), 123);
EXPECT_EQ(operand->AsUint32(index), 123);
EXPECT_EQ(operand->AsInt64(index), 123);
EXPECT_EQ(operand->AsUint64(index), 123);
}
}
} // namespace