Message ID | 1568183141-67641-5-git-send-email-zhiwei_liu@c-sky.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | RISC-V: support vector extension | expand |
On Wed, Sep 11, 2019 at 2:38 PM liuzhiwei <zhiwei_liu@c-sky.com> wrote: > From: LIU Zhiwei <zhiwei_liu@c-sky.com> > > Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com> > --- > target/riscv/Makefile.objs | 2 +- > target/riscv/helper.h | 3 + > target/riscv/insn32.decode | 5 ++ > target/riscv/insn_trans/trans_rvv.inc.c | 46 ++++++++++++ > target/riscv/translate.c | 1 + > target/riscv/vector_helper.c | 126 > ++++++++++++++++++++++++++++++++ > 6 files changed, 182 insertions(+), 1 deletion(-) > create mode 100644 target/riscv/insn_trans/trans_rvv.inc.c > create mode 100644 target/riscv/vector_helper.c > > diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs > index b1c79bc..d577cef 100644 > --- a/target/riscv/Makefile.objs > +++ b/target/riscv/Makefile.objs > @@ -1,4 +1,4 @@ > -obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o > gdbstub.o pmp.o > +obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o > vector_helper.o gdbstub.o pmp.o > > DECODETREE = $(SRC_PATH)/scripts/decodetree.py > > diff --git a/target/riscv/helper.h b/target/riscv/helper.h > index debb22a..652f8c3 100644 > --- a/target/riscv/helper.h > +++ b/target/riscv/helper.h > @@ -76,3 +76,6 @@ DEF_HELPER_2(mret, tl, env, tl) > DEF_HELPER_1(wfi, void, env) > DEF_HELPER_1(tlb_flush, void, env) > #endif > +/* Vector functions */ > +DEF_HELPER_4(vector_vsetvli, void, env, i32, i32, i32) > +DEF_HELPER_4(vector_vsetvl, void, env, i32, i32, i32) > diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode > index 77f794e..5dc009c 100644 > --- a/target/riscv/insn32.decode > +++ b/target/riscv/insn32.decode > @@ -62,6 +62,7 @@ > @r_rm ....... ..... ..... ... ..... ....... %rs2 %rs1 %rm %rd > @r2_rm ....... ..... ..... ... ..... ....... %rs1 %rm %rd > @r2 ....... ..... ..... ... ..... ....... %rs1 %rd > +@r2_zimm . zimm:11 ..... ... ..... ....... %rs1 %rd > > @sfence_vma ....... ..... ..... ... ..... ....... %rs2 %rs1 > @sfence_vm ....... ..... ..... ... ..... ....... %rs1 > @@ -203,3 +204,7 @@ fcvt_w_d 1100001 00000 ..... ... ..... 1010011 > @r2_rm > fcvt_wu_d 1100001 00001 ..... ... ..... 1010011 @r2_rm > fcvt_d_w 1101001 00000 ..... ... ..... 1010011 @r2_rm > fcvt_d_wu 1101001 00001 ..... ... ..... 1010011 @r2_rm > + > +# *** RV32V Extension *** > +vsetvli 0 ........... ..... 111 ..... 1010111 @r2_zimm > +vsetvl 1000000 ..... ..... 111 ..... 1010111 @r > diff --git a/target/riscv/insn_trans/trans_rvv.inc.c > b/target/riscv/insn_trans/trans_rvv.inc.c > new file mode 100644 > index 0000000..82e7ad6 > --- /dev/null > +++ b/target/riscv/insn_trans/trans_rvv.inc.c > @@ -0,0 +1,46 @@ > +/* > + * RISC-V translation routines for the RVV Standard Extension. > + * > + * Copyright (c) 2019 C-SKY Limited. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms and conditions of the GNU General Public License, > + * version 2 or later, as published by the Free Software Foundation. > + * > + * This program is distributed in the hope it will be useful, but WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > for > + * more details. > + * > + * You should have received a copy of the GNU General Public License > along with > + * this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#define GEN_VECTOR_R(INSN) \ > +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \ > +{ \ > + TCGv_i32 s1 = tcg_const_i32(a->rs1); \ > + TCGv_i32 s2 = tcg_const_i32(a->rs2); \ > + TCGv_i32 d = tcg_const_i32(a->rd); \ > + gen_helper_vector_##INSN(cpu_env, s1, s2, d); \ > + tcg_temp_free_i32(s1); \ > + tcg_temp_free_i32(s2); \ > + tcg_temp_free_i32(d); \ > + return true; \ > +} > + > +#define GEN_VECTOR_R2_ZIMM(INSN) \ > +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \ > +{ \ > + TCGv_i32 s1 = tcg_const_i32(a->rs1); \ > + TCGv_i32 zimm = tcg_const_i32(a->zimm); \ > + TCGv_i32 d = tcg_const_i32(a->rd); \ > + gen_helper_vector_##INSN(cpu_env, s1, zimm, d); \ > + tcg_temp_free_i32(s1); \ > + tcg_temp_free_i32(zimm); \ > + tcg_temp_free_i32(d); \ > + return true; \ > +} > + > +GEN_VECTOR_R2_ZIMM(vsetvli) > +GEN_VECTOR_R(vsetvl) > diff --git a/target/riscv/translate.c b/target/riscv/translate.c > index 8d6ab73..587c23e 100644 > --- a/target/riscv/translate.c > +++ b/target/riscv/translate.c > @@ -706,6 +706,7 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, > #include "insn_trans/trans_rva.inc.c" > #include "insn_trans/trans_rvf.inc.c" > #include "insn_trans/trans_rvd.inc.c" > +#include "insn_trans/trans_rvv.inc.c" > #include "insn_trans/trans_privileged.inc.c" > > /* > diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c > new file mode 100644 > index 0000000..b279e6f > --- /dev/null > +++ b/target/riscv/vector_helper.c > @@ -0,0 +1,126 @@ > +/* > + * RISC-V Vectore Extension Helpers for QEMU. > + * > + * Copyright (c) 2019 C-SKY Limited. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms and conditions of the GNU General Public License, > + * version 2 or later, as published by the Free Software Foundation. > + * > + * This program is distributed in the hope it will be useful, but WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > for > + * more details. > + * > + * You should have received a copy of the GNU General Public License > along with > + * this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "qemu/osdep.h" > +#include "cpu.h" > +#include "exec/exec-all.h" > +#include "exec/helper-proto.h" > +#include <math.h> > + > +#define VECTOR_HELPER(name) HELPER(glue(vector_, name)) > + > +static inline void vector_vtype_set_ill(CPURISCVState *env) > +{ > + env->vfp.vtype = ((target_ulong)1) << (sizeof(target_ulong) - 1); > + return; > +} > + > env->vfp.vtype = ((target_ulong)1) << (sizeof(target_ulong) * 8 - 1); > +static inline int vector_vtype_get_sew(CPURISCVState *env) > +{ > + return (env->vfp.vtype >> 2) & 0x7; > +} > + > extract64(env->vfp.vtype, 2, 3); > +static inline int vector_get_width(CPURISCVState *env) > +{ > + return 8 * (1 << vector_vtype_get_sew(env)); > +} > + > +static inline int vector_get_lmul(CPURISCVState *env) > +{ > + return 1 << (env->vfp.vtype & 0x3); > +} > + > extract64(env->vfp.vtype, 0, 2); > +static inline int vector_get_vlmax(CPURISCVState *env) > +{ > + return vector_get_lmul(env) * VLEN / vector_get_width(env); > +} > + > +void VECTOR_HELPER(vsetvl)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, > + uint32_t rd) > +{ > + int sew, max_sew, vlmax, vl; > + > + if (rs2 == 0) { > + vector_vtype_set_ill(env); > + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); > + return; > + } > + env->vfp.vtype = env->gpr[rs2]; > + sew = 1 << vector_get_width(env) / 8; > + max_sew = sizeof(target_ulong); > + > + if (env->misa & RVD) { > + max_sew = max_sew > 8 ? max_sew : 8; > + } else if (env->misa & RVF) { > + max_sew = max_sew > 4 ? max_sew : 4; > + } As far as i understand, max_sew is defined by ELEN but not by existing floating-point extensions. ELEN should be configurable through command line cpu parameter. + if (sew > max_sew) { > + vector_vtype_set_ill(env); > + return; > + } > + > + vlmax = vector_get_vlmax(env); > + if (rs1 == 0) { > + vl = vlmax; > + } else if (env->gpr[rs1] <= vlmax) { > + vl = env->gpr[rs1]; > + } else if (env->gpr[rs1] < 2 * vlmax) { > + vl = ceil(env->gpr[rs1] / 2); > + } else { > + vl = vlmax; > + } > + env->vfp.vl = vl; > + env->gpr[rd] = vl; > + env->vfp.vstart = 0; > + return; > +} > + > +void VECTOR_HELPER(vsetvli)(CPURISCVState *env, uint32_t rs1, uint32_t > zimm, > + uint32_t rd) > +{ > + int sew, max_sew, vlmax, vl; > + > + env->vfp.vtype = zimm; > + sew = vector_get_width(env) / 8; > + max_sew = sizeof(target_ulong); > + > + if (env->misa & RVD) { > + max_sew = max_sew > 8 ? max_sew : 8; > + } else if (env->misa & RVF) { > + max_sew = max_sew > 4 ? max_sew : 4; > + } > + if (sew > max_sew) { > + vector_vtype_set_ill(env); > + return; > + } > + The same comment described above. > + vlmax = vector_get_vlmax(env); > + if (rs1 == 0) { > + vl = vlmax; > + } else if (env->gpr[rs1] <= vlmax) { > + vl = env->gpr[rs1]; > + } else if (env->gpr[rs1] < 2 * vlmax) { > + vl = ceil(env->gpr[rs1] / 2); > + } else { > + vl = vlmax; > + } > + env->vfp.vl = vl; > + env->gpr[rd] = vl; > + env->vfp.vstart = 0; > + return; > +} > -- > 2.7.4 > > >
> +void VECTOR_HELPER(vsetvl)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, > + uint32_t rd) > +{ > + int sew, max_sew, vlmax, vl; > + > + if (rs2 == 0) { > + vector_vtype_set_ill(env); > + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); > + return; > + } I don't see that vsetvl, rs2 == r0 should raise SIGILL. Is that requirement new, after the 0.7.1 specification? If so, this should happen in the translator and not here. You should *not* change cpu state (setting vill here) before raising SIGILL. As far as I can see "vsetvl rd, rs1, r0" == "vsetvli rd, rs1, e8". > + env->vfp.vtype = env->gpr[rs2]; You should pass the rs2 register by value, not by index. > + sew = 1 << vector_get_width(env) / 8; > + max_sew = sizeof(target_ulong); > + > + if (env->misa & RVD) { > + max_sew = max_sew > 8 ? max_sew : 8; > + } else if (env->misa & RVF) { > + max_sew = max_sew > 4 ? max_sew : 4; > + } > + if (sew > max_sew) { > + vector_vtype_set_ill(env); > + return; > + } > + > + vlmax = vector_get_vlmax(env); > + if (rs1 == 0) { > + vl = vlmax; > + } else if (env->gpr[rs1] <= vlmax) { > + vl = env->gpr[rs1]; > + } else if (env->gpr[rs1] < 2 * vlmax) { > + vl = ceil(env->gpr[rs1] / 2); > + } else { > + vl = vlmax; > + } You should pass rs1 register by value, not by index. The special case of rs1 == r0 can be handled by passing the value (target_ulong)-1, which will match the final case above. > + env->vfp.vl = vl; > + env->gpr[rd] = vl; > + env->vfp.vstart = 0; > + return; > +} You should return vl and have it assigned to rd by the translator code, and not assign it here. > +void VECTOR_HELPER(vsetvli)(CPURISCVState *env, uint32_t rs1, uint32_t zimm, > + uint32_t rd) You should not require a separate helper function for this. Passing the zimm constant as the value for rs2 above is the correct mapping between the two instructions. r~
diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs index b1c79bc..d577cef 100644 --- a/target/riscv/Makefile.objs +++ b/target/riscv/Makefile.objs @@ -1,4 +1,4 @@ -obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o gdbstub.o pmp.o +obj-y += translate.o op_helper.o cpu_helper.o cpu.o csr.o fpu_helper.o vector_helper.o gdbstub.o pmp.o DECODETREE = $(SRC_PATH)/scripts/decodetree.py diff --git a/target/riscv/helper.h b/target/riscv/helper.h index debb22a..652f8c3 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -76,3 +76,6 @@ DEF_HELPER_2(mret, tl, env, tl) DEF_HELPER_1(wfi, void, env) DEF_HELPER_1(tlb_flush, void, env) #endif +/* Vector functions */ +DEF_HELPER_4(vector_vsetvli, void, env, i32, i32, i32) +DEF_HELPER_4(vector_vsetvl, void, env, i32, i32, i32) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 77f794e..5dc009c 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -62,6 +62,7 @@ @r_rm ....... ..... ..... ... ..... ....... %rs2 %rs1 %rm %rd @r2_rm ....... ..... ..... ... ..... ....... %rs1 %rm %rd @r2 ....... ..... ..... ... ..... ....... %rs1 %rd +@r2_zimm . zimm:11 ..... ... ..... ....... %rs1 %rd @sfence_vma ....... ..... ..... ... ..... ....... %rs2 %rs1 @sfence_vm ....... ..... ..... ... ..... ....... %rs1 @@ -203,3 +204,7 @@ fcvt_w_d 1100001 00000 ..... ... ..... 1010011 @r2_rm fcvt_wu_d 1100001 00001 ..... ... ..... 1010011 @r2_rm fcvt_d_w 1101001 00000 ..... ... ..... 1010011 @r2_rm fcvt_d_wu 1101001 00001 ..... ... ..... 1010011 @r2_rm + +# *** RV32V Extension *** +vsetvli 0 ........... ..... 111 ..... 1010111 @r2_zimm +vsetvl 1000000 ..... ..... 111 ..... 1010111 @r diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c new file mode 100644 index 0000000..82e7ad6 --- /dev/null +++ b/target/riscv/insn_trans/trans_rvv.inc.c @@ -0,0 +1,46 @@ +/* + * RISC-V translation routines for the RVV Standard Extension. + * + * Copyright (c) 2019 C-SKY Limited. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define GEN_VECTOR_R(INSN) \ +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \ +{ \ + TCGv_i32 s1 = tcg_const_i32(a->rs1); \ + TCGv_i32 s2 = tcg_const_i32(a->rs2); \ + TCGv_i32 d = tcg_const_i32(a->rd); \ + gen_helper_vector_##INSN(cpu_env, s1, s2, d); \ + tcg_temp_free_i32(s1); \ + tcg_temp_free_i32(s2); \ + tcg_temp_free_i32(d); \ + return true; \ +} + +#define GEN_VECTOR_R2_ZIMM(INSN) \ +static bool trans_##INSN(DisasContext *ctx, arg_##INSN * a) \ +{ \ + TCGv_i32 s1 = tcg_const_i32(a->rs1); \ + TCGv_i32 zimm = tcg_const_i32(a->zimm); \ + TCGv_i32 d = tcg_const_i32(a->rd); \ + gen_helper_vector_##INSN(cpu_env, s1, zimm, d); \ + tcg_temp_free_i32(s1); \ + tcg_temp_free_i32(zimm); \ + tcg_temp_free_i32(d); \ + return true; \ +} + +GEN_VECTOR_R2_ZIMM(vsetvli) +GEN_VECTOR_R(vsetvl) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 8d6ab73..587c23e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -706,6 +706,7 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, #include "insn_trans/trans_rva.inc.c" #include "insn_trans/trans_rvf.inc.c" #include "insn_trans/trans_rvd.inc.c" +#include "insn_trans/trans_rvv.inc.c" #include "insn_trans/trans_privileged.inc.c" /* diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c new file mode 100644 index 0000000..b279e6f --- /dev/null +++ b/target/riscv/vector_helper.c @@ -0,0 +1,126 @@ +/* + * RISC-V Vectore Extension Helpers for QEMU. + * + * Copyright (c) 2019 C-SKY Limited. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include <math.h> + +#define VECTOR_HELPER(name) HELPER(glue(vector_, name)) + +static inline void vector_vtype_set_ill(CPURISCVState *env) +{ + env->vfp.vtype = ((target_ulong)1) << (sizeof(target_ulong) - 1); + return; +} + +static inline int vector_vtype_get_sew(CPURISCVState *env) +{ + return (env->vfp.vtype >> 2) & 0x7; +} + +static inline int vector_get_width(CPURISCVState *env) +{ + return 8 * (1 << vector_vtype_get_sew(env)); +} + +static inline int vector_get_lmul(CPURISCVState *env) +{ + return 1 << (env->vfp.vtype & 0x3); +} + +static inline int vector_get_vlmax(CPURISCVState *env) +{ + return vector_get_lmul(env) * VLEN / vector_get_width(env); +} + +void VECTOR_HELPER(vsetvl)(CPURISCVState *env, uint32_t rs1, uint32_t rs2, + uint32_t rd) +{ + int sew, max_sew, vlmax, vl; + + if (rs2 == 0) { + vector_vtype_set_ill(env); + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + return; + } + env->vfp.vtype = env->gpr[rs2]; + sew = 1 << vector_get_width(env) / 8; + max_sew = sizeof(target_ulong); + + if (env->misa & RVD) { + max_sew = max_sew > 8 ? max_sew : 8; + } else if (env->misa & RVF) { + max_sew = max_sew > 4 ? max_sew : 4; + } + if (sew > max_sew) { + vector_vtype_set_ill(env); + return; + } + + vlmax = vector_get_vlmax(env); + if (rs1 == 0) { + vl = vlmax; + } else if (env->gpr[rs1] <= vlmax) { + vl = env->gpr[rs1]; + } else if (env->gpr[rs1] < 2 * vlmax) { + vl = ceil(env->gpr[rs1] / 2); + } else { + vl = vlmax; + } + env->vfp.vl = vl; + env->gpr[rd] = vl; + env->vfp.vstart = 0; + return; +} + +void VECTOR_HELPER(vsetvli)(CPURISCVState *env, uint32_t rs1, uint32_t zimm, + uint32_t rd) +{ + int sew, max_sew, vlmax, vl; + + env->vfp.vtype = zimm; + sew = vector_get_width(env) / 8; + max_sew = sizeof(target_ulong); + + if (env->misa & RVD) { + max_sew = max_sew > 8 ? max_sew : 8; + } else if (env->misa & RVF) { + max_sew = max_sew > 4 ? max_sew : 4; + } + if (sew > max_sew) { + vector_vtype_set_ill(env); + return; + } + + vlmax = vector_get_vlmax(env); + if (rs1 == 0) { + vl = vlmax; + } else if (env->gpr[rs1] <= vlmax) { + vl = env->gpr[rs1]; + } else if (env->gpr[rs1] < 2 * vlmax) { + vl = ceil(env->gpr[rs1] / 2); + } else { + vl = vlmax; + } + env->vfp.vl = vl; + env->gpr[rd] = vl; + env->vfp.vstart = 0; + return; +}