reorganise src and dest vector-element offsets
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 5 Oct 2018 14:26:20 +0000 (15:26 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 5 Oct 2018 14:26:20 +0000 (15:26 +0100)
pass in pointer to offsets from processor_t->state.srcoffs and destoffs
into sv_insn_t so that the element state information about how many
parallel elements have been executed is recorded.

in this way it will be possible to restart a loop at the right place
if there is an exception (such as a memory cache miss on a LOAD/STORE)

riscv/insn_template_sv.cc
riscv/processor.h
riscv/sv.cc
riscv/sv_decode.h

index cab74d7c8f9ea254589f58183eec7050bb6b45e1..83b04d8d5572b4176ffec2e6d2a2c1f10e4cfebf 100644 (file)
@@ -19,11 +19,11 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
   // REGS_PATTERN is generated by id_regs.py (per opcode)
   unsigned int floatintmap = REGS_PATTERN;
   reg_t dest_pred = ~0x0;
-  int dest_offs = 0;
+  int *dest_offs = &(p->get_state()->destoffs);
   bool zeroing = false;
 #ifdef INSN_CATEGORY_TWINPREDICATION
   reg_t src_pred = ~0x0;
-  int src_offs = 0;
+  int *src_offs = &(p->get_state()->srcoffs);
   bool zeroingsrc = false;
 #endif
   sv_insn_t insn(p, bits, floatintmap, PRED_ARGS, OFFS_ARGS);
@@ -59,47 +59,47 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
   {
     insn.reset_vloop_check();
 #ifdef INSN_CATEGORY_TWINPREDICATION
-    if (src_offs >= vlen) {
+    if (*src_offs >= vlen) {
         break;
     }
-    if (dest_offs >= vlen) {
+    if (*dest_offs >= vlen) {
         break;
     }
 #ifdef INSN_C_MV
         fprintf(stderr, "pre twin reg %s src %d dest %d pred %lx %lx\n",
-            xstr(INSN), src_offs, dest_offs, src_pred, dest_pred);
+            xstr(INSN), *src_offs, *dest_offs, src_pred, dest_pred);
 #endif
     if (!zeroingsrc)
     {
-      while ((src_pred & (1<<src_offs)) == 0) {
-          src_offs += 1;
-          if (src_offs >= vlen) {
+      while ((src_pred & (1<<*src_offs)) == 0) {
+          *src_offs += 1;
+          if (*src_offs >= vlen) {
               break;
           }
       }
     }
     if (!zeroing)
     {
-      while ((dest_pred & (1<<dest_offs)) == 0) {
-          dest_offs += 1;
-          if (dest_offs >= vlen) {
+      while ((dest_pred & (1<<*dest_offs)) == 0) {
+          *dest_offs += 1;
+          if (*dest_offs >= vlen) {
               break;
           }
       }
     }
-    if (src_offs >= vlen || dest_offs >= vlen) {
+    if (*src_offs >= vlen || *dest_offs >= vlen) {
         break; // end vector loop if either src or dest pred reaches end
     }
     if (vlen > 1)
     {
         fprintf(stderr, "twin reg %s src %d dest %d pred %lx %lx\n",
-            xstr(INSN), src_offs, dest_offs, src_pred, dest_pred);
+            xstr(INSN), *src_offs, *dest_offs, src_pred, dest_pred);
     }
 #endif
 #ifdef INSN_C_MV
     fprintf(stderr, "pre loop reg %s %x vloop %d %d %d" \
                       "vlen %d stop %d pred %lx rdv %lx rd %d rvc2 %d\n",
-                xstr(INSN), INSNCODE, voffs, src_offs, dest_offs,
+                xstr(INSN), INSNCODE, voffs, *src_offs, *dest_offs,
                 vlen, insn.stop_vloop(),
                 dest_pred & (1<<voffs), READ_REG(insn._rd()),
                 insn._rd(), insn._rvc_rs2());
@@ -107,7 +107,7 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
       #include INCLUDEFILE
 #ifdef DEST_PREDINT
       // don't check inversion here as dest_pred has already been inverted
-      if (zeroing && ((dest_pred & (1<<dest_offs)) == 0))
+      if (zeroing && ((dest_pred & (1<<*dest_offs)) == 0))
       {
           // insn._rd() would be predicated: have to use insn._rd() here
           WRITE_REG(insn._DEST_REG(), 0);
@@ -132,10 +132,18 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
         break;
       }
 #ifdef INSN_CATEGORY_TWINPREDICATION
-      src_offs += 1;
+      *src_offs += 1;
 #endif
-      dest_offs += 1;
+      *dest_offs += 1;
   }
+  // ok at the **END** of the looping we set the (ref'd) dest_offs and
+  // src_offs to zero.  this allows any exceptions that are thrown
+  // to leave dest_offs and src_offs as they are, such that when
+  // the instruction is re-run it continues from where things left off.
+  *dest_offs = 0;
+#ifdef INSN_CATEGORY_TWINPREDICATION
+  *src_offs = 0;
+#endif
 #else
   insn_t insn(bits);
   #include INCLUDEFILE
index 2e87d5e25cd02f3d392bd4461ec1d539906038d2..fe06ec4d3999bb23d84b5e67d2e7cf46f80fd1b6 100644 (file)
@@ -129,8 +129,8 @@ struct state_t
 #ifdef SPIKE_SIMPLEV
   uint64_t vl;
   uint64_t mvl;
-  uint64_t destoffs; // destination loop element offset
-  uint64_t srcoffs;  // source loop element offset (used in twin-predication)
+  int destoffs; // destination loop element offset
+  int srcoffs;  // source loop element offset (used in twin-predication)
   sv_reg_csr_entry sv_csrs[SV_CSR_SZ];
   sv_reg_entry     sv_int_tb[NXPR];
   sv_reg_entry     sv_fp_tb[NFPR];
index 9cc46507e524b5dfafd3d917762841426bd8dd0e..a6bf42a6708fb45af0ef7eefc7180b4aa251a78e 100644 (file)
@@ -66,7 +66,7 @@ bool sv_insn_t::sv_check_reg(bool intreg, uint64_t reg)
  * of SV.  it's "supposed" to "just" be a vectorisation API. it isn't:
  * it's quite a bit more.
  */
-uint64_t sv_insn_t::remap(uint64_t reg, bool intreg, int &voffs)
+uint64_t sv_insn_t::remap(uint64_t reg, bool intreg, int voffs)
 {
   // okaay so first determine which map to use.  intreg is passed
   // in (ultimately) from id_regs.py's examination of the use of
index 7bffe1b47934c6f611a72f5053988cf27ff8d1a0..45c0ae5cc28633e9a0c593f5908c6c8981ee9e00 100644 (file)
@@ -22,18 +22,18 @@ class sv_insn_t: public insn_t
 public:
   sv_insn_t(processor_t *pr, insn_bits_t bits, unsigned int f,
             uint64_t &p_rd, uint64_t &p_rs1, uint64_t &p_rs2, uint64_t &p_rs3,
-            int &o_rd, int &o_rs1, int &o_rs2, int &o_rs3) :
+            int *o_rd, int *o_rs1, int *o_rs2, int *o_rs3) :
             insn_t(bits), p(pr), vloop_continue(false), fimap(f),
             offs_rd(o_rd), offs_rs1(o_rs1), offs_rs2(o_rs2), offs_rs3(o_rs3),
             prd(p_rd), prs1(p_rs1), prs2(p_rs2), prs3(p_rs3) {}
-  uint64_t rd () { return predicated(_rd (), offs_rd, prd); }
-  uint64_t rs1() { return predicated(_rs1(), offs_rs1, prs1); }
-  uint64_t rs2() { return predicated(_rs2(), offs_rs2, prs2); }
-  uint64_t rs3() { return predicated(_rs3(), offs_rs3, prs3); }
-  uint64_t rvc_rs1 () { return predicated(_rvc_rs1 (), offs_rs1, prs1); }
-  uint64_t rvc_rs1s() { return predicated(_rvc_rs1s(), offs_rs1, prs1); }
-  uint64_t rvc_rs2 () { return predicated(_rvc_rs2 (), offs_rs2, prs2); }
-  uint64_t rvc_rs2s() { return predicated(_rvc_rs2s(), offs_rs2, prs2); }
+  uint64_t rd () { return predicated(_rd (), *offs_rd, prd); }
+  uint64_t rs1() { return predicated(_rs1(), *offs_rs1, prs1); }
+  uint64_t rs2() { return predicated(_rs2(), *offs_rs2, prs2); }
+  uint64_t rs3() { return predicated(_rs3(), *offs_rs3, prs3); }
+  uint64_t rvc_rs1 () { return predicated(_rvc_rs1 (), *offs_rs1, prs1); }
+  uint64_t rvc_rs1s() { return predicated(_rvc_rs1s(), *offs_rs1, prs1); }
+  uint64_t rvc_rs2 () { return predicated(_rvc_rs2 (), *offs_rs2, prs2); }
+  uint64_t rvc_rs2s() { return predicated(_rvc_rs2s(), *offs_rs2, prs2); }
 
   uint64_t _rd () { return _remap(insn_t::rd (), fimap & REG_RD , offs_rd); }
   uint64_t _rs1() { return _remap(insn_t::rs1(), fimap & REG_RS1, offs_rs1); }
@@ -60,10 +60,10 @@ public:
 private:
   bool vloop_continue;
   unsigned int fimap;
-  int &offs_rd;
-  int &offs_rs1;
-  int &offs_rs2;
-  int &offs_rs3;
+  int *offs_rd;
+  int *offs_rs1;
+  int *offs_rs2;
+  int *offs_rs3;
   uint64_t &prd;
   uint64_t &prs1;
   uint64_t &prs2;
@@ -71,18 +71,18 @@ private:
 
   // remaps the register through the lookup table.
   // will need to take the current loop index/offset somehow
-  uint64_t remap(uint64_t reg, bool isint, int &offs);
+  uint64_t remap(uint64_t reg, bool isint, int offs);
 
   // cached version of remap: if remap is called multiple times
   // by an emulated instruction it would increment the loop offset
   // before it's supposed to.
-  uint64_t _remap(uint64_t reg, bool isint, int &offs)
+  uint64_t _remap(uint64_t reg, bool isint, int *offs)
   {
     if (sv_check_reg(isint, reg))
     {
         vloop_continue = true;
     }
-    return remap(reg, isint, offs);
+    return remap(reg, isint, *offs);
   }
 
   uint64_t predicated(uint64_t reg, int offs, uint64_t pred);