ab_riscv_interpreter/v/zvexx/reduction/
zvexx_reduction_helpers.rs1use crate::v::vector_registers::{VRegGroup, VectorRegistersExt};
3use crate::v::zvexx::arith::zvexx_arith_helpers::sign_extend;
4use crate::v::zvexx::load::zvexx_load_helpers::{mask_bit, snapshot_mask};
5use crate::v::zvexx::zvexx_helpers::WideningSew;
6use ab_riscv_primitives::prelude::*;
7use core::hint::cold_path;
8
9#[inline(always)]
14#[doc(hidden)]
15#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
16pub fn execute_reduce_op<Reg, Env, F>(
17 env: &mut Env,
18 vd: VReg,
19 vs2: VRegGroup<Env::Hart>,
20 vs1: VReg,
21 vm: bool,
22 sew: Vsew,
23 op: F,
24) where
25 Reg: Register,
26 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
27 F: Fn(u64, u64, Vsew) -> u64,
28{
29 let vl = vs2.vl();
33 if vl.get() == Vl::ZERO {
34 cold_path();
35 return;
36 }
37 let init = env
38 .read_vregs()
39 .read_first(vs1, sew.as_eew())
40 .expect("Element width never exceeds `ELEN`, which never exceeds `VLEN`; qed");
41 let mask_buf = snapshot_mask(env.read_vregs(), vm);
42 let mut acc = init;
43 for i in vl.indices() {
44 if !mask_bit(&mask_buf, i) {
45 continue;
46 }
47 let elem = env
48 .read_vregs()
49 .read(vs2, i)
50 .expect("`i < vl` of `vs2`; qed");
51 acc = op(acc, elem, sew);
52 }
53 env.write_vregs()
54 .write_first(vd, sew.as_eew(), acc)
55 .expect("Element width never exceeds `ELEN`, which never exceeds `VLEN`; qed");
56 env.mark_vs_dirty();
57}
58
59#[inline(always)]
64#[doc(hidden)]
65#[cfg_attr(feature = "no-panic", no_panic_const::no_panic)]
66pub fn execute_widening_reduce_op<const SIGN_EXTEND_SRC: bool, Reg, Env, F>(
67 env: &mut Env,
68 vd: VReg,
69 vs2: VRegGroup<Env::Hart>,
70 vs1: VReg,
71 vm: bool,
72 sew: WideningSew<Env::Hart>,
73 op: F,
74) where
75 Reg: Register,
76 Env: VectorRegistersExt<Hart: HartConfig<Reg = Reg>>,
77 F: Fn(u64, u64, Vsew) -> u64,
78{
79 let wide_sew = sew.wide();
80 let sew = sew.narrow();
81 let vl = vs2.vl();
82 if vl.get() == Vl::ZERO {
83 cold_path();
84 return;
85 }
86 let init = env
87 .read_vregs()
88 .read_first(vs1, wide_sew.as_eew())
89 .expect("Element width never exceeds `ELEN`, which never exceeds `VLEN`; qed");
90 let mask_buf = snapshot_mask(env.read_vregs(), vm);
91 let mut acc = init;
92 for i in vl.indices() {
93 if !mask_bit(&mask_buf, i) {
94 continue;
95 }
96 let raw = env
97 .read_vregs()
98 .read(vs2, i)
99 .expect("`i < vl` of `vs2`; qed");
100 let elem = if SIGN_EXTEND_SRC {
101 sign_extend(raw, sew).cast_unsigned()
102 } else {
103 raw
104 };
105 acc = op(acc, elem, wide_sew);
106 }
107 env.write_vregs()
108 .write_first(vd, wide_sew.as_eew(), acc)
109 .expect("Element width never exceeds `ELEN`, which never exceeds `VLEN`; qed");
110 env.mark_vs_dirty();
111}