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