#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
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)
// 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;
(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:
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
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;
+}
+