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