From 0ea61b1f3030b79bd79baeaee256e7c3903986eb Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 13 Nov 2018 13:38:33 +0000 Subject: [PATCH] redo SV CSRs to use a stack-based mechanism --- riscv/encoding.h | 20 +++---------- riscv/processor.cc | 56 ++++++++++++++----------------------- riscv/processor.h | 3 ++ riscv/sv.cc | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 51 deletions(-) diff --git a/riscv/encoding.h b/riscv/encoding.h index 6dc3e92..77f464e 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -892,14 +892,8 @@ #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) diff --git a/riscv/processor.cc b/riscv/processor.cc index 0161abe..fadd194 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -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: diff --git a/riscv/processor.h b/riscv/processor.h index 8b7163c..0ae0617 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -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 diff --git a/riscv/sv.cc b/riscv/sv.cc index 60fd665..2096351 100644 --- a/riscv/sv.cc +++ b/riscv/sv.cc @@ -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; +} + -- 2.30.2