Fix `vsrans.h` support
Add encoding unit test coverage
PiperOrigin-RevId: 558201551
diff --git a/sim/kelvin_encoding.cc b/sim/kelvin_encoding.cc
index 53047f0..9e3eee4 100644
--- a/sim/kelvin_encoding.cc
+++ b/sim/kelvin_encoding.cc
@@ -402,14 +402,14 @@
return 2;
}
- // Func1 0b010 VSrans[u][.r] also needs 2x src1 registers.
- if ((func1 == 0b010) && (sz == 0) &&
+ // Func1 0b010 VSrans.[b,h].[u][.r] also needs 2x src1 registers.
+ if ((func1 == 0b010) && ((sz == 0) || (sz == 1)) &&
(func2_ignore_unsigned == 0b010000 ||
func2_ignore_unsigned == 0b010010)) {
return 2;
}
- // Func1 0b010 VSraqs[u][.r] needs 4x src1 registers.
+ // Func1 0b010 VSraqs.b.[u][.r] needs 4x src1 registers.
if ((func1 == 0b010) && (sz == 0) &&
(func2_ignore_unsigned == 0b011000 ||
func2_ignore_unsigned == 0b011010)) {
diff --git a/sim/test/BUILD b/sim/test/BUILD
index 73a0b56..6e1ac0a 100644
--- a/sim/test/BUILD
+++ b/sim/test/BUILD
@@ -17,8 +17,10 @@
],
deps = [
"//sim:kelvin_decoder",
+ "//sim:kelvin_isa",
"//sim:kelvin_state",
"@com_google_googletest//:gtest_main",
+ "@com_google_mpact-riscv//riscv:riscv_state",
],
)
diff --git a/sim/test/kelvin_encoding_test.cc b/sim/test/kelvin_encoding_test.cc
index 0037c7b..66ec918 100644
--- a/sim/test/kelvin_encoding_test.cc
+++ b/sim/test/kelvin_encoding_test.cc
@@ -1,7 +1,11 @@
#include "sim/kelvin_encoding.h"
+#include <cstdint>
+
+#include "sim/kelvin_enums.h"
#include "sim/kelvin_state.h"
#include "googletest/include/gtest/gtest.h"
+#include "riscv/riscv_register.h"
namespace {
@@ -9,6 +13,8 @@
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;
// RV32I
constexpr uint32_t kLui = 0b0000000000000000000000000'0110111;
@@ -94,6 +100,15 @@
delete state_;
}
+ RV32VectorSourceOperand *VectorSourceEncodeHelper(
+ uint32_t inst_word, OpcodeEnum opcode, SourceOpEnum source_op) const {
+ enc_->ParseInstruction(inst_word);
+ EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), opcode);
+ auto source = enc_->GetSource(SlotEnum::kKelvin, 0, opcode, source_op, 0);
+ return reinterpret_cast<mpact::sim::riscv::RV32VectorSourceOperand *>(
+ source);
+ }
+
KelvinState *state_;
KelvinEncoding *enc_;
};
@@ -300,4 +315,41 @@
enc_->ParseInstruction(kRemu);
EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kRemu);
}
+
+TEST_F(KelvinEncodingTest, VsraxsWideningVs1) {
+ constexpr uint32_t kVSransBase = 0b010000'000001'000000'00'001000'0'010'00;
+ auto v_src = VectorSourceEncodeHelper(kVSransBase, OpcodeEnum::kVsransBVv,
+ SourceOpEnum::kVs1);
+ EXPECT_EQ(v_src->size(), 2);
+ delete v_src;
+
+ // Test vsrans.b.r.vv
+ v_src = VectorSourceEncodeHelper(kVSransBase | (1 << 27),
+ OpcodeEnum::kVsransBRVv, SourceOpEnum::kVs1);
+ EXPECT_EQ(v_src->size(), 2);
+ delete v_src;
+
+ // Test vsrans.h.vv
+ v_src = VectorSourceEncodeHelper(kVSransBase | (1 << 12),
+ OpcodeEnum::kVsransHVv, SourceOpEnum::kVs1);
+ EXPECT_EQ(v_src->size(), 2);
+ delete v_src;
+
+ // Test vsraqs.b.vv
+ v_src = VectorSourceEncodeHelper(kVSransBase | (1 << 29),
+ OpcodeEnum::kVsraqsBVv, SourceOpEnum::kVs1);
+ EXPECT_EQ(v_src->size(), 4);
+ delete v_src;
+
+ // Test vsraqs.b.r.vv
+ v_src = VectorSourceEncodeHelper(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(kVSransBase | (2 << 12));
+ EXPECT_EQ(enc_->GetOpcode(SlotEnum::kKelvin, 0), OpcodeEnum::kNone);
+}
+
} // namespace