add variable bitwidth on read/write regs
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 25 Oct 2018 23:57:56 +0000 (00:57 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 25 Oct 2018 23:57:56 +0000 (00:57 +0100)
riscv/insn_template_sv.cc
riscv/processor.cc
riscv/sv.cc
riscv/sv_insn_redirect.cc

index f49d2c733ce3d12ba14d02bff10fb03cf111d141..fecb9d02ab28617e26764a71527beb0580099d2d 100644 (file)
@@ -124,7 +124,7 @@ reg_t sv_proc_t::FN(processor_t* p, insn_t s_insn, reg_t pc)
   // identify which regs have had their CSR entries set as vectorised.
   // really could do with a macro for-loop here... oh well...
   // integer ops, RD, RS1, RS2, RS3 (use sv_int_tb)
-  if (insn.sv_check_reg(true, 16))
+  if (insn.sv_check_reg(true, 15))
   {
     fprintf(stderr, "reg %s %x rd %ld rs1 %ld rs2 %ld vlen %d\n",
             xstr(INSN), INSNCODE, s_insn.rd(), s_insn.rs1(), s_insn.rs2(),
@@ -139,6 +139,10 @@ reg_t sv_proc_t::FN(processor_t* p, insn_t s_insn, reg_t pc)
   for (int voffs=0; voffs < vlen; voffs++)
   {
     insn.reset_vloop_check();
+#ifdef INSN_C_MV
+        fprintf(stderr, "pre twin reg %s src %d dest %d pred %lx %lx vlen %d\n",
+            xstr(INSN), *src_offs, *dest_offs, src_pred, dest_pred, vlen);
+#endif
 #ifdef INSN_C_BEQZ
         fprintf(stderr, "pre twin reg %s src %lx dest %d pred %lx %lx\n",
             xstr(INSN), _target_reg, *dest_offs, target_pred, dest_pred);
index a7f6a923aba526f427e8852b92e3fb6dead9b6f0..90f5a92e0ee16b18b8006c51431d9334f7358cd9 100644 (file)
@@ -373,17 +373,18 @@ void processor_t::set_csr(int which, reg_t val)
     case CSR_SVREGCFG6:
     case CSR_SVREGCFG7:
     {
+      uint64_t v = (uint64_t)val;
       // identify which (pair) of SV config CAM registers are being set
       int tbidx = (which - CSR_SVREGCFG0) * 2;
-      fprintf(stderr, "set REGCFG %d %lx\n", tbidx, val);
+      fprintf(stderr, "set REGCFG %d %lx\n", tbidx, v);
       // lower 16 bits go into even, upper into odd...
-      state.sv_csrs[tbidx].u = get_field(val, 0xffff);
-      state.sv_csrs[tbidx+1].u = get_field(val, 0xffff<<16);
+      state.sv_csrs[tbidx].u = get_field(v, 0xffffUL);
+      state.sv_csrs[tbidx+1].u = get_field(v, 0xffffUL<<16);
       int clroffset = 2;
       if (xlen == 64)
       {
-          state.sv_csrs[tbidx+2].u = get_field(val, 0xffffUL<<32);
-          state.sv_csrs[tbidx+3].u = get_field(val, 0xffffUL<<48);
+          state.sv_csrs[tbidx+2].u = get_field(v, 0xffffUL<<32);
+          state.sv_csrs[tbidx+3].u = get_field(v, 0xffffUL<<48);
         clroffset = 4;
       }
       // clear out all CSRs above the one(s) being set: this ensures that
@@ -437,14 +438,16 @@ void processor_t::set_csr(int which, reg_t val)
     {
       // comments removed as it's near-identical to the regs version
       // TODO: macro-ify
+      uint64_t v = (uint64_t)val;
       int tbidx = (which - CSR_SVPREDCFG0) * 2;
-      state.sv_pred_csrs[tbidx].u = get_field(val, 0xffff);
-      state.sv_pred_csrs[tbidx+1].u = get_field(val, 0xffff0000);
+      fprintf(stderr, "set PREDCFG %d %lx\n", tbidx, v);
+      state.sv_pred_csrs[tbidx].u = get_field(v, 0xffff);
+      state.sv_pred_csrs[tbidx+1].u = get_field(v, 0xffff0000);
       int clroffset = 2;
       if (xlen == 64)
       {
-          state.sv_pred_csrs[tbidx+2].u = get_field(val, 0xffffUL<<32);
-          state.sv_pred_csrs[tbidx+3].u = get_field(val, 0xffffUL<<48);
+          state.sv_pred_csrs[tbidx+2].u = get_field(v, 0xffffUL<<32);
+          state.sv_pred_csrs[tbidx+3].u = get_field(v, 0xffffUL<<48);
           clroffset = 4;
       }
       for (int i = tbidx+clroffset; i < 16; i++)
@@ -476,8 +479,8 @@ void processor_t::set_csr(int which, reg_t val)
         r->inv    = c->b.inv;
         r->packed = c->b.packed;
         r->active = true;
-        fprintf(stderr, "setting PREDCFG type:%d zero:%d %d %d\n",
-                        c->b.type, r->zero, (int)idx, (int)r->regidx);
+        fprintf(stderr, "setting PREDCFG %d type:%d zero:%d %d %d\n",
+                        i, c->b.type, r->zero, (int)idx, (int)r->regidx);
       }
       break;
     }
index 151c8fc8d22bade832864beae477181bdcdaabbf..c85c23d7b5cdac6e3620ab128ecfc42198a760a6 100644 (file)
@@ -206,6 +206,7 @@ reg_t sv_insn_t::predicate(uint64_t reg, bool intreg, bool &zeroing)
     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 predicate = p->s.READ_REG(rs); // macros go through processor_t state
index 5298bc1087e8e9c9ffc5c25de70cb0029556fc46..62aaaf9345a9b9cb3705c326b51dfaaca63bcbae 100644 (file)
@@ -94,12 +94,32 @@ void (sv_proc_t::DO_WRITE_FREG)(reg_spec_t const& spec, freg_t const& value)
 
 void (sv_proc_t::WRITE_REG)(reg_spec_t const& spec, sv_reg_t const& value)
 {
+    uint64_t wval = (uint64_t)value;
     //WRITE_REG( reg, value ); // XXX TODO: replace properly
     reg_t reg = spec.reg;
+    int bitwidth = get_bitwidth(_insn->reg_elwidth(reg, true), xlen);
+    unsigned int shift = 0;
+    unsigned int offs = 0;
     if (spec.offset) {
-        reg += *spec.offset;
+        unsigned int nbytes = xlen / bitwidth;
+        offs = *spec.offset;
+        shift = offs % nbytes;
+        offs /= nbytes;
+        reg += offs;
     }
-    STATE.XPR.write(reg, value);
+    if (xlen != bitwidth)
+    {
+        uint64_t data = _insn->p->get_state()->XPR[reg];
+        uint64_t mask = ((1UL<<bitwidth)-1UL) << (shift*bitwidth);
+        wval = wval << (shift*bitwidth); // gets element within the reg-block
+        uint64_t ndata = data & (uint64_t)(~mask); // masks off the right bits
+        wval |= ndata;
+        fprintf(stderr, "writereg %d bitwidth %d offs %d shift %d %lx " \
+                        " %lx %lx %lx\n",
+                        spec.reg, bitwidth, offs, shift, data,
+                        ndata, mask, wval);
+    }
+    STATE.XPR.write(reg, wval);
 }
 
 freg_t (sv_proc_t::READ_FREG)(reg_spec_t const& spec)
@@ -117,20 +137,24 @@ reg_t (sv_proc_t::READ_REG)(reg_spec_t const& spec)
     reg_t reg = spec.reg;
     int bitwidth = get_bitwidth(_insn->reg_elwidth(reg, true), xlen);
     int shift = 0;
+    int offs = 0;
     if (spec.offset && spec.reg != 2) { // XXX HACK on spec.reg != 2
-        int offs = *spec.offset;
         int nbytes = xlen / bitwidth;
+        offs = *spec.offset;
         shift = offs % nbytes;
         offs /= nbytes;
-        reg += *spec.offset;
+        reg += offs;
     }
     uint64_t data = _insn->p->get_state()->XPR[reg];
+    uint64_t ndata = data;
     if (xlen != bitwidth)
     {
-        data = data >> (shift*8); // gets the right element within the reg-block
-        data &= ((1<<bitwidth)-1); // masks off the right bits
+        ndata = data >> (shift*bitwidth); // gets element within the reg-block
+        ndata &= ((1UL<<bitwidth)-1UL); // masks off the right bits
+        fprintf(stderr, "readreg %d bitwidth %d offs %d shift %d %lx->%lx\n",
+                        spec.reg, bitwidth, offs, shift, data, ndata);
     }
-    return data;
+    return ndata;
 }
 
 sv_reg_t sv_proc_t::get_intreg(reg_spec_t const&spec)