start to update predicated Branch to latest spec
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 29 Nov 2018 09:25:08 +0000 (09:25 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 29 Nov 2018 09:25:08 +0000 (09:25 +0000)
riscv/insn_template_sv.cc
riscv/sv.cc
riscv/sv_decode.h

index a4ebbc4ef345767c9472a9a2968ec46c8ef5bfa4..c73e3fde29e0cc4be104bc3235befac54ccb7581 100644 (file)
@@ -13,7 +13,7 @@
 
 #ifdef INSN_TYPE_BRANCH
     #define set_pc(x) insn.setpc(xlen, vlen, npc, x, \
-                                 *dest_offs, target_reg);
+                                 *dest_offs, target_reg, zeroingtarg, invtarg);
 #else
     #define set_pc _set_pc
 #endif
@@ -286,12 +286,15 @@ reg_t sv_proc_t::FN(processor_t* p, insn_t s_insn, reg_t pc)
   // ok, at the end of the loop, if the predicates are equal,
   // we're good to branch.  use the saved address (to avoid
   // calculating the BRANCH_TARGET macro again)
-  uint64_t mask = (1<<vlen) - 1;
-  if (insn.get_if_one_reg_vectorised() &&
-      (insn.get_saved_branch_rd() & mask) == (target_pred & mask))
+  if (r->active) // only when predication is set
   {
-    fprintf(stderr, "vector branch ACTIVE\n");
-    _set_pc(insn.get_saved_branch_addr());
+    uint64_t mask = (1<<vlen) - 1;
+    if (insn.get_if_one_reg_vectorised() &&
+        (insn.get_saved_branch_rd() & mask) == (target_pred & mask))
+    {
+      fprintf(stderr, "vector branch ACTIVE\n");
+      _set_pc(insn.get_saved_branch_addr());
+    }
   }
 #endif
   // ok at the **END** of the looping we set the (ref'd) dest_offs and
index 946281ae4e92df7902502bd8f2b6333dd23cbbaa..4a0cb4284e8e56f07fde44516f154bb038a1d3c0 100644 (file)
@@ -214,9 +214,29 @@ reg_spec_t sv_insn_t::remap(uint64_t reg, bool intreg, int *voffs)
  */
 reg_t sv_insn_t::predicate(uint64_t reg, bool intreg, bool &zeroing)
 {
-    bool inv = false;
-    return predicate(reg, intreg, zeroing, inv);
+  sv_reg_entry *pr = get_regentry(reg, intreg);
+  if (!pr->active)
+  {
+    return ~0x0; // *REGISTER* not active: return all-1s (unconditional "on")
+  }
+  sv_pred_entry *r = get_predentry(reg, intreg);
+  if (!r->active)
+  {
+    return ~0x0; // *PREDICATION* not active: return all-1s (unconditional "on")
+  }
+  zeroing = r->zero;
+  fprintf(stderr, "predicate read %ld -> %ld\n", reg, r->regidx);
+  reg = r->regidx;
+  reg_spec_t rs = {reg, NULL};
+  reg_t pred = p->s.READ_REG(rs); // macros go through processor_t state
+  if (r->inv)
+  {
+    return ~pred;
+  }
+  return pred;
 }
+
+// XXX WARNING: this fn does NOT invert the predicate (if r->inv return ~pred)
 reg_t sv_insn_t::predicate(uint64_t reg, bool intreg, bool &zeroing, bool &inv)
 {
   sv_reg_entry *pr = get_regentry(reg, intreg);
@@ -230,14 +250,11 @@ reg_t sv_insn_t::predicate(uint64_t reg, bool intreg, bool &zeroing, bool &inv)
     return ~0x0; // *PREDICATION* not active: return all-1s (unconditional "on")
   }
   zeroing = r->zero;
+  inv = r->inv;
   fprintf(stderr, "predicate read %ld -> %ld\n", reg, r->regidx);
   reg = r->regidx;
   reg_spec_t rs = {reg, NULL};
   reg_t predicate = p->s.READ_REG(rs); // macros go through processor_t state
-  if (r->inv)
-  {
-    return ~predicate;
-  }
   return predicate;
 }
 
@@ -301,10 +318,10 @@ uint64_t sv_insn_t::rd_bitset(reg_t reg, int bit, bool set)
 }
 
 void sv_insn_t::setpc(int xlen, int vlen, reg_t &npc, reg_t addr, uint64_t offs,
-                      reg_t *target_reg)
+                      reg_t *target_reg, bool zeroing, bool inv)
 {
     save_branch_addr = addr;
-    if (not at_least_one_reg_vectorised)
+    if (not at_least_one_reg_vectorised) // scalar-scalar: make the branch
     {
         _set_pc(addr);
         return;
@@ -320,11 +337,18 @@ void sv_insn_t::setpc(int xlen, int vlen, reg_t &npc, reg_t addr, uint64_t offs,
     if ((1<<offs) & prs1)
     {
         if (target_reg) {
-            save_branch_rd = rd_bitset(*target_reg, offs, true);
+            save_branch_rd = rd_bitset(*target_reg, offs, !zeroing);
         } else {
-            save_branch_rd |= (1<<offs);
+            if (zeroing)
+                save_branch_rd &= ~(1UL<<offs);
+            else
+                save_branch_rd |= (1UL<<offs);
         }
     }
+    else if (inv) // target pred, meaning of inv bit is overloaded
+    {
+      vloop_continue = false;
+    }
     fprintf(stderr, "setpc %lx offs %ld predicate %lx rs1 %ld rs2 %ld\n",
             save_branch_rd, offs, prs1,
             p->s.READ_REG(rs1()), p->s.READ_REG(rs2()));
index 9a0b76eee3214f7c7ed33dbb8b8254719e81769c..f1d53fc32768dd218a29f6316a3c1df9400d1eaf 100644 (file)
@@ -88,7 +88,7 @@ public:
                                 use_offs ? offs_sp : NULL); }
 
   void setpc(int xlen, int vlen, reg_t &npc, reg_t addr, uint64_t offs,
-             reg_t *target_reg);
+             reg_t *target_reg, bool zeroing, bool inv);
 
   // used for predicated branches. sets bit N if val=true; clears bit N if false
   uint64_t rd_bitset(reg_t reg, int bit, bool val);