| // 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/decoder/format.h" |
| |
| #include "absl/status/status.h" |
| #include "googlemock/include/gmock/gmock.h" // IWYU pragma: keep |
| #include "googletest/include/gtest/gtest.h" |
| #include "mpact/sim/decoder/bin_encoding_info.h" |
| #include "mpact/sim/decoder/decoder_error_listener.h" |
| #include "mpact/sim/decoder/overlay.h" |
| |
| namespace { |
| |
| using ::mpact::sim::decoder::DecoderErrorListener; |
| using ::mpact::sim::decoder::bin_format::BinEncodingInfo; |
| using ::mpact::sim::decoder::bin_format::Format; |
| |
| /* The test format is defined as: |
| * |
| * fields: |
| * unsigned func3[3]; |
| * unsigned imm3[3]; |
| * unsigned rs1p[3]; |
| * unsigned imm2[2]; |
| * unsigned rdp[3]; |
| * unsigned op[2]; |
| * overlays: |
| * unsigned imm_w[7] = imm2[0], imm3, imm2[1], 0b00; |
| */ |
| |
| class FormatTest : public testing::Test { |
| protected: |
| FormatTest() { |
| error_listener_ = new DecoderErrorListener(); |
| encoding_info_ = new BinEncodingInfo("OpcodeEnum", error_listener_); |
| } |
| |
| ~FormatTest() override { |
| delete error_listener_; |
| delete encoding_info_; |
| } |
| |
| DecoderErrorListener* error_listener_; |
| BinEncodingInfo* encoding_info_; |
| }; |
| |
| TEST_F(FormatTest, Constructor) { |
| auto* format = new Format("format_name", 16, encoding_info_); |
| EXPECT_EQ(format->name(), "format_name"); |
| EXPECT_EQ(format->declared_width(), 16); |
| EXPECT_EQ(format->computed_width(), 0); |
| EXPECT_EQ(format->ComputeAndCheckFormatWidth().code(), |
| absl::StatusCode::kInternal); |
| EXPECT_EQ(format->encoding_info(), encoding_info_); |
| delete format; |
| |
| format = new Format("derived_format", 16, "base_format", encoding_info_); |
| EXPECT_EQ(format->name(), "derived_format"); |
| EXPECT_EQ(format->declared_width(), 16); |
| EXPECT_EQ(format->computed_width(), 0); |
| EXPECT_EQ(format->ComputeAndCheckFormatWidth().code(), |
| absl::StatusCode::kInternal); |
| EXPECT_EQ(format->encoding_info(), encoding_info_); |
| delete format; |
| } |
| |
| TEST_F(FormatTest, AddFields) { |
| auto* format = new Format("format", 16, encoding_info_); |
| ASSERT_TRUE(format->AddField("func3", /*is_signed=*/false, 3).ok()); |
| ASSERT_TRUE(format->AddField("imm3", /*is_signed=*/false, 3).ok()); |
| ASSERT_TRUE(format->AddField("rs1p", /*is_signed=*/false, 3).ok()); |
| ASSERT_TRUE(format->AddField("imm2", /*is_signed=*/false, 2).ok()); |
| ASSERT_TRUE(format->AddField("rdp", /*is_signed=*/false, 3).ok()); |
| ASSERT_TRUE(format->AddField("op", /*is_signed=*/false, 2).ok()); |
| ASSERT_TRUE(format->ComputeAndCheckFormatWidth().ok()); |
| EXPECT_EQ(format->declared_width(), format->computed_width()); |
| for (auto& name : {"func3", "imm3", "rs1p", "imm2", "rdp", "op"}) { |
| auto* field = format->GetField(name); |
| ASSERT_NE(field, nullptr); |
| EXPECT_EQ(field->name, name); |
| } |
| EXPECT_EQ(format->GetField("NotAField"), nullptr); |
| delete format; |
| } |
| |
| TEST_F(FormatTest, AddOverlay) { |
| auto* format = new Format("format", 16, encoding_info_); |
| ASSERT_TRUE(format->AddField("func3", /*is_signed=*/false, 3).ok()); |
| ASSERT_TRUE(format->AddField("imm3", /*is_signed=*/false, 3).ok()); |
| ASSERT_TRUE(format->AddField("rs1p", /*is_signed=*/false, 3).ok()); |
| ASSERT_TRUE(format->AddField("imm2", /*is_signed=*/false, 2).ok()); |
| ASSERT_TRUE(format->AddField("rdp", /*is_signed=*/false, 3).ok()); |
| ASSERT_TRUE(format->AddField("op", /*is_signed=*/false, 2).ok()); |
| auto result = format->AddFieldOverlay("imm_w", /*is_signed=*/false, 7); |
| ASSERT_TRUE(result.status().ok()); |
| EXPECT_NE(result.value(), nullptr); |
| EXPECT_EQ(result.value()->name(), "imm_w"); |
| EXPECT_EQ(result.value()->declared_width(), 7); |
| ASSERT_TRUE(format->ComputeAndCheckFormatWidth().ok()); |
| delete format; |
| } |
| |
| // The GenerateExtractors is not tested in this unit test. It will be tested |
| // during integration. |
| |
| } // namespace |