redo SV CSRs to use a stack-based mechanism
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 13 Nov 2018 13:38:33 +0000 (13:38 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 13 Nov 2018 13:38:33 +0000 (13:38 +0000)
riscv/encoding.h
riscv/processor.cc
riscv/processor.h
riscv/sv.cc

index 6dc3e924069df6bfc5b246bebac8ef4929337c50..77f464e3b409d98b9748480079c967f9903f41ac 100644 (file)
 #define CSR_MHPMEVENT29 0x33d
 #define CSR_MHPMEVENT30 0x33e
 #define CSR_MHPMEVENT31 0x33f
-#define CSR_SVREGCFG0 0x4c0
-#define CSR_SVREGCFG1 0x4c1
-#define CSR_SVREGCFG2 0x4c2
-#define CSR_SVREGCFG3 0x4c3
-#define CSR_SVREGCFG4 0x4c4
-#define CSR_SVREGCFG5 0x4c5
-#define CSR_SVREGCFG6 0x4c6
-#define CSR_SVREGCFG7 0x4c7
+#define CSR_SVREGTOP 0x4c0
+#define CSR_SVREGBOT 0x4c1
 #define CSR_SVPREDCFG0 0x4c8
 #define CSR_SVPREDCFG1 0x4c9
 #define CSR_SVPREDCFG2 0x4ca
@@ -1280,14 +1274,8 @@ DECLARE_CSR(usvcfg, CSR_USVCFG)
 DECLARE_CSR(usvstate, CSR_USVSTATE)
 DECLARE_CSR(usvvl, CSR_USVVL)
 DECLARE_CSR(usvmvl, CSR_USVMVL)
-DECLARE_CSR(svregcfg0, CSR_SVREGCFG0)
-DECLARE_CSR(svregcfg1, CSR_SVREGCFG1)
-DECLARE_CSR(svregcfg2, CSR_SVREGCFG2)
-DECLARE_CSR(svregcfg3, CSR_SVREGCFG3)
-DECLARE_CSR(svregcfg4, CSR_SVREGCFG4)
-DECLARE_CSR(svregcfg5, CSR_SVREGCFG5)
-DECLARE_CSR(svregcfg6, CSR_SVREGCFG6)
-DECLARE_CSR(svregcfg7, CSR_SVREGCFG7)
+DECLARE_CSR(svregtop, CSR_SVREGTOP)
+DECLARE_CSR(svregbot, CSR_SVREGBOT)
 DECLARE_CSR(svpredcfg0, CSR_SVPREDCFG0)
 DECLARE_CSR(svpredcfg1, CSR_SVPREDCFG1)
 DECLARE_CSR(svpredcfg2, CSR_SVPREDCFG2)
index 0161abec6fd5d85b0c68bd3468aebbad1ab72233..fadd19445154888ec2fb6c0695649eca83fd4578 100644 (file)
@@ -535,35 +535,27 @@ void processor_t::set_csr(int which, reg_t val)
       // TODO XXX throw exception if val == 0
       fprintf(stderr, "set VL %lx\n", state.sv().vl);
       break;
-    case CSR_SVREGCFG0:
-    case CSR_SVREGCFG1:
-    case CSR_SVREGCFG2:
-    case CSR_SVREGCFG3:
-    case CSR_SVREGCFG4:
-    case CSR_SVREGCFG5:
-    case CSR_SVREGCFG6:
-    case CSR_SVREGCFG7:
+    case CSR_SVREGTOP:
+    case CSR_SVREGBOT:
     {
+      bool top = (which == CSR_SVREGTOP);
       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, v);
-      // lower 16 bits go into even, upper into odd...
-      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().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
-      // when it comes to context-switching, it's clear what needs to be saved
-      for (int i = tbidx+clroffset; i < 16; i++)
-      {
-          fprintf(stderr, "clr REGCFG %d\n", i);
-          state.sv().sv_csrs[i].u = 0;
+      fprintf(stderr, "set SVREG %d %lx\n", top, v);
+      int start = 0;
+      int end = 0;
+      state.get_csr_start_end(start, end);
+      uint64_t res_old = 0;
+      // read 2 16-bit entries for RV32, 4 16-bit entries for RV64
+      for (int i = 0; i < (xlen == 64) ? 4 : 2; i++) {
+          uint64_t mask = 0xffffUL << (i*16UL);
+          uint64_t svcfg = get_field(v, mask);
+          fprintf(stderr, "SVREG mask %lx cfg %lx\n", mask, svcfg);
+          if (!svcfg && i > 0) {
+            break;
+          }
+          // see regpush on how this works.
+          uint64_t res = state.sv().regpush(svcfg, end, top);
+          res_old |= res << (i * 16UL);
       }
       state.sv_csr_reg_unpack();
       break;
@@ -865,14 +857,8 @@ reg_t processor_t::get_csr(int which)
              (state.sv().state_bank<<24)  | (state.sv().state_size<<26);
     case CSR_USVMVL:
       return state.sv().mvl;
-    case CSR_SVREGCFG0:
-    case CSR_SVREGCFG1:
-    case CSR_SVREGCFG2:
-    case CSR_SVREGCFG3:
-    case CSR_SVREGCFG4:
-    case CSR_SVREGCFG5:
-    case CSR_SVREGCFG6:
-    case CSR_SVREGCFG7:
+    case CSR_SVREGTOP:
+    case CSR_SVREGBOT:
       return 0;// XXX TODO: return correct entry
     case CSR_SVPREDCFG0:
     case CSR_SVPREDCFG1:
index 8b7163ccf3c20c2bef49fb2b84fa85c64a0f2e0b..0ae06175857b1bf767cd0894c4d64629b9174b24 100644 (file)
@@ -103,6 +103,9 @@ typedef struct
   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];
+
+  uint64_t regpush(uint16_t csrval, int len, bool top);
+
 } sv_csr_t;
 #endif
 
index 60fd66530e98e1d2cc32e390161f0b2352d5302a..2096351da8ab2eb33cefe67753ff264ba72ced5d 100644 (file)
@@ -327,3 +327,73 @@ uint8_t sv_insn_t::reg_elwidth(reg_t reg, bool intreg)
     return 0;
 }
 
+uint64_t sv_csr_t::regpush(uint16_t csrval, int len, bool top)
+{
+    // when csrval == 0 it means "pop".
+    // when reg != 0 and an existing entry exists, it means "change reg"
+    // when reg != 0 and an existing entry doesn't exist, it means "push"
+    // push/pop are to top when top is true, otherwise to bottom.
+    uint64_t reg = get_field(csrval, 0x1f);
+    int idx = 0;
+    int topstack = -1;
+    for (idx = 0; idx < len; idx++)
+    {
+        if (sv_csrs[idx].u == 0) {
+            topstack = idx; // used to count to end (for pop/push)
+            break;
+        } else if (reg != 0 && sv_csrs[idx].b.regkey == reg) {
+            sv_csrs[idx].u = csrval; // change reg
+            return 0; // no popping
+        }
+    }
+    // ok entry not found, is reg==0, means "pop"
+    if (csrval == 0) {
+        uint64_t popped = 0;
+        if (top) {
+            if (topstack == 0) {
+                return 0;
+            }
+            topstack -= 1;
+            uint64_t popped = sv_csrs[topstack].u;
+            sv_csrs[topstack].u = 0;
+            fprintf(stderr, "regcsr clr %d\n", topstack);
+        } else {
+            uint64_t popped = sv_csrs[0].u;
+            for (idx = 0; idx < topstack-1; idx++) {
+                sv_csrs[idx].u = sv_csrs[idx+1].u;
+                fprintf(stderr, "regcsr clr shuffle %d %d\n", idx, idx+1);
+            }
+            sv_csrs[topstack].u = 0;
+            fprintf(stderr, "regcsr clr %d\n", topstack);
+        }
+        return popped;
+    }
+    // ok entry not found, reg != 0, means "push", are we pushing to top?
+    if (top) {
+        if (topstack == len-1) { // not enough room
+            uint64_t popped = sv_csrs[0].u;
+            for (idx = 0; idx < topstack-1; idx++) {
+                sv_csrs[idx].u = sv_csrs[idx+1].u;
+                fprintf(stderr, "regcsr shuffle %d %d\n", idx, idx+1);
+            }
+            sv_csrs[topstack].u = csrval;
+            fprintf(stderr, "regcsr set %d %lx\n", topstack, csrval);
+            return popped;
+        } else {
+            sv_csrs[topstack].u = csrval;
+            fprintf(stderr, "regcsr set %d %lx\n", topstack, csrval);
+            return 0;
+        }
+    }
+    // no, we're pushing at bottom
+    uint64_t popped = 0;
+    if (topstack == len-1) { // not enough room
+        popped = sv_csrs[topstack].u; // top's going to get wiped
+    }
+    for (idx = topstack; idx > 0; idx--) {
+        sv_csrs[idx].u = sv_csrs[idx-1].u;
+    }
+    sv_csrs[0].u = csrval; // put in at bottom
+    return popped;
+}
+