From 3307ab393e20f8eb1a5732f71f4dd11da5dde665 Mon Sep 17 00:00:00 2001 From: Saurav Singh Date: Thu, 18 Jun 2026 05:36:49 +0000 Subject: [PATCH 1/6] :bug: [dispatcher] Clear use_vs1 for VWXUNARY0 instructions vmv.x.s, vcpop.m and vfirst.m are decoded in the OPMVV path, where use_vs1 defaults to 1'b1. For these instructions the rs1 field encodes the sub-opcode rather than a vector register, so leaving use_vs1 asserted makes the main sequencer raise a spurious hazard against whatever register number happens to occupy the rs1 field. Clear use_vs1 in the VWXUNARY0 block, mirroring the sibling 6'b010100 (VMSBF/VMSOF/VMSIF) block that already does this. Refs #436 --- hardware/src/ara_dispatcher.sv | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hardware/src/ara_dispatcher.sv b/hardware/src/ara_dispatcher.sv index e5f9e06d5..2e8e29865 100644 --- a/hardware/src/ara_dispatcher.sv +++ b/hardware/src/ara_dispatcher.sv @@ -1497,6 +1497,13 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( acc_resp_o.req_ready = 1'b0; acc_resp_o.resp_valid = 1'b0; + // VWXUNARY0 (vmv.x.s, vcpop.m, vfirst.m) do not read vs1: + // the rs1 field encodes the sub-opcode, not a vector register. + // Leaving use_vs1 asserted (the OPMVV default) makes the main + // sequencer detect a spurious hazard against whatever register + // number happens to sit in the rs1 field. + ara_req.use_vs1 = 1'b0; + case (insn.varith_type.rs1) 5'b00000: begin ara_req.op = ara_pkg::VMVXS; From 7a862313dca89b95abb2e2b5fda994261fc49b6a Mon Sep 17 00:00:00 2001 From: Saurav Singh Date: Thu, 18 Jun 2026 05:45:44 +0000 Subject: [PATCH 2/6] :white_check_mark: [apps] Add vmv_x_s_hazard regression reproducer Add a self-checking app that exercises the VWXUNARY0 spurious-vs1 hazard (#436). vmv.x.s decodes with rs1 = 0, which a buggy dispatcher reads as a false dependency on v0; the app writes v0 immediately before each vmv.x.s reading an unrelated source, in a tight chain. The dominant failure mode is serialization/deadlock rather than data corruption: a hang is caught by the testbench cycle-timeout, while the scalar read-back guards against result corruption. Build with `make bin/vmv_x_s_hazard`; run on Spike (`make spike-run-vmv_x_s_hazard`) or the Verilated model (`make simv app=vmv_x_s_hazard`). Refs #436 --- apps/vmv_x_s_hazard/main.c | 82 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 apps/vmv_x_s_hazard/main.c diff --git a/apps/vmv_x_s_hazard/main.c b/apps/vmv_x_s_hazard/main.c new file mode 100644 index 000000000..6b1f69c2e --- /dev/null +++ b/apps/vmv_x_s_hazard/main.c @@ -0,0 +1,82 @@ +// Copyright 2026 ETH Zurich and University of Bologna. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Regression reproducer for issue #436. +// +// The VWXUNARY0 instructions (vmv.x.s, vcpop.m, vfirst.m) are decoded in the +// OPMVV path of ara_dispatcher.sv, where ara_req.use_vs1 defaults to 1'b1. +// Their rs1 field encodes the *sub-opcode*, not a vector register: +// +// vmv.x.s -> rs1 = 0b00000 (0) -> a buggy dispatcher reads a false vs1 = v0 +// vcpop.m -> rs1 = 0b10000 (16) -> false vs1 = v16 +// vfirst.m -> rs1 = 0b10001 (17) -> false vs1 = v17 +// +// Leaving use_vs1 asserted makes the main sequencer raise a spurious RAW hazard +// against whatever register number occupies the rs1 field. The dominant failure +// mode is serialization or a deadlock (not data corruption), so: +// * a hang is caught by the testbench cycle-timeout, and +// * we additionally self-check the returned scalars to guard against any +// regression that would corrupt the result while "fixing" the hazard. +// +// This test deliberately writes v0 immediately before each vmv.x.s that reads +// an unrelated source register, building a tight producer/consumer chain on the +// register the bug falsely depends on. + +#include + +#ifdef SPIKE +#include "util.h" +#include +#elif defined ARA_LINUX +#include +#else +#include "printf.h" +#endif + +#define N_ITERS 8 + +int main() { + uint64_t vl; + int errors = 0; + + // SEW = 64, LMUL = 1 + asm volatile("vsetvli %0, zero, e64, m1, ta, ma" : "=r"(vl)); + + // Tight chain: write v0 (the register vmv.x.s falsely depends on), write the + // real source v8, then read back element 0 from v8 via vmv.x.s. A correct + // dispatcher does not stall on v0 here. + for (int i = 0; i < N_ITERS; i++) { + uint64_t poison = 0xAAAA000000000000ULL | (uint64_t)i; // goes into v0 + uint64_t src = 0x1122334455660000ULL | (uint64_t)i; // goes into v8 + uint64_t out; + + asm volatile("vmv.s.x v0, %0" ::"r"(poison)); // false-dependency target + asm volatile("vmv.s.x v8, %0" ::"r"(src)); // actual source element 0 + asm volatile("vmv.x.s %0, v8" : "=r"(out)); // must read v8, not wait on v0 + + if (out != src) { + printf("vmv.x.s iter %d: got 0x%lx, expected 0x%lx\n", i, out, src); + errors++; + } + } + + if (errors == 0) + printf("vmv_x_s_hazard: PASS\n"); + else + printf("vmv_x_s_hazard: FAIL (%d errors)\n", errors); + + return errors; +} From 07dab91bb59d2f09b3aebcccc96503e0cfaddc7e Mon Sep 17 00:00:00 2001 From: Saurav Singh Date: Thu, 18 Jun 2026 08:49:02 +0000 Subject: [PATCH 3/6] :bug: [dispatcher] Tag full vd..vd+nf for segment loads/stores The per-vreg EEW tracker (eew_d) only tagged EMUL consecutive registers from the base vd. Segment loads/stores write (nf+1) groups of EMUL registers, so vd+1..vd+nf kept the reset-default EW8; a later read at the real EEW saw a mismatch and triggered an on-read reshuffle that byte-packed the data across lanes. Detect segment memory ops (VLE/VLSE/VLXE/VSE/VSSE/VSXE with nf != 0) and tag (nf+1)*EMUL consecutive destination registers. Verified with a Spike-vs-Ara differential (vlseg_eew, vlseg4e16 at e16/m1, 4 lanes, VLEN=4096): after the fix Ara matches Spike on all four fields {1,2,3,4},{11,12,13,14},{21,22,23,24},{31,32,33,34}. Refs #453 --- apps/vlseg_eew/main.c | 60 ++++++++++++++++++++++++++++++++++ hardware/src/ara_dispatcher.sv | 51 ++++++++++++----------------- 2 files changed, 81 insertions(+), 30 deletions(-) create mode 100644 apps/vlseg_eew/main.c diff --git a/apps/vlseg_eew/main.c b/apps/vlseg_eew/main.c new file mode 100644 index 000000000..917449a0b --- /dev/null +++ b/apps/vlseg_eew/main.c @@ -0,0 +1,60 @@ +// Copyright 2026 ETH Zurich and University of Bologna. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Spike-vs-Ara differential probe for issue #453 (segment load corrupts +// vd+1..vd+nf on read-back when EEW != EW8). +// +// vlseg4e16.v writes v8..v11. The per-vreg EEW tracker only tagged the base vd, +// so reading v9/v10/v11 back triggered a spurious on-read reshuffle that +// byte-packs the data. We load 4 segments of 4 fields, store each field, and +// print them; diff Spike vs Ara. + +#include + +#ifdef SPIKE +#include "util.h" +#include +#elif defined ARA_LINUX +#include +#else +#include "printf.h" +#endif + +static volatile uint16_t in_buf[16]; // 4 elements x 4 fields, element-major +static volatile uint16_t f0[4], f1[4], f2[4], f3[4]; + +int main() { + uint64_t vl; + + // in_buf[i*4 + j] = base[j] + i, with base = {1, 11, 21, 31} + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + in_buf[i * 4 + j] = (uint16_t)((j * 10 + 1) + i); + + asm volatile("vsetivli %0, 4, e16, m1, ta, ma" : "=r"(vl)); + asm volatile("vlseg4e16.v v8, (%0)" ::"r"(in_buf)); + asm volatile("vse16.v v8, (%0)" ::"r"(f0) : "memory"); + asm volatile("vse16.v v9, (%0)" ::"r"(f1) : "memory"); + asm volatile("vse16.v v10, (%0)" ::"r"(f2) : "memory"); + asm volatile("vse16.v v11, (%0)" ::"r"(f3) : "memory"); + + // Expected: f0={1,2,3,4} f1={11,12,13,14} f2={21,22,23,24} f3={31,32,33,34} + for (int i = 0; i < 4; i++) printf("a%d=%d\n", i, (int)f0[i]); + for (int i = 0; i < 4; i++) printf("b%d=%d\n", i, (int)f1[i]); + for (int i = 0; i < 4; i++) printf("c%d=%d\n", i, (int)f2[i]); + for (int i = 0; i < 4; i++) printf("d%d=%d\n", i, (int)f3[i]); + return 0; +} diff --git a/hardware/src/ara_dispatcher.sv b/hardware/src/ara_dispatcher.sv index 2e8e29865..639f0240b 100644 --- a/hardware/src/ara_dispatcher.sv +++ b/hardware/src/ara_dispatcher.sv @@ -3706,38 +3706,29 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( // Update the EEW if (ara_req_valid_d && ara_req.use_vd && ara_req_ready_i) begin + automatic int unsigned regs_per_emul; + automatic int unsigned regs_to_tag; + automatic logic is_seg_mem_op; unique case (ara_req.emul) - LMUL_1: begin - for (int i = 0; i < 1; i++) begin - eew_d[ara_req.vd + i] = ara_req.vtype.vsew; - eew_valid_d[ara_req.vd + i] = 1'b1; - end - end - LMUL_2: begin - for (int i = 0; i < 2; i++) begin - eew_d[ara_req.vd + i] = ara_req.vtype.vsew; - eew_valid_d[ara_req.vd + i] = 1'b1; - end - end - LMUL_4: begin - for (int i = 0; i < 4; i++) begin - eew_d[ara_req.vd + i] = ara_req.vtype.vsew; - eew_valid_d[ara_req.vd + i] = 1'b1; - end - end - LMUL_8: begin - for (int i = 0; i < 8; i++) begin - eew_d[ara_req.vd + i] = ara_req.vtype.vsew; - eew_valid_d[ara_req.vd + i] = 1'b1; - end - end - default: begin // EMUL < 1 - for (int i = 0; i < 1; i++) begin - eew_d[ara_req.vd + i] = ara_req.vtype.vsew; - eew_valid_d[ara_req.vd + i] = 1'b1; - end - end + LMUL_2: regs_per_emul = 2; + LMUL_4: regs_per_emul = 4; + LMUL_8: regs_per_emul = 8; + default: regs_per_emul = 1; // LMUL_1 and EMUL < 1 endcase + // Segment loads/stores write (nf+1) groups of EMUL consecutive registers + // (vd, vd+EMUL, ...). Without tagging them all, vd+1..vd+nf keep the + // reset-default EW8 and a later read triggers a spurious on-read reshuffle + // that byte-packs the data (#453). + is_seg_mem_op = (ara_req.op inside {VLE, VLSE, VLXE, VSE, VSSE, VSXE}) + && (ara_req.nf != 3'b000); + regs_to_tag = is_seg_mem_op ? regs_per_emul * (int'(ara_req.nf) + 1) + : regs_per_emul; + for (int i = 0; i < 32; i++) begin + if (i < regs_to_tag) begin + eew_d[ara_req.vd + i] = ara_req.vtype.vsew; + eew_valid_d[ara_req.vd + i] = 1'b1; + end + end end // Any valid non-config instruction is a NOP if vl == 0, with some exceptions, From a371e9a5eb1115b7876d37aebc24561e15b7262c Mon Sep 17 00:00:00 2001 From: Saurav Singh Date: Thu, 18 Jun 2026 17:34:39 +0000 Subject: [PATCH 4/6] :bug: [dispatcher] Force vsext/vzext.vf8 source width to EW8 VXUNARY0 VF8 set `eew_vs2 = eew_q[vs2]`, i.e. the source register's last-written element width. When that tracked eew was wider than the 1/8-width view (e.g. the source was last written at e16), the ZExt8/SExt8 opqueue conversion - which only handles EW8 - falls through and the operand is forwarded unconverted, producing a wrong result. vf8 is only legal at SEW=e64, so the source elements are always EW8. Force `eew_vs2 = EW8`, mirroring how VF4/VF2 already use the computed narrower width rather than the tracked eew. Verified against Spike: `vzext.vf8` of e16 0xa04f now yields v14[0]=0x4f, v14[1]=0xa0 (Ara previously returned 0xa04f, 0). Refs #452 --- apps/vzext_vf8/main.c | 32 ++++++++++++++++++++++++++++++++ hardware/src/ara_dispatcher.sv | 10 ++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 apps/vzext_vf8/main.c diff --git a/apps/vzext_vf8/main.c b/apps/vzext_vf8/main.c new file mode 100644 index 000000000..412b9f186 --- /dev/null +++ b/apps/vzext_vf8/main.c @@ -0,0 +1,32 @@ +// Copyright 2026 ETH Zurich and University of Bologna. +// SPDX-License-Identifier: Apache-2.0 +// +// Spike-vs-Ara differential probe for issue #452 (vzext.vf8 reads the wrong +// source width). v28[0] (e16) = 0xa04f; vzext.vf8 to e64 should zero-extend the +// 8-bit sub-elements: v14[0]=0x4f, v14[1]=0xa0. Register-only (no race). + +#include +#ifdef SPIKE +#include "util.h" +#include +#elif defined ARA_LINUX +#include +#else +#include "printf.h" +#endif + +int main() { + uint64_t x20, x21; + uint64_t v = 0xa04f; + + asm volatile("vsetivli x8, 1, e16, mf4, ta, ma"); + asm volatile("vmv.s.x v28, %0" ::"r"(v)); + asm volatile("vsetivli x8, 27, e64, m1, ta, ma"); + asm volatile("vzext.vf8 v14, v28"); + asm volatile("vmv.x.s %0, v14" : "=r"(x20)); // expect 0x4f = 79 + asm volatile("vslidedown.vi v15, v14, 1"); + asm volatile("vmv.x.s %0, v15" : "=r"(x21)); // expect 0xa0 = 160 + + printf("x20=%d x21=%d\n", (int)x20, (int)x21); + return 0; +} diff --git a/hardware/src/ara_dispatcher.sv b/hardware/src/ara_dispatcher.sv index 639f0240b..3f813f08e 100644 --- a/hardware/src/ara_dispatcher.sv +++ b/hardware/src/ara_dispatcher.sv @@ -1667,7 +1667,12 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( case (insn.varith_type.rs1) 5'b00010: begin // VZEXT.VF8 ara_req.conversion_vs2 = OpQueueConversionZExt8; - ara_req.eew_vs2 = eew_q[insn.varith_type.rs2]; + // The source is 1/8 the destination width. VF8 is only legal + // at SEW=e64, so the source elements are always EW8. Using the + // tracked eew_q here was wrong: a stale eew (e.g. e16) makes the + // ZExt8 opqueue conversion (which only handles EW8) fall through, + // leaving the operand unconverted. (#452) + ara_req.eew_vs2 = EW8; ara_req.cvt_resize = CVT_WIDE; ara_req.emul = csr_vtype_q.vlmul; lmul_vs2 = prev_lmul(prev_lmul(prev_lmul(csr_vtype_q.vlmul))); @@ -1679,7 +1684,8 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( end 5'b00011: begin // VSEXT.VF8 ara_req.conversion_vs2 = OpQueueConversionSExt8; - ara_req.eew_vs2 = eew_q[insn.varith_type.rs2]; + // See VZEXT.VF8 above: source is always EW8 (VF8 needs e64). (#452) + ara_req.eew_vs2 = EW8; ara_req.cvt_resize = CVT_WIDE; ara_req.emul = csr_vtype_q.vlmul; lmul_vs2 = prev_lmul(prev_lmul(prev_lmul(csr_vtype_q.vlmul))); From a29a2657bead815df3427bbd358b27fb4abfc5d7 Mon Sep 17 00:00:00 2001 From: Saurav Singh Date: Thu, 18 Jun 2026 19:13:36 +0000 Subject: [PATCH 5/6] :bug: [dispatcher] Reject masked vmerge/vfmerge with vd=v0 A masked vector instruction's destination group must not overlap the mask source v0 (RVV spec), unless it writes a mask or scalar result. vmerge and vfmerge are always masked by v0 and write a full vector, so vd=v0 is illegal. Ara executed it instead of trapping. Raise illegal-instruction when the merge form (vm=0) targets vd=v0, across the OPIVV/OPIVX/OPIVI integer encodings and the OPFVF float encoding. The vmv.v.*/vfmv.v.f forms (vm=1) share the funct6 but are unmasked and remain legal with vd=v0. Verified against Spike with a trap probe: vmerge.vim v0, v20, -2, v0 now traps with mcause=2 (illegal instruction), while the preceding legal vmv.v.x v0 setup does not trap. Refs #460 --- apps/vmerge_v0_illegal/main.c | 60 ++++++++++++++++++++++++++++++++++ hardware/src/ara_dispatcher.sv | 19 ++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 apps/vmerge_v0_illegal/main.c diff --git a/apps/vmerge_v0_illegal/main.c b/apps/vmerge_v0_illegal/main.c new file mode 100644 index 000000000..5e6cccb44 --- /dev/null +++ b/apps/vmerge_v0_illegal/main.c @@ -0,0 +1,60 @@ +// Copyright 2026 ETH Zurich and University of Bologna. +// SPDX-License-Identifier: Apache-2.0 +// +// Spike-vs-Ara differential trap probe for issue #460: a masked vmerge whose +// destination is v0 (also the mask source) must raise an illegal-instruction +// exception (mcause=2). vmv.v.* (vm=1) with vd=v0 stays legal. +// +// vsetivli x8, 10, e8, m4 +// vmv.v.x v0, -1 ; legal (vm=1), must NOT trap +// vmv.v.x v20, 0x33 ; legal +// marker = 1 ; proves setup did not trap +// vmerge.vim v0, v20, -2, v0 ; illegal -> trap, mcause=2 +// Expected (both): cause=2, marker=1. + +#include +#ifdef SPIKE +#include "util.h" +#include +#elif defined ARA_LINUX +#include +#else +#include "printf.h" +#endif + +volatile uint64_t g_cause = 0xbad; +volatile uint64_t g_marker = 0; + +asm(".global mtvec_handler\n" + ".align 2\n" + "mtvec_handler:\n" + " addi sp, sp, -16\n" + " sd t0, 0(sp)\n" + " sd t1, 8(sp)\n" + " csrr t0, mcause\n la t1, g_cause\n sd t0, 0(t1)\n" + " la t0, trap_resume\n csrw mepc, t0\n" + " ld t0, 0(sp)\n ld t1, 8(sp)\n addi sp, sp, 16\n" + " mret\n"); + +extern char trap_resume[]; +uintptr_t handle_trap(uintptr_t cause, uintptr_t epc, uintptr_t regs) { + (void)epc; + (void)regs; + g_cause = cause; + return (uintptr_t)trap_resume; +} + +int main() { + asm volatile("fence" ::: "memory"); + asm volatile("vsetivli x8, 10, e8, m4"); + asm volatile("li t0, -1\n vmv.v.x v0, t0" ::: "t0"); // legal (vm=1) + asm volatile("li t0, 0x33\n vmv.v.x v20, t0" ::: "t0"); // legal + g_marker = 1; // setup did not trap + asm volatile("vmerge.vim v0, v20, -2, v0\n" // illegal + ".global trap_resume\n" + "trap_resume:\n"); + asm volatile("fence" ::: "memory"); + + printf("cause=%d marker=%d\n", (int)g_cause, (int)g_marker); + return 0; +} diff --git a/hardware/src/ara_dispatcher.sv b/hardware/src/ara_dispatcher.sv index 3f813f08e..491ee8c47 100644 --- a/hardware/src/ara_dispatcher.sv +++ b/hardware/src/ara_dispatcher.sv @@ -844,6 +844,11 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( 6'b010111: begin ara_req.op = ara_pkg::VMERGE; ara_req.use_vs2 = !insn.varith_type.vm; // vmv.v.v does not use vs2 + // A masked vmerge (vm=0) writes a full vector, so its vd + // must not overlap the mask source v0. vmv.v.v (vm=1) is + // exempt. (#460) + if (!insn.varith_type.vm && insn.varith_type.rd == 5'd0) + illegal_insn = 1'b1; // With a normal vmv.v.v, copy input eew to output // to avoid unnecessary reshuffles if (insn.varith_type.vm) begin @@ -1120,6 +1125,9 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( 6'b010111: begin ara_req.op = ara_pkg::VMERGE; ara_req.use_vs2 = !insn.varith_type.vm; // vmv.v.x does not use vs2 + // Masked vmerge vd must not overlap the mask source v0. (#460) + if (!insn.varith_type.vm && insn.varith_type.rd == 5'd0) + illegal_insn = 1'b1; end 6'b100000: ara_req.op = ara_pkg::VSADDU; 6'b100001: ara_req.op = ara_pkg::VSADD; @@ -1320,6 +1328,9 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( 6'b010111: begin ara_req.op = ara_pkg::VMERGE; ara_req.use_vs2 = !insn.varith_type.vm; // vmv.v.i does not use vs2 + // Masked vmerge vd must not overlap the mask source v0. (#460) + if (!insn.varith_type.vm && insn.varith_type.rd == 5'd0) + illegal_insn = 1'b1; end 6'b100000: ara_req.op = ara_pkg::VSADDU; 6'b100001: ara_req.op = ara_pkg::VSADD; @@ -2670,7 +2681,13 @@ module ara_dispatcher import ara_pkg::*; import rvv_pkg::*; #( // This instruction ignores LMUL checks skip_lmul_checks = 1'b1; end - 6'b010111: ara_req.op = ara_pkg::VMERGE; + 6'b010111: begin + ara_req.op = ara_pkg::VMERGE; + // Masked vfmerge vd must not overlap the mask source v0; + // vfmv.v.f (vm=1) is exempt. (#460) + if (!insn.varith_type.vm && insn.varith_type.rd == 5'd0) + illegal_insn = 1'b1; + end 6'b011000: begin ara_req.op = ara_pkg::VMFEQ; ara_req.use_vd_op = 1'b1; From f1a7030e6fff5be85c9a5b99816fd418befed0e7 Mon Sep 17 00:00:00 2001 From: Saurav Singh Date: Sat, 20 Jun 2026 09:36:12 +0000 Subject: [PATCH 6/6] :memo: [changelog] Document pr/dispatcher-fixes --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 542eb153d..4fa805b98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + + - Add `vmv_x_s_hazard` app: regression reproducer for the VWXUNARY0 vs1 hazard (#436) + - Add `vlseg_eew` app: Spike-vs-Ara differential probe for the segment-load EEW tracker bug (#453) + - Add `vzext_vf8` app: Spike-vs-Ara differential probe for the vzext/vsext.vf8 source-width bug (#452) + - Add `vmerge_v0_illegal` app: Spike-vs-Ara trap probe for the masked vmerge vd=v0 legality check (#460) + ### Fixed + - Clear `use_vs1` for VWXUNARY0 (`vmv.x.s`, `vcpop.m`, `vfirst.m`) to avoid a spurious vs1 hazard (#436) + - Tag all destination registers of segment loads/stores in the EEW tracker, fixing corrupted vd+1..vd+nf read-back (#453) + - Force the `vsext.vf8`/`vzext.vf8` source element width to EW8 instead of the tracked eew, fixing a wrong result when the source register's last-written eew was not the 1/8-width view (#452) + - Raise illegal-instruction for a masked `vmerge`/`vfmerge` whose destination is `v0` (overlaps the mask source), matching the RVV vd/v0 overlap rule; `vmv.v.*`/`vfmv.v.f` (vm=1) stay legal (#460) - Fix dump vtrace script for vsetvli instructions without x0 (ideal dispatcher) - Fix Pathfinder and FFT performance - Stall Ara and wait for ara_idle upon CSR write/read