From d14bf485f2038bdbbe82c00322fcb7deac892022 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sat, 3 Nov 2018 06:56:49 +0000 Subject: [PATCH] add state redirection for CSR get/set depending on processor mode --- riscv/insn_template_sv.cc | 6 +-- riscv/processor.cc | 82 ++++++++++++++++++++++++--------------- riscv/processor.h | 36 ++++++++++++----- riscv/sv.cc | 10 ++--- riscv/sv.h | 4 +- 5 files changed, 87 insertions(+), 51 deletions(-) diff --git a/riscv/insn_template_sv.cc b/riscv/insn_template_sv.cc index 61b4abd..1b3ca4f 100644 --- a/riscv/insn_template_sv.cc +++ b/riscv/insn_template_sv.cc @@ -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 diff --git a/riscv/processor.cc b/riscv/processor.cc index 90f5a92..9df3698 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -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() } } } + diff --git a/riscv/processor.h b/riscv/processor.h index 93fa39c..7d2a609 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -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; diff --git a/riscv/sv.cc b/riscv/sv.cc index f5af866..75dac8a 100644 --- a/riscv/sv.cc +++ b/riscv/sv.cc @@ -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; } diff --git a/riscv/sv.h b/riscv/sv.h index 21f07d4..af4402a 100644 --- a/riscv/sv.h +++ b/riscv/sv.h @@ -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. -- 2.30.2