kelvin_encoding cleanup
* Use RV32Register type for scalar registers
* Extend the test coverage
* Use mpact_riscv scalar register alias list.
PiperOrigin-RevId: 560188046
diff --git a/sim/kelvin_encoding.cc b/sim/kelvin_encoding.cc
index fa6acc5..e638d1e 100644
--- a/sim/kelvin_encoding.cc
+++ b/sim/kelvin_encoding.cc
@@ -14,6 +14,7 @@
#include "absl/strings/str_cat.h"
#include "absl/types/span.h"
#include "riscv/riscv_register.h"
+#include "riscv/riscv_register_aliases.h"
#include "riscv/riscv_state.h"
#include "mpact/sim/generic/immediate_operand.h"
#include "mpact/sim/generic/literal_operand.h"
@@ -162,24 +163,24 @@
[this]() -> SourceOperandInterface * {
int num = encoding::r_type::ExtractRs1(inst_word_);
if (num == 0)
- return new mpact::sim::generic::IntLiteralOperand<0>({1},
- xreg_alias_[0]);
+ return new mpact::sim::generic::IntLiteralOperand<0>(
+ {1}, mpact::sim::riscv::kXRegisterAliases[0]);
return GetRegisterSourceOp<mpact::sim::riscv::RV32Register>(
state_,
absl::StrCat(mpact::sim::riscv::RiscVState::kXregPrefix, num),
- xreg_alias_[num]);
+ mpact::sim::riscv::kXRegisterAliases[num]);
}));
source_op_getters_.insert(std::make_pair(
static_cast<int>(SourceOpEnum::kRs2),
[this]() -> SourceOperandInterface * {
int num = encoding::r_type::ExtractRs2(inst_word_);
if (num == 0)
- return new mpact::sim::generic::IntLiteralOperand<0>({1},
- xreg_alias_[0]);
+ return new mpact::sim::generic::IntLiteralOperand<0>(
+ {1}, mpact::sim::riscv::kXRegisterAliases[0]);
return GetRegisterSourceOp<mpact::sim::riscv::RV32Register>(
state_,
absl::StrCat(mpact::sim::riscv::RiscVState::kXregPrefix, num),
- xreg_alias_[num]);
+ mpact::sim::riscv::kXRegisterAliases[num]);
}));
source_op_getters_.insert(
std::make_pair(static_cast<int>(SourceOpEnum::kSImm12), [this]() {
@@ -201,7 +202,7 @@
if (form == 3) {
if (reg_num == 0) {
return new mpact::sim::generic::IntLiteralOperand<0>(
- {1}, xreg_alias_[0]);
+ {1}, mpact::sim::riscv::kXRegisterAliases[0]);
}
// `vs1` is stored in bit[19:14], but scalar xs1 is in bit[19:15]
// (same as the regular riscv32 encoding)
@@ -209,7 +210,7 @@
return GetRegisterSourceOp<mpact::sim::riscv::RV32Register>(
state_,
absl::StrCat(mpact::sim::riscv::RiscVState::kXregPrefix, reg_num),
- xreg_alias_[reg_num]);
+ mpact::sim::riscv::kXRegisterAliases[reg_num]);
}
if (opcode_ == OpcodeEnum::kAdwinit) {
// Borrow the strip_mine setting to set 4x registers.
@@ -228,7 +229,7 @@
if (form == 2 || form == 3 || opcode_ == OpcodeEnum::kAconvVxv) {
if (reg_num == 0) {
return new mpact::sim::generic::IntLiteralOperand<0>(
- {1}, xreg_alias_[0]);
+ {1}, mpact::sim::riscv::kXRegisterAliases[0]);
}
// `vs2` is stored in bit[26:20], but scalar xs2 is in bit[25:20]
// (same as in the regular riscv32 encoding)
@@ -236,7 +237,7 @@
return GetRegisterSourceOp<mpact::sim::riscv::RV32Register>(
state_,
absl::StrCat(mpact::sim::riscv::RiscVState::kXregPrefix, reg_num),
- xreg_alias_[reg_num]);
+ mpact::sim::riscv::kXRegisterAliases[reg_num]);
}
return GetVectorRegisterSourceOp<mpact::sim::riscv::RVVectorRegister>(
state_, reg_num, strip_mine, 1 /* widen_factor */);
@@ -282,11 +283,11 @@
int num = encoding::r_type::ExtractRd(inst_word_);
if (num == 0) {
return GetRegisterDestinationOp<mpact::sim::riscv::RV32Register>(
- state_, "X0Dest", 0, xreg_alias_[0]);
+ state_, "X0Dest", 0, mpact::sim::riscv::kXRegisterAliases[0]);
} else {
- return GetRegisterDestinationOp<mpact::sim::riscv::RVFpRegister>(
+ return GetRegisterDestinationOp<mpact::sim::riscv::RV32Register>(
state_, absl::StrCat(KelvinState::kXregPrefix, num), latency,
- xreg_alias_[num]);
+ mpact::sim::riscv::kXRegisterAliases[num]);
}
}));
dest_op_getters_.emplace(
@@ -312,14 +313,14 @@
// to "vs1" register. And it has to be a scalar register in that case.
if (reg_num == 0) {
return GetRegisterDestinationOp<mpact::sim::riscv::RV32Register>(
- state_, "X0Dest", 0, xreg_alias_[0]);
+ state_, "X0Dest", 0, mpact::sim::riscv::kXRegisterAliases[0]);
} else {
// `vs1` is stored in bit[19:14], but scalar xs1 is in bit[19:15]
// (same as the regular riscv32 encoding)
reg_num >>= 1;
- return GetRegisterDestinationOp<mpact::sim::riscv::RVFpRegister>(
+ return GetRegisterDestinationOp<mpact::sim::riscv::RV32Register>(
state_, absl::StrCat(KelvinState::kXregPrefix, reg_num), latency,
- xreg_alias_[reg_num]);
+ mpact::sim::riscv::kXRegisterAliases[reg_num]);
}
}));
dest_op_getters_.insert(std::make_pair(static_cast<int>(DestOpEnum::kNone),
@@ -351,7 +352,7 @@
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 ",
+ index, " for instruction ",
kOpcodeNames[static_cast<int>(opcode)]);
return nullptr;
}
diff --git a/sim/kelvin_encoding.h b/sim/kelvin_encoding.h
index 17a131b..528473a 100644
--- a/sim/kelvin_encoding.h
+++ b/sim/kelvin_encoding.h
@@ -82,11 +82,6 @@
using DestOpGetterMap = absl::flat_hash_map<
int, absl::AnyInvocable<DestinationOperandInterface *(int)>>;
- const std::string xreg_alias_[32] = {
- "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0",
- "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5",
- "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"};
-
SourceOpGetterMap &source_op_getters() { return source_op_getters_; }
DestOpGetterMap &dest_op_getters() { return dest_op_getters_; }
diff --git a/sim/test/kelvin_encoding_test.cc b/sim/test/kelvin_encoding_test.cc
index 3542b76..b83ac69 100644
--- a/sim/test/kelvin_encoding_test.cc
+++ b/sim/test/kelvin_encoding_test.cc
@@ -18,11 +18,11 @@
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 RV32SourceOperand = mpact::sim::generic::RegisterSourceOperand<uint32_t>;
using DestOpEnum = kelvin::sim::isa32::DestOpEnum;
using RV32VectorDestOperand = mpact::sim::riscv::RV32VectorDestinationOperand;
using RV32DestOperand =
- mpact::sim::generic::RegisterDestinationOperand<uint64_t>;
+ mpact::sim::generic::RegisterDestinationOperand<uint32_t>;
// RV32I
constexpr uint32_t kLui = 0b0000000000000000000000000'0110111;
@@ -68,7 +68,6 @@
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
@@ -97,6 +96,10 @@
// Kelvin VLd
constexpr uint32_t kVld = 0b000000'000000'000000'00'000000'0'111'11;
+// Kelvin vector ops
+constexpr uint32_t kVAddBase = 0b000000'000000'000001'00'000010'0'000'00;
+constexpr uint32_t kAconvBase = 0b001000'000001'010000'10'110000'0'00'101;
+
class KelvinEncodingTest : public testing::Test {
protected:
KelvinEncodingTest() {
@@ -244,7 +247,7 @@
TEST_F(KelvinEncodingTest, KelvinMemoryOpcodes) {
enc_->ParseInstruction(kFlushall);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kFlushall);
- enc_->ParseInstruction(SetRs1(kFlushat, kRdValue));
+ enc_->ParseInstruction(SetRs1(kFlushall, kRdValue));
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kFlushat);
}
@@ -325,13 +328,38 @@
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kRemu);
}
+TEST_F(KelvinEncodingTest, NoSourceDest) {
+ enc_->ParseInstruction(kVld);
+ auto *src = enc_->GetSource(SlotEnum::kKelvin, 0, OpcodeEnum::kVldBX,
+ SourceOpEnum::kNone, 0);
+ EXPECT_EQ(src, nullptr);
+ auto *src_op = enc_->GetSource(SlotEnum::kKelvin, 0, OpcodeEnum::kVldBX,
+ SourceOpEnum::kPastMaxValue, 0);
+ EXPECT_EQ(src_op, nullptr);
+
+ auto *dest = enc_->GetDestination(SlotEnum::kKelvin, 0, OpcodeEnum::kVldBX,
+ DestOpEnum::kNone, 0, /*latency=*/0);
+ EXPECT_EQ(dest, nullptr);
+
+ auto *dest_op =
+ enc_->GetDestination(SlotEnum::kKelvin, 0, OpcodeEnum::kVldBX,
+ DestOpEnum::kPastMaxValue, 0, /*latency=*/0);
+ EXPECT_EQ(dest_op, nullptr);
+}
+
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.b.x (x = x0)
+ auto *src = EncodeOpHelper<RV32SourceOperand>(kVld, OpcodeEnum::kVldBX,
+ SourceOpEnum::kVs1);
+ EXPECT_EQ(src->AsString(), "0");
+ delete src;
+
// Test vld.w.l.xx
- auto *src = EncodeOpHelper<RV32SourceOperand>(
+ src = EncodeOpHelper<RV32SourceOperand>(
SetSz(SetRs1(kVld, kRdValue), 0b10) | (0b10 << 20 /* xs2 */) |
(0b1 << 26 /* length */),
OpcodeEnum::kVldWLXx, SourceOpEnum::kVs1);
@@ -353,8 +381,14 @@
EXPECT_EQ(v_src->AsString(), "v0");
delete v_src;
+ // Test xs1 as x0
+ auto *dest = EncodeOpHelper<RV32DestOperand>(kVstBase, OpcodeEnum::kVstBX,
+ DestOpEnum::kVs1);
+ EXPECT_EQ(dest->AsString(), "zero");
+ delete dest;
+
// Test xs1 in vst.w.l.xx as destination
- auto *dest = EncodeOpHelper<RV32DestOperand>(
+ dest = EncodeOpHelper<RV32DestOperand>(
SetSz(SetRs1(kVstBase, kRdValue), 0b10) | (0b10 << 20 /* xs2 */) |
(1 << 26 /* length */),
OpcodeEnum::kVstWLXx, DestOpEnum::kVs1);
@@ -442,11 +476,16 @@
delete v_src;
// Test aconv.vxv
- constexpr uint32_t kAVConvBase = 0b001000'000001'010000'10'110000'0'00'101;
v_src = EncodeOpHelper<RV32VectorSourceOperand>(
- kAVConvBase, OpcodeEnum::kAconvVxv, SourceOpEnum::kVs1);
+ kAconvBase, OpcodeEnum::kAconvVxv, SourceOpEnum::kVs1);
EXPECT_EQ(v_src->size(), 8);
delete v_src;
+
+ // No widening for vadd.b.vv
+ v_src = EncodeOpHelper<RV32VectorSourceOperand>(
+ kVAddBase, OpcodeEnum::kVaddBVv, SourceOpEnum::kVs1);
+ EXPECT_EQ(v_src->size(), 1);
+ delete v_src;
}
TEST_F(KelvinEncodingTest, KelvinWideningVd) {
@@ -536,12 +575,24 @@
}
TEST_F(KelvinEncodingTest, KelvinEncodeVs3) {
- constexpr uint32_t kACovBase = 0b001000'000001'010000'10'110000'0'00'101;
auto *v_src = EncodeOpHelper<RV32VectorSourceOperand>(
- kACovBase, OpcodeEnum::kAconvVxv, SourceOpEnum::kVs3);
+ kAconvBase, OpcodeEnum::kAconvVxv, SourceOpEnum::kVs3);
EXPECT_EQ(v_src->AsString(), "v8");
EXPECT_EQ(v_src->size(), 8);
delete v_src;
}
+TEST_F(KelvinEncodingTest, KelvinEncodeVs2) {
+ auto *v_src = EncodeOpHelper<RV32VectorSourceOperand>(
+ kVAddBase, OpcodeEnum::kVaddBVv, SourceOpEnum::kVs2);
+ EXPECT_EQ(v_src->size(), 1);
+ EXPECT_EQ(v_src->AsString(), "v0");
+ delete v_src;
+
+ auto *src = EncodeOpHelper<RV32SourceOperand>(
+ kVAddBase | 0b10, OpcodeEnum::kVaddBVx, SourceOpEnum::kVs2);
+ EXPECT_EQ(src->AsString(), "0");
+ delete src;
+}
+
} // namespace