blob: d9623216731703abe58f7860f6a62e172595b112 [file] [log] [blame]
#include "sim/kelvin_encoding.h"
#include <any>
#include <cstdint>
#include <type_traits>
#include "sim/kelvin_enums.h"
#include "sim/kelvin_state.h"
#include "googletest/include/gtest/gtest.h"
#include "riscv/riscv_register.h"
#include "mpact/sim/generic/register.h"
namespace {
using kelvin::sim::KelvinState;
using kelvin::sim::isa32::KelvinEncoding;
using SlotEnum = kelvin::sim::isa32::SlotEnum;
using OpcodeEnum = kelvin::sim::isa32::OpcodeEnum;
using SourceOpEnum = kelvin::sim::isa32::SourceOpEnum;
using RV32VectorSourceOperand = mpact::sim::riscv::RV32VectorSourceOperand;
using RV32SourceOperand = mpact::sim::generic::RegisterSourceOperand<uint64_t>;
using DestOpEnum = kelvin::sim::isa32::DestOpEnum;
using RV32VectorDestOperand = mpact::sim::riscv::RV32VectorDestinationOperand;
using RV32DestOperand =
mpact::sim::generic::RegisterDestinationOperand<uint64_t>;
// RV32I
constexpr uint32_t kLui = 0b0000000000000000000000000'0110111;
constexpr uint32_t kAuipc = 0b0000000000000000000000000'0010111;
constexpr uint32_t kJal = 0b00000000000000000000'00000'1101111;
constexpr uint32_t kJalr = 0b00000000000'00000'000'00000'1100111;
constexpr uint32_t kBeq = 0b0000000'00000'00000'000'00000'1100011;
constexpr uint32_t kBne = 0b0000000'00000'00000'001'00000'1100011;
constexpr uint32_t kBlt = 0b0000000'00000'00000'100'00000'1100011;
constexpr uint32_t kBge = 0b0000000'00000'00000'101'00000'1100011;
constexpr uint32_t kBltu = 0b0000000'00000'00000'110'00000'1100011;
constexpr uint32_t kBgeu = 0b0000000'00000'00000'111'00000'1100011;
constexpr uint32_t kLb = 0b000000000000'00000'000'00000'0000011;
constexpr uint32_t kLh = 0b000000000000'00000'001'00000'0000011;
constexpr uint32_t kLw = 0b000000000000'00000'010'00000'0000011;
constexpr uint32_t kLbu = 0b000000000000'00000'100'00000'0000011;
constexpr uint32_t kLhu = 0b000000000000'00000'101'00000'0000011;
constexpr uint32_t kSb = 0b0000000'00000'00000'000'00000'0100011;
constexpr uint32_t kSh = 0b0000000'00000'00000'001'00000'0100011;
constexpr uint32_t kSw = 0b0000000'00000'00000'010'00000'0100011;
constexpr uint32_t kAddi = 0b000000000000'00000'000'00000'0010011;
constexpr uint32_t kSlti = 0b000000000000'00000'010'00000'0010011;
constexpr uint32_t kSltiu = 0b000000000000'00000'011'00000'0010011;
constexpr uint32_t kXori = 0b000000000000'00000'100'00000'0010011;
constexpr uint32_t kOri = 0b000000000000'00000'110'00000'0010011;
constexpr uint32_t kAndi = 0b000000000000'00000'111'00000'0010011;
constexpr uint32_t kSlli = 0b0000000'00000'00000'001'00000'0010011;
constexpr uint32_t kSrli = 0b0000000'00000'00000'101'00000'0010011;
constexpr uint32_t kSrai = 0b0100000'00000'00000'101'00000'0010011;
constexpr uint32_t kAdd = 0b0000000'00000'00000'000'00000'0110011;
constexpr uint32_t kSub = 0b0100000'00000'00000'000'00000'0110011;
constexpr uint32_t kSll = 0b0000000'00000'00000'001'00000'0110011;
constexpr uint32_t kSlt = 0b0000000'00000'00000'010'00000'0110011;
constexpr uint32_t kSltu = 0b0000000'00000'00000'011'00000'0110011;
constexpr uint32_t kXor = 0b0000000'00000'00000'100'00000'0110011;
constexpr uint32_t kSrl = 0b0000000'00000'00000'101'00000'0110011;
constexpr uint32_t kSra = 0b0100000'00000'00000'101'00000'0110011;
constexpr uint32_t kOr = 0b0000000'00000'00000'110'00000'0110011;
constexpr uint32_t kAnd = 0b0000000'00000'00000'111'00000'0110011;
constexpr uint32_t kFence = 0b000000000000'00000'000'00000'0001111;
constexpr uint32_t kEcall = 0b000000000000'00000'000'00000'1110011;
constexpr uint32_t kEbreak = 0b000000000001'00000'000'00000'1110011;
constexpr uint32_t kMpause = 0b000010000000'00000'000'00000'1110011;
// Kelvin Memory ops
constexpr uint32_t kFlushall = 0b001001100000'00000'000'00000'1110111;
constexpr uint32_t kFlushat = 0b001001100000'00000'000'00000'1110111;
// RV32 Zifencei
constexpr uint32_t kFencei = 0b000000000000'00000'001'00000'0001111;
// RV32 Zicsr
constexpr uint32_t kCsrw = 0b000000000000'00000'001'00000'1110011;
constexpr uint32_t kCsrs = 0b000000000000'00000'010'00000'1110011;
constexpr uint32_t kCsrc = 0b000000000000'00000'011'00000'1110011;
constexpr uint32_t kCsrwi = 0b000000000000'00000'101'00000'1110011;
constexpr uint32_t kCsrsi = 0b000000000000'00000'110'00000'1110011;
constexpr uint32_t kCsrci = 0b000000000000'00000'111'00000'1110011;
// RV32M
constexpr uint32_t kMul = 0b0000001'00000'00000'000'00000'0110011;
constexpr uint32_t kMulh = 0b0000001'00000'00000'001'00000'0110011;
constexpr uint32_t kMulhsu = 0b0000001'00000'00000'010'00000'0110011;
constexpr uint32_t kMulhu = 0b0000001'00000'00000'011'00000'0110011;
constexpr uint32_t kDiv = 0b0000001'00000'00000'100'00000'0110011;
constexpr uint32_t kDivu = 0b0000001'00000'00000'101'00000'0110011;
constexpr uint32_t kRem = 0b0000001'00000'00000'110'00000'0110011;
constexpr uint32_t kRemu = 0b0000001'00000'00000'111'00000'0110011;
// Kelvin System Op
constexpr uint32_t kGetMaxVl = 0b0001'0'00'00000'00000'000'00000'111'0111;
// Kelvin Logging Op
constexpr uint32_t kFLog = 0b011'1100'00000'00000'000'00000'111'0111;
// Kelvin VLd
constexpr uint32_t kVld = 0b000000'000000'000000'00'000000'0'111'11;
class KelvinEncodingTest : public testing::Test {
protected:
KelvinEncodingTest() {
state_ = new KelvinState("test", mpact::sim::riscv::RiscVXlen::RV32);
enc_ = new KelvinEncoding(state_);
}
~KelvinEncodingTest() override {
delete enc_;
delete state_;
}
template <typename T>
T *EncodeOpHelper(uint32_t inst_word, OpcodeEnum opcode, std::any op) const {
enc_->ParseInstruction(inst_word);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), opcode);
if (std::is_same<T, RV32SourceOperand>::value ||
std::is_same<T, RV32VectorSourceOperand>::value) {
auto *source = enc_->GetSource(SlotEnum::kKelvin, 0, opcode,
std::any_cast<SourceOpEnum>(op), 0);
return reinterpret_cast<T *>(source);
}
auto *dest = enc_->GetDestination(SlotEnum::kKelvin, 0, opcode,
std::any_cast<DestOpEnum>(op), 0,
/*latency=*/0);
return reinterpret_cast<T *>(dest);
}
KelvinState *state_;
KelvinEncoding *enc_;
};
constexpr int kRdValue = 1;
constexpr int kSuccValue = 0xf;
constexpr int kPredValue = 0xf;
static uint32_t SetRd(uint32_t iword, uint32_t rdval) {
return (iword | ((rdval & 0x1f) << 7));
}
static uint32_t SetRs1(uint32_t iword, uint32_t rsval) {
return (iword | ((rsval & 0x1f) << 15));
}
static uint32_t SetRs2(uint32_t iword, uint32_t rsval) {
return (iword | ((rsval & 0x1f) << 20));
}
static uint32_t SetPred(uint32_t iword, uint32_t pred) {
return (iword | ((pred & 0xf) << 24));
}
static uint32_t SetSucc(uint32_t iword, uint32_t succ) {
return (iword | ((succ & 0xf) << 20));
}
static inline uint32_t SetSz(uint32_t iword, uint32_t sz) {
return (iword | ((sz & 0x3) << 12));
}
TEST_F(KelvinEncodingTest, RV32IOpcodes) {
enc_->ParseInstruction(SetRd(kLui, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kLui);
enc_->ParseInstruction(SetRd(kAuipc, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kAuipc);
enc_->ParseInstruction(SetRd(kJal, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kJal);
enc_->ParseInstruction(SetRd(kJalr, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kJalr);
enc_->ParseInstruction(kBeq);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kBeq);
enc_->ParseInstruction(kBne);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kBne);
enc_->ParseInstruction(kBlt);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kBlt);
enc_->ParseInstruction(kBge);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kBge);
enc_->ParseInstruction(kBltu);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kBltu);
enc_->ParseInstruction(kBgeu);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kBgeu);
enc_->ParseInstruction(SetRd(kLb, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kLb);
enc_->ParseInstruction(SetRd(kLh, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kLh);
enc_->ParseInstruction(SetRd(kLw, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kLw);
enc_->ParseInstruction(SetRd(kLbu, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kLbu);
enc_->ParseInstruction(SetRd(kLhu, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kLhu);
enc_->ParseInstruction(SetRd(kSb, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSb);
enc_->ParseInstruction(SetRd(kSh, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSh);
enc_->ParseInstruction(SetRd(kSw, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSw);
enc_->ParseInstruction(SetRd(kAddi, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kAddi);
enc_->ParseInstruction(SetRd(kSlti, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSlti);
enc_->ParseInstruction(SetRd(kSltiu, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSltiu);
enc_->ParseInstruction(SetRd(kXori, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kXori);
enc_->ParseInstruction(SetRd(kOri, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kOri);
enc_->ParseInstruction(SetRd(kAndi, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kAndi);
enc_->ParseInstruction(SetRd(kSlli, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSlli);
enc_->ParseInstruction(SetRd(kSrli, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSrli);
enc_->ParseInstruction(SetRd(kSrai, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSrai);
enc_->ParseInstruction(SetRd(kAdd, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kAdd);
enc_->ParseInstruction(SetRd(kSub, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSub);
enc_->ParseInstruction(SetRd(kSll, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSll);
enc_->ParseInstruction(SetRd(kSlt, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSlt);
enc_->ParseInstruction(SetRd(kSltu, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSltu);
enc_->ParseInstruction(SetRd(kXor, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kXor);
enc_->ParseInstruction(SetRd(kSrl, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSrl);
enc_->ParseInstruction(SetRd(kSra, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSra);
enc_->ParseInstruction(SetRd(kOr, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kOr);
enc_->ParseInstruction(SetRd(kAnd, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kAnd);
enc_->ParseInstruction(SetSucc(SetPred(kFence, kPredValue), kSuccValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kFence);
enc_->ParseInstruction(kEcall);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kEcall);
enc_->ParseInstruction(kEbreak);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kEbreak);
enc_->ParseInstruction(kMpause);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kMpause);
}
TEST_F(KelvinEncodingTest, KelvinMemoryOpcodes) {
enc_->ParseInstruction(kFlushall);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kFlushall);
enc_->ParseInstruction(SetRs1(kFlushat, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kFlushat);
}
TEST_F(KelvinEncodingTest, KelvinSystemOpcodes) {
enc_->ParseInstruction(SetRd(kGetMaxVl, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kGetmaxvlB);
enc_->ParseInstruction(SetRd(SetRs1(kGetMaxVl, kRdValue), kRdValue) |
(0b1) << 25);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kGetvlHX);
enc_->ParseInstruction(
SetRd(SetRs1(SetRs2(kGetMaxVl, kRdValue), kRdValue), kRdValue) |
(0b10 << 25));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kGetvlWXx);
}
TEST_F(KelvinEncodingTest, KelvinLogOpcodes) {
enc_->ParseInstruction(SetRs1(kFLog, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kFlog);
enc_->ParseInstruction(SetRs1(kFLog, kRdValue) | (0b01 << 12));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kSlog);
enc_->ParseInstruction(SetRs1(kFLog, kRdValue) | (0b10 << 12));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kClog);
enc_->ParseInstruction(SetRs1(kFLog, kRdValue) | (0b11 << 12));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kKlog);
}
TEST_F(KelvinEncodingTest, ZifenceiOpcodes) {
// RV32 Zifencei
enc_->ParseInstruction(kFencei);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kFencei);
}
TEST_F(KelvinEncodingTest, ZicsrOpcodes) {
// RV32 Zicsr
enc_->ParseInstruction(SetRd(kCsrw, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrw);
enc_->ParseInstruction(SetRd(SetRs1(kCsrs, kRdValue), kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrs);
enc_->ParseInstruction(SetRd(SetRs1(kCsrc, kRdValue), kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrc);
enc_->ParseInstruction(kCsrw);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrwNr);
enc_->ParseInstruction(kCsrs);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrsNw);
enc_->ParseInstruction(kCsrc);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrcNw);
enc_->ParseInstruction(SetRd(kCsrwi, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrwi);
enc_->ParseInstruction(SetRd(SetRs1(kCsrsi, kRdValue), kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrsi);
enc_->ParseInstruction(SetRd(SetRs1(kCsrci, kRdValue), kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrci);
enc_->ParseInstruction(kCsrwi);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrwiNr);
enc_->ParseInstruction(kCsrsi);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrsiNw);
enc_->ParseInstruction(kCsrci);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kCsrrciNw);
}
TEST_F(KelvinEncodingTest, RV32MOpcodes) {
// RV32M
enc_->ParseInstruction(kMul);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kMul);
enc_->ParseInstruction(kMulh);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kMulh);
enc_->ParseInstruction(kMulhsu);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kMulhsu);
enc_->ParseInstruction(kMulhu);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kMulhu);
enc_->ParseInstruction(kDiv);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kDiv);
enc_->ParseInstruction(kDivu);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kDivu);
enc_->ParseInstruction(kRem);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kRem);
enc_->ParseInstruction(kRemu);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kRemu);
}
TEST_F(KelvinEncodingTest, KelvinVldEncodeXs1Xs2) {
enc_->ParseInstruction(SetRs1(kVld, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kVldBX);
enc_->ParseInstruction(SetSz(SetRs1(kVld, kRdValue), 0b1));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kVldHX);
// Test vld.w.l.xx
auto *src = EncodeOpHelper<RV32SourceOperand>(
SetSz(SetRs1(kVld, kRdValue), 0b10) | (0b10 << 20 /* xs2 */) |
(0b1 << 26 /* length */),
OpcodeEnum::kVldWLXx, SourceOpEnum::kVs1);
EXPECT_EQ(src->AsString(), "ra");
delete src;
src = EncodeOpHelper<RV32SourceOperand>(
SetSz(SetRs1(kVld, kRdValue), 0b10) | (0b10 << 20 /* xs2 */) |
(0b1 << 26 /* length */),
OpcodeEnum::kVldWLXx, SourceOpEnum::kVs2);
EXPECT_EQ(src->AsString(), "sp");
delete src;
}
TEST_F(KelvinEncodingTest, KelvinVstEncodeXs1Xs2Vd) {
constexpr uint32_t kVstBase = 0b001000'000000'000000'00'000000'0'111'11;
// Test vd in vst.b.x as source
auto *v_src = EncodeOpHelper<RV32VectorSourceOperand>(
SetRs1(kVstBase, kRdValue), OpcodeEnum::kVstBX, SourceOpEnum::kVd);
EXPECT_EQ(v_src->AsString(), "v0");
delete v_src;
// Test xs1 in vst.w.l.xx as destination
auto *dest = EncodeOpHelper<RV32DestOperand>(
SetSz(SetRs1(kVstBase, kRdValue), 0b10) | (0b10 << 20 /* xs2 */) |
(1 << 26 /* length */),
OpcodeEnum::kVstWLXx, DestOpEnum::kVs1);
EXPECT_EQ(dest->AsString(), "ra");
delete dest;
// Test xs2 in vstq.b.s.xx as source
auto *src = EncodeOpHelper<RV32SourceOperand>(
SetRs1(kVstBase, kRdValue) | (1 << 30 /* vstq */) |
(0b10 << 20 /* xs2 */) | (1 << 27 /* stride */),
OpcodeEnum::kVstqBSXx, SourceOpEnum::kVs2);
EXPECT_EQ(src->AsString(), "sp");
delete src;
}
TEST_F(KelvinEncodingTest, KelvinWideningVs1) {
constexpr uint32_t kVSransBase = 0b010000'000001'000000'00'001000'0'010'00;
auto *v_src = EncodeOpHelper<RV32VectorSourceOperand>(
kVSransBase, OpcodeEnum::kVsransBVv, SourceOpEnum::kVs1);
EXPECT_EQ(v_src->size(), 2);
delete v_src;
// Test vsrans.b.r.vv
v_src = EncodeOpHelper<RV32VectorSourceOperand>(
kVSransBase | (1 << 27 /* vsrans.r */), OpcodeEnum::kVsransBRVv,
SourceOpEnum::kVs1);
EXPECT_EQ(v_src->size(), 2);
delete v_src;
// Test vsrans.h.vv
v_src = EncodeOpHelper<RV32VectorSourceOperand>(
SetSz(kVSransBase, 0b1), OpcodeEnum::kVsransHVv, SourceOpEnum::kVs1);
EXPECT_EQ(v_src->size(), 2);
delete v_src;
// Test vsraqs.b.vv
v_src = EncodeOpHelper<RV32VectorSourceOperand>(
kVSransBase | (1 << 29 /* vsraqs */), OpcodeEnum::kVsraqsBVv,
SourceOpEnum::kVs1);
EXPECT_EQ(v_src->size(), 4);
delete v_src;
// Test vsraqs.b.r.vv
v_src = EncodeOpHelper<RV32VectorSourceOperand>(
kVSransBase | (1 << 29) | (1 << 27), OpcodeEnum::kVsraqsBRVv,
SourceOpEnum::kVs1);
EXPECT_EQ(v_src->size(), 4);
delete v_src;
// Test illegal vsrans (vsrans.w.vv)
enc_->ParseInstruction(SetSz(kVSransBase, 0b10));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kNone);
// Test vacc.h.vv
constexpr uint32_t kVAccsBase = 0b001010'000001'000000'00'001000'0'100'00;
v_src = EncodeOpHelper<RV32VectorSourceOperand>(
SetSz(kVAccsBase, 0b1), OpcodeEnum::kVaccHVv, SourceOpEnum::kVs1);
EXPECT_EQ(v_src->size(), 2);
delete v_src;
// Test vacc.w.u.vv
v_src = EncodeOpHelper<RV32VectorSourceOperand>(
SetSz(kVAccsBase, 0b10) | (1 << 26), OpcodeEnum::kVaccWUVv,
SourceOpEnum::kVs1);
EXPECT_EQ(v_src->size(), 2);
delete v_src;
}
TEST_F(KelvinEncodingTest, KelvinWideningVd) {
// No widening for vld
auto *v_dest = EncodeOpHelper<RV32VectorDestOperand>(
SetRs1(kVld, kRdValue), OpcodeEnum::kVldBX, DestOpEnum::kVd);
EXPECT_EQ(v_dest->size(), 1);
delete v_dest;
// Test vaddw.h.vv
constexpr uint32_t kVAddwBase = 0b000100'000001'000000'00'001000'0'100'00;
v_dest = EncodeOpHelper<RV32VectorDestOperand>(
SetSz(kVAddwBase, 0b1), OpcodeEnum::kVaddwHVv, DestOpEnum::kVd);
EXPECT_EQ(v_dest->size(), 2);
delete v_dest;
// Test vsubw.w.u.vv
v_dest = EncodeOpHelper<RV32VectorDestOperand>(
SetSz(kVAddwBase, 0b10) | (0b11 << 26 /* vsubw.u */),
OpcodeEnum::kVsubwWUVv, DestOpEnum::kVd);
EXPECT_EQ(v_dest->size(), 2);
delete v_dest;
// Test vmvp.vv
constexpr uint32_t kVMvpBase = 0b001101'000001'000000'00'001000'0'001'00;
v_dest = EncodeOpHelper<RV32VectorDestOperand>(kVMvpBase, OpcodeEnum::kVmvpVv,
DestOpEnum::kVd);
EXPECT_EQ(v_dest->size(), 2);
delete v_dest;
// Test vmulw.h.vv
constexpr uint32_t kVMulwBase = 0b000100'000001'000000'00'001000'0'011'00;
v_dest = EncodeOpHelper<RV32VectorDestOperand>(
SetSz(kVMulwBase, 0b1), OpcodeEnum::kVmulwHVv, DestOpEnum::kVd);
EXPECT_EQ(v_dest->size(), 2);
delete v_dest;
// Test vmulw.w.u.vv
v_dest = EncodeOpHelper<RV32VectorDestOperand>(
SetSz(kVMulwBase, 0b10) | (1 << 26 /* vmulw.u */), OpcodeEnum::kVmulwWUVv,
DestOpEnum::kVd);
EXPECT_EQ(v_dest->size(), 2);
delete v_dest;
// Test vevnodd.b.vv
constexpr uint32_t kVEvnoddBase = 0b011000'000001'000000'00'001000'0'110'00;
v_dest = EncodeOpHelper<RV32VectorDestOperand>(
kVEvnoddBase | (0b10 << 26 /* vevenodd */), OpcodeEnum::kVevnoddBVv,
DestOpEnum::kVd);
EXPECT_EQ(v_dest->size(), 2);
delete v_dest;
// Test vzip.h.vv
v_dest = EncodeOpHelper<RV32VectorDestOperand>(
SetSz(kVEvnoddBase, 0b1) | (0b100 << 26 /* vzip */), OpcodeEnum::kVzipHVv,
DestOpEnum::kVd);
EXPECT_EQ(v_dest->size(), 2);
delete v_dest;
}
} // namespace