From: Luke Kenneth Casson Leighton Date: Thu, 25 Oct 2018 23:57:56 +0000 (+0100) Subject: add variable bitwidth on read/write regs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=33188ae6d82c907b6bb6091143a9d45dac6659db;p=riscv-isa-sim.git add variable bitwidth on read/write regs --- diff --git a/riscv/insn_template_sv.cc b/riscv/insn_template_sv.cc index f49d2c7..fecb9d0 100644 --- a/riscv/insn_template_sv.cc +++ b/riscv/insn_template_sv.cc @@ -124,7 +124,7 @@ reg_t sv_proc_t::FN(processor_t* p, insn_t s_insn, reg_t pc) // identify which regs have had their CSR entries set as vectorised. // really could do with a macro for-loop here... oh well... // integer ops, RD, RS1, RS2, RS3 (use sv_int_tb) - if (insn.sv_check_reg(true, 16)) + if (insn.sv_check_reg(true, 15)) { fprintf(stderr, "reg %s %x rd %ld rs1 %ld rs2 %ld vlen %d\n", xstr(INSN), INSNCODE, s_insn.rd(), s_insn.rs1(), s_insn.rs2(), @@ -139,6 +139,10 @@ reg_t sv_proc_t::FN(processor_t* p, insn_t s_insn, reg_t pc) for (int voffs=0; voffs < vlen; voffs++) { insn.reset_vloop_check(); +#ifdef INSN_C_MV + fprintf(stderr, "pre twin reg %s src %d dest %d pred %lx %lx vlen %d\n", + xstr(INSN), *src_offs, *dest_offs, src_pred, dest_pred, vlen); +#endif #ifdef INSN_C_BEQZ fprintf(stderr, "pre twin reg %s src %lx dest %d pred %lx %lx\n", xstr(INSN), _target_reg, *dest_offs, target_pred, dest_pred); diff --git a/riscv/processor.cc b/riscv/processor.cc index a7f6a92..90f5a92 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -373,17 +373,18 @@ void processor_t::set_csr(int which, reg_t val) case CSR_SVREGCFG6: case CSR_SVREGCFG7: { + 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, val); + 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(val, 0xffff); - state.sv_csrs[tbidx+1].u = get_field(val, 0xffff<<16); + state.sv_csrs[tbidx].u = get_field(v, 0xffffUL); + state.sv_csrs[tbidx+1].u = get_field(v, 0xffffUL<<16); int clroffset = 2; if (xlen == 64) { - state.sv_csrs[tbidx+2].u = get_field(val, 0xffffUL<<32); - state.sv_csrs[tbidx+3].u = get_field(val, 0xffffUL<<48); + state.sv_csrs[tbidx+2].u = get_field(v, 0xffffUL<<32); + state.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 @@ -437,14 +438,16 @@ void processor_t::set_csr(int which, reg_t val) { // comments removed as it's near-identical to the regs version // TODO: macro-ify + uint64_t v = (uint64_t)val; int tbidx = (which - CSR_SVPREDCFG0) * 2; - state.sv_pred_csrs[tbidx].u = get_field(val, 0xffff); - state.sv_pred_csrs[tbidx+1].u = get_field(val, 0xffff0000); + 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); int clroffset = 2; if (xlen == 64) { - state.sv_pred_csrs[tbidx+2].u = get_field(val, 0xffffUL<<32); - state.sv_pred_csrs[tbidx+3].u = get_field(val, 0xffffUL<<48); + state.sv_pred_csrs[tbidx+2].u = get_field(v, 0xffffUL<<32); + state.sv_pred_csrs[tbidx+3].u = get_field(v, 0xffffUL<<48); clroffset = 4; } for (int i = tbidx+clroffset; i < 16; i++) @@ -476,8 +479,8 @@ void processor_t::set_csr(int which, reg_t val) r->inv = c->b.inv; r->packed = c->b.packed; r->active = true; - fprintf(stderr, "setting PREDCFG type:%d zero:%d %d %d\n", - c->b.type, r->zero, (int)idx, (int)r->regidx); + fprintf(stderr, "setting PREDCFG %d type:%d zero:%d %d %d\n", + i, c->b.type, r->zero, (int)idx, (int)r->regidx); } break; } diff --git a/riscv/sv.cc b/riscv/sv.cc index 151c8fc..c85c23d 100644 --- a/riscv/sv.cc +++ b/riscv/sv.cc @@ -206,6 +206,7 @@ reg_t sv_insn_t::predicate(uint64_t reg, bool intreg, bool &zeroing) return ~0x0; // *PREDICATION* not active: return all-1s (unconditional "on") } zeroing = r->zero; + fprintf(stderr, "predicate read %ld -> %ld\n", reg, r->regidx); reg = r->regidx; reg_spec_t rs = {reg, NULL}; reg_t predicate = p->s.READ_REG(rs); // macros go through processor_t state diff --git a/riscv/sv_insn_redirect.cc b/riscv/sv_insn_redirect.cc index 5298bc1..62aaaf9 100644 --- a/riscv/sv_insn_redirect.cc +++ b/riscv/sv_insn_redirect.cc @@ -94,12 +94,32 @@ void (sv_proc_t::DO_WRITE_FREG)(reg_spec_t const& spec, freg_t const& value) void (sv_proc_t::WRITE_REG)(reg_spec_t const& spec, sv_reg_t const& value) { + uint64_t wval = (uint64_t)value; //WRITE_REG( reg, value ); // XXX TODO: replace properly reg_t reg = spec.reg; + int bitwidth = get_bitwidth(_insn->reg_elwidth(reg, true), xlen); + unsigned int shift = 0; + unsigned int offs = 0; if (spec.offset) { - reg += *spec.offset; + unsigned int nbytes = xlen / bitwidth; + offs = *spec.offset; + shift = offs % nbytes; + offs /= nbytes; + reg += offs; } - STATE.XPR.write(reg, value); + if (xlen != bitwidth) + { + uint64_t data = _insn->p->get_state()->XPR[reg]; + uint64_t mask = ((1UL<reg_elwidth(reg, true), xlen); int shift = 0; + int offs = 0; if (spec.offset && spec.reg != 2) { // XXX HACK on spec.reg != 2 - int offs = *spec.offset; int nbytes = xlen / bitwidth; + offs = *spec.offset; shift = offs % nbytes; offs /= nbytes; - reg += *spec.offset; + reg += offs; } uint64_t data = _insn->p->get_state()->XPR[reg]; + uint64_t ndata = data; if (xlen != bitwidth) { - data = data >> (shift*8); // gets the right element within the reg-block - data &= ((1<> (shift*bitwidth); // gets element within the reg-block + ndata &= ((1UL<%lx\n", + spec.reg, bitwidth, offs, shift, data, ndata); } - return data; + return ndata; } sv_reg_t sv_proc_t::get_intreg(reg_spec_t const&spec)