Internal change
PiperOrigin-RevId: 550427286
diff --git a/sim/kelvin_encoding.cc b/sim/kelvin_encoding.cc
index 9bd3987..a92b6c3 100644
--- a/sim/kelvin_encoding.cc
+++ b/sim/kelvin_encoding.cc
@@ -202,6 +202,9 @@
return new mpact::sim::generic::IntLiteralOperand<0>(
{1}, xreg_alias_[0]);
}
+ // `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 GetRegisterSourceOp<mpact::sim::riscv::RV32Register>(
state_,
absl::StrCat(mpact::sim::riscv::RiscVState::kXregPrefix, reg_num),
@@ -222,6 +225,9 @@
return new mpact::sim::generic::IntLiteralOperand<0>(
{1}, xreg_alias_[0]);
}
+ // `vs2` is stored in bit[26:20], but scalar xs2 is in bit[25:20]
+ // (same as in the regular riscv32 encoding)
+ reg_num = reg_num & 0x1F;
return GetRegisterSourceOp<mpact::sim::riscv::RV32Register>(
state_,
absl::StrCat(mpact::sim::riscv::RiscVState::kXregPrefix, reg_num),
@@ -230,6 +236,17 @@
return GetVectorRegisterSourceOp<mpact::sim::riscv::RVVectorRegister>(
state_, reg_num, strip_mine, 1 /* widen_factor */);
});
+ source_op_getters_.emplace(
+ // vst and vstq use `vd` field as the source for the vector store.
+ static_cast<int>(SourceOpEnum::kVd),
+ [this]() -> SourceOperandInterface * {
+ auto reg_num = encoding::kelvin_v2_args_type::ExtractVd(inst_word_);
+ bool strip_mine = encoding::kelvin_v2_args_type::ExtractM(inst_word_);
+ if (opcode_ < OpcodeEnum::kVstBLXx || opcode_ > OpcodeEnum::kVstqWSpXxM)
+ return nullptr;
+ return GetVectorRegisterSourceOp<mpact::sim::riscv::RVVectorRegister>(
+ state_, reg_num, strip_mine, 1 /* widen_factor */);
+ });
source_op_getters_.insert(std::make_pair(
static_cast<int>(SourceOpEnum::kNone), []() { return nullptr; }));
}
diff --git a/sim/test/BUILD b/sim/test/BUILD
index f0c8147..7cf1e1d 100644
--- a/sim/test/BUILD
+++ b/sim/test/BUILD
@@ -2,6 +2,7 @@
exports_files([
"testfiles/hello_world_rv32imf.elf",
+ "testfiles/kelvin_vldvst.elf",
"testfiles/rv32i.elf",
"testfiles/rv32m.elf",
"testfiles/rv32soft_fp.elf",
@@ -52,6 +53,7 @@
data = [
"testfiles/hello_world_mpause.elf",
"testfiles/hello_world_rv32imf.elf",
+ "testfiles/kelvin_vldvst.elf",
"testfiles/rv32i.elf",
"testfiles/rv32m.elf",
"testfiles/rv32soft_fp.elf",
diff --git a/sim/test/kelvin_top_test.cc b/sim/test/kelvin_top_test.cc
index 6b218c9..28e4b8b 100644
--- a/sim/test/kelvin_top_test.cc
+++ b/sim/test/kelvin_top_test.cc
@@ -29,6 +29,7 @@
constexpr char kRV32mElfFileName[] = "rv32m.elf";
constexpr char kRV32SoftFloatElfFileName[] = "rv32soft_fp.elf";
constexpr char kRV32fElfFileName[] = "rv32uf_fadd.elf";
+constexpr char kKelvinVldVstFileName[] = "kelvin_vldvst.elf";
// The depot path to the test directory.
constexpr char kDepotPath[] = "sim/test/";
@@ -329,4 +330,18 @@
}
}
+TEST_F(KelvinTopTest, RunKelvinVectorProgram) {
+ LoadFile(kKelvinVldVstFileName);
+ testing::internal::CaptureStdout();
+ EXPECT_OK(kelvin_top_->WriteRegister("pc", entry_point_));
+ EXPECT_OK(kelvin_top_->Run());
+ EXPECT_OK(kelvin_top_->Wait());
+ auto halt_result = kelvin_top_->GetLastHaltReason();
+ CHECK_OK(halt_result);
+ EXPECT_EQ(static_cast<int>(halt_result.value()),
+ static_cast<int>(HaltReason::kUserRequest));
+ const std::string stdout_str = testing::internal::GetCapturedStdout();
+ EXPECT_THAT(stdout_str, testing::HasSubstr("vld_vst test passed!"));
+}
+
} // namespace
diff --git a/sim/test/testfiles/kelvin_vldvst.elf b/sim/test/testfiles/kelvin_vldvst.elf
new file mode 100755
index 0000000..34916db
--- /dev/null
+++ b/sim/test/testfiles/kelvin_vldvst.elf
Binary files differ