blob: b1b3f3c514bda9f9c2426c4f16786a89ddc55b82 [file] [log] [blame]
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cheriot/riscv_cheriot_rvv_encoding.h"
#include <cstdint>
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "cheriot/cheriot_getters.h"
#include "cheriot/cheriot_register.h"
#include "cheriot/cheriot_rvv_getters.h"
#include "cheriot/cheriot_state.h"
#include "cheriot/riscv_cheriot_encoding_common.h"
#include "cheriot/riscv_cheriot_rvv_bin_decoder.h"
#include "cheriot/riscv_cheriot_rvv_decoder.h"
#include "cheriot/riscv_cheriot_rvv_enums.h"
#include "mpact/sim/generic/type_helpers.h"
namespace mpact {
namespace sim {
namespace cheriot {
namespace isa32_rvv {
using Extractors = ::mpact::sim::cheriot::encoding_rvv::Extractors;
RiscVCheriotRVVEncoding::RiscVCheriotRVVEncoding(CheriotState *state)
: RiscVCheriotEncodingCommon(state) {
source_op_getters_.emplace(*SourceOpEnum::kNone, []() { return nullptr; });
dest_op_getters_.emplace(*DestOpEnum::kNone,
[](int latency) { return nullptr; });
// Add Cheriot ISA source and destination operand getters.
AddCheriotSourceGetters<SourceOpEnum, Extractors>(source_op_getters_, this);
AddCheriotDestGetters<DestOpEnum, Extractors>(dest_op_getters_, this);
// Add non-fp RVV source and destination operand getters.
AddCheriotRVVSourceGetters<SourceOpEnum, Extractors>(source_op_getters_,
this);
AddCheriotRVVDestGetters<DestOpEnum, Extractors>(dest_op_getters_, this);
// Verify that all source and destination op enum values have a getter.
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;
}
}
}
// Parse the instruction word to determine the opcode.
void RiscVCheriotRVVEncoding::ParseInstruction(uint32_t inst_word) {
inst_word_ = inst_word;
if ((inst_word_ & 0x3) == 3) {
auto [opcode, format] = mpact::sim::cheriot::encoding_rvv::
DecodeRiscVCheriotRVVInst32WithFormat(inst_word_);
opcode_ = opcode;
format_ = format;
return;
}
auto [opcode, format] =
mpact::sim::cheriot::encoding_rvv::DecodeRiscVCheriotRVVInst16WithFormat(
static_cast<uint16_t>(inst_word_ & 0xffff));
opcode_ = opcode;
format_ = format;
}
DestinationOperandInterface *RiscVCheriotRVVEncoding::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 *RiscVCheriotRVVEncoding::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 isa32_rvv
} // namespace cheriot
} // namespace sim
} // namespace mpact