From: Luke Kenneth Casson Leighton Date: Thu, 27 Sep 2018 11:03:26 +0000 (+0100) Subject: add sv predication function X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d34ff3b34a62e75bd991b987ccb8634a4605a982;p=riscv-isa-sim.git add sv predication function --- diff --git a/riscv/sv.cc b/riscv/sv.cc index 6be5872..4acc9d2 100644 --- a/riscv/sv.cc +++ b/riscv/sv.cc @@ -5,7 +5,8 @@ sv_reg_csr_entry sv_csrs[SV_CSR_SZ]; sv_reg_entry sv_int_tb[NXPR]; sv_reg_entry sv_fp_tb[NFPR]; sv_pred_csr_entry sv_pred_csrs[SV_CSR_SZ]; -sv_pred_entry sv_pred_tb[NXPR]; +sv_pred_entry sv_pred_int_tb[NXPR]; +sv_pred_entry sv_pred_fp_tb[NFPR]; bool sv_check_reg(bool intreg, uint64_t reg) { @@ -92,3 +93,53 @@ uint64_t sv_insn_t::remap(uint64_t reg, bool intreg, int &voffs) return reg; } +/* gets the predication value (if active). returns all-1s if not active + * also returns whether zeroing is enabled/disabled for this register. + * + * uses the same sort of lookup logic as remap: + * + * - first thing to note is, there is one CSR table for FP and one for INT + * (so, FP regs can be predicated separately from INT ones) + * - redirection occurs if the CSR entry for the register is "active". + * - inversion of the predication can be set (so it's possible to have + * the same actual register value be unchanged yet be referred to by + * *TWO* redirections, one with inversion, one with not). + * + * note that this function *actually* returns the value of the (integer) + * register file, hence why processor_t has to be passed in + * + * note also that *even scalar* ops will be predicated (i.e. if a register + * has been set active=true and isvec=false in sv_int_tb or sv_fp_tb). + * the way to ensure that scalar ops are not predicated is: set VLEN=0, + * set active=false in sv_int_tb/sv_fp_tb for that register, or switch off + * the predication for that register (sv_pred_int_tb/sv_pred_fb_tb). + * + * note also that the hard limit on SV maximum vector length is actually + * down to the number of bits in the predication i.e. the bitwidth of integer + * registers (i.e. XLEN bits). + */ +reg_t sv_insn_t::predicate(processor_t *p, uint64_t reg, + bool intreg, bool &zeroing) +{ + sv_pred_entry *r; + if (intreg) + { + r = &sv_pred_int_tb[reg]; + } + else + { + r = &sv_pred_fp_tb[reg]; + } + if (!r->active) + { + return ~0x0; // not active: return all-1s (unconditional "on") + } + zeroing = r->zero; + reg = r->regidx; + reg_t predicate = READ_REG(reg); // macros go through processor_t state + if (r->inv) + { + return ~predicate; + } + return predicate; +} diff --git a/riscv/sv.h b/riscv/sv.h index f42b3d4..1911cad 100644 --- a/riscv/sv.h +++ b/riscv/sv.h @@ -60,8 +60,9 @@ typedef struct { unsigned int active: 1; // enabled=1, disabled=0 } sv_pred_entry; -// 32 entries, only integer regs are predicates. -extern sv_pred_entry sv_pred_tb[NXPR]; +// 32 entries +extern sv_pred_entry sv_pred_int_tb[NXPR]; +extern sv_pred_entry sv_pred_fp_tb[NFPR]; bool sv_check_reg(bool intreg, uint64_t reg); diff --git a/riscv/sv_decode.h b/riscv/sv_decode.h index eca0e77..967c23a 100644 --- a/riscv/sv_decode.h +++ b/riscv/sv_decode.h @@ -5,6 +5,7 @@ #include "sv.h" #include "decode.h" +#include "processor.h" #define REG_RD 0x1 #define REG_RS1 0x2 @@ -36,6 +37,8 @@ public: cached_rs2 = 0xff; cached_rs3 = 0xff; } + reg_t predicate(processor_t* p, uint64_t reg, bool isint, bool &zeroing); + private: unsigned int fimap; uint64_t cached_rd;