| // 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 |
| // |
| // 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. |
| |
| #ifndef THIRD_PARTY_MPACT_RISCV_TEST_RISCV_GETTERS_ZFH_H_ |
| #define THIRD_PARTY_MPACT_RISCV_TEST_RISCV_GETTERS_ZFH_H_ |
| |
| #include <cstdint> |
| #include <string> |
| |
| #include "absl/strings/str_cat.h" |
| #include "mpact/sim/generic/immediate_operand.h" |
| #include "mpact/sim/generic/literal_operand.h" |
| #include "mpact/sim/generic/type_helpers.h" |
| #include "riscv/riscv_encoding_common.h" |
| #include "riscv/riscv_getter_helpers.h" |
| #include "riscv/riscv_getters_vector.h" |
| #include "riscv/riscv_register.h" |
| #include "riscv/riscv_register_aliases.h" |
| |
| namespace mpact { |
| namespace sim { |
| namespace riscv { |
| |
| using ::mpact::sim::generic::operator*; // NOLINT: is used below (clang error). |
| |
| template <typename Enum, typename Extractors, typename IntegerRegister> |
| void AddRiscVZfhSourceScalarGetters(SourceOpGetterMap &getter_map, |
| RiscVEncodingCommon *common) { |
| // Source operand getters. |
| Insert(getter_map, *Enum::kRs1, [common]() -> SourceOperandInterface * { |
| int num = Extractors::Inst32Format::ExtractRs1(common->inst_word()); |
| if (num == 0) return new generic::IntLiteralOperand<0>({1}); |
| return GetRegisterSourceOp<IntegerRegister>( |
| common->state(), absl::StrCat(RiscVState::kXregPrefix, num), |
| kXRegisterAliases[num]); |
| }); |
| // I in IImm12 stands for IType instructions. |
| Insert(getter_map, *Enum::kIImm12, [common]() -> SourceOperandInterface * { |
| const auto num = Extractors::IType::ExtractImm12(common->inst_word()); |
| return new generic::ImmediateOperand<int32_t>(num); |
| }); |
| // S in SImm12 stands for SType instructions. |
| Insert(getter_map, *Enum::kSImm12, [common]() -> SourceOperandInterface * { |
| const auto num = Extractors::SType::ExtractSImm(common->inst_word()); |
| return new generic::ImmediateOperand<int32_t>(num); |
| }); |
| Insert(getter_map, *Enum::kRm, [common]() -> SourceOperandInterface * { |
| const auto num = |
| Extractors::Inst32Format::ExtractFunc3(common->inst_word()); |
| return new generic::ImmediateOperand<uint8_t>(num); |
| }); |
| } |
| |
| template <typename Enum, typename Extractors, typename FloatRegister> |
| void AddRiscVZfhSourceFloatGetters(SourceOpGetterMap &getter_map, |
| RiscVEncodingCommon *common) { |
| // Source operand getters. |
| Insert(getter_map, *Enum::kFrs1, [common]() -> SourceOperandInterface * { |
| int num = Extractors::Inst32Format::ExtractRs1(common->inst_word()); |
| return GetRegisterSourceOp<FloatRegister>( |
| common->state(), absl::StrCat(RiscVState::kFregPrefix, num), |
| kFRegisterAliases[num]); |
| }); |
| Insert(getter_map, *Enum::kFrs2, [common]() -> SourceOperandInterface * { |
| int num = Extractors::Inst32Format::ExtractRs2(common->inst_word()); |
| return GetRegisterSourceOp<FloatRegister>( |
| common->state(), absl::StrCat(RiscVState::kFregPrefix, num), |
| kFRegisterAliases[num]); |
| }); |
| Insert(getter_map, *Enum::kFrs3, [common]() -> SourceOperandInterface * { |
| int num = Extractors::Inst32Format::ExtractRs3(common->inst_word()); |
| return GetRegisterSourceOp<FloatRegister>( |
| common->state(), absl::StrCat(RiscVState::kFregPrefix, num), |
| kFRegisterAliases[num]); |
| }); |
| } |
| |
| template <typename Enum, typename Extractors, typename IntegerRegister> |
| void AddRiscVZfhDestScalarGetters(DestOpGetterMap &getter_map, |
| RiscVEncodingCommon *common) { |
| // Destination operand getters. |
| Insert(getter_map, *Enum::kRd, |
| [common](int latency) -> DestinationOperandInterface * { |
| auto num = Extractors::Inst32Format::ExtractRd(common->inst_word()); |
| std::string name = absl::StrCat(RiscVState::kXregPrefix, num); |
| return mpact::sim::riscv::GetRegisterDestinationOp<IntegerRegister>( |
| common->state(), name, latency); |
| }); |
| Insert(getter_map, *Enum::kFflags, |
| [common](int latency) -> DestinationOperandInterface * { |
| return GetCSRSetBitsDestinationOp<uint32_t>(common->state(), |
| "fflags", latency, ""); |
| }); |
| } |
| |
| template <typename Enum, typename Extractors, typename FloatRegister> |
| void AddRiscVZfhDestFloatGetters(DestOpGetterMap &getter_map, |
| RiscVEncodingCommon *common) { |
| // Destination operand getters. |
| Insert(getter_map, *Enum::kFrd, |
| [common](int latency) -> DestinationOperandInterface * { |
| auto num = Extractors::Inst32Format::ExtractRd(common->inst_word()); |
| std::string name = absl::StrCat(RiscVState::kFregPrefix, num); |
| return mpact::sim::riscv::GetRegisterDestinationOp<FloatRegister>( |
| common->state(), name, latency); |
| }); |
| } |
| |
| // This function is used to add the simple resource getters to the given |
| // "getter map". The function is templated on the enum type that defines the |
| // simple resource types, the Extractors type that defines the bit |
| // extraction functions, and the IntRegister and FpRegister types that are used |
| // to construct the register operand. |
| template <typename Enum, typename Extractors> |
| void AddRiscVZfhSimpleResourceGetters(SimpleResourceGetterMap &getter_map, |
| RiscVEncodingCommon *common) { |
| // TODO(julianmb): Add resource getters when appropriate. |
| } |
| |
| } // namespace riscv |
| } // namespace sim |
| } // namespace mpact |
| |
| #endif // THIRD_PARTY_MPACT_RISCV_TEST_RISCV_GETTERS_ZFH_H_ |