blob: 0037c7b761e77ca622949061816bb20d6c83269f [file] [log] [blame]
#include "sim/kelvin_encoding.h"
#include "sim/kelvin_state.h"
#include "googletest/include/gtest/gtest.h"
namespace {
using kelvin::sim::KelvinState;
using kelvin::sim::isa32::KelvinEncoding;
using SlotEnum = kelvin::sim::isa32::SlotEnum;
using OpcodeEnum = kelvin::sim::isa32::OpcodeEnum;
// 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_;
}
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));
}
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, KelvinVldOpcodes) {
enc_->ParseInstruction(SetRs1(kVld, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kVldBX);
enc_->ParseInstruction(SetRs1(kVld, kRdValue) | (0b01 << 12 /* sz */));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kVldHX);
enc_->ParseInstruction(SetRs1(kVld, kRdValue) | (0b10 << 12 /* sz */) |
(0b10 << 20 /* xs2 */) | (0b1 << 26 /* length */));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kVldWLXx);
}
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);
}
} // namespace