Added strings to access enum names of generated Op and Resource enums. Added tests to verify that each encoding class covers all the enums. PiperOrigin-RevId: 694634449 Change-Id: Ie2ed3764755df436ad9d68c925c45b6f01086dd7
diff --git a/cheriot/riscv_cheriot_encoding.h b/cheriot/riscv_cheriot_encoding.h index b5af035..7bcaa72 100644 --- a/cheriot/riscv_cheriot_encoding.h +++ b/cheriot/riscv_cheriot_encoding.h
@@ -42,6 +42,11 @@ class RiscVCheriotEncoding : public RiscVCheriotEncodingCommon, public RiscVCheriotEncodingBase { public: + using SourceOpGetterMap = + absl::flat_hash_map<int, absl::AnyInvocable<SourceOperandInterface *()>>; + using DestOpGetterMap = absl::flat_hash_map< + int, absl::AnyInvocable<DestinationOperandInterface *(int)>>; + explicit RiscVCheriotEncoding(CheriotState *state); // Parses an instruction and determines the opcode. @@ -92,12 +97,10 @@ return 0; } - private: - using SourceOpGetterMap = - absl::flat_hash_map<int, absl::AnyInvocable<SourceOperandInterface *()>>; - using DestOpGetterMap = absl::flat_hash_map< - int, absl::AnyInvocable<DestinationOperandInterface *(int)>>; + const SourceOpGetterMap &source_op_getters() { return source_op_getters_; } + const DestOpGetterMap &dest_op_getters() { return dest_op_getters_; } + private: SourceOpGetterMap source_op_getters_; DestOpGetterMap dest_op_getters_; OpcodeEnum opcode_;
diff --git a/cheriot/riscv_cheriot_rvv_encoding.h b/cheriot/riscv_cheriot_rvv_encoding.h index 2ac1bde..1aa0907 100644 --- a/cheriot/riscv_cheriot_rvv_encoding.h +++ b/cheriot/riscv_cheriot_rvv_encoding.h
@@ -42,6 +42,11 @@ class RiscVCheriotRVVEncoding : public RiscVCheriotEncodingCommon, public RiscVCheriotRVVEncodingBase { public: + using SourceOpGetterMap = + absl::flat_hash_map<int, absl::AnyInvocable<SourceOperandInterface *()>>; + using DestOpGetterMap = absl::flat_hash_map< + int, absl::AnyInvocable<DestinationOperandInterface *(int)>>; + explicit RiscVCheriotRVVEncoding(CheriotState *state); // Parses an instruction and determines the opcode. @@ -92,12 +97,10 @@ return 0; } - private: - using SourceOpGetterMap = - absl::flat_hash_map<int, absl::AnyInvocable<SourceOperandInterface *()>>; - using DestOpGetterMap = absl::flat_hash_map< - int, absl::AnyInvocable<DestinationOperandInterface *(int)>>; + const SourceOpGetterMap &source_op_getters() { return source_op_getters_; } + const DestOpGetterMap &dest_op_getters() { return dest_op_getters_; } + private: SourceOpGetterMap source_op_getters_; DestOpGetterMap dest_op_getters_; OpcodeEnum opcode_;
diff --git a/cheriot/test/BUILD b/cheriot/test/BUILD index 4912d0a..3616d1d 100644 --- a/cheriot/test/BUILD +++ b/cheriot/test/BUILD
@@ -148,6 +148,22 @@ ) cc_test( + name = "riscv_cheriot_rvv_encoding_test", + size = "small", + srcs = [ + "riscv_cheriot_rvv_encoding_test.cc", + ], + deps = [ + "//cheriot:cheriot_state", + "//cheriot:riscv_cheriot_rvv_decoder", + "//cheriot:riscv_cheriot_rvv_isa", + "@com_google_googletest//:gtest_main", + "@com_google_mpact-sim//mpact/sim/generic:type_helpers", + "@com_google_mpact-sim//mpact/sim/util/memory", + ], +) + +cc_test( name = "riscv_cheriot_a_instructions_test", size = "small", srcs = [
diff --git a/cheriot/test/riscv_cheriot_encoding_test.cc b/cheriot/test/riscv_cheriot_encoding_test.cc index 4226c71..4cc6346 100644 --- a/cheriot/test/riscv_cheriot_encoding_test.cc +++ b/cheriot/test/riscv_cheriot_encoding_test.cc
@@ -28,6 +28,10 @@ using ::mpact::sim::cheriot::isa32::kOpcodeNames; using ::mpact::sim::cheriot::isa32::RiscVCheriotEncoding; using ::mpact::sim::generic::operator*; // NOLINT: is used below (clang error). +using ::mpact::sim::cheriot::isa32::DestOpEnum; +using ::mpact::sim::cheriot::isa32::kDestOpNames; +using ::mpact::sim::cheriot::isa32::kSourceOpNames; +using ::mpact::sim::cheriot::isa32::SourceOpEnum; using ::mpact::sim::util::TaggedFlatDemandMemory; using SlotEnum = mpact::sim::cheriot::isa32::SlotEnum; using OpcodeEnum = mpact::sim::cheriot::isa32::OpcodeEnum; @@ -223,6 +227,22 @@ return (iword | ((val & 0x1f) << 2)); } +TEST_F(RiscVCheriotEncodingTest, SourceOperands) { + auto &getters = enc_->source_op_getters(); + for (int i = *SourceOpEnum::kNone; i < *SourceOpEnum::kPastMaxValue; ++i) { + EXPECT_TRUE(getters.contains(i)) << "No source operand for enum value " << i + << " (" << kSourceOpNames[i] << ")"; + } +} + +TEST_F(RiscVCheriotEncodingTest, DestOperands) { + auto &getters = enc_->dest_op_getters(); + for (int i = *DestOpEnum::kNone; i < *DestOpEnum::kPastMaxValue; ++i) { + EXPECT_TRUE(getters.contains(i)) << "No dest operand for enum value " << i + << " (" << kDestOpNames[i] << ")"; + } +} + TEST_F(RiscVCheriotEncodingTest, RV32IOpcodes) { enc_->ParseInstruction(SetRd(kLui, kRdValue)); EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Cheriot, 0), OpcodeEnum::kLui);
diff --git a/cheriot/test/riscv_cheriot_rvv_encoding_test.cc b/cheriot/test/riscv_cheriot_rvv_encoding_test.cc new file mode 100644 index 0000000..4f38e72 --- /dev/null +++ b/cheriot/test/riscv_cheriot_rvv_encoding_test.cc
@@ -0,0 +1,70 @@ +// Copyright 2024 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 +// +// http://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 "cheriot/riscv_cheriot_rvv_encoding.h" + +#include "cheriot/cheriot_state.h" +#include "cheriot/riscv_cheriot_rvv_enums.h" +#include "googlemock/include/gmock/gmock.h" +#include "mpact/sim/generic/type_helpers.h" +#include "mpact/sim/util/memory/tagged_flat_demand_memory.h" + +namespace { + +using ::mpact::sim::cheriot::CheriotState; +using ::mpact::sim::cheriot::isa32_rvv::RiscVCheriotRVVEncoding; +using ::mpact::sim::generic::operator*; // NOLINT: is used below (clang error). +using ::mpact::sim::cheriot::isa32_rvv::DestOpEnum; +using ::mpact::sim::cheriot::isa32_rvv::kDestOpNames; +using ::mpact::sim::cheriot::isa32_rvv::kSourceOpNames; +using ::mpact::sim::cheriot::isa32_rvv::SourceOpEnum; +using ::mpact::sim::util::TaggedFlatDemandMemory; +using SlotEnum = mpact::sim::cheriot::isa32_rvv::SlotEnum; +using OpcodeEnum = mpact::sim::cheriot::isa32_rvv::OpcodeEnum; + +class RiscVCheriotRVVEncodingTest : public testing::Test { + protected: + RiscVCheriotRVVEncodingTest() { + mem_ = new TaggedFlatDemandMemory(8); + state_ = new CheriotState("test", mem_, nullptr); + enc_ = new RiscVCheriotRVVEncoding(state_); + } + ~RiscVCheriotRVVEncodingTest() override { + delete enc_; + delete mem_; + delete state_; + } + + TaggedFlatDemandMemory *mem_; + CheriotState *state_; + RiscVCheriotRVVEncoding *enc_; +}; + +TEST_F(RiscVCheriotRVVEncodingTest, SourceOperands) { + auto &getters = enc_->source_op_getters(); + for (int i = *SourceOpEnum::kNone; i < *SourceOpEnum::kPastMaxValue; ++i) { + EXPECT_TRUE(getters.contains(i)) << "No source operand for enum value " << i + << " (" << kSourceOpNames[i] << ")"; + } +} + +TEST_F(RiscVCheriotRVVEncodingTest, DestOperands) { + auto &getters = enc_->dest_op_getters(); + for (int i = *DestOpEnum::kNone; i < *DestOpEnum::kPastMaxValue; ++i) { + EXPECT_TRUE(getters.contains(i)) << "No dest operand for enum value " << i + << " (" << kDestOpNames[i] << ")"; + } +} + +} // namespace