Split Zfh32 and Zfh64 isa and bin_fmt Adjust the encoding and tests to cover Zfh64 as well. PiperOrigin-RevId: 764813758 Change-Id: I54f5192fcc3299ca1a7dc95ad0b7079a2e2648aa
diff --git a/riscv/BUILD b/riscv/BUILD index 962213f..ca708da 100644 --- a/riscv/BUILD +++ b/riscv/BUILD
@@ -678,11 +678,24 @@ ) mpact_isa_decoder( - name = "zfh_isa", + name = "zfh32_isa", src = "riscv_zfh.isa", includes = [], - isa_name = "ZFH", - prefix = "zfh", + isa_name = "ZFH32", + prefix = "zfh32", + deps = [ + ":riscv_g", + ":riscv_zfh_instructions", + "@com_google_absl//absl/functional:bind_front", + ], +) + +mpact_isa_decoder( + name = "zfh64_isa", + src = "riscv_zfh.isa", + includes = [], + isa_name = "ZFH64", + prefix = "zfh64", deps = [ ":riscv_g", ":riscv_zfh_instructions", @@ -691,15 +704,28 @@ ) mpact_bin_fmt_decoder( - name = "zfh_bin_fmt", - src = "riscv_zfh.bin_fmt", + name = "zfh32_bin_fmt", + src = "riscv_zfh32.bin_fmt", decoder_name = "ZFH", includes = [ "riscv32g.bin_fmt", ], - prefix = "zfh", + prefix = "zfh32", deps = [ - ":zfh_isa", + ":zfh32_isa", + ], +) + +mpact_bin_fmt_decoder( + name = "zfh64_bin_fmt", + src = "riscv_zfh64.bin_fmt", + decoder_name = "ZFH", + includes = [ + "riscv32g.bin_fmt", + ], + prefix = "zfh64", + deps = [ + ":zfh64_isa", ], )
diff --git a/riscv/riscv_zfh.isa b/riscv/riscv_zfh.isa index 66c944d..5aec5ae 100644 --- a/riscv/riscv_zfh.isa +++ b/riscv/riscv_zfh.isa
@@ -15,13 +15,20 @@ // This file contains the ISA description of the RiscV ZFH extention // instructions. -isa ZFH { - namespace mpact::sim::riscv::zfh; +isa ZFH32 { + namespace mpact::sim::riscv::zfh32; slots { riscv32_zfh; } } +isa ZFH64 { + namespace mpact::sim::riscv::zfh64; + slots { + riscv64_zfh; + } +} + // First disasm field is 18 char wide and left justified. disasm widths = {-18}; @@ -97,7 +104,7 @@ opcodes { flh{(: rs1, I_imm12 : ), (: : frd)}, resources: {next_pc, rs1 : frd[0..]}, - semfunc: "&RV64::RiscVILhu", "&RV64::RiscVZfhFlhChild", + semfunc: "&RV64::RiscVILhu", "&RiscVZfhFlhChild", disasm: "flh", "%frd, %I_imm12(%rs1)"; fsh{: rs1, S_imm12, frs2}, resources: {next_pc, rs1, frs2},
diff --git a/riscv/riscv_zfh.bin_fmt b/riscv/riscv_zfh32.bin_fmt similarity index 94% rename from riscv/riscv_zfh.bin_fmt rename to riscv/riscv_zfh32.bin_fmt index 7ed55d4..9a49ae9 100644 --- a/riscv/riscv_zfh.bin_fmt +++ b/riscv/riscv_zfh32.bin_fmt
@@ -15,15 +15,15 @@ #include "riscv/riscv32g.bin_fmt" decoder ZFH { - namespace mpact::sim::riscv::zfh; + namespace mpact::sim::riscv::zfh32; opcode_enum = "OpcodeEnum"; includes { - #include "riscv/zfh_decoder.h" + #include "riscv/zfh32_decoder.h" } - RiscVZfhInst32 = { RiscVZfhminInst32 }; + RiscVZfhInst32 = { RiscVZfh32Inst32 }; } -instruction group RiscVZfhminInst32[32] : Inst32Format { +instruction group RiscVZfh32Inst32[32] : Inst32Format { flh : IType : func3 == 0b001, opcode == 0b000'0111; fsh : SType : func3 == 0b001, opcode == 0b010'0111; fmv_xh : RType : func7 == 0b1110010, rs2 == 0, func3 == 0b000, opcode == 0b1010011;
diff --git a/riscv/riscv_zfh.bin_fmt b/riscv/riscv_zfh64.bin_fmt similarity index 94% copy from riscv/riscv_zfh.bin_fmt copy to riscv/riscv_zfh64.bin_fmt index 7ed55d4..538628c 100644 --- a/riscv/riscv_zfh.bin_fmt +++ b/riscv/riscv_zfh64.bin_fmt
@@ -15,15 +15,15 @@ #include "riscv/riscv32g.bin_fmt" decoder ZFH { - namespace mpact::sim::riscv::zfh; + namespace mpact::sim::riscv::zfh64; opcode_enum = "OpcodeEnum"; includes { - #include "riscv/zfh_decoder.h" + #include "riscv/zfh64_decoder.h" } - RiscVZfhInst32 = { RiscVZfhminInst32 }; + RiscVZfhInst32 = { RiscVZfh64Inst32 }; } -instruction group RiscVZfhminInst32[32] : Inst32Format { +instruction group RiscVZfh64Inst32[32] : Inst32Format { flh : IType : func3 == 0b001, opcode == 0b000'0111; fsh : SType : func3 == 0b001, opcode == 0b010'0111; fmv_xh : RType : func7 == 0b1110010, rs2 == 0, func3 == 0b000, opcode == 0b1010011;
diff --git a/riscv/test/BUILD b/riscv/test/BUILD index fe13e35..31d9040 100644 --- a/riscv/test/BUILD +++ b/riscv/test/BUILD
@@ -118,7 +118,6 @@ deps = [ "//riscv:riscv_g", "//riscv:riscv_state", - "@com_google_absl//absl/log", "@com_google_absl//absl/log:check", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", @@ -373,7 +372,6 @@ "zvbb_encoding_test.cc", ], deps = [ - "//riscv:riscv32g_bitmanip_decoder", "//riscv:riscv_state", "//riscv:zvbb_decoder", "//riscv:zvbb_isa", @@ -383,40 +381,23 @@ ], ) -cc_library( - name = "zfh_decoder", - testonly = True, - srcs = [ - "zfh_encoding.cc", - ], - hdrs = [ - "riscv_getters_zfh.h", - "zfh_encoding.h", - ], - copts = ["-O3"], - deps = [ - "//riscv:riscv_encoding_common", - "//riscv:riscv_getters", - "//riscv:riscv_state", - "//riscv:zfh_bin_fmt", - "//riscv:zfh_isa", - "@com_google_absl//absl/log", - "@com_google_absl//absl/strings", - "@com_google_mpact-sim//mpact/sim/generic:core", - "@com_google_mpact-sim//mpact/sim/generic:type_helpers", - ], -) - cc_test( name = "zfh_encoding_test", size = "small", srcs = [ + "riscv_getters_zfh.h", + "zfh_encoding.h", "zfh_encoding_test.cc", ], deps = [ - ":zfh_decoder", + "//riscv:riscv_encoding_common", + "//riscv:riscv_getters", "//riscv:riscv_state", - "//riscv:zfh_isa", + "//riscv:zfh32_bin_fmt", + "//riscv:zfh32_isa", + "//riscv:zfh64_bin_fmt", + "//riscv:zfh64_isa", + "@com_google_absl//absl/log", "@com_google_absl//absl/random", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", @@ -588,7 +569,6 @@ "@com_google_absl//absl/base", "@com_google_absl//absl/log:check", "@com_google_absl//absl/numeric:int128", - "@com_google_absl//absl/random", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", "@com_google_mpact-sim//mpact/sim/generic:instruction", @@ -655,7 +635,6 @@ "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", - "@com_google_mpact-sim//mpact/sim/generic:core", "@com_google_mpact-sim//mpact/sim/generic:instruction", "@com_google_mpact-sim//mpact/sim/generic:type_helpers", ], @@ -680,7 +659,6 @@ "//riscv:riscv_fp_state", "//riscv:riscv_state", "//riscv:riscv_v", - "@com_google_absl//absl/log", "@com_google_absl//absl/random", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:span", @@ -776,7 +754,6 @@ "//riscv:riscv32g_decoder", "//riscv:riscv64g_decoder", "//riscv:riscv_arm_semihost", - "//riscv:riscv_fp_state", "//riscv:riscv_state", "//riscv:riscv_top", "@com_google_absl//absl/log:check", @@ -832,7 +809,6 @@ "@com_google_absl//absl/log:check", "@com_google_googletest//:gtest_main", "@com_google_mpact-sim//mpact/sim/generic:core", - "@com_googlesource_code_re2//:re2", ], ) @@ -907,7 +883,6 @@ "@com_google_googletest//:gtest_main", "@com_google_mpact-sim//mpact/sim/generic:core", "@com_google_mpact-sim//mpact/sim/generic:instruction", - "@com_google_mpact-sim//mpact/sim/generic:type_helpers", ], ) @@ -924,7 +899,6 @@ "@com_google_googletest//:gtest_main", "@com_google_mpact-sim//mpact/sim/generic:core", "@com_google_mpact-sim//mpact/sim/generic:instruction", - "@com_google_mpact-sim//mpact/sim/generic:type_helpers", ], ) @@ -995,7 +969,6 @@ deps = [ ":riscv_vector_instructions_test_base", "//riscv:riscv_state", - "//riscv:riscv_v", "//riscv:riscv_vector_basic_bit_manipulation_instructions", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main",
diff --git a/riscv/test/zfh_encoding.cc b/riscv/test/zfh_encoding.cc deleted file mode 100644 index 7be9df3..0000000 --- a/riscv/test/zfh_encoding.cc +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2025 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 "riscv/test/zfh_encoding.h" - -#include <cstdint> - -#include "absl/log/log.h" -#include "absl/strings/str_cat.h" -#include "mpact/sim/generic/simple_resource_operand.h" -#include "mpact/sim/generic/type_helpers.h" -#include "riscv/riscv_getter_helpers.h" -#include "riscv/riscv_register.h" -#include "riscv/riscv_state.h" -#include "riscv/test/riscv_getters_zfh.h" -#include "riscv/zfh_bin_decoder.h" -#include "riscv/zfh_decoder.h" -#include "riscv/zfh_enums.h" - -namespace mpact::sim::riscv::zfh { - -using ::mpact::sim::generic::operator*; // NOLINT: clang-tidy false positive. - -ZFHEncoding::ZFHEncoding(RiscVState *state) - : state_(state), - inst_word_(0), - opcode_(OpcodeEnum::kNone), - format_(FormatEnum::kNone) { - resource_delay_line_ = - state_->CreateAndAddDelayLine<generic::SimpleResourceDelayLine>(8); - // Initialize getters. - source_op_getters_.emplace(*SourceOpEnum::kNone, []() { return nullptr; }); - dest_op_getters_.emplace(*DestOpEnum::kNone, - [](int latency) { return nullptr; }); - simple_resource_getters_.emplace(*SimpleResourceEnum::kNone, - []() { return nullptr; }); - complex_resource_getters_.emplace( - *ComplexResourceEnum::kNone, - [](int latency, int end) { return nullptr; }); - - AddRiscVZfhSourceScalarGetters<SourceOpEnum, Extractors, RVXRegister>( - source_op_getters_, this); - AddRiscVZfhSourceFloatGetters<SourceOpEnum, Extractors, RVFpRegister>( - source_op_getters_, this); - AddRiscVZfhDestScalarGetters<DestOpEnum, Extractors, RVXRegister>( - dest_op_getters_, this); - AddRiscVZfhDestFloatGetters<DestOpEnum, Extractors, RVFpRegister>( - dest_op_getters_, this); - AddRiscVZfhSimpleResourceGetters<SimpleResourceEnum, Extractors>( - simple_resource_getters_, this); - - // Verify that there are getters for each enum value. - for (int i = *SourceOpEnum::kNone; i < *SourceOpEnum::kPastMaxValue; ++i) { - if (source_op_getters_.find(i) == source_op_getters_.end()) { - LOG(ERROR) << "No getter for source op enum value " << i; - } - } - for (int i = *DestOpEnum::kNone; i < *DestOpEnum::kPastMaxValue; ++i) { - if (dest_op_getters_.find(i) == dest_op_getters_.end()) { - LOG(ERROR) << "No getter for destination op enum value " << i; - } - } - for (int i = *SimpleResourceEnum::kNone; - i < *SimpleResourceEnum::kPastMaxValue; ++i) { - if (simple_resource_getters_.find(i) == simple_resource_getters_.end()) { - LOG(ERROR) << "No getter for simple resource enum value " << i; - } - } -} - -ZFHEncoding::~ZFHEncoding() { delete resource_pool_; } - -void ZFHEncoding::ParseInstruction(uint32_t inst_word) { - inst_word_ = inst_word; - auto [opcode, format] = DecodeRiscVZfhInst32WithFormat(inst_word_); - opcode_ = opcode; - format_ = format; -} - -ResourceOperandInterface *ZFHEncoding::GetComplexResourceOperand( - SlotEnum, int, OpcodeEnum, ComplexResourceEnum resource, int begin, - int end) { - return nullptr; -} - -ResourceOperandInterface *ZFHEncoding::GetSimpleResourceOperand( - SlotEnum, int, OpcodeEnum, SimpleResourceVector &resource_vec, int end) { - return nullptr; -} - -DestinationOperandInterface *ZFHEncoding::GetDestination(SlotEnum, int, - OpcodeEnum opcode, - DestOpEnum dest_op, - int dest_no, - int latency) { - int index = static_cast<int>(dest_op); - auto iter = dest_op_getters_.find(index); - if (iter == dest_op_getters_.end()) { - LOG(ERROR) << absl::StrCat("No getter for destination op enum value ", - index, "for instruction ", - kOpcodeNames[static_cast<int>(opcode)]); - return nullptr; - } - return (iter->second)(latency); -} - -SourceOperandInterface *ZFHEncoding::GetSource(SlotEnum, int, OpcodeEnum opcode, - SourceOpEnum source_op, - int source_no) { - int index = static_cast<int>(source_op); - auto iter = source_op_getters_.find(index); - if (iter == source_op_getters_.end()) { - LOG(ERROR) << absl::StrCat("No getter for source op enum value ", index, - " for instruction ", - kOpcodeNames[static_cast<int>(opcode)]); - return nullptr; - } - return (iter->second)(); -} - -} // namespace mpact::sim::riscv::zfh
diff --git a/riscv/test/zfh_encoding.h b/riscv/test/zfh_encoding.h index 9e77a56..eb7311e 100644 --- a/riscv/test/zfh_encoding.h +++ b/riscv/test/zfh_encoding.h
@@ -18,50 +18,197 @@ #include <cstdint> #include <string> +#include "absl/log/log.h" +#include "mpact/sim/generic/operand_interface.h" #include "mpact/sim/generic/simple_resource.h" #include "mpact/sim/generic/simple_resource_operand.h" #include "riscv/riscv_encoding_common.h" #include "riscv/riscv_getter_helpers.h" +#include "riscv/riscv_register.h" #include "riscv/riscv_state.h" -#include "riscv/zfh_bin_decoder.h" -#include "riscv/zfh_decoder.h" -#include "riscv/zfh_enums.h" +#include "riscv/test/riscv_getters_zfh.h" +#include "riscv/zfh32_bin_decoder.h" +#include "riscv/zfh32_decoder.h" +#include "riscv/zfh32_enums.h" +#include "riscv/zfh64_bin_decoder.h" +#include "riscv/zfh64_decoder.h" +#include "riscv/zfh64_enums.h" namespace mpact::sim::riscv::zfh { -// This class provides the interface between the generated instruction decoder -// framework (which is agnostic of the actual bit representation of -// instructions) and the instruction representation. This class provides methods -// to return the opcode, source operands, and destination operands for -// instructions according to the operand fields in the encoding. -class ZFHEncoding : public ZFHEncodingBase, public RiscVEncodingCommon { - public: - explicit ZFHEncoding(RiscVState *state); - ~ZFHEncoding() override; +template <int XLen> +class ZfhEncoding; - void ParseInstruction(uint32_t inst_word); +template <int XLen> +struct ZfhTraits; + +template <> +struct ZfhTraits<32> { + using EncodingBase = ::mpact::sim::riscv::zfh32::ZFH32EncodingBase; + using SlotEnum = ::mpact::sim::riscv::zfh32::SlotEnum; + using OpcodeEnum = ::mpact::sim::riscv::zfh32::OpcodeEnum; + using FormatEnum = ::mpact::sim::riscv::zfh32::FormatEnum; + using DestOpEnum = ::mpact::sim::riscv::zfh32::DestOpEnum; + using SourceOpEnum = ::mpact::sim::riscv::zfh32::SourceOpEnum; + using ComplexResourceEnum = ::mpact::sim::riscv::zfh32::ComplexResourceEnum; + using SimpleResourceEnum = ::mpact::sim::riscv::zfh32::SimpleResourceEnum; + using PredOpEnum = ::mpact::sim::riscv::zfh32::PredOpEnum; + using SimpleResourceVector = ::mpact::sim::riscv::zfh32::SimpleResourceVector; + using Extractors = ::mpact::sim::riscv::zfh32::Extractors; + using XRegister = ::mpact::sim::riscv::RV32Register; + using SelfEncoding = ZfhEncoding<32>; + static constexpr int kXLen = 32; + static constexpr const char *const *kOpcodeNames = + ::mpact::sim::riscv::zfh32::kOpcodeNames; +}; + +template <> +struct ZfhTraits<64> { + using EncodingBase = ::mpact::sim::riscv::zfh64::ZFH64EncodingBase; + using SlotEnum = ::mpact::sim::riscv::zfh64::SlotEnum; + using OpcodeEnum = ::mpact::sim::riscv::zfh64::OpcodeEnum; + using FormatEnum = ::mpact::sim::riscv::zfh64::FormatEnum; + using DestOpEnum = ::mpact::sim::riscv::zfh64::DestOpEnum; + using SourceOpEnum = ::mpact::sim::riscv::zfh64::SourceOpEnum; + using ComplexResourceEnum = ::mpact::sim::riscv::zfh64::ComplexResourceEnum; + using SimpleResourceEnum = ::mpact::sim::riscv::zfh64::SimpleResourceEnum; + using PredOpEnum = ::mpact::sim::riscv::zfh64::PredOpEnum; + using SimpleResourceVector = ::mpact::sim::riscv::zfh64::SimpleResourceVector; + using Extractors = ::mpact::sim::riscv::zfh64::Extractors; + using XRegister = ::mpact::sim::riscv::RV64Register; + using SelfEncoding = ZfhEncoding<64>; + static constexpr int kXLen = 64; + static constexpr const char *const *kOpcodeNames = + ::mpact::sim::riscv::zfh64::kOpcodeNames; +}; + +template <int XLen> +class ZfhEncoding : public ZfhTraits<XLen>::EncodingBase, + public RiscVEncodingCommon { + public: + using OpcodeEnum = ZfhTraits<XLen>::OpcodeEnum; + using FormatEnum = ZfhTraits<XLen>::FormatEnum; + using DestOpEnum = ZfhTraits<XLen>::DestOpEnum; + using SourceOpEnum = ZfhTraits<XLen>::SourceOpEnum; + using ComplexResourceEnum = ZfhTraits<XLen>::ComplexResourceEnum; + using SimpleResourceEnum = ZfhTraits<XLen>::SimpleResourceEnum; + using PredOpEnum = ZfhTraits<XLen>::PredOpEnum; + using SlotEnum = ZfhTraits<XLen>::SlotEnum; + using SimpleResourceVector = ZfhTraits<XLen>::SimpleResourceVector; + using Extractors = ZfhTraits<XLen>::Extractors; + using XRegister = ZfhTraits<XLen>::XRegister; + + explicit ZfhEncoding(RiscVState *state) + : state_(state), + inst_word_(0), + opcode_(OpcodeEnum::kNone), + format_(FormatEnum::kNone) { + resource_delay_line_ = + state_->CreateAndAddDelayLine<generic::SimpleResourceDelayLine>(8); + // Initialize getters. + source_op_getters_.insert({*SourceOpEnum::kNone, []() { return nullptr; }}); + dest_op_getters_.insert( + {*DestOpEnum::kNone, [](int latency) { return nullptr; }}); + simple_resource_getters_.insert( + {*SimpleResourceEnum::kNone, []() { return nullptr; }}); + complex_resource_getters_.insert( + {*ComplexResourceEnum::kNone, + [](int latency, int end) { return nullptr; }}); + + AddRiscVZfhSourceScalarGetters<SourceOpEnum, Extractors, XRegister>( + source_op_getters_, this); + AddRiscVZfhSourceFloatGetters<SourceOpEnum, Extractors, RVFpRegister>( + source_op_getters_, this); + AddRiscVZfhDestScalarGetters<DestOpEnum, Extractors, XRegister>( + dest_op_getters_, this); + AddRiscVZfhDestFloatGetters<DestOpEnum, Extractors, RVFpRegister>( + dest_op_getters_, this); + AddRiscVZfhSimpleResourceGetters<SimpleResourceEnum, Extractors>( + simple_resource_getters_, this); + + // Verify that there are getters for each enum value. + for (int i = *SourceOpEnum::kNone; i < *SourceOpEnum::kPastMaxValue; ++i) { + if (!source_op_getters_.contains(i)) { + LOG(ERROR) << "No getter for source op enum value " << i; + } + } + for (int i = *DestOpEnum::kNone; i < *DestOpEnum::kPastMaxValue; ++i) { + if (!dest_op_getters_.contains(i)) { + LOG(ERROR) << "No getter for destination op enum value " << i; + } + } + for (int i = *SimpleResourceEnum::kNone; + i < *SimpleResourceEnum::kPastMaxValue; ++i) { + if (!simple_resource_getters_.contains(i)) { + LOG(ERROR) << "No getter for simple resource enum value " << i; + } + } + } + + ~ZfhEncoding() { delete resource_pool_; } + + void ParseInstruction(uint32_t inst_word) { + inst_word_ = inst_word; + if constexpr (XLen == 32) { + auto [opcode, format] = + ::mpact::sim::riscv::zfh32::DecodeRiscVZfhInst32WithFormat( + inst_word_); + opcode_ = opcode; + format_ = format; + } else { + auto [opcode, format] = + ::mpact::sim::riscv::zfh64::DecodeRiscVZfhInst32WithFormat( + inst_word_); + opcode_ = opcode; + format_ = format; + } + } + OpcodeEnum GetOpcode(SlotEnum, int) override { return opcode_; } FormatEnum GetFormat(SlotEnum, int) { return format_; } - PredicateOperandInterface *GetPredicate(SlotEnum, int, OpcodeEnum, - PredOpEnum) override { + ::mpact::sim::generic::PredicateOperandInterface *GetPredicate( + SlotEnum, int, OpcodeEnum, PredOpEnum) override { return nullptr; } ResourceOperandInterface *GetSimpleResourceOperand( - SlotEnum, int, OpcodeEnum, SimpleResourceVector &resource_vec, - int end) override; + SlotEnum, int, OpcodeEnum, SimpleResourceVector &resource_vec, int end) { + return nullptr; + } ResourceOperandInterface *GetComplexResourceOperand( SlotEnum, int, OpcodeEnum, ComplexResourceEnum resource, int begin, - int end) override; + int end) { + return nullptr; + } - SourceOperandInterface *GetSource(SlotEnum, int, OpcodeEnum, SourceOpEnum op, - int source_no) override; + DestinationOperandInterface *GetDestination(SlotEnum, int, OpcodeEnum opcode, + DestOpEnum dest_op, int dest_no, + int latency) { + int index = static_cast<int>(dest_op); + auto iter = dest_op_getters_.find(index); + if (iter == dest_op_getters_.end()) { + LOG(ERROR) << absl::StrCat( + "No getter for destination op enum value ", index, "for instruction ", + ZfhTraits<XLen>::kOpcodeNames[static_cast<int>(opcode)]); + return nullptr; + } + return (iter->second)(latency); + } - DestinationOperandInterface *GetDestination(SlotEnum, int, OpcodeEnum, - DestOpEnum op, int dest_no, - int latency) override; + SourceOperandInterface *GetSource(SlotEnum, int, OpcodeEnum opcode, + SourceOpEnum source_op, int source_no) { + int index = static_cast<int>(source_op); + auto iter = source_op_getters_.find(index); + if (iter == source_op_getters_.end()) { + LOG(ERROR) << absl::StrCat( + "No getter for source op enum value ", index, " for instruction ", + ZfhTraits<XLen>::kOpcodeNames[static_cast<int>(opcode)]); + return nullptr; + } + return (iter->second)(); + } int GetLatency(SlotEnum, int, OpcodeEnum, DestOpEnum, int) override { return 0; @@ -97,7 +244,6 @@ generic::SimpleResourceDelayLine *resource_delay_line_ = nullptr; generic::SimpleResourcePool *resource_pool_ = nullptr; }; - } // namespace mpact::sim::riscv::zfh #endif // THIRD_PARTY_MPACT_RISCV_TEST_ZFH_ENCODING_H_
diff --git a/riscv/test/zfh_encoding_test.cc b/riscv/test/zfh_encoding_test.cc index f767556..044a9a4 100644 --- a/riscv/test/zfh_encoding_test.cc +++ b/riscv/test/zfh_encoding_test.cc
@@ -20,6 +20,7 @@ #include <ios> #include <memory> #include <tuple> +#include <vector> #include "absl/random/random.h" #include "absl/strings/str_cat.h" @@ -30,7 +31,9 @@ #include "mpact/sim/util/memory/flat_demand_memory.h" #include "riscv/riscv_register.h" #include "riscv/riscv_state.h" -#include "riscv/zfh_enums.h" +#include "riscv/zfh32_enums.h" +#include "riscv/zfh64_enums.h" +#include "testing/base/public/gmock.h" #include "testing/base/public/gunit.h" // Test that hand crafted zfh instructions are decoded and parsed correctly. @@ -41,23 +44,11 @@ using ::mpact::sim::generic::ImmediateOperand; using ::mpact::sim::generic::RegisterDestinationOperand; using ::mpact::sim::generic::SourceOperandInterface; -using mpact::sim::riscv::RiscVState; -using mpact::sim::riscv::RiscVXlen; -using mpact::sim::riscv::RVFpRegister; -using mpact::sim::riscv::RVXRegister; -using mpact::sim::util::FlatDemandMemory; - -using mpact::sim::riscv::zfh::kComplexResourceNames; -using mpact::sim::riscv::zfh::kDestOpNames; -using mpact::sim::riscv::zfh::kSourceOpNames; - -using SlotEnum = mpact::sim::riscv::zfh::SlotEnum; -using OpcodeEnum = mpact::sim::riscv::zfh::OpcodeEnum; -using SourceOpEnum = mpact::sim::riscv::zfh::SourceOpEnum; -using DestOpEnum = mpact::sim::riscv::zfh::DestOpEnum; -using ComplexResourceEnum = mpact::sim::riscv::zfh::ComplexResourceEnum; - -using mpact::sim::riscv::zfh::ZFHEncoding; +using ::mpact::sim::riscv::RiscVState; +using ::mpact::sim::riscv::RiscVXlen; +using ::mpact::sim::riscv::RVFpRegister; +using ::mpact::sim::riscv::zfh::ZfhEncoding; +using ::mpact::sim::util::FlatDemandMemory; // imm12 | rs1 | | rd | opcode constexpr uint32_t kFlh = 0b000000000000'00000'001'00000'0000111; @@ -120,11 +111,53 @@ // rs3 |f2| rs2 | rs1 |rm | rd | opcode constexpr uint32_t kFnmsubH = 0b00000'10'00000'00000'000'00000'1001011; -class ZfhEncodingTest : public testing::Test { +struct Zfh32Config { + using XRegister = ::mpact::sim::riscv::RV32Register; + using XValue = typename XRegister::ValueType; + using SlotEnum = ::mpact::sim::riscv::zfh32::SlotEnum; + using DestOpEnum = ::mpact::sim::riscv::zfh32::DestOpEnum; + using SourceOpEnum = ::mpact::sim::riscv::zfh32::SourceOpEnum; + using OpcodeEnum = ::mpact::sim::riscv::zfh32::OpcodeEnum; + using ComplexResourceEnum = ::mpact::sim::riscv::zfh32::ComplexResourceEnum; + using SimpleResourceEnum = ::mpact::sim::riscv::zfh32::SimpleResourceEnum; + static constexpr RiscVXlen rvXLen = RiscVXlen::RV32; + static constexpr int kXLen = 32; + static constexpr int slot = static_cast<int>(SlotEnum::kRiscv32Zfh); + static constexpr const char *const *kSourceOpNames = + ::mpact::sim::riscv::zfh32::kSourceOpNames; + static constexpr const char *const *kDestOpNames = + ::mpact::sim::riscv::zfh32::kDestOpNames; + static constexpr const char *const *kComplexResourceNames = + ::mpact::sim::riscv::zfh32::kComplexResourceNames; +}; + +struct Zfh64Config { + using XRegister = ::mpact::sim::riscv::RV64Register; + using XValue = typename XRegister::ValueType; + using SlotEnum = ::mpact::sim::riscv::zfh64::SlotEnum; + using DestOpEnum = ::mpact::sim::riscv::zfh64::DestOpEnum; + using SourceOpEnum = ::mpact::sim::riscv::zfh64::SourceOpEnum; + using OpcodeEnum = ::mpact::sim::riscv::zfh64::OpcodeEnum; + using ComplexResourceEnum = ::mpact::sim::riscv::zfh64::ComplexResourceEnum; + using SimpleResourceEnum = ::mpact::sim::riscv::zfh64::SimpleResourceEnum; + static constexpr RiscVXlen rvXLen = RiscVXlen::RV64; + static constexpr int kXLen = 64; + static constexpr int slot = static_cast<int>(SlotEnum::kRiscv64Zfh); + static constexpr const char *const *kSourceOpNames = + ::mpact::sim::riscv::zfh64::kSourceOpNames; + static constexpr const char *const *kDestOpNames = + ::mpact::sim::riscv::zfh64::kDestOpNames; + static constexpr const char *const *kComplexResourceNames = + ::mpact::sim::riscv::zfh64::kComplexResourceNames; +}; + +template <typename ConfigT> +struct ZfhEncodingTest : public testing::Test { protected: ZfhEncodingTest() { - state_ = new RiscVState("test", RiscVXlen::RV32, &memory_); - enc_ = new ZFHEncoding(state_); + state_ = new RiscVState("test", ConfigT::rvXLen, &memory_); + enc_ = new ZfhEncoding<ConfigT::kXLen>(state_); + expected_slot_ = static_cast<ConfigT::SlotEnum>(ConfigT::slot); } ~ZfhEncodingTest() override { @@ -132,51 +165,72 @@ delete state_; } - void ScalarRs1Helper(uint32_t, OpcodeEnum); - void FloatFrdHelper(uint32_t, OpcodeEnum); - void FloatSourceHelper(uint32_t, OpcodeEnum, int); - void FloatSourceHelper(uint32_t, OpcodeEnum, SourceOpEnum, int); - void FloatFrs1Helper(uint32_t, OpcodeEnum); - void FloatFrs2Helper(uint32_t, OpcodeEnum); - void FloatFrs3Helper(uint32_t, OpcodeEnum); - void FloatRmHelper(uint32_t, OpcodeEnum); + typename ConfigT::XValue RandomizeScalarRegister(int); + void ParseInstructionWithRs1(uint32_t, int); + typename ConfigT::XValue GetRs1SourceValue(typename ConfigT::OpcodeEnum); + void FloatFrdHelper(uint32_t, typename ConfigT::OpcodeEnum); + void FloatSourceHelper(uint32_t, typename ConfigT::OpcodeEnum, int); + void FloatSourceHelper(uint32_t, typename ConfigT::OpcodeEnum, + typename ConfigT::SourceOpEnum, int); + void FloatFrs1Helper(uint32_t, typename ConfigT::OpcodeEnum); + void FloatFrs2Helper(uint32_t, typename ConfigT::OpcodeEnum); + void FloatFrs3Helper(uint32_t, typename ConfigT::OpcodeEnum); + void FloatRmHelper(uint32_t, typename ConfigT::OpcodeEnum); + ConfigT::OpcodeEnum GetOpcode(); FlatDemandMemory memory_; RiscVState *state_; - ZFHEncoding *enc_; + ZfhEncoding<ConfigT::kXLen> *enc_; absl::BitGen gen_; + typename ConfigT::SlotEnum expected_slot_; }; -void ZfhEncodingTest::ScalarRs1Helper(uint32_t binary_instruction, - OpcodeEnum opcode_enum) { - int rs1_offset = 15; - uint32_t base_instruction = binary_instruction & ~(0x0000'001F << rs1_offset); - for (int rs1_index = 0; rs1_index < 32; ++rs1_index) { - uint32_t expected_value = rs1_index ? absl::Uniform<uint32_t>(gen_) : 0; - - // Set the register value with a test value. - RVXRegister *rs1_reg; - std::tie(rs1_reg, std::ignore) = state_->GetRegister<RVXRegister>( - absl::StrCat("x", static_cast<uint32_t>(rs1_index))); - rs1_reg->data_buffer()->Set<uint32_t>(0, expected_value); - - // Parse the instruction and get the source operand. - uint32_t rs1_adjustment = static_cast<uint32_t>(rs1_index) << rs1_offset; - enc_->ParseInstruction(base_instruction | rs1_adjustment); - std::unique_ptr<SourceOperandInterface> src(enc_->GetSource( - SlotEnum::kRiscv32Zfh, 0, opcode_enum, SourceOpEnum::kRs1, 0)); - - // Pull the value from the source operand and compare it to the expected - // value. - EXPECT_EQ(src->AsUint32(0), expected_value) - << "rs1_index: " << rs1_index << ", expected_value: " << std::hex - << expected_value << ", observed value: " << std::hex - << src->AsUint32(0); - } +template <typename ConfigT> +ConfigT::OpcodeEnum ZfhEncodingTest<ConfigT>::GetOpcode() { + return static_cast<ConfigT::OpcodeEnum>(enc_->GetOpcode(expected_slot_, 0)); } -void ZfhEncodingTest::FloatFrdHelper(uint32_t binary_instruction, - OpcodeEnum opcode_enum) { +template <typename ConfigT> +typename ConfigT::XValue ZfhEncodingTest<ConfigT>::RandomizeScalarRegister( + int register_index) { + using XRegister = typename ConfigT::XRegister; + using XValue = typename ConfigT::XValue; + XValue register_value = register_index ? absl::Uniform<XValue>(gen_) : 0; + XRegister *rs1_reg; + std::tie(rs1_reg, std::ignore) = state_->GetRegister<XRegister>( + absl::StrCat("x", static_cast<uint32_t>(register_index))); + rs1_reg->data_buffer()->template Set<XValue>(0, register_value); + return register_value; +} + +template <typename ConfigT> +void ZfhEncodingTest<ConfigT>::ParseInstructionWithRs1( + uint32_t binary_instruction, int rs1_index) { + int rs1_offset = 15; + uint32_t rs1_adjustment = static_cast<uint32_t>(rs1_index) << rs1_offset; + enc_->ParseInstruction(binary_instruction | rs1_adjustment); +} + +template <typename ConfigT> +typename ConfigT::XValue ZfhEncodingTest<ConfigT>::GetRs1SourceValue( + typename ConfigT::OpcodeEnum opcode_enum) { + using XValue = typename ConfigT::XValue; + std::unique_ptr<SourceOperandInterface> src(enc_->GetSource( + expected_slot_, 0, opcode_enum, ConfigT::SourceOpEnum::kRs1, 0)); + + XValue observed_value; + if constexpr (ConfigT::kXLen == 32) { + observed_value = src->AsUint32(0); + } else { + observed_value = src->AsUint64(0); + } + return observed_value; +} + +// TODO: b/421177084 - Move EXPECT_* out of helpers and back to test body. +template <typename ConfigT> +void ZfhEncodingTest<ConfigT>::FloatFrdHelper( + uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) { int frd_offset = 7; uint32_t base_instruction = binary_instruction & ~(0x0000'001F << frd_offset); for (int frd_index = 0; frd_index < 32; ++frd_index) { @@ -193,8 +247,8 @@ enc_->ParseInstruction(base_instruction | frd_adjustment); std::unique_ptr<RegisterDestinationOperand<RVFpRegister>> dst( static_cast<RegisterDestinationOperand<RVFpRegister> *>( - enc_->GetDestination(SlotEnum::kRiscv32Zfh, 0, opcode_enum, - DestOpEnum::kFrd, 0, 0))); + enc_->GetDestination(expected_slot_, 0, opcode_enum, + ConfigT::DestOpEnum::kFrd, 0, 0))); // Pull the value from the destination operand and compare it to the // expected value. @@ -206,25 +260,27 @@ } } -void ZfhEncodingTest::FloatSourceHelper(uint32_t binary_instruction, - OpcodeEnum opcode_enum, - SourceOpEnum source_op_enum, - int offset) { +// TODO: b/421177084 - Move EXPECT_* out of helpers and back to test body. +template <typename ConfigT> +void ZfhEncodingTest<ConfigT>::FloatSourceHelper( + uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum, + typename ConfigT::SourceOpEnum source_op_enum, int offset) { + using RegisterValue = typename RVFpRegister::ValueType; uint32_t base_instruction = binary_instruction & ~(0x0000'001F << offset); for (uint32_t frs1_index = 0; frs1_index < 32; ++frs1_index) { uint32_t src_adjustment = frs1_index << offset; - uint64_t expected_value = absl::Uniform<uint64_t>(gen_); + RegisterValue expected_value = absl::Uniform<RegisterValue>(gen_); // Set the register value with a test value. RVFpRegister *frs1_reg; std::tie(frs1_reg, std::ignore) = state_->GetRegister<RVFpRegister>(absl::StrCat("f", frs1_index)); - frs1_reg->data_buffer()->Set<uint64_t>(0, expected_value); + frs1_reg->data_buffer()->Set<RegisterValue>(0, expected_value); // Parse the instruction and get the source operand. enc_->ParseInstruction(base_instruction | src_adjustment); - std::unique_ptr<SourceOperandInterface> src(enc_->GetSource( - SlotEnum::kRiscv32Zfh, 0, opcode_enum, source_op_enum, 0)); + std::unique_ptr<SourceOperandInterface> src( + enc_->GetSource(expected_slot_, 0, opcode_enum, source_op_enum, 0)); // Pull the value from the source operand and compare it to the expected // value. @@ -235,637 +291,696 @@ } } -void ZfhEncodingTest::FloatFrs1Helper(uint32_t binary_instruction, - OpcodeEnum opcode_enum) { - FloatSourceHelper(binary_instruction, opcode_enum, SourceOpEnum::kFrs1, 15); +template <typename ConfigT> +void ZfhEncodingTest<ConfigT>::FloatFrs1Helper( + uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) { + FloatSourceHelper(binary_instruction, opcode_enum, + ConfigT::SourceOpEnum::kFrs1, 15); } -void ZfhEncodingTest::FloatFrs2Helper(uint32_t binary_instruction, - OpcodeEnum opcode_enum) { - FloatSourceHelper(binary_instruction, opcode_enum, SourceOpEnum::kFrs2, 20); +template <typename ConfigT> +void ZfhEncodingTest<ConfigT>::FloatFrs2Helper( + uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) { + FloatSourceHelper(binary_instruction, opcode_enum, + ConfigT::SourceOpEnum::kFrs2, 20); } -void ZfhEncodingTest::FloatFrs3Helper(uint32_t binary_instruction, - OpcodeEnum opcode_enum) { - FloatSourceHelper(binary_instruction, opcode_enum, SourceOpEnum::kFrs3, 27); +template <typename ConfigT> +void ZfhEncodingTest<ConfigT>::FloatFrs3Helper( + uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) { + FloatSourceHelper(binary_instruction, opcode_enum, + ConfigT::SourceOpEnum::kFrs3, 27); } -void ZfhEncodingTest::FloatRmHelper(uint32_t binary_instruction, - OpcodeEnum opcode_enum) { +// TODO: b/421177084 - Move EXPECT_* out of helpers and back to test body. +template <typename ConfigT> +void ZfhEncodingTest<ConfigT>::FloatRmHelper( + uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) { for (int rm = 0; rm <= 6; ++rm) { uint32_t rm_adjustment = rm << 12; enc_->ParseInstruction(kFcvtSh | rm_adjustment); - std::unique_ptr<SourceOperandInterface> src(enc_->GetSource( - SlotEnum::kRiscv32Zfh, 0, OpcodeEnum::kFcvtSh, SourceOpEnum::kRm, 0)); + std::unique_ptr<SourceOperandInterface> src( + enc_->GetSource(expected_slot_, 0, ConfigT::OpcodeEnum::kFcvtSh, + ConfigT::SourceOpEnum::kRm, 0)); EXPECT_EQ(src->AsUint32(0), rm); } } -TEST_F(ZfhEncodingTest, 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] << ")"; +using MyTypes = ::testing::Types<Zfh32Config, Zfh64Config>; +TYPED_TEST_SUITE(ZfhEncodingTest, MyTypes); + +TYPED_TEST(ZfhEncodingTest, SourceOperands) { + auto &getters = this->enc_->source_op_getters(); + for (int i = *TypeParam::SourceOpEnum::kNone; + i < *TypeParam::SourceOpEnum::kPastMaxValue; ++i) { + EXPECT_TRUE(getters.contains(i)) + << "No source operand for enum value " << i << " (" + << TypeParam::kSourceOpNames[i] << ")"; } } -TEST_F(ZfhEncodingTest, 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] << ")"; +TYPED_TEST(ZfhEncodingTest, DestOperands) { + auto &getters = this->enc_->dest_op_getters(); + for (int i = *TypeParam::DestOpEnum::kNone; + i < *TypeParam::DestOpEnum::kPastMaxValue; ++i) { + EXPECT_TRUE(getters.contains(i)) + << "No dest operand for enum value " << i << " (" + << TypeParam::kDestOpNames[i] << ")"; } } -// TODO(julianmb): Add simple resource getters when appropriate. -// TEST_F(ZfhEncodingTest, SimpleResources) { -// auto &getters = enc_->simple_resource_getters(); -// for (int i = *SimpleResourceEnum::kNone; -// i < *SimpleResourceEnum::kPastMaxValue; ++i) { -// EXPECT_TRUE(getters.contains(i)) << "No source operand for enum value " -// << i -// << " (" << kSimpleResourceNames[i] << -// ")"; -// } -// } +// TODO: b/420935002 - Add simple resource getters and tests when we start using +// them. -TEST_F(ZfhEncodingTest, ComplexResources) { - auto &getters = enc_->source_op_getters(); - for (int i = *ComplexResourceEnum::kNone; - i < *ComplexResourceEnum::kPastMaxValue; ++i) { - EXPECT_TRUE(getters.contains(i)) << "No source operand for enum value " << i - << " (" << kComplexResourceNames[i] << ")"; +TYPED_TEST(ZfhEncodingTest, ComplexResources) { + auto &getters = this->enc_->source_op_getters(); + for (int i = *TypeParam::ComplexResourceEnum::kNone; + i < *TypeParam::ComplexResourceEnum::kPastMaxValue; ++i) { + EXPECT_TRUE(getters.contains(i)) + << "No source operand for enum value " << i << " (" + << TypeParam::kComplexResourceNames[i] << ")"; } } -TEST_F(ZfhEncodingTest, Flh) { - enc_->ParseInstruction(kFlh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFlh); +TYPED_TEST(ZfhEncodingTest, Flh) { + this->enc_->ParseInstruction(kFlh); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFlh); } -TEST_F(ZfhEncodingTest, Flh_imm12) { +TYPED_TEST(ZfhEncodingTest, Flh_imm12) { for (int iter = 0; iter < 1000; ++iter) { int32_t expected_imm = - absl::Uniform<int32_t>(gen_, -1 * (1 << 11), 1 << 11); + absl::Uniform<int32_t>(this->gen_, -1 * (1 << 11), 1 << 11); bool sign = expected_imm < 0; uint32_t imm_adjustment = (sign ? 0x8000'0000 : 0) | ((expected_imm & 0x0000'07FF) << 20); - enc_->ParseInstruction(kFlh | imm_adjustment); + this->enc_->ParseInstruction(kFlh | imm_adjustment); std::unique_ptr<ImmediateOperand<int32_t>> src( - static_cast<ImmediateOperand<int32_t> *>( - enc_->GetSource(SlotEnum::kRiscv32Zfh, 0, OpcodeEnum::kFlh, - SourceOpEnum::kIImm12, 0))); + static_cast<ImmediateOperand<int32_t> *>(this->enc_->GetSource( + this->expected_slot_, 0, TypeParam::OpcodeEnum::kFlh, + TypeParam::SourceOpEnum::kIImm12, 0))); EXPECT_EQ(src->AsInt32(0), expected_imm); } } -TEST_F(ZfhEncodingTest, Flh_rs1) { ScalarRs1Helper(kFlh, OpcodeEnum::kFlh); } - -TEST_F(ZfhEncodingTest, Flh_frd) { FloatFrdHelper(kFlh, OpcodeEnum::kFlh); } - -TEST_F(ZfhEncodingTest, Fsh) { - enc_->ParseInstruction(kFsh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFsh); +TYPED_TEST(ZfhEncodingTest, Flh_rs1) { + using XValue = typename TypeParam::XValue; + std::vector<int> failed_scalar_sources; + for (int register_index = 0; register_index < 32; register_index++) { + XValue test_register_value = this->RandomizeScalarRegister(register_index); + this->ParseInstructionWithRs1(kFlh, register_index); + XValue source_value = this->GetRs1SourceValue(TypeParam::OpcodeEnum::kFlh); + if (source_value != test_register_value) { + failed_scalar_sources.push_back(register_index); + } + } + EXPECT_THAT(failed_scalar_sources, ::testing::IsEmpty()); } -TEST_F(ZfhEncodingTest, Fsh_imm12) { +TYPED_TEST(ZfhEncodingTest, Flh_frd) { + this->FloatFrdHelper(kFlh, TypeParam::OpcodeEnum::kFlh); +} + +TYPED_TEST(ZfhEncodingTest, Fsh) { + this->enc_->ParseInstruction(kFsh); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsh); +} + +TYPED_TEST(ZfhEncodingTest, Fsh_imm12) { for (int iter = 0; iter < 1000; ++iter) { int32_t expected_imm = - absl::Uniform<int32_t>(gen_, -1 * (1 << 11), 1 << 11); + absl::Uniform<int32_t>(this->gen_, -1 * (1 << 11), 1 << 11); bool sign = expected_imm < 0; uint32_t imm_adjustment = (sign ? 0x8000'0000 : 0) | ((expected_imm & 0x0000'001F) << 7) | ((expected_imm & 0x0000'07E0) << 20); - enc_->ParseInstruction(kFsh | imm_adjustment); + this->enc_->ParseInstruction(kFsh | imm_adjustment); std::unique_ptr<ImmediateOperand<int32_t>> src( - static_cast<ImmediateOperand<int32_t> *>( - enc_->GetSource(SlotEnum::kRiscv32Zfh, 0, OpcodeEnum::kFsh, - SourceOpEnum::kSImm12, 0))); + static_cast<ImmediateOperand<int32_t> *>(this->enc_->GetSource( + this->expected_slot_, 0, TypeParam::OpcodeEnum::kFsh, + TypeParam::SourceOpEnum::kSImm12, 0))); EXPECT_EQ(src->AsInt32(0), expected_imm); } } -TEST_F(ZfhEncodingTest, Fsh_rs1) { ScalarRs1Helper(kFsh, OpcodeEnum::kFsh); } - -TEST_F(ZfhEncodingTest, Fsh_frs2) { FloatFrs2Helper(kFsh, OpcodeEnum::kFsh); } - -TEST_F(ZfhEncodingTest, FmvXh) { - enc_->ParseInstruction(kFmvXh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFmvXh); +TYPED_TEST(ZfhEncodingTest, Fsh_rs1) { + using XValue = typename TypeParam::XValue; + std::vector<int> failed_scalar_sources; + for (int register_index = 0; register_index < 32; register_index++) { + XValue test_register_value = this->RandomizeScalarRegister(register_index); + this->ParseInstructionWithRs1(kFsh, register_index); + XValue source_value = this->GetRs1SourceValue(TypeParam::OpcodeEnum::kFsh); + if (source_value != test_register_value) { + failed_scalar_sources.push_back(register_index); + } + } + EXPECT_THAT(failed_scalar_sources, ::testing::IsEmpty()); } -TEST_F(ZfhEncodingTest, FmvXh_frs1) { - FloatFrs1Helper(kFmvXh, OpcodeEnum::kFmvXh); +TYPED_TEST(ZfhEncodingTest, Fsh_frs2) { + this->FloatFrs2Helper(kFsh, TypeParam::OpcodeEnum::kFsh); } -TEST_F(ZfhEncodingTest, FmvXh_rd) { +TYPED_TEST(ZfhEncodingTest, FmvXh) { + this->enc_->ParseInstruction(kFmvXh); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmvXh); +} + +TYPED_TEST(ZfhEncodingTest, FmvXh_frs1) { + this->FloatFrs1Helper(kFmvXh, TypeParam::OpcodeEnum::kFmvXh); +} + +TYPED_TEST(ZfhEncodingTest, FmvXh_rd) { + using XRegister = TypeParam::XRegister; + using XValue = typename TypeParam::XRegister::ValueType; for (uint32_t rd_index = 1; rd_index < 32; ++rd_index) { uint32_t rd_adjustment = rd_index << 7; - uint32_t expected_value = absl::Uniform<uint32_t>(gen_); - RVXRegister *rd_reg; + XValue expected_value = absl::Uniform<XValue>(this->gen_); + XRegister *rd_reg; std::tie(rd_reg, std::ignore) = - state_->GetRegister<RVXRegister>(absl::StrCat("x", rd_index)); - rd_reg->data_buffer()->Set<uint32_t>(0, expected_value); - enc_->ParseInstruction(kFmvXh | rd_adjustment); - std::unique_ptr<RegisterDestinationOperand<RVXRegister>> dst( - static_cast<RegisterDestinationOperand<RVXRegister> *>( - enc_->GetDestination(SlotEnum::kRiscv32Zfh, 0, OpcodeEnum::kFmvXh, - DestOpEnum::kRd, 0, 0))); - uint32_t observed_value = - dst->GetRegister()->data_buffer()->Get<uint32_t>(0); + this->state_->template GetRegister<XRegister>( + absl::StrCat("x", rd_index)); + rd_reg->data_buffer()->template Set<XValue>(0, expected_value); + this->enc_->ParseInstruction(kFmvXh | rd_adjustment); + std::unique_ptr<RegisterDestinationOperand<XRegister>> dst( + static_cast<RegisterDestinationOperand<XRegister> *>( + this->enc_->GetDestination(this->expected_slot_, 0, + TypeParam::OpcodeEnum::kFmvXh, + TypeParam::DestOpEnum::kRd, 0, 0))); + XValue observed_value = + dst->GetRegister()->data_buffer()->template Get<XValue>(0); EXPECT_EQ(observed_value, expected_value); } } -TEST_F(ZfhEncodingTest, FmvHx) { - enc_->ParseInstruction(kFmvHx); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFmvHx); +TYPED_TEST(ZfhEncodingTest, FmvHx) { + this->enc_->ParseInstruction(kFmvHx); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmvHx); } -TEST_F(ZfhEncodingTest, FmvHx_rs1) { - ScalarRs1Helper(kFmvHx, OpcodeEnum::kFmvHx); +TYPED_TEST(ZfhEncodingTest, FmvHx_rs1) { + using XValue = typename TypeParam::XValue; + std::vector<int> failed_scalar_sources; + for (int register_index = 0; register_index < 32; register_index++) { + XValue test_register_value = this->RandomizeScalarRegister(register_index); + this->ParseInstructionWithRs1(kFmvHx, register_index); + XValue source_value = + this->GetRs1SourceValue(TypeParam::OpcodeEnum::kFmvHx); + if (source_value != test_register_value) { + failed_scalar_sources.push_back(register_index); + } + } + EXPECT_THAT(failed_scalar_sources, ::testing::IsEmpty()); } -TEST_F(ZfhEncodingTest, FmvHx_frd) { - FloatFrdHelper(kFmvHx, OpcodeEnum::kFmvHx); +TYPED_TEST(ZfhEncodingTest, FmvHx_frd) { + this->FloatFrdHelper(kFmvHx, TypeParam::OpcodeEnum::kFmvHx); } -TEST_F(ZfhEncodingTest, FcvtSh) { - enc_->ParseInstruction(kFcvtSh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtSh); +TYPED_TEST(ZfhEncodingTest, FcvtSh) { + this->enc_->ParseInstruction(kFcvtSh); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtSh); } -TEST_F(ZfhEncodingTest, FcvtSh_frs1) { - FloatFrs1Helper(kFcvtSh, OpcodeEnum::kFcvtSh); +TYPED_TEST(ZfhEncodingTest, FcvtSh_frs1) { + this->FloatFrs1Helper(kFcvtSh, TypeParam::OpcodeEnum::kFcvtSh); } -TEST_F(ZfhEncodingTest, FcvtSh_frd) { - FloatFrdHelper(kFcvtSh, OpcodeEnum::kFcvtSh); +TYPED_TEST(ZfhEncodingTest, FcvtSh_frd) { + this->FloatFrdHelper(kFcvtSh, TypeParam::OpcodeEnum::kFcvtSh); } -TEST_F(ZfhEncodingTest, FcvtSh_rm) { - FloatRmHelper(kFcvtSh, OpcodeEnum::kFcvtSh); +TYPED_TEST(ZfhEncodingTest, FcvtSh_rm) { + this->FloatRmHelper(kFcvtSh, TypeParam::OpcodeEnum::kFcvtSh); } -TEST_F(ZfhEncodingTest, FcvtHs) { - enc_->ParseInstruction(kFcvtHs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtHs); +TYPED_TEST(ZfhEncodingTest, FcvtHs) { + this->enc_->ParseInstruction(kFcvtHs); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHs); } -TEST_F(ZfhEncodingTest, FcvtHs_frs1) { - FloatFrs1Helper(kFcvtHs, OpcodeEnum::kFcvtHs); +TYPED_TEST(ZfhEncodingTest, FcvtHs_frs1) { + this->FloatFrs1Helper(kFcvtHs, TypeParam::OpcodeEnum::kFcvtHs); } -TEST_F(ZfhEncodingTest, FcvtHs_frd) { - FloatFrdHelper(kFcvtHs, OpcodeEnum::kFcvtHs); +TYPED_TEST(ZfhEncodingTest, FcvtHs_frd) { + this->FloatFrdHelper(kFcvtHs, TypeParam::OpcodeEnum::kFcvtHs); } -TEST_F(ZfhEncodingTest, FcvtHs_rm) { - FloatRmHelper(kFcvtHs, OpcodeEnum::kFcvtHs); +TYPED_TEST(ZfhEncodingTest, FcvtHs_rm) { + this->FloatRmHelper(kFcvtHs, TypeParam::OpcodeEnum::kFcvtHs); } -TEST_F(ZfhEncodingTest, FcvtDh) { - enc_->ParseInstruction(kFcvtDh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtDh); +TYPED_TEST(ZfhEncodingTest, FcvtDh) { + this->enc_->ParseInstruction(kFcvtDh); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtDh); } -TEST_F(ZfhEncodingTest, FcvtDh_frs1) { - FloatFrs1Helper(kFcvtDh, OpcodeEnum::kFcvtDh); +TYPED_TEST(ZfhEncodingTest, FcvtDh_frs1) { + this->FloatFrs1Helper(kFcvtDh, TypeParam::OpcodeEnum::kFcvtDh); } -TEST_F(ZfhEncodingTest, FcvtDh_frd) { - FloatFrdHelper(kFcvtDh, OpcodeEnum::kFcvtDh); +TYPED_TEST(ZfhEncodingTest, FcvtDh_frd) { + this->FloatFrdHelper(kFcvtDh, TypeParam::OpcodeEnum::kFcvtDh); } -TEST_F(ZfhEncodingTest, FcvtDh_rm) { - FloatRmHelper(kFcvtDh, OpcodeEnum::kFcvtDh); +TYPED_TEST(ZfhEncodingTest, FcvtDh_rm) { + this->FloatRmHelper(kFcvtDh, TypeParam::OpcodeEnum::kFcvtDh); } -TEST_F(ZfhEncodingTest, FcvtHd) { - enc_->ParseInstruction(kFcvtHd); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtHd); +TYPED_TEST(ZfhEncodingTest, FcvtHd) { + this->enc_->ParseInstruction(kFcvtHd); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHd); } -TEST_F(ZfhEncodingTest, FcvtHd_frs1) { - FloatFrs1Helper(kFcvtHd, OpcodeEnum::kFcvtHd); +TYPED_TEST(ZfhEncodingTest, FcvtHd_frs1) { + this->FloatFrs1Helper(kFcvtHd, TypeParam::OpcodeEnum::kFcvtHd); } -TEST_F(ZfhEncodingTest, FcvtHd_frd) { - FloatFrdHelper(kFcvtHd, OpcodeEnum::kFcvtHd); +TYPED_TEST(ZfhEncodingTest, FcvtHd_frd) { + this->FloatFrdHelper(kFcvtHd, TypeParam::OpcodeEnum::kFcvtHd); } -TEST_F(ZfhEncodingTest, FcvtHd_rm) { - FloatRmHelper(kFcvtHd, OpcodeEnum::kFcvtHd); +TYPED_TEST(ZfhEncodingTest, FcvtHd_rm) { + this->FloatRmHelper(kFcvtHd, TypeParam::OpcodeEnum::kFcvtHd); } -TEST_F(ZfhEncodingTest, FaddH) { - enc_->ParseInstruction(kFaddH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFaddH); +TYPED_TEST(ZfhEncodingTest, FaddH) { + this->enc_->ParseInstruction(kFaddH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFaddH); } -TEST_F(ZfhEncodingTest, FaddH_frs1) { - FloatFrs1Helper(kFaddH, OpcodeEnum::kFaddH); +TYPED_TEST(ZfhEncodingTest, FaddH_frs1) { + this->FloatFrs1Helper(kFaddH, TypeParam::OpcodeEnum::kFaddH); } -TEST_F(ZfhEncodingTest, FaddH_frs2) { - FloatFrs2Helper(kFaddH, OpcodeEnum::kFaddH); +TYPED_TEST(ZfhEncodingTest, FaddH_frs2) { + this->FloatFrs2Helper(kFaddH, TypeParam::OpcodeEnum::kFaddH); } -TEST_F(ZfhEncodingTest, FaddH_frd) { - FloatFrdHelper(kFaddH, OpcodeEnum::kFaddH); +TYPED_TEST(ZfhEncodingTest, FaddH_frd) { + this->FloatFrdHelper(kFaddH, TypeParam::OpcodeEnum::kFaddH); } -TEST_F(ZfhEncodingTest, FaddH_rm) { FloatRmHelper(kFaddH, OpcodeEnum::kFaddH); } +TYPED_TEST(ZfhEncodingTest, FaddH_rm) { + this->FloatRmHelper(kFaddH, TypeParam::OpcodeEnum::kFaddH); +} -TEST_F(ZfhEncodingTest, FsubH) { - enc_->ParseInstruction(kFsubH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFsubH); +TYPED_TEST(ZfhEncodingTest, FsubH) { + this->enc_->ParseInstruction(kFsubH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsubH); } -TEST_F(ZfhEncodingTest, FsubH_frs1) { - FloatFrs1Helper(kFsubH, OpcodeEnum::kFsubH); +TYPED_TEST(ZfhEncodingTest, FsubH_frs1) { + this->FloatFrs1Helper(kFsubH, TypeParam::OpcodeEnum::kFsubH); } -TEST_F(ZfhEncodingTest, FsubH_frs2) { - FloatFrs2Helper(kFsubH, OpcodeEnum::kFsubH); +TYPED_TEST(ZfhEncodingTest, FsubH_frs2) { + this->FloatFrs2Helper(kFsubH, TypeParam::OpcodeEnum::kFsubH); } -TEST_F(ZfhEncodingTest, FsubH_frd) { - FloatFrdHelper(kFsubH, OpcodeEnum::kFsubH); +TYPED_TEST(ZfhEncodingTest, FsubH_frd) { + this->FloatFrdHelper(kFsubH, TypeParam::OpcodeEnum::kFsubH); } -TEST_F(ZfhEncodingTest, FsubH_rm) { FloatRmHelper(kFsubH, OpcodeEnum::kFsubH); } +TYPED_TEST(ZfhEncodingTest, FsubH_rm) { + this->FloatRmHelper(kFsubH, TypeParam::OpcodeEnum::kFsubH); +} -TEST_F(ZfhEncodingTest, FmulH) { - enc_->ParseInstruction(kFmulH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFmulH); +TYPED_TEST(ZfhEncodingTest, FmulH) { + this->enc_->ParseInstruction(kFmulH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmulH); } -TEST_F(ZfhEncodingTest, FmulH_frs1) { - FloatFrs1Helper(kFmulH, OpcodeEnum::kFmulH); +TYPED_TEST(ZfhEncodingTest, FmulH_frs1) { + this->FloatFrs1Helper(kFmulH, TypeParam::OpcodeEnum::kFmulH); } -TEST_F(ZfhEncodingTest, FmulH_frs2) { - FloatFrs2Helper(kFmulH, OpcodeEnum::kFmulH); +TYPED_TEST(ZfhEncodingTest, FmulH_frs2) { + this->FloatFrs2Helper(kFmulH, TypeParam::OpcodeEnum::kFmulH); } -TEST_F(ZfhEncodingTest, FmulH_frd) { - FloatFrdHelper(kFmulH, OpcodeEnum::kFmulH); +TYPED_TEST(ZfhEncodingTest, FmulH_frd) { + this->FloatFrdHelper(kFmulH, TypeParam::OpcodeEnum::kFmulH); } -TEST_F(ZfhEncodingTest, FmulH_rm) { FloatRmHelper(kFmulH, OpcodeEnum::kFmulH); } +TYPED_TEST(ZfhEncodingTest, FmulH_rm) { + this->FloatRmHelper(kFmulH, TypeParam::OpcodeEnum::kFmulH); +} -TEST_F(ZfhEncodingTest, FdivH) { - enc_->ParseInstruction(kFdivH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFdivH); +TYPED_TEST(ZfhEncodingTest, FdivH) { + this->enc_->ParseInstruction(kFdivH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFdivH); } -TEST_F(ZfhEncodingTest, FdivH_frs1) { - FloatFrs1Helper(kFdivH, OpcodeEnum::kFdivH); +TYPED_TEST(ZfhEncodingTest, FdivH_frs1) { + this->FloatFrs1Helper(kFdivH, TypeParam::OpcodeEnum::kFdivH); } -TEST_F(ZfhEncodingTest, FdivH_frs2) { - FloatFrs2Helper(kFdivH, OpcodeEnum::kFdivH); +TYPED_TEST(ZfhEncodingTest, FdivH_frs2) { + this->FloatFrs2Helper(kFdivH, TypeParam::OpcodeEnum::kFdivH); } -TEST_F(ZfhEncodingTest, FdivH_frd) { - FloatFrdHelper(kFdivH, OpcodeEnum::kFdivH); +TYPED_TEST(ZfhEncodingTest, FdivH_frd) { + this->FloatFrdHelper(kFdivH, TypeParam::OpcodeEnum::kFdivH); } -TEST_F(ZfhEncodingTest, FdivH_rm) { FloatRmHelper(kFdivH, OpcodeEnum::kFdivH); } +TYPED_TEST(ZfhEncodingTest, FdivH_rm) { + this->FloatRmHelper(kFdivH, TypeParam::OpcodeEnum::kFdivH); +} -TEST_F(ZfhEncodingTest, FminH) { - enc_->ParseInstruction(kFminH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFminH); +TYPED_TEST(ZfhEncodingTest, FminH) { + this->enc_->ParseInstruction(kFminH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFminH); } -TEST_F(ZfhEncodingTest, FminH_frs1) { - FloatFrs1Helper(kFminH, OpcodeEnum::kFminH); +TYPED_TEST(ZfhEncodingTest, FminH_frs1) { + this->FloatFrs1Helper(kFminH, TypeParam::OpcodeEnum::kFminH); } -TEST_F(ZfhEncodingTest, FminH_frs2) { - FloatFrs2Helper(kFminH, OpcodeEnum::kFminH); +TYPED_TEST(ZfhEncodingTest, FminH_frs2) { + this->FloatFrs2Helper(kFminH, TypeParam::OpcodeEnum::kFminH); } -TEST_F(ZfhEncodingTest, FminH_frd) { - FloatFrdHelper(kFminH, OpcodeEnum::kFminH); +TYPED_TEST(ZfhEncodingTest, FminH_frd) { + this->FloatFrdHelper(kFminH, TypeParam::OpcodeEnum::kFminH); } -TEST_F(ZfhEncodingTest, FmaxH) { - enc_->ParseInstruction(kFmaxH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFmaxH); +TYPED_TEST(ZfhEncodingTest, FmaxH) { + this->enc_->ParseInstruction(kFmaxH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmaxH); } -TEST_F(ZfhEncodingTest, FmaxH_frs1) { - FloatFrs1Helper(kFmaxH, OpcodeEnum::kFmaxH); +TYPED_TEST(ZfhEncodingTest, FmaxH_frs1) { + this->FloatFrs1Helper(kFmaxH, TypeParam::OpcodeEnum::kFmaxH); } -TEST_F(ZfhEncodingTest, FmaxH_frs2) { - FloatFrs2Helper(kFmaxH, OpcodeEnum::kFmaxH); +TYPED_TEST(ZfhEncodingTest, FmaxH_frs2) { + this->FloatFrs2Helper(kFmaxH, TypeParam::OpcodeEnum::kFmaxH); } -TEST_F(ZfhEncodingTest, FmaxH_frd) { - FloatFrdHelper(kFmaxH, OpcodeEnum::kFmaxH); +TYPED_TEST(ZfhEncodingTest, FmaxH_frd) { + this->FloatFrdHelper(kFmaxH, TypeParam::OpcodeEnum::kFmaxH); } -TEST_F(ZfhEncodingTest, FsgnjH) { - enc_->ParseInstruction(kFsgnjH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFsgnjH); +TYPED_TEST(ZfhEncodingTest, FsgnjH) { + this->enc_->ParseInstruction(kFsgnjH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsgnjH); } -TEST_F(ZfhEncodingTest, FsgnjH_frs1) { - FloatFrs1Helper(kFsgnjH, OpcodeEnum::kFsgnjH); +TYPED_TEST(ZfhEncodingTest, FsgnjH_frs1) { + this->FloatFrs1Helper(kFsgnjH, TypeParam::OpcodeEnum::kFsgnjH); } -TEST_F(ZfhEncodingTest, FsgnjH_frs2) { - FloatFrs2Helper(kFsgnjH, OpcodeEnum::kFsgnjH); +TYPED_TEST(ZfhEncodingTest, FsgnjH_frs2) { + this->FloatFrs2Helper(kFsgnjH, TypeParam::OpcodeEnum::kFsgnjH); } -TEST_F(ZfhEncodingTest, FsgnjH_frd) { - FloatFrdHelper(kFsgnjH, OpcodeEnum::kFsgnjH); +TYPED_TEST(ZfhEncodingTest, FsgnjH_frd) { + this->FloatFrdHelper(kFsgnjH, TypeParam::OpcodeEnum::kFsgnjH); } -TEST_F(ZfhEncodingTest, FsgnjnH) { - enc_->ParseInstruction(kFsgnjnH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFsgnjnH); +TYPED_TEST(ZfhEncodingTest, FsgnjnH) { + this->enc_->ParseInstruction(kFsgnjnH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsgnjnH); } -TEST_F(ZfhEncodingTest, FsgnjnH_frs1) { - FloatFrs1Helper(kFsgnjnH, OpcodeEnum::kFsgnjnH); +TYPED_TEST(ZfhEncodingTest, FsgnjnH_frs1) { + this->FloatFrs1Helper(kFsgnjnH, TypeParam::OpcodeEnum::kFsgnjnH); } -TEST_F(ZfhEncodingTest, FsgnjnH_frs2) { - FloatFrs2Helper(kFsgnjnH, OpcodeEnum::kFsgnjnH); +TYPED_TEST(ZfhEncodingTest, FsgnjnH_frs2) { + this->FloatFrs2Helper(kFsgnjnH, TypeParam::OpcodeEnum::kFsgnjnH); } -TEST_F(ZfhEncodingTest, FsgnjnH_frd) { - FloatFrdHelper(kFsgnjnH, OpcodeEnum::kFsgnjnH); +TYPED_TEST(ZfhEncodingTest, FsgnjnH_frd) { + this->FloatFrdHelper(kFsgnjnH, TypeParam::OpcodeEnum::kFsgnjnH); } -TEST_F(ZfhEncodingTest, FsgnjxH) { - enc_->ParseInstruction(kFsgnjxH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFsgnjxH); +TYPED_TEST(ZfhEncodingTest, FsgnjxH) { + this->enc_->ParseInstruction(kFsgnjxH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsgnjxH); } -TEST_F(ZfhEncodingTest, FsgnjxH_frs1) { - FloatFrs1Helper(kFsgnjxH, OpcodeEnum::kFsgnjxH); +TYPED_TEST(ZfhEncodingTest, FsgnjxH_frs1) { + this->FloatFrs1Helper(kFsgnjxH, TypeParam::OpcodeEnum::kFsgnjxH); } -TEST_F(ZfhEncodingTest, FsgnjxH_frs2) { - FloatFrs2Helper(kFsgnjxH, OpcodeEnum::kFsgnjxH); +TYPED_TEST(ZfhEncodingTest, FsgnjxH_frs2) { + this->FloatFrs2Helper(kFsgnjxH, TypeParam::OpcodeEnum::kFsgnjxH); } -TEST_F(ZfhEncodingTest, FsgnjxH_frd) { - FloatFrdHelper(kFsgnjxH, OpcodeEnum::kFsgnjxH); +TYPED_TEST(ZfhEncodingTest, FsgnjxH_frd) { + this->FloatFrdHelper(kFsgnjxH, TypeParam::OpcodeEnum::kFsgnjxH); } -TEST_F(ZfhEncodingTest, FsqrtH) { - enc_->ParseInstruction(kFsqrtH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFsqrtH); +TYPED_TEST(ZfhEncodingTest, FsqrtH) { + this->enc_->ParseInstruction(kFsqrtH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsqrtH); } -TEST_F(ZfhEncodingTest, FsqrtH_frs1) { - FloatFrs1Helper(kFsqrtH, OpcodeEnum::kFsqrtH); +TYPED_TEST(ZfhEncodingTest, FsqrtH_frs1) { + this->FloatFrs1Helper(kFsqrtH, TypeParam::OpcodeEnum::kFsqrtH); } -TEST_F(ZfhEncodingTest, FsqrtH_rm) { - FloatRmHelper(kFsqrtH, OpcodeEnum::kFsqrtH); +TYPED_TEST(ZfhEncodingTest, FsqrtH_rm) { + this->FloatRmHelper(kFsqrtH, TypeParam::OpcodeEnum::kFsqrtH); } -TEST_F(ZfhEncodingTest, FsqrtH_frd) { - FloatFrdHelper(kFsqrtH, OpcodeEnum::kFsqrtH); +TYPED_TEST(ZfhEncodingTest, FsqrtH_frd) { + this->FloatFrdHelper(kFsqrtH, TypeParam::OpcodeEnum::kFsqrtH); } -TEST_F(ZfhEncodingTest, FcvtHw) { - enc_->ParseInstruction(kFcvtHw); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtHw); +TYPED_TEST(ZfhEncodingTest, FcvtHw) { + this->enc_->ParseInstruction(kFcvtHw); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHw); } -TEST_F(ZfhEncodingTest, FcvtHw_frs1) { - FloatFrs1Helper(kFcvtHw, OpcodeEnum::kFcvtHw); +TYPED_TEST(ZfhEncodingTest, FcvtHw_frs1) { + this->FloatFrs1Helper(kFcvtHw, TypeParam::OpcodeEnum::kFcvtHw); } -TEST_F(ZfhEncodingTest, FcvtHw_rm) { - FloatRmHelper(kFcvtHw, OpcodeEnum::kFcvtHw); +TYPED_TEST(ZfhEncodingTest, FcvtHw_rm) { + this->FloatRmHelper(kFcvtHw, TypeParam::OpcodeEnum::kFcvtHw); } -TEST_F(ZfhEncodingTest, FcvtHw_frd) { - FloatFrdHelper(kFcvtHw, OpcodeEnum::kFcvtHw); +TYPED_TEST(ZfhEncodingTest, FcvtHw_frd) { + this->FloatFrdHelper(kFcvtHw, TypeParam::OpcodeEnum::kFcvtHw); } -TEST_F(ZfhEncodingTest, FcvtWh) { - enc_->ParseInstruction(kFcvtWh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtWh); +TYPED_TEST(ZfhEncodingTest, FcvtWh) { + this->enc_->ParseInstruction(kFcvtWh); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtWh); } -TEST_F(ZfhEncodingTest, FcvtWh_frs1) { - FloatFrs1Helper(kFcvtWh, OpcodeEnum::kFcvtWh); +TYPED_TEST(ZfhEncodingTest, FcvtWh_frs1) { + this->FloatFrs1Helper(kFcvtWh, TypeParam::OpcodeEnum::kFcvtWh); } -TEST_F(ZfhEncodingTest, FcvtWh_rm) { - FloatRmHelper(kFcvtWh, OpcodeEnum::kFcvtWh); +TYPED_TEST(ZfhEncodingTest, FcvtWh_rm) { + this->FloatRmHelper(kFcvtWh, TypeParam::OpcodeEnum::kFcvtWh); } -TEST_F(ZfhEncodingTest, FcvtWh_frd) { - FloatFrdHelper(kFcvtWh, OpcodeEnum::kFcvtWh); +TYPED_TEST(ZfhEncodingTest, FcvtWh_frd) { + this->FloatFrdHelper(kFcvtWh, TypeParam::OpcodeEnum::kFcvtWh); } -TEST_F(ZfhEncodingTest, FcvtHwu) { - enc_->ParseInstruction(kFcvtHwu); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtHwu); +TYPED_TEST(ZfhEncodingTest, FcvtHwu) { + this->enc_->ParseInstruction(kFcvtHwu); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHwu); } -TEST_F(ZfhEncodingTest, FcvtHwu_frs1) { - FloatFrs1Helper(kFcvtHwu, OpcodeEnum::kFcvtHwu); +TYPED_TEST(ZfhEncodingTest, FcvtHwu_frs1) { + this->FloatFrs1Helper(kFcvtHwu, TypeParam::OpcodeEnum::kFcvtHwu); } -TEST_F(ZfhEncodingTest, FcvtHwu_rm) { - FloatRmHelper(kFcvtHwu, OpcodeEnum::kFcvtHwu); +TYPED_TEST(ZfhEncodingTest, FcvtHwu_rm) { + this->FloatRmHelper(kFcvtHwu, TypeParam::OpcodeEnum::kFcvtHwu); } -TEST_F(ZfhEncodingTest, FcvtHwu_frd) { - FloatFrdHelper(kFcvtHwu, OpcodeEnum::kFcvtHwu); +TYPED_TEST(ZfhEncodingTest, FcvtHwu_frd) { + this->FloatFrdHelper(kFcvtHwu, TypeParam::OpcodeEnum::kFcvtHwu); } -TEST_F(ZfhEncodingTest, FcvtWuh) { - enc_->ParseInstruction(kFcvtWuh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtWuh); +TYPED_TEST(ZfhEncodingTest, FcvtWuh) { + this->enc_->ParseInstruction(kFcvtWuh); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtWuh); } -TEST_F(ZfhEncodingTest, FcvtWuh_frs1) { - FloatFrs1Helper(kFcvtWuh, OpcodeEnum::kFcvtWuh); +TYPED_TEST(ZfhEncodingTest, FcvtWuh_frs1) { + this->FloatFrs1Helper(kFcvtWuh, TypeParam::OpcodeEnum::kFcvtWuh); } -TEST_F(ZfhEncodingTest, FcvtWuh_rm) { - FloatRmHelper(kFcvtWuh, OpcodeEnum::kFcvtWuh); +TYPED_TEST(ZfhEncodingTest, FcvtWuh_rm) { + this->FloatRmHelper(kFcvtWuh, TypeParam::OpcodeEnum::kFcvtWuh); } -TEST_F(ZfhEncodingTest, FcvtWuh_frd) { - FloatFrdHelper(kFcvtWuh, OpcodeEnum::kFcvtWuh); +TYPED_TEST(ZfhEncodingTest, FcvtWuh_frd) { + this->FloatFrdHelper(kFcvtWuh, TypeParam::OpcodeEnum::kFcvtWuh); } -TEST_F(ZfhEncodingTest, FcmpeqH) { - enc_->ParseInstruction(kFcmpeqH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcmpeqH); +TYPED_TEST(ZfhEncodingTest, FcmpeqH) { + this->enc_->ParseInstruction(kFcmpeqH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcmpeqH); } -TEST_F(ZfhEncodingTest, FcmpeqH_frs1) { - FloatFrs1Helper(kFcmpeqH, OpcodeEnum::kFcmpeqH); +TYPED_TEST(ZfhEncodingTest, FcmpeqH_frs1) { + this->FloatFrs1Helper(kFcmpeqH, TypeParam::OpcodeEnum::kFcmpeqH); } -TEST_F(ZfhEncodingTest, FcmpeqH_frs2) { - FloatFrs2Helper(kFcmpeqH, OpcodeEnum::kFcmpeqH); +TYPED_TEST(ZfhEncodingTest, FcmpeqH_frs2) { + this->FloatFrs2Helper(kFcmpeqH, TypeParam::OpcodeEnum::kFcmpeqH); } -TEST_F(ZfhEncodingTest, FcmpeqH_frd) { - FloatFrdHelper(kFcmpeqH, OpcodeEnum::kFcmpeqH); +TYPED_TEST(ZfhEncodingTest, FcmpeqH_frd) { + this->FloatFrdHelper(kFcmpeqH, TypeParam::OpcodeEnum::kFcmpeqH); } -TEST_F(ZfhEncodingTest, FcmpltH) { - enc_->ParseInstruction(kFcmpltH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcmpltH); +TYPED_TEST(ZfhEncodingTest, FcmpltH) { + this->enc_->ParseInstruction(kFcmpltH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcmpltH); } -TEST_F(ZfhEncodingTest, FcmpltH_frs1) { - FloatFrs1Helper(kFcmpltH, OpcodeEnum::kFcmpltH); +TYPED_TEST(ZfhEncodingTest, FcmpltH_frs1) { + this->FloatFrs1Helper(kFcmpltH, TypeParam::OpcodeEnum::kFcmpltH); } -TEST_F(ZfhEncodingTest, FcmpltH_frs2) { - FloatFrs2Helper(kFcmpltH, OpcodeEnum::kFcmpltH); +TYPED_TEST(ZfhEncodingTest, FcmpltH_frs2) { + this->FloatFrs2Helper(kFcmpltH, TypeParam::OpcodeEnum::kFcmpltH); } -TEST_F(ZfhEncodingTest, FcmpltH_frd) { - FloatFrdHelper(kFcmpltH, OpcodeEnum::kFcmpltH); +TYPED_TEST(ZfhEncodingTest, FcmpltH_frd) { + this->FloatFrdHelper(kFcmpltH, TypeParam::OpcodeEnum::kFcmpltH); } -TEST_F(ZfhEncodingTest, FcmpleH) { - enc_->ParseInstruction(kFcmpleH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcmpleH); +TYPED_TEST(ZfhEncodingTest, FcmpleH) { + this->enc_->ParseInstruction(kFcmpleH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcmpleH); } -TEST_F(ZfhEncodingTest, FcmpleH_frs1) { - FloatFrs1Helper(kFcmpleH, OpcodeEnum::kFcmpleH); +TYPED_TEST(ZfhEncodingTest, FcmpleH_frs1) { + this->FloatFrs1Helper(kFcmpleH, TypeParam::OpcodeEnum::kFcmpleH); } -TEST_F(ZfhEncodingTest, FcmpleH_frs2) { - FloatFrs2Helper(kFcmpleH, OpcodeEnum::kFcmpleH); +TYPED_TEST(ZfhEncodingTest, FcmpleH_frs2) { + this->FloatFrs2Helper(kFcmpleH, TypeParam::OpcodeEnum::kFcmpleH); } -TEST_F(ZfhEncodingTest, FcmpleH_frd) { - FloatFrdHelper(kFcmpleH, OpcodeEnum::kFcmpleH); +TYPED_TEST(ZfhEncodingTest, FcmpleH_frd) { + this->FloatFrdHelper(kFcmpleH, TypeParam::OpcodeEnum::kFcmpleH); } -TEST_F(ZfhEncodingTest, FclassH) { - enc_->ParseInstruction(kFclassH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFclassH); +TYPED_TEST(ZfhEncodingTest, FclassH) { + this->enc_->ParseInstruction(kFclassH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFclassH); } -TEST_F(ZfhEncodingTest, FclassH_frs1) { - FloatFrs1Helper(kFclassH, OpcodeEnum::kFclassH); +TYPED_TEST(ZfhEncodingTest, FclassH_frs1) { + this->FloatFrs1Helper(kFclassH, TypeParam::OpcodeEnum::kFclassH); } -TEST_F(ZfhEncodingTest, FclassH_frd) { - FloatFrdHelper(kFclassH, OpcodeEnum::kFclassH); +TYPED_TEST(ZfhEncodingTest, FclassH_frd) { + this->FloatFrdHelper(kFclassH, TypeParam::OpcodeEnum::kFclassH); } -TEST_F(ZfhEncodingTest, FmaddH) { - enc_->ParseInstruction(kFmaddH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFmaddH); +TYPED_TEST(ZfhEncodingTest, FmaddH) { + this->enc_->ParseInstruction(kFmaddH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmaddH); } -TEST_F(ZfhEncodingTest, FmaddH_frs1) { - FloatFrs1Helper(kFmaddH, OpcodeEnum::kFmaddH); +TYPED_TEST(ZfhEncodingTest, FmaddH_frs1) { + this->FloatFrs1Helper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH); } -TEST_F(ZfhEncodingTest, FmaddH_frs2) { - FloatFrs2Helper(kFmaddH, OpcodeEnum::kFmaddH); +TYPED_TEST(ZfhEncodingTest, FmaddH_frs2) { + this->FloatFrs2Helper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH); } -TEST_F(ZfhEncodingTest, FmaddH_frs3) { - FloatFrs3Helper(kFmaddH, OpcodeEnum::kFmaddH); +TYPED_TEST(ZfhEncodingTest, FmaddH_frs3) { + this->FloatFrs3Helper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH); } -TEST_F(ZfhEncodingTest, FmaddH_rm) { - FloatRmHelper(kFmaddH, OpcodeEnum::kFmaddH); +TYPED_TEST(ZfhEncodingTest, FmaddH_rm) { + this->FloatRmHelper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH); } -TEST_F(ZfhEncodingTest, FmaddH_frd) { - FloatFrdHelper(kFmaddH, OpcodeEnum::kFmaddH); +TYPED_TEST(ZfhEncodingTest, FmaddH_frd) { + this->FloatFrdHelper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH); } -TEST_F(ZfhEncodingTest, FmsubH) { - enc_->ParseInstruction(kFmsubH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFmsubH); +TYPED_TEST(ZfhEncodingTest, FmsubH) { + this->enc_->ParseInstruction(kFmsubH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmsubH); } -TEST_F(ZfhEncodingTest, FmsubH_frs1) { - FloatFrs1Helper(kFmsubH, OpcodeEnum::kFmsubH); +TYPED_TEST(ZfhEncodingTest, FmsubH_frs1) { + this->FloatFrs1Helper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH); } -TEST_F(ZfhEncodingTest, FmsubH_frs2) { - FloatFrs2Helper(kFmsubH, OpcodeEnum::kFmsubH); +TYPED_TEST(ZfhEncodingTest, FmsubH_frs2) { + this->FloatFrs2Helper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH); } -TEST_F(ZfhEncodingTest, FmsubH_frs3) { - FloatFrs3Helper(kFmsubH, OpcodeEnum::kFmsubH); +TYPED_TEST(ZfhEncodingTest, FmsubH_frs3) { + this->FloatFrs3Helper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH); } -TEST_F(ZfhEncodingTest, FmsubH_rm) { - FloatRmHelper(kFmsubH, OpcodeEnum::kFmsubH); +TYPED_TEST(ZfhEncodingTest, FmsubH_rm) { + this->FloatRmHelper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH); } -TEST_F(ZfhEncodingTest, FmsubH_frd) { - FloatFrdHelper(kFmsubH, OpcodeEnum::kFmsubH); +TYPED_TEST(ZfhEncodingTest, FmsubH_frd) { + this->FloatFrdHelper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH); } -TEST_F(ZfhEncodingTest, FnmaddH) { - enc_->ParseInstruction(kFnmaddH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFnmaddH); +TYPED_TEST(ZfhEncodingTest, FnmaddH) { + this->enc_->ParseInstruction(kFnmaddH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFnmaddH); } -TEST_F(ZfhEncodingTest, FnmaddH_frs1) { - FloatFrs1Helper(kFnmaddH, OpcodeEnum::kFnmaddH); +TYPED_TEST(ZfhEncodingTest, FnmaddH_frs1) { + this->FloatFrs1Helper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH); } -TEST_F(ZfhEncodingTest, FnmaddH_frs2) { - FloatFrs2Helper(kFnmaddH, OpcodeEnum::kFnmaddH); +TYPED_TEST(ZfhEncodingTest, FnmaddH_frs2) { + this->FloatFrs2Helper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH); } -TEST_F(ZfhEncodingTest, FnmaddH_frs3) { - FloatFrs3Helper(kFnmaddH, OpcodeEnum::kFnmaddH); +TYPED_TEST(ZfhEncodingTest, FnmaddH_frs3) { + this->FloatFrs3Helper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH); } -TEST_F(ZfhEncodingTest, FnmaddH_rm) { - FloatRmHelper(kFnmaddH, OpcodeEnum::kFnmaddH); +TYPED_TEST(ZfhEncodingTest, FnmaddH_rm) { + this->FloatRmHelper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH); } -TEST_F(ZfhEncodingTest, FnmaddH_frd) { - FloatFrdHelper(kFnmaddH, OpcodeEnum::kFnmaddH); +TYPED_TEST(ZfhEncodingTest, FnmaddH_frd) { + this->FloatFrdHelper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH); } -TEST_F(ZfhEncodingTest, FnmsubH) { - enc_->ParseInstruction(kFnmsubH); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFnmsubH); +TYPED_TEST(ZfhEncodingTest, FnmsubH) { + this->enc_->ParseInstruction(kFnmsubH); + EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFnmsubH); } -TEST_F(ZfhEncodingTest, FnmsubH_frs1) { - FloatFrs1Helper(kFnmsubH, OpcodeEnum::kFnmsubH); +TYPED_TEST(ZfhEncodingTest, FnmsubH_frs1) { + this->FloatFrs1Helper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH); } -TEST_F(ZfhEncodingTest, FnmsubH_frs2) { - FloatFrs2Helper(kFnmsubH, OpcodeEnum::kFnmsubH); +TYPED_TEST(ZfhEncodingTest, FnmsubH_frs2) { + this->FloatFrs2Helper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH); } -TEST_F(ZfhEncodingTest, FnmsubH_frs3) { - FloatFrs3Helper(kFnmsubH, OpcodeEnum::kFnmsubH); +TYPED_TEST(ZfhEncodingTest, FnmsubH_frs3) { + this->FloatFrs3Helper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH); } -TEST_F(ZfhEncodingTest, FnmsubH_rm) { - FloatRmHelper(kFnmsubH, OpcodeEnum::kFnmsubH); +TYPED_TEST(ZfhEncodingTest, FnmsubH_rm) { + this->FloatRmHelper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH); } -TEST_F(ZfhEncodingTest, FnmsubH_frd) { - FloatFrdHelper(kFnmsubH, OpcodeEnum::kFnmsubH); +TYPED_TEST(ZfhEncodingTest, FnmsubH_frd) { + this->FloatFrdHelper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH); } } // namespace