add state redirection for CSR get/set depending on processor mode
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 3 Nov 2018 06:56:49 +0000 (06:56 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 3 Nov 2018 06:56:49 +0000 (06:56 +0000)
riscv/insn_template_sv.cc
riscv/processor.cc
riscv/processor.h
riscv/sv.cc
riscv/sv.h

index 61b4abd015369129ff0f898b56bb716d3e872caf..1b3ca4f39087b2fdd8fd7e130e35826200119d96 100644 (file)
@@ -46,17 +46,17 @@ reg_t sv_proc_t::FN(processor_t* p, insn_t s_insn, reg_t pc)
   insn_bits_t bits = s_insn.bits();
   int vlen = 0;
   if (p->get_state()->prv == 0) { // XXX HACK - disable in supervisor mode
-    vlen = p->get_state()->vl;
+    vlen = p->get_state()->sv().vl;
   }
   // need to know if register is used as float or int.
   // REGS_PATTERN is generated by id_regs.py (per opcode)
   unsigned int floatintmap = REGS_PATTERN;
   reg_t dest_pred = ~0x0;
-  int *dest_offs = &(p->get_state()->destoffs);
+  int *dest_offs = &(p->get_state()->sv().destoffs);
   bool zeroing = false;
 #ifdef INSN_CATEGORY_TWINPREDICATION
   reg_t src_pred = ~0x0;
-  int *src_offs = &(p->get_state()->srcoffs);
+  int *src_offs = &(p->get_state()->sv().srcoffs);
   bool zeroingsrc = false;
 #endif
 #ifdef INSN_TYPE_BRANCH
index 90f5a92e0ee16b18b8006c51431d9334f7358cd9..9df369867c91f4138636f8c525dfc2050171fb3e 100644 (file)
@@ -140,6 +140,23 @@ void state_t::reset(reg_t max_isa)
     mcontrol[i].type = 2;
 }
 
+int state_t::sv_csr_sz()
+{
+    if (prv == PRV_M)
+        return SV_MCSR_SZ;
+    if (prv == PRV_S)
+        return SV_SCSR_SZ;
+    return SV_UCSR_SZ;
+}
+sv_csr_t &state_t::sv()
+{
+    if (prv == PRV_M)
+        return get_msv();
+    if (prv == PRV_S)
+        return get_ssv();
+    return get_usv();
+}
+
 void processor_t::set_debug(bool value)
 {
   debug = value;
@@ -348,21 +365,21 @@ void processor_t::set_csr(int which, reg_t val)
   {
 #ifdef SPIKE_SIMPLEV
     case CSR_USVMVL:
-      state.mvl = std::min(val, (uint64_t)64); // limited to XLEN width
+      state.sv().mvl = std::min(val, (uint64_t)64); // limited to XLEN width
       // TODO XXX throw exception if val == 0
-      fprintf(stderr, "set MVL %lx\n", state.mvl);
+      fprintf(stderr, "set MVL %lx\n", state.sv().mvl);
       break;
     case CSR_USVSTATE:
       // bits 0-5: mvl - 6-11: vl - 12-17: srcoffs - 18-23: destoffs
       set_csr(CSR_USVMVL, get_field(val, 0x1f   )+1);
       set_csr(CSR_USVVL , get_field(val, 0x1f<<6)+1);
-      state.srcoffs  = std::min(get_field(val, 0x1f<<12), state.vl-1);
-      state.destoffs = std::min(get_field(val, 0x1f<<18), state.vl-1);
+      state.sv().srcoffs  = std::min(get_field(val, 0x1f<<12), state.sv().vl-1);
+      state.sv().destoffs = std::min(get_field(val, 0x1f<<18), state.sv().vl-1);
       break;
     case CSR_USVVL:
-      state.vl = std::min(state.mvl, val);
+      state.sv().vl = std::min(state.sv().mvl, val);
       // TODO XXX throw exception if val == 0
-      fprintf(stderr, "set VL %lx\n", state.vl);
+      fprintf(stderr, "set VL %lx\n", state.sv().vl);
       break;
     case CSR_SVREGCFG0:
     case CSR_SVREGCFG1:
@@ -378,13 +395,13 @@ void processor_t::set_csr(int which, reg_t val)
       int tbidx = (which - CSR_SVREGCFG0) * 2;
       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(v, 0xffffUL);
-      state.sv_csrs[tbidx+1].u = get_field(v, 0xffffUL<<16);
+      state.sv().sv_csrs[tbidx].u = get_field(v, 0xffffUL);
+      state.sv().sv_csrs[tbidx+1].u = get_field(v, 0xffffUL<<16);
       int clroffset = 2;
       if (xlen == 64)
       {
-          state.sv_csrs[tbidx+2].u = get_field(v, 0xffffUL<<32);
-          state.sv_csrs[tbidx+3].u = get_field(v, 0xffffUL<<48);
+          state.sv().sv_csrs[tbidx+2].u = get_field(v, 0xffffUL<<32);
+          state.sv().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
@@ -392,17 +409,17 @@ void processor_t::set_csr(int which, reg_t val)
       for (int i = tbidx+clroffset; i < 16; i++)
       {
           fprintf(stderr, "clr REGCFG %d\n", i);
-          state.sv_csrs[i].u = 0;
+          state.sv().sv_csrs[i].u = 0;
       }
       // okaaay and now "unpack" the CAM to make it easier to use.  this
       // approach is not designed to be efficient right now.  optimise later
       // first clear the old tables
-      memset(state.sv_int_tb, 0, sizeof(state.sv_int_tb));
-      memset(state.sv_fp_tb, 0, sizeof(state.sv_fp_tb));
+      memset(state.sv().sv_int_tb, 0, sizeof(state.sv().sv_int_tb));
+      memset(state.sv().sv_fp_tb, 0, sizeof(state.sv().sv_fp_tb));
       // now walk the CAM and unpack it
-      for (int i = 0; i < SV_CSR_SZ; i++)
+      for (int i = 0; i < state.sv_csr_sz(); i++)
       {
-        union sv_reg_csr_entry *c = &state.sv_csrs[i];
+        union sv_reg_csr_entry *c = &state.sv().sv_csrs[i];
         uint64_t idx = c->b.regkey;
         sv_reg_entry *r;
         if (c->u == 0)
@@ -412,11 +429,11 @@ void processor_t::set_csr(int which, reg_t val)
         // XXX damn.  this basically duplicates sv_insn_t::get_regentry.
         if (c->b.type == 1)
         {
-            r = &state.sv_int_tb[idx];
+            r = &state.sv().sv_int_tb[idx];
         }
         else
         {
-            r = &state.sv_fp_tb[idx];
+            r = &state.sv().sv_fp_tb[idx];
         }
         r->elwidth = c->b.elwidth;
         r->regidx = c->b.regidx;
@@ -441,24 +458,24 @@ void processor_t::set_csr(int which, reg_t val)
       uint64_t v = (uint64_t)val;
       int tbidx = (which - CSR_SVPREDCFG0) * 2;
       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);
+      state.sv().sv_pred_csrs[tbidx].u = get_field(v, 0xffff);
+      state.sv().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(v, 0xffffUL<<32);
-          state.sv_pred_csrs[tbidx+3].u = get_field(v, 0xffffUL<<48);
+          state.sv().sv_pred_csrs[tbidx+2].u = get_field(v, 0xffffUL<<32);
+          state.sv().sv_pred_csrs[tbidx+3].u = get_field(v, 0xffffUL<<48);
           clroffset = 4;
       }
       for (int i = tbidx+clroffset; i < 16; i++)
       {
-          state.sv_pred_csrs[i].u = 0;
+          state.sv().sv_pred_csrs[i].u = 0;
       }
-      memset(state.sv_pred_int_tb, 0, sizeof(state.sv_pred_int_tb));
-      memset(state.sv_pred_fp_tb, 0, sizeof(state.sv_pred_fp_tb));
-      for (int i = 0; i < SV_CSR_SZ; i++)
+      memset(state.sv().sv_pred_int_tb, 0, sizeof(state.sv().sv_pred_int_tb));
+      memset(state.sv().sv_pred_fp_tb, 0, sizeof(state.sv().sv_pred_fp_tb));
+      for (int i = 0; i < state.sv_csr_sz(); i++)
       {
-        union sv_pred_csr_entry *c = &state.sv_pred_csrs[i];
+        union sv_pred_csr_entry *c = &state.sv().sv_pred_csrs[i];
         uint64_t idx = c->b.regkey;
         if (c->u == 0)
         {
@@ -468,11 +485,11 @@ void processor_t::set_csr(int which, reg_t val)
         // XXX damn.  this basically duplicates sv_insn_t::get_predentry.
         if (c->b.type == 1)
         {
-            r = &state.sv_pred_int_tb[idx];
+            r = &state.sv().sv_pred_int_tb[idx];
         }
         else
         {
-            r = &state.sv_pred_fp_tb[idx];
+            r = &state.sv().sv_pred_fp_tb[idx];
         }
         r->regidx = c->b.regidx;
         r->zero   = c->b.zero;
@@ -710,12 +727,12 @@ reg_t processor_t::get_csr(int which)
   {
 #ifdef SPIKE_SIMPLEV
     case CSR_USVVL:
-      return state.vl;
+      return state.sv().vl;
     case CSR_USVSTATE:
-      return (state.vl-1)            | ((state.mvl-1)<<6) |
-             (state.srcoffs<<12)     | (state.destoffs<<18) ;
+      return (state.sv().vl-1)            | ((state.sv().mvl-1)<<6) |
+             (state.sv().srcoffs<<12)     | (state.sv().destoffs<<18) ;
     case CSR_USVMVL:
-      return state.mvl;
+      return state.sv().mvl;
     case CSR_SVREGCFG0:
     case CSR_SVREGCFG1:
     case CSR_SVREGCFG2:
@@ -997,3 +1014,4 @@ void processor_t::trigger_updated()
     }
   }
 }
+
index 93fa39c5b0a2a7518d9e22bca557bfb557ab79c0..7d2a609b9eebbc3caf00b00dd13c17a98f2f2879 100644 (file)
@@ -88,6 +88,22 @@ typedef struct
   bool load;
 } mcontrol_t;
 
+#ifdef SPIKE_SIMPLEV
+typedef struct
+{
+  uint64_t vl;
+  uint64_t mvl;
+  int destoffs; // destination loop element offset
+  int srcoffs;  // source loop element offset (used in twin-predication)
+  sv_reg_csr_entry sv_csrs[SV_UCSR_SZ];
+  sv_reg_entry     sv_int_tb[NXPR];
+  sv_reg_entry     sv_fp_tb[NFPR];
+  sv_pred_csr_entry sv_pred_csrs[SV_UCSR_SZ];
+  sv_pred_entry     sv_pred_int_tb[NXPR];
+  sv_pred_entry     sv_pred_fp_tb[NFPR];
+} sv_csr_t;
+#endif
+
 // architectural state of a RISC-V hart
 struct state_t
 {
@@ -134,16 +150,16 @@ struct state_t
   reg_t tdata2[num_triggers];
 
 #ifdef SPIKE_SIMPLEV
-  uint64_t vl;
-  uint64_t mvl;
-  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];
-  sv_pred_csr_entry sv_pred_csrs[SV_CSR_SZ];
-  sv_pred_entry     sv_pred_int_tb[NXPR];
-  sv_pred_entry     sv_pred_fp_tb[NFPR];
+  sv_csr_t msv;
+  sv_csr_t ssv;
+  sv_csr_t usv;
+
+  int sv_csr_sz();
+  sv_csr_t &sv();
+  sv_csr_t &get_msv() { return msv; }
+  sv_csr_t &get_ssv() { return ssv; }
+  sv_csr_t &get_usv() { return usv; }
+
 #endif
 
   uint32_t fflags;
index f5af8666e92c1cc8ae0833847bab5b3cafcb03b9..75dac8a919b5dacad4ace51fb822d725cd67af9d 100644 (file)
@@ -85,11 +85,11 @@ sv_pred_entry* sv_insn_t::get_predentry(uint64_t reg, bool intreg)
   sv_pred_entry *r;
   if (intreg)
   {
-    return &p->get_state()->sv_pred_int_tb[reg];
+    return &p->get_state()->sv().sv_pred_int_tb[reg];
   }
   else
   {
-    return &p->get_state()->sv_pred_fp_tb[reg];
+    return &p->get_state()->sv().sv_pred_fp_tb[reg];
   }
 }
 
@@ -102,11 +102,11 @@ sv_reg_entry* sv_insn_t::get_regentry(uint64_t reg, bool intreg)
   sv_reg_entry *r;
   if (intreg)
   {
-    return &p->get_state()->sv_int_tb[reg];
+    return &p->get_state()->sv().sv_int_tb[reg];
   }
   else
   {
-    return &p->get_state()->sv_fp_tb[reg];
+    return &p->get_state()->sv().sv_fp_tb[reg];
   }
 }
 
@@ -250,7 +250,7 @@ reg_spec_t sv_insn_t::predicated(reg_spec_t const& spec, uint64_t pred)
 
 bool sv_insn_t::stop_vloop(void)
 {
-    return (p->get_state()->vl == 0) || !vloop_continue;
+    return (p->get_state()->sv().vl == 0) || !vloop_continue;
 }
 
 
index 21f07d4e2b6b12d26422fb0168987a3399c7c76d..af4402ae303715094b53c4947212c662ff5d61eb 100644 (file)
@@ -31,7 +31,9 @@ union sv_reg_csr_entry {
 // platforms, and a minimum of 4 for int/fp.
 // this to be able to use SV for contiguous register save/restore
 // in around 2 instructions rather than massive blocks of 31
-#define SV_CSR_SZ 16 // TODO: only 4? for RV32?
+#define SV_UCSR_SZ 16 // TODO: only 4? for RV32?
+#define SV_MCSR_SZ 4
+#define SV_SCSR_SZ 4
 
 // this is the "unpacked" table, generated from the CAM above
 // there are 2 of them: one for FP, one for INT regs.