No public description PiperOrigin-RevId: 967225262 Change-Id: Iab2f390d93552633c50869f0ed07f84522ab53b7
diff --git a/riscv/riscv_vector_fp_unary_instructions.cc b/riscv/riscv_vector_fp_unary_instructions.cc index fbe3786..58c6d09 100644 --- a/riscv/riscv_vector_fp_unary_instructions.cc +++ b/riscv/riscv_vector_fp_unary_instructions.cc
@@ -14,6 +14,7 @@ #include "riscv/riscv_vector_fp_unary_instructions.h" +#include <algorithm> #include <cmath> #include <cstdint> #include <limits> @@ -70,27 +71,50 @@ const int sew = rv_vector->selected_element_width(); auto dest_op = static_cast<RV32VectorDestinationOperand*>(inst->Destination(0)); - auto dest_db = dest_op->CopyDataBuffer(); switch (sew) { - case 4: - for (int i = 0; i < vl; ++i) { - dest_db->Set<uint32_t>( - i, generic::GetInstructionSource<uint32_t>(inst, 0, 0)); + case 4: { + using Vd = uint32_t; + int elements_per_vector = + rv_vector->vector_register_byte_length() / sizeof(Vd); + int max_regs = (vl + elements_per_vector - 1) / elements_per_vector; + int vector_index = 0; + for (int reg = 0; reg < max_regs; reg++) { + auto* dest_db = dest_op->CopyDataBuffer(reg); + auto dest_span = dest_db->Get<Vd>(); + int element_count = std::min(elements_per_vector, vl - vector_index); + uint32_t val = generic::GetInstructionSource<uint32_t>(inst, 0, 0); + for (int i = 0; i < element_count; ++i) { + dest_span[i] = val; + vector_index++; + } + dest_db->Submit(); } break; - case 8: - for (int i = 0; i < vl; ++i) { - dest_db->Set<uint64_t>( - i, generic::GetInstructionSource<uint64_t>(inst, 0, 0)); + } + case 8: { + using Vd = uint64_t; + int elements_per_vector = + rv_vector->vector_register_byte_length() / sizeof(Vd); + int max_regs = (vl + elements_per_vector - 1) / elements_per_vector; + int vector_index = 0; + for (int reg = 0; reg < max_regs; reg++) { + auto* dest_db = dest_op->CopyDataBuffer(reg); + auto dest_span = dest_db->Get<Vd>(); + int element_count = std::min(elements_per_vector, vl - vector_index); + uint64_t val = generic::GetInstructionSource<uint64_t>(inst, 0, 0); + for (int i = 0; i < element_count; ++i) { + dest_span[i] = val; + vector_index++; + } + dest_db->Submit(); } break; + } default: - dest_db->DecRef(); - LOG(ERROR) << "Vfmv.s.f: Illegal sew (" << sew << ")"; + LOG(ERROR) << "Vfmv.v.f: Illegal sew (" << sew << ")"; rv_vector->set_vector_exception(); return; } - dest_db->Submit(); rv_vector->clear_vstart(); }
diff --git a/riscv/riscv_vector_permute_instructions.cc b/riscv/riscv_vector_permute_instructions.cc index 090fb5a..f69903c 100644 --- a/riscv/riscv_vector_permute_instructions.cc +++ b/riscv/riscv_vector_permute_instructions.cc
@@ -298,7 +298,14 @@ // Compute result. Vd src_value = slide_value; int src_index = vector_index - offset; - if ((src_index > 0) && (src_index < rv_vector->max_vector_length())) { + // Fix for slide1 instructions: + // 1. For vslide1up (offset=1), src_index=0 is valid (vs2[0]), so check + // src_index >= 0. + // 2. For vslide1down (offset=-1), when vector_index=vl-1, src_index=vl. + // We must use + // slide_value if src_index >= vl (num_elements), not + // max_vector_length (VLMAX). + if ((src_index >= 0) && (src_index < num_elements)) { src_value = generic::GetInstructionSource<Vd>(inst, 0, src_index); } dest_span[i] = src_value;
diff --git a/riscv/test/riscv_vector_fp_unary_instructions_test.cc b/riscv/test/riscv_vector_fp_unary_instructions_test.cc index a15e57b..0984864 100644 --- a/riscv/test/riscv_vector_fp_unary_instructions_test.cc +++ b/riscv/test/riscv_vector_fp_unary_instructions_test.cc
@@ -55,6 +55,7 @@ using ::mpact::sim::riscv::Vfcvtxufv; using ::mpact::sim::riscv::Vfmvfs; using ::mpact::sim::riscv::Vfmvsf; +using ::mpact::sim::riscv::Vfmvvf; using ::mpact::sim::riscv::Vfncvtffw; using ::mpact::sim::riscv::Vfncvtfxuw; using ::mpact::sim::riscv::Vfncvtfxw; @@ -733,6 +734,50 @@ } } +// Test vfmv.v.f instruction - broadcast scalar fp register across vector +// register group. +TEST_F(RiscVFPUnaryInstructionsTest, VfmvBroadcastScalar) { + SetSemanticFunction(&Vfmvvf); + AppendRegisterOperands<RVFpRegister>({kFs1Name}, {}); + AppendVectorRegisterOperands({}, {kVd}); + for (int byte_sew : {4, 8}) { + for (int lmul_index = 0; lmul_index < 7; lmul_index++) { + int lmul8 = kLmul8Values[lmul_index]; + int vlen = lmul8 * kVectorLengthInBytes / (8 * byte_sew); + if (vlen == 0) vlen = 1; + uint32_t vtype = + (kSewSettingsByByteSize[byte_sew] << 3) | kLmulSettings[lmul_index]; + ConfigureVectorUnit(vtype, vlen); + ClearVectorRegisterGroup(kVd, 8); + auto value = RandomValue<RVFpRegister::ValueType>(); + freg_[kFs1]->data_buffer()->Set<RVFpRegister::ValueType>(0, value); + instruction_->Execute(); + EXPECT_FALSE(rv_vector_->vector_exception()); + int num_elements_per_reg = kVectorLengthInBytes / byte_sew; + for (int i = 0; i < vlen; i++) { + int reg_offset = i / num_elements_per_reg; + int elem_idx = i % num_elements_per_reg; + switch (byte_sew) { + case 4: + EXPECT_EQ( + vreg_[kVd + reg_offset]->data_buffer()->Get<uint32_t>(elem_idx), + static_cast<uint32_t>(value)) + << "byte_sew: " << byte_sew << " lmul: " << lmul_index + << " i: " << i; + break; + case 8: + EXPECT_EQ( + vreg_[kVd + reg_offset]->data_buffer()->Get<uint64_t>(elem_idx), + static_cast<uint64_t>(value)) + << "byte_sew: " << byte_sew << " lmul: " << lmul_index + << " i: " << i; + break; + } + } + } + } +} + // Test narrowing convert from unsigned integer to fp. TEST_F(RiscVFPUnaryInstructionsTest, Vfncvtfxuw) { SetSemanticFunction(&Vfncvtfxuw);