add sv predication function
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 27 Sep 2018 11:03:26 +0000 (12:03 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 27 Sep 2018 11:03:26 +0000 (12:03 +0100)
riscv/sv.cc
riscv/sv.h
riscv/sv_decode.h

index 6be58725128e8c35ff4593b8bd235398dcd28bbc..4acc9d2b90b7fae2d0026d3e4d15e2719567a294 100644 (file)
@@ -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;
+}
index f42b3d420778bcab076b7e3359038c5a393548cc..1911cad05a36a3106bb8fca80ebcb99fd91ab887 100644 (file)
@@ -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);
 
index eca0e777d022a35911e8b1e5d66de680a09a99c5..967c23a6b581c3719997a86badc9ba26d442f8bd 100644 (file)
@@ -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;