blob: 7db0cb4e1bc38a797c0bb65d829e817aceea8f8d [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 "riscv/riscv64g_encoding.h"
#include <cstdint>
#include <string>
#include <utility>
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "mpact/sim/generic/immediate_operand.h"
#include "mpact/sim/generic/literal_operand.h"
#include "mpact/sim/generic/simple_resource.h"
#include "mpact/sim/generic/simple_resource_operand.h"
#include "riscv/riscv64g_bin_decoder.h"
#include "riscv/riscv64g_decoder.h"
#include "riscv/riscv64g_enums.h"
#include "riscv/riscv_register.h"
#include "riscv/riscv_state.h"
namespace mpact {
namespace sim {
namespace riscv {
namespace isa64 {
using generic::SimpleResourceOperand;
// Generic helper functions to create register operands.
template <typename RegType>
inline DestinationOperandInterface* GetRegisterDestinationOp(RiscVState* state,
std::string name,
int latency) {
auto* reg = state->GetRegister<RegType>(name).first;
return reg->CreateDestinationOperand(latency);
}
template <typename RegType>
inline DestinationOperandInterface* GetRegisterDestinationOp(
RiscVState* state, std::string name, int latency, std::string op_name) {
auto* reg = state->GetRegister<RegType>(name).first;
return reg->CreateDestinationOperand(latency, op_name);
}
template <typename T>
inline DestinationOperandInterface* GetCSRSetBitsDestinationOp(
RiscVState* state, std::string name, int latency, std::string op_name) {
auto result = state->csr_set()->GetCsr(name);
if (!result.ok()) {
LOG(ERROR) << "No such CSR '" << name << "'";
return nullptr;
}
auto* csr = result.value();
auto* op = csr->CreateSetDestinationOperand(latency, op_name);
return op;
}
template <typename RegType>
inline SourceOperandInterface* GetRegisterSourceOp(RiscVState* state,
std::string name) {
auto* reg = state->GetRegister<RegType>(name).first;
auto* op = reg->CreateSourceOperand();
return op;
}
template <typename RegType>
inline SourceOperandInterface* GetRegisterSourceOp(RiscVState* state,
std::string name,
std::string op_name) {
auto* reg = state->GetRegister<RegType>(name).first;
auto* op = reg->CreateSourceOperand(op_name);
return op;
}
RiscV64GEncoding::RiscV64GEncoding(RiscVState* state)
: RiscV64GEncoding(state, true) {}
RiscV64GEncoding::RiscV64GEncoding(RiscVState* state, bool use_abi_names)
: state_(state) {
if (use_abi_names) {
xreg_alias_ = xreg_abi_names_;
} else {
xreg_alias_ = xreg_names_;
}
InitializeSourceOperandGetters();
InitializeDestinationOperandGetters();
InitializeSimpleResourceGetters();
resource_pool_ = new generic::SimpleResourcePool("RiscV64G", 128);
resource_delay_line_ =
state_->CreateAndAddDelayLine<generic::SimpleResourceDelayLine>(8);
}
RiscV64GEncoding::~RiscV64GEncoding() { delete resource_pool_; }
void RiscV64GEncoding::InitializeSourceOperandGetters() {
// Source operand getters.
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kAAq),
[this]() -> SourceOperandInterface* {
if (encoding64::inst32_format::ExtractAq(inst_word_)) {
return new generic::IntLiteralOperand<1>();
}
return new generic::IntLiteralOperand<0>();
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kARl),
[this]() -> SourceOperandInterface* {
if (encoding64::inst32_format::ExtractRl(inst_word_)) {
return new generic::IntLiteralOperand<1>();
}
return new generic::IntLiteralOperand<0>();
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kIUimm6), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::r_s_type::ExtractRUimm6(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kBImm12), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::inst32_format::ExtractBImm(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kC3drs2), [this]() {
auto num = encoding64::inst16_format::ExtractCsRs2(inst_word_);
return GetRegisterSourceOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kC3rs1), [this]() {
auto num = encoding64::inst16_format::ExtractCsRs1(inst_word_);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kC3rs2), [this]() {
auto num = encoding64::inst16_format::ExtractCsRs2(inst_word_);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kCSRUimm5), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst32_format::ExtractIUimm5(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kCdrs2), [this]() {
auto num = encoding64::c_r::ExtractRs2(inst_word_);
return GetRegisterSourceOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kCrs1), [this]() {
auto num = encoding64::c_r::ExtractRs1(inst_word_);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kCrs2), [this]() {
auto num = encoding64::c_r::ExtractRs2(inst_word_);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kCsr), [this]() {
auto csr_indx = encoding64::i_type::ExtractUImm12(inst_word_);
auto res = state_->csr_set()->GetCsr(csr_indx);
if (!res.ok()) {
return new generic::ImmediateOperand<uint32_t>(csr_indx);
}
auto* csr = res.value();
return new generic::ImmediateOperand<uint32_t>(csr_indx, csr->name());
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kDrs1), [this]() {
int num = encoding64::r_type::ExtractRs1(inst_word_);
return GetRegisterSourceOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kDrs2), [this]() {
int num = encoding64::r_type::ExtractRs2(inst_word_);
return GetRegisterSourceOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kDrs3), [this]() {
int num = encoding64::r4_type::ExtractRs3(inst_word_);
return GetRegisterSourceOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kFrs1), [this]() {
int num = encoding64::r_type::ExtractRs1(inst_word_);
return GetRegisterSourceOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kFrs2), [this]() {
int num = encoding64::r_type::ExtractRs2(inst_word_);
return GetRegisterSourceOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kFrs3), [this]() {
int num = encoding64::r4_type::ExtractRs3(inst_word_);
return GetRegisterSourceOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICbImm8), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::inst16_format::ExtractBimm(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICiImm6), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::c_i::ExtractImm6(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICiImm612), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::inst16_format::ExtractImm18(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICiUimm6), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst16_format::ExtractUimm6(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICiUimm6x4), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst16_format::ExtractCiImmW(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICiUimm6x8), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst16_format::ExtractCiImmD(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICiImm6x16), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::inst16_format::ExtractCiImm10(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICiwUimm8x4), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst16_format::ExtractCiwImm10(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICjImm11), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::inst16_format::ExtractJimm(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kIClUimm5x4), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst16_format::ExtractClImmW(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kIClUimm5x8), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst16_format::ExtractClImmD(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICssUimm6x4), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst16_format::ExtractCssImmW(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kICssUimm6x8), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst16_format::ExtractCssImmD(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kIImm12), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::inst32_format::ExtractImm12(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kIUimm5), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::inst32_format::ExtractRUimm5(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kJImm12), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::inst32_format::ExtractImm12(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kJImm20), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::inst32_format::ExtractJImm(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kPred), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::fence::ExtractPred(inst_word_));
}));
source_op_getters_.insert(std::make_pair(
static_cast<int>(SourceOpEnum::kRm), [this]() -> SourceOperandInterface* {
uint32_t rm = (inst_word_ >> 12) & 0x7;
switch (rm) {
case 0:
return new generic::IntLiteralOperand<0>();
case 1:
return new generic::IntLiteralOperand<1>();
case 2:
return new generic::IntLiteralOperand<2>();
case 3:
return new generic::IntLiteralOperand<3>();
case 4:
return new generic::IntLiteralOperand<4>();
case 5:
return new generic::IntLiteralOperand<5>();
case 6:
return new generic::IntLiteralOperand<6>();
case 7:
return new generic::IntLiteralOperand<7>();
default:
return nullptr;
}
}));
source_op_getters_.insert(std::make_pair(
static_cast<int>(SourceOpEnum::kRd), [this]() -> SourceOperandInterface* {
int num = encoding64::r_type::ExtractRd(inst_word_);
if (num == 0)
return new generic::IntLiteralOperand<0>({1}, xreg_alias_[0]);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}));
source_op_getters_.insert(std::make_pair(
static_cast<int>(SourceOpEnum::kRs1),
[this]() -> SourceOperandInterface* {
int num = encoding64::r_type::ExtractRs1(inst_word_);
if (num == 0)
return new generic::IntLiteralOperand<0>({1}, xreg_alias_[0]);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}));
source_op_getters_.insert(std::make_pair(
static_cast<int>(SourceOpEnum::kRs2),
[this]() -> SourceOperandInterface* {
int num = encoding64::r_type::ExtractRs2(inst_word_);
if (num == 0)
return new generic::IntLiteralOperand<0>({1}, xreg_alias_[0]);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
xreg_alias_[num]);
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kSImm12), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::s_type::ExtractSImm(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kSucc), [this]() {
return new generic::ImmediateOperand<uint32_t>(
encoding64::fence::ExtractSucc(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kUImm20), [this]() {
return new generic::ImmediateOperand<int32_t>(
encoding64::u_type::ExtractUImm(inst_word_));
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kX0), [this]() {
return new generic::IntLiteralOperand<0>({1}, xreg_alias_[0]);
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kX2), [this]() {
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, 2), xreg_alias_[2]);
}
return GetRegisterSourceOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, 2), xreg_alias_[2]);
}));
source_op_getters_.insert(std::make_pair(
static_cast<int>(SourceOpEnum::kNone), []() { return nullptr; }));
}
void RiscV64GEncoding::InitializeDestinationOperandGetters() {
// Destination operand getters.
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kC3drd), [this](int latency) {
int num = encoding64::inst16_format::ExtractClRd(inst_word_);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num), latency,
xreg_alias_[num]);
}
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num), latency,
xreg_alias_[num]);
}));
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kC3rd), [this](int latency) {
int num = encoding64::inst16_format::ExtractClRd(inst_word_);
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num), latency,
xreg_alias_[num]);
}));
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kC3rs1), [this](int latency) {
int num = encoding64::inst16_format::ExtractClRs1(inst_word_);
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num), latency,
xreg_alias_[num]);
}
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, num), latency,
xreg_alias_[num]);
}));
dest_op_getters_.insert(std::make_pair(static_cast<int>(DestOpEnum::kCsr),
[](int latency) { return nullptr; }));
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kDrd), [this](int latency) {
int num = encoding64::r_type::ExtractRd(inst_word_);
return GetRegisterDestinationOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num), latency);
}));
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kFrd), [this](int latency) {
int num = encoding64::r_type::ExtractRd(inst_word_);
return GetRegisterDestinationOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kFregPrefix, num), latency);
}));
dest_op_getters_.insert(std::make_pair(
static_cast<int>(DestOpEnum::kNextPc), [this](int latency) {
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterDestinationOp<RV64Register>(
state_, RiscVState::kPcName, latency);
}
return GetRegisterDestinationOp<RV64Register>(
state_, RiscVState::kPcName, latency);
}));
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kRd),
[this](int latency) -> DestinationOperandInterface* {
int num = encoding64::r_type::ExtractRd(inst_word_);
if (num == 0) {
return GetRegisterDestinationOp<RV64Register>(
state_, "X0Dest", 0, xreg_alias_[0]);
} else {
return GetRegisterDestinationOp<RVFpRegister>(
state_, absl::StrCat(RiscVState::kXregPrefix, num),
latency, xreg_alias_[num]);
}
}));
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kX0), [this](int) {
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterDestinationOp<RV64Register>(state_, "X0Dest", 0,
xreg_alias_[0]);
}
return GetRegisterDestinationOp<RV64Register>(state_, "X0Dest", 0,
xreg_alias_[0]);
}));
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kX1), [this](int latency) {
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, 1), latency,
xreg_alias_[1]);
}
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, 1), latency,
xreg_alias_[1]);
}));
dest_op_getters_.insert(
std::make_pair(static_cast<int>(DestOpEnum::kX2), [this](int latency) {
if (state_->xlen() == RiscVXlen::RV32) {
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, 2), latency,
xreg_alias_[2]);
}
return GetRegisterDestinationOp<RV64Register>(
state_, absl::StrCat(RiscVState::kXregPrefix, 2), latency,
xreg_alias_[2]);
}));
dest_op_getters_.insert(std::make_pair(
static_cast<int>(DestOpEnum::kFflags), [this](int latency) {
return GetCSRSetBitsDestinationOp<uint32_t>(state_, "fflags", latency,
"");
}));
dest_op_getters_.insert(std::make_pair(static_cast<int>(DestOpEnum::kNone),
[](int latency) { return nullptr; }));
}
// Parse the instruction word to determine the opcode.
void RiscV64GEncoding::ParseInstruction(uint32_t inst_word) {
inst_word_ = inst_word;
if ((inst_word_ & 0x3) == 3) {
opcode_ = mpact::sim::riscv::encoding64::DecodeRiscVGInst32(inst_word_);
return;
}
opcode_ = mpact::sim::riscv::encoding64::DecodeRiscVCInst16(
static_cast<uint16_t>(inst_word_ & 0xffff));
}
void RiscV64GEncoding::InitializeComplexResourceOperandGetters() {
complex_resource_getters_.insert(
std::make_pair(static_cast<int>(ComplexResourceEnum::kNone),
[](int begin, int end) { return nullptr; }));
}
ResourceOperandInterface* RiscV64GEncoding::GetComplexResourceOperand(
SlotEnum, int, OpcodeEnum, ComplexResourceEnum resource, int begin,
int end) {
int index = static_cast<int>(resource);
auto iter = complex_resource_getters_.find(index);
if (iter == complex_resource_getters_.end()) {
LOG(WARNING) << "No complex resource getter found for resource: " << index;
return nullptr;
}
return (iter->second)(begin, end);
}
void RiscV64GEncoding::InitializeSimpleResourceGetters() {
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kNone), []() { return nullptr; }));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kC3drd),
[this]() -> generic::SimpleResource* {
int num = encoding64::inst16_format::ExtractClRd(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kC3drs2),
[this]() -> generic::SimpleResource* {
int num = encoding64::inst16_format::ExtractCsRs2(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kC3rd),
[this]() -> generic::SimpleResource* {
int num = encoding64::inst16_format::ExtractClRd(inst_word_);
// If num is 0 it refers to the zero register. No resource.
if (num == 0) return nullptr;
return resource_pool_->GetOrAddResource(absl::StrCat("x", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kC3rs1),
[this]() -> generic::SimpleResource* {
int num = encoding64::inst16_format::ExtractClRs1(inst_word_);
// If num is 0 it refers to the zero register. No resource.
if (num == 0) return nullptr;
return resource_pool_->GetOrAddResource(absl::StrCat("x", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kC3rs2),
[this]() -> generic::SimpleResource* {
int num = encoding64::inst16_format::ExtractCsRs2(inst_word_);
// If num is 0 it refers to the zero register. No resource.
if (num == 0) return nullptr;
return resource_pool_->GetOrAddResource(absl::StrCat("x", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kCdrs2),
[this]() -> generic::SimpleResource* {
auto num = encoding64::c_r::ExtractRs2(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kCrs1),
[this]() -> generic::SimpleResource* {
auto num = encoding64::c_r::ExtractRs1(inst_word_);
// If num is 0 it refers to the zero register. No resource.
if (num == 0) return nullptr;
return resource_pool_->GetOrAddResource(absl::StrCat("x", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kCrs2),
[this]() -> generic::SimpleResource* {
auto num = encoding64::c_r::ExtractRs2(inst_word_);
// If num is 0 it refers to the zero register. No resource.
if (num == 0) return nullptr;
return resource_pool_->GetOrAddResource(absl::StrCat("x", num));
}));
simple_resource_getters_.insert(
std::make_pair(static_cast<int>(SimpleResourceEnum::kCsr),
[this]() -> generic::SimpleResource* {
return resource_pool_->GetOrAddResource("csr");
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kDrd),
[this]() -> generic::SimpleResource* {
auto num = encoding64::r4_type::ExtractRd(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kDrs1),
[this]() -> generic::SimpleResource* {
auto num = encoding64::a_type::ExtractRs1(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kDrs2),
[this]() -> generic::SimpleResource* {
auto num = encoding64::a_type::ExtractRs2(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kDrs3),
[this]() -> generic::SimpleResource* {
auto num = encoding64::r4_type::ExtractRs3(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kFrd),
[this]() -> generic::SimpleResource* {
auto num = encoding64::r4_type::ExtractRd(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kFrs1),
[this]() -> generic::SimpleResource* {
auto num = encoding64::r4_type::ExtractRs1(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kFrs2),
[this]() -> generic::SimpleResource* {
auto num = encoding64::r4_type::ExtractRs2(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kFrs3),
[this]() -> generic::SimpleResource* {
auto num = encoding64::r4_type::ExtractRs3(inst_word_);
return resource_pool_->GetOrAddResource(absl::StrCat("d", num));
}));
simple_resource_getters_.insert(
std::make_pair(static_cast<int>(SimpleResourceEnum::kNextPc),
[this]() -> generic::SimpleResource* {
return resource_pool_->GetOrAddResource("next_pc");
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kRd),
[this]() -> generic::SimpleResource* {
auto num = encoding64::a_type::ExtractRd(inst_word_);
// If num is 0 it refers to the zero register. No resource.
if (num == 0) return nullptr;
return resource_pool_->GetOrAddResource(absl::StrCat("x", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kRs1),
[this]() -> generic::SimpleResource* {
auto num = encoding64::a_type::ExtractRs1(inst_word_);
// If num is 0 it refers to the zero register. No resource.
if (num == 0) return nullptr;
return resource_pool_->GetOrAddResource(absl::StrCat("x", num));
}));
simple_resource_getters_.insert(std::make_pair(
static_cast<int>(SimpleResourceEnum::kRs2),
[this]() -> generic::SimpleResource* {
auto num = encoding64::a_type::ExtractRs2(inst_word_);
// If num is 0 it refers to the zero register. No resource.
if (num == 0) return nullptr;
return resource_pool_->GetOrAddResource(absl::StrCat("x", num));
}));
// X0 is constant 0, so no resource issue.
simple_resource_getters_.insert(
std::make_pair(static_cast<int>(SimpleResourceEnum::kX0),
[]() -> generic::SimpleResource* { return nullptr; }));
simple_resource_getters_.insert(
std::make_pair(static_cast<int>(SimpleResourceEnum::kX1),
[this]() -> generic::SimpleResource* {
return resource_pool_->GetOrAddResource("x1");
}));
simple_resource_getters_.insert(
std::make_pair(static_cast<int>(SimpleResourceEnum::kX2),
[this]() -> generic::SimpleResource* {
return resource_pool_->GetOrAddResource("x2");
}));
}
ResourceOperandInterface* RiscV64GEncoding::GetSimpleResourceOperand(
SlotEnum, int, OpcodeEnum, SimpleResourceVector& resource_vec, int end) {
if (resource_vec.empty()) return nullptr;
auto* resource_set = resource_pool_->CreateResourceSet();
for (auto resource_enum : resource_vec) {
int index = static_cast<int>(resource_enum);
auto iter = simple_resource_getters_.find(index);
if (iter == simple_resource_getters_.end()) {
LOG(WARNING) << "No getter for simple resource " << index;
continue;
}
auto* resource = (iter->second)();
auto status = resource_set->AddResource(resource);
if (!status.ok()) {
LOG(ERROR) << "Unable to add resource to resource set ("
<< static_cast<int>(resource_enum) << ")";
}
}
auto* op = new SimpleResourceOperand(resource_set, end, resource_delay_line_);
return op;
}
DestinationOperandInterface* RiscV64GEncoding::GetDestination(
SlotEnum, int, OpcodeEnum, 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) << "No getter for destination op " << index;
return nullptr;
}
return (iter->second)(latency);
}
SourceOperandInterface* RiscV64GEncoding::GetSource(SlotEnum, int, OpcodeEnum,
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()) return nullptr;
return (iter->second)();
}
} // namespace isa64
} // namespace riscv
} // namespace sim
} // namespace mpact