From: Max Chou <max.chou@sifive.com>
To: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org,
Palmer Dabbelt <palmer@dabbelt.com>,
Alistair Francis <Alistair.Francis@wdc.com>,
Weiwei Li <liwei1518@gmail.com>,
Liu Zhiwei <zhiwei_liu@linux.alibaba.com>,
Chao Liu <chao.liu@processmission.com>,
Frank Chang <frank.chang@sifive.com>
Subject: Re: [PATCH 3/5] target/riscv: rvv: Add SiFive custom int8 matmul instructions
Date: Fri, 7 Aug 2026 16:50:02 +0800 [thread overview]
Message-ID: <anWYFy7730o4auCV@sifive.com> (raw)
In-Reply-To: <537a0ac1-8970-4ffc-934d-293d44f159c0@oss.qualcomm.com>
On 2026-08-06 18:13, Daniel Henrique Barboza wrote:
>
>
> On 7/21/2026 9:20 AM, Max Chou wrote:
> > From: Frank Chang <frank.chang@sifive.com>
> >
> > Add the 8 SiFive custom int8 matrix-multiply vector instructions:
> > sf.vqmacc{u,,us,su}.4x8x4 and sf.vqmacc{u,,us,su}.2x8x2. Each name
> > suffix encodes the signedness of vs1/vs2.
> > The 4x8x4 forms multiply-accumulate a 4x8 by 8x4 int8 tile into a
> > 4x4 int32 result; the 2x8x2 forms use a 2x8 by 8x2 tile producing a
> > 2x2 int32 result. Both Xsfvqmaccqoq/Xsfvqmaccdod extensions are
> > gated on vlenb >= 32, sew == 8 and vm == 1, per the SiFive Int8
> > Matrix Multiplication Extensions Specification.
> >
> > Signed-off-by: Frank Chang <frank.chang@sifive.com>
> > Signed-off-by: Max Chou <max.chou@sifive.com>
> > ---
>
> One thing that caught my attention is adding what is, at least for now,
> a vendor specific helper in vector_helper.c which is a common code
> helper. Existing vendor extensions in QEMU doesn't do that, at least
> from what I can see.
>
> All this said, I have a suspicion that the code for this extension will
> be re-used in zvldot/zvbdot, so keeping this helper in vector_helper.c
> is ok to me.
>
>
Hi Daniel,
I believe we can move the vendor helper to the new helper file at v2.
Additionally, we can extract the common part into vector_helper.c or
vector_internal.h for related ISA extensions in the future.
In fact, I’m preparing the upstream patchset for Zvdota/Zvbdota
extensions and will send it after a release tag is added to the
riscv-isa-manual repository.
Thanks,
rnax
> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
>
>
> > MAINTAINERS | 7 ++
> > target/riscv/cpu_cfg.h | 5 ++
> > target/riscv/helper.h | 10 +++
> > target/riscv/meson.build | 1 +
> > target/riscv/tcg/insn_trans/trans_xsf.c.inc | 98 +++++++++++++++++++++
> > target/riscv/tcg/translate.c | 3 +
> > target/riscv/tcg/vector_helper.c | 74 ++++++++++++++++
> > target/riscv/xsf.decode | 30 +++++++
> > 8 files changed, 228 insertions(+)
> > create mode 100644 target/riscv/tcg/insn_trans/trans_xsf.c.inc
> > create mode 100644 target/riscv/xsf.decode
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 97dcc78ded..94cd63eeba 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -389,6 +389,13 @@ F: target/riscv/XVentanaCondOps.decode
> > F: target/riscv/insn_trans/trans_xventanacondops.c.inc
> > F: disas/riscv-xventana*
> > +RISC-V SiFive (Xsf*) extensions
> > +M: Max Chou <max.chou@sifive.com>
> > +L: qemu-riscv@nongnu.org
> > +S: Supported
> > +F: target/riscv/xsf.decode
> > +F: target/riscv/tcg/insn_trans/trans_xsf.c.inc
> > +
> > RENESAS RX CPUs
> > R: Yoshinori Sato <yoshinori.sato@nifty.com>
> > S: Orphan
> > diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> > index 211d0708ba..d6db1cfb7c 100644
> > --- a/target/riscv/cpu_cfg.h
> > +++ b/target/riscv/cpu_cfg.h
> > @@ -51,6 +51,11 @@ static inline bool has_xthead_p(const RISCVCPUConfig *cfg)
> > cfg->ext_xtheadmempair || cfg->ext_xtheadsync;
> > }
> > +static inline bool has_xsf_p(const RISCVCPUConfig *cfg)
> > +{
> > + return cfg->ext_xsfvqmaccdod || cfg->ext_xsfvqmaccqoq;
> > +}
> > +
> > #define MATERIALISE_EXT_PREDICATE(ext) \
> > static inline bool has_ ## ext ## _p(const RISCVCPUConfig *cfg) \
> > { \
> > diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> > index 542b7c264f..4234f46271 100644
> > --- a/target/riscv/helper.h
> > +++ b/target/riscv/helper.h
> > @@ -1358,3 +1358,13 @@ DEF_HELPER_1(ssamoswap_disabled, void, env)
> > /* Zalrsc SC write probe */
> > DEF_HELPER_FLAGS_3(sc_probe_write, TCG_CALL_NO_WG, void, env, tl, tl)
> > +
> > +/* SiFive Custom int8 Matrix-Multiply */
> > +DEF_HELPER_5(sf_vqmaccu_4x8x4, void, ptr, ptr, ptr, env, i32)
> > +DEF_HELPER_5(sf_vqmacc_4x8x4, void, ptr, ptr, ptr, env, i32)
> > +DEF_HELPER_5(sf_vqmaccus_4x8x4, void, ptr, ptr, ptr, env, i32)
> > +DEF_HELPER_5(sf_vqmaccsu_4x8x4, void, ptr, ptr, ptr, env, i32)
> > +DEF_HELPER_5(sf_vqmaccu_2x8x2, void, ptr, ptr, ptr, env, i32)
> > +DEF_HELPER_5(sf_vqmacc_2x8x2, void, ptr, ptr, ptr, env, i32)
> > +DEF_HELPER_5(sf_vqmaccus_2x8x2, void, ptr, ptr, ptr, env, i32)
> > +DEF_HELPER_5(sf_vqmaccsu_2x8x2, void, ptr, ptr, ptr, env, i32)
> > diff --git a/target/riscv/meson.build b/target/riscv/meson.build
> > index 42d0f6d538..c06526adb2 100644
> > --- a/target/riscv/meson.build
> > +++ b/target/riscv/meson.build
> > @@ -6,6 +6,7 @@ gen = [
> > decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
> > decodetree.process('xmips.decode', extra_args: '--static-decode=decode_xmips'),
> > decodetree.process('xlrbr.decode', extra_args: '--static-decode=decode_xlrbr'),
> > + decodetree.process('xsf.decode', extra_args: '--static-decode=decode_xsf'),
> > ]
> > riscv_ss = ss.source_set()
> > diff --git a/target/riscv/tcg/insn_trans/trans_xsf.c.inc b/target/riscv/tcg/insn_trans/trans_xsf.c.inc
> > new file mode 100644
> > index 0000000000..1677352689
> > --- /dev/null
> > +++ b/target/riscv/tcg/insn_trans/trans_xsf.c.inc
> > @@ -0,0 +1,98 @@
> > +/*
> > + * RISC-V translation routines for the SiFive vendor extensions (xsf*)
> > + *
> > + * Copyright (c) 2023 SiFive, Inc.
> > + *
> > + * SPDX-License-Identifier: GPL-2.0-or-later
> > + */
> > +
> > +
> > +/*
> > + * SiFive Xsfvqmaccdod/Xsfvqmaccqoq custom int8 matrix-multiply extensions
> > + */
> > +static bool sf_int8_matmul_check(DisasContext *s, arg_rmrr *a)
> > +{
> > + return require_rvv(s) &&
> > + vext_check_isa_ill(s) &&
> > + s->vstart_eq_zero &&
> > + (s->cfg_ptr->vlenb >= 32) &&
> > + (s->sew == MO_8) &&
> > + (a->vm == 1);
> > +}
> > +
> > +static bool sf_int8_matmul_4x8x4_check(DisasContext *s, arg_rmrr *a)
> > +{
> > + /*
> > + * vd has EMUL=2*LMUL
> > + * vs2 has EMUL=LMUL
> > + * vs1 has EMUL=1
> > + * vd must not overlap vs1
> > + */
> > + return sf_int8_matmul_check(s, a) &&
> > + (s->cfg_ptr->ext_xsfvqmaccqoq) &&
> > + (s->lmul <= 2) &&
> > + require_align(a->rd, s->lmul + 1) &&
> > + require_align(a->rs2, s->lmul) &&
> > + require_align(a->rs1, 0) &&
> > + require_noover(a->rd, s->lmul + 1, a->rs2, s->lmul) &&
> > + !is_overlapped(a->rd, 1 << MAX(s->lmul + 1, 0), a->rs1, 1);
> > +}
> > +
> > +static bool sf_int8_matmul_2x8x2_check(DisasContext *s, arg_rmrr *a)
> > +{
> > + /*
> > + * vd has EMUL=LMUL
> > + * vs2 has EMUL=LMUL
> > + * vs1 has EMUL=1
> > + * vd must not overlap vs1
> > + */
> > + return sf_int8_matmul_check(s, a) &&
> > + (s->cfg_ptr->ext_xsfvqmaccdod) &&
> > + require_align(a->rd, s->lmul) &&
> > + require_align(a->rs2, s->lmul) &&
> > + require_align(a->rs1, 0) &&
> > + !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs1, 1);
> > +}
> > +
> > +static bool sf_int8_matmul_op(DisasContext *s, arg_rmrr *a, uint8_t seq)
> > +{
> > + static gen_helper_gvec_3_ptr * const fns[8] = {
> > + gen_helper_sf_vqmaccu_4x8x4, gen_helper_sf_vqmacc_4x8x4,
> > + gen_helper_sf_vqmaccus_4x8x4, gen_helper_sf_vqmaccsu_4x8x4,
> > + gen_helper_sf_vqmaccu_2x8x2, gen_helper_sf_vqmacc_2x8x2,
> > + gen_helper_sf_vqmaccus_2x8x2, gen_helper_sf_vqmaccsu_2x8x2,
> > + };
> > +
> > + /*
> > + * The helper raises an illegal-instruction exception when vl is not a
> > + * multiple of the tile size; save the opcode so mtval/stval report the
> > + * faulting instruction if that exception is thrown.
> > + */
> > + decode_save_opc(s, 0);
> > +
> > + tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
> > + vreg_ofs(s, a->rs2), tcg_env,
> > + s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, 0, fns[seq]);
> > +
> > + finalize_rvv_inst(s);
> > +
> > + return true;
> > +}
> > +
> > +#define GEN_SF_INT8_MATMUL_TRANS(NAME, CHECK, SEQ) \
> > +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
> > +{ \
> > + if (CHECK(s, a)) { \
> > + return sf_int8_matmul_op(s, a, SEQ); \
> > + } \
> > + return false; \
> > +}
> > +
> > +GEN_SF_INT8_MATMUL_TRANS(sf_vqmaccu_4x8x4, sf_int8_matmul_4x8x4_check, 0)
> > +GEN_SF_INT8_MATMUL_TRANS(sf_vqmacc_4x8x4, sf_int8_matmul_4x8x4_check, 1)
> > +GEN_SF_INT8_MATMUL_TRANS(sf_vqmaccus_4x8x4, sf_int8_matmul_4x8x4_check, 2)
> > +GEN_SF_INT8_MATMUL_TRANS(sf_vqmaccsu_4x8x4, sf_int8_matmul_4x8x4_check, 3)
> > +GEN_SF_INT8_MATMUL_TRANS(sf_vqmaccu_2x8x2, sf_int8_matmul_2x8x2_check, 4)
> > +GEN_SF_INT8_MATMUL_TRANS(sf_vqmacc_2x8x2, sf_int8_matmul_2x8x2_check, 5)
> > +GEN_SF_INT8_MATMUL_TRANS(sf_vqmaccus_2x8x2, sf_int8_matmul_2x8x2_check, 6)
> > +GEN_SF_INT8_MATMUL_TRANS(sf_vqmaccsu_2x8x2, sf_int8_matmul_2x8x2_check, 7)
> > diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c
> > index 9684dbe752..41e3dd2fe2 100644
> > --- a/target/riscv/tcg/translate.c
> > +++ b/target/riscv/tcg/translate.c
> > @@ -1216,10 +1216,12 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
> > #include "decode-xthead.c.inc"
> > #include "decode-xmips.c.inc"
> > #include "decode-xlrbr.c.inc"
> > +#include "decode-xsf.c.inc"
> > #include "insn_trans/trans_xthead.c.inc"
> > #include "insn_trans/trans_xventanacondops.c.inc"
> > #include "insn_trans/trans_xmips.c.inc"
> > #include "insn_trans/trans_xlrbr.c.inc"
> > +#include "insn_trans/trans_xsf.c.inc"
> > /* Include the auto-generated decoder for 16 bit insn */
> > #include "decode-insn16.c.inc"
> > @@ -1240,6 +1242,7 @@ const RISCVDecoder decoder_table[] = {
> > { has_xthead_p, decode_xthead},
> > { has_XVentanaCondOps_p, decode_XVentanaCodeOps},
> > { has_xlrbr_p, decode_xlrbr},
> > + { has_xsf_p, decode_xsf },
> > };
> > const size_t decoder_table_size = ARRAY_SIZE(decoder_table);
> > diff --git a/target/riscv/tcg/vector_helper.c b/target/riscv/tcg/vector_helper.c
> > index e321ca2616..a9b5d861dc 100644
> > --- a/target/riscv/tcg/vector_helper.c
> > +++ b/target/riscv/tcg/vector_helper.c
> > @@ -5871,3 +5871,77 @@ GEN_VEXT_INT_EXT(vsext_vf2_d, int64_t, int32_t, H8, H4)
> > GEN_VEXT_INT_EXT(vsext_vf4_w, int32_t, int8_t, H4, H1)
> > GEN_VEXT_INT_EXT(vsext_vf4_d, int64_t, int16_t, H8, H2)
> > GEN_VEXT_INT_EXT(vsext_vf8_d, int64_t, int8_t, H8, H1)
> > +
> > +/* SiFive Custom int8 Matrix-Multiply */
> > +#define SF_QOP_SUU_B int32_t, uint8_t, uint8_t, int32_t, int32_t
> > +#define SF_QOP_SUS_B int32_t, uint8_t, int8_t, int32_t, int32_t
> > +#define SF_QOP_SSU_B int32_t, int8_t, uint8_t, int32_t, int32_t
> > +#define SF_QOP_SSS_B int32_t, int8_t, int8_t, int32_t, int32_t
> > +
> > +/*
> > + * vd may overlap vs2, we need to allocate an additional vd array
> > + * to save temporary results of vd and write them back at the end.
> > + */
> > +#define GEN_VEXT_SF_INT8_MATMUL(NAME, TD, T1, T2, TX1, TX2, \
> > + HD, HS1, HS2, ROWS, COLS, TILE_SIZE) \
> > +void HELPER(NAME)(void *vd, void *vs1, void *vs2, \
> > + CPURISCVState *env, uint32_t desc) \
> > +{ \
> > + int it, il, in, im, ivd, ivs1, ivs2; \
> > + TD *vds; \
> > + \
> > + if (env->vl % TILE_SIZE) { \
> > + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); \
> > + return; \
> > + } \
> > + \
> > + VSTART_CHECK_EARLY_EXIT(env, env->vl); \
> > + \
> > + vds = g_malloc0(sizeof(TD) * \
> > + ROWS * ROWS * (env->vl / TILE_SIZE)); \
> > + \
> > + for (it = 0; it < (env->vl / TILE_SIZE); it++) { \
> > + for (il = 0; il < ROWS; il++) { \
> > + for (in = 0; in < ROWS; in++) { \
> > + ivd = ROWS * ROWS * it + ROWS * il + in; \
> > + vds[ivd] = *((TD *)vd + HD(ivd)); \
> > + for (im = 0; im < COLS; im++) { \
> > + ivs1 = il * COLS + im; \
> > + ivs2 = TILE_SIZE * it + im * ROWS + in; \
> > + T1 s1 = *((T1 *)vs1 + HS1(ivs1)); \
> > + T2 s2 = *((T2 *)vs2 + HS2(ivs2)); \
> > + vds[ivd] += (TX1)s1 * (TX2)s2; \
> > + } \
> > + } \
> > + } \
> > + } \
> > + \
> > + for (it = 0; it < (env->vl / TILE_SIZE); it++) { \
> > + for (il = 0; il < ROWS; il++) { \
> > + for (in = 0; in < ROWS; in++) { \
> > + ivd = ROWS * ROWS * it + ROWS * il + in; \
> > + *((TD *)vd + HD(ivd)) = vds[ivd]; \
> > + } \
> > + } \
> > + } \
> > + \
> > + env->vstart = 0; \
> > + g_free(vds); \
> > +}
> > +
> > +RVVCALL(GEN_VEXT_SF_INT8_MATMUL, sf_vqmaccu_4x8x4, SF_QOP_SUU_B,
> > + H4, H1, H1, 4, 8, 32)
> > +RVVCALL(GEN_VEXT_SF_INT8_MATMUL, sf_vqmacc_4x8x4, SF_QOP_SSS_B,
> > + H4, H1, H1, 4, 8, 32)
> > +RVVCALL(GEN_VEXT_SF_INT8_MATMUL, sf_vqmaccus_4x8x4, SF_QOP_SUS_B,
> > + H4, H1, H1, 4, 8, 32)
> > +RVVCALL(GEN_VEXT_SF_INT8_MATMUL, sf_vqmaccsu_4x8x4, SF_QOP_SSU_B,
> > + H4, H1, H1, 4, 8, 32)
> > +RVVCALL(GEN_VEXT_SF_INT8_MATMUL, sf_vqmaccu_2x8x2, SF_QOP_SUU_B,
> > + H4, H1, H1, 2, 8, 16)
> > +RVVCALL(GEN_VEXT_SF_INT8_MATMUL, sf_vqmacc_2x8x2, SF_QOP_SSS_B,
> > + H4, H1, H1, 2, 8, 16)
> > +RVVCALL(GEN_VEXT_SF_INT8_MATMUL, sf_vqmaccus_2x8x2, SF_QOP_SUS_B,
> > + H4, H1, H1, 2, 8, 16)
> > +RVVCALL(GEN_VEXT_SF_INT8_MATMUL, sf_vqmaccsu_2x8x2, SF_QOP_SSU_B,
> > + H4, H1, H1, 2, 8, 16)
> > diff --git a/target/riscv/xsf.decode b/target/riscv/xsf.decode
> > new file mode 100644
> > index 0000000000..bb585046ab
> > --- /dev/null
> > +++ b/target/riscv/xsf.decode
> > @@ -0,0 +1,30 @@
> > +#
> > +# RISC-V translation routines for the SiFive vendor extensions
> > +#
> > +# Copyright (c) 2023 SiFive, Inc.
> > +#
> > +# SPDX-License-Identifier: GPL-2.0-or-later
> > +
> > +# Fields:
> > +%rs2 20:5
> > +%rs1 15:5
> > +%rd 7:5
> > +%vm 25:1
> > +
> > +# Argument sets:
> > +&rmrr vm rd rs1 rs2 !extern
> > +
> > +# Formats:
> > +@r_vm_1 ...... . ..... ..... ... ..... ....... &rmrr vm=1 %rs2 %rs1 %rd
> > +
> > +# *** Xsfvqmaccqoq: SiFive custom int8 matrix-multiply (4x8x4 tile) ***
> > +sf_vqmaccu_4x8x4 111100 1 ..... ..... 010 ..... 1011011 @r_vm_1
> > +sf_vqmacc_4x8x4 111101 1 ..... ..... 010 ..... 1011011 @r_vm_1
> > +sf_vqmaccus_4x8x4 111110 1 ..... ..... 010 ..... 1011011 @r_vm_1
> > +sf_vqmaccsu_4x8x4 111111 1 ..... ..... 010 ..... 1011011 @r_vm_1
> > +
> > +# *** Xsfvqmaccdod: SiFive custom int8 matrix-multiply (2x8x2 tile) ***
> > +sf_vqmaccu_2x8x2 101100 1 ..... ..... 010 ..... 1011011 @r_vm_1
> > +sf_vqmacc_2x8x2 101101 1 ..... ..... 010 ..... 1011011 @r_vm_1
> > +sf_vqmaccus_2x8x2 101110 1 ..... ..... 010 ..... 1011011 @r_vm_1
> > +sf_vqmaccsu_2x8x2 101111 1 ..... ..... 010 ..... 1011011 @r_vm_1
>
next prev parent reply other threads:[~2026-08-07 8:50 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-21 12:20 [PATCH 0/5] target/riscv: Add SiFive Xsfvqmaccdod/Xsfvqmaccqoq int8 matmul extensions Max Chou
2026-07-21 12:20 ` [PATCH 1/5] target/riscv: Add cfg property for SiFive " Max Chou
2026-08-06 21:04 ` Daniel Henrique Barboza
2026-07-21 12:20 ` [PATCH 2/5] target/riscv: Add SiFive custom int8 matmul extension implied rules Max Chou
2026-08-06 21:07 ` Daniel Henrique Barboza
2026-08-07 8:32 ` Max Chou
2026-07-21 12:20 ` [PATCH 3/5] target/riscv: rvv: Add SiFive custom int8 matmul instructions Max Chou
2026-08-06 21:13 ` Daniel Henrique Barboza
2026-08-07 8:50 ` Max Chou [this message]
2026-07-21 12:20 ` [PATCH 4/5] disas/riscv: Add disassembler support for Xsfvqmaccdod/Xsfvqmaccqoq Max Chou
2026-08-06 21:15 ` Daniel Henrique Barboza
2026-07-21 12:20 ` [PATCH 5/5] tests/tcg/riscv64: Add tests for SiFive int8 matmul extensions Max Chou
2026-08-06 21:15 ` Daniel Henrique Barboza
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=anWYFy7730o4auCV@sifive.com \
--to=max.chou@sifive.com \
--cc=Alistair.Francis@wdc.com \
--cc=chao.liu@processmission.com \
--cc=daniel.barboza@oss.qualcomm.com \
--cc=frank.chang@sifive.com \
--cc=liwei1518@gmail.com \
--cc=palmer@dabbelt.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-riscv@nongnu.org \
--cc=zhiwei_liu@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox