From 7bc68407d92c4e94203eed79c8190ef5bcef05fe Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 30 Sep 2018 09:15:17 +0100 Subject: [PATCH] lots of debugging of predication, found other errors lots of stuff here: * changed sv reg and pred entry layout to make them a bit more human-readable: put the key and idx on byte-boundaries * bug in SV REG setting (getting int table instead of fp one, twice) * bug(s) in SV PRED table setting (zeroing the reg tables, using idx not key and more) * stop lookup of predication if the *REGISTER* entry is inactive (but not if it is a scalar, because scalar predication is ok) this was the final piece of the puzzle that got predication working * added a useful macro for creating SV REG and PRED CAM table entries predication now working including zeroing --- riscv/insn_template_sv.cc | 1 + riscv/processor.cc | 29 ++++++++++++++++++++++------- riscv/sv.cc | 7 ++++++- riscv/sv.h | 10 ++++++++-- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/riscv/insn_template_sv.cc b/riscv/insn_template_sv.cc index 9cd5a41..c2f4b1a 100644 --- a/riscv/insn_template_sv.cc +++ b/riscv/insn_template_sv.cc @@ -23,6 +23,7 @@ reg_t FN(processor_t* p, insn_t s_insn, reg_t pc) dest_pred, dest_pred, dest_pred, dest_pred); bool zeroing; #if defined(USING_REG_RD) || defined(USING_REG_FRD) + // use the ORIGINAL, i.e. NON-REDIRECTED, register here dest_pred = insn.predicate(s_insn.rd(), floatintmap & REG_RD, zeroing); #endif // identify which regs have had their CSR entries set as vectorised. diff --git a/riscv/processor.cc b/riscv/processor.cc index 7c17432..a53ab1e 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -392,7 +392,7 @@ void processor_t::set_csr(int which, reg_t val) } else { - r = &state.sv_int_tb[idx]; + r = &state.sv_fp_tb[idx]; } r->elwidth = c->b.elwidth; r->regidx = c->b.regidx; @@ -422,12 +422,16 @@ void processor_t::set_csr(int which, reg_t val) { state.sv_pred_csrs[i].u = 0; } - 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_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++) { union sv_pred_csr_entry *c = &state.sv_pred_csrs[i]; - uint64_t idx = c->b.regidx; + uint64_t idx = c->b.regkey; + if (c->u == 0) + { + break; + } sv_pred_entry *r; // XXX damn. this basically duplicates sv_insn_t::get_predentry. if (c->b.type == 1) @@ -436,12 +440,14 @@ void processor_t::set_csr(int which, reg_t val) } else { - r = &state.sv_pred_int_tb[idx]; + r = &state.sv_pred_fp_tb[idx]; } r->regidx = c->b.regidx; r->zero = c->b.zero; r->inv = c->b.inv; - r->active = true; + r->active = c->b.active; + fprintf(stderr, "setting PREDCFG type:%d zero:%d %d %d\n", + c->b.type, r->zero, (int)idx, (int)r->regidx); } break; } @@ -683,7 +689,16 @@ reg_t processor_t::get_csr(int which) case CSR_SVREGCFG5: case CSR_SVREGCFG6: case CSR_SVREGCFG7: - return 0; + return 0;// XXX TODO: return correct entry + case CSR_SVPREDCFG0: + case CSR_SVPREDCFG1: + case CSR_SVPREDCFG2: + case CSR_SVPREDCFG3: + case CSR_SVPREDCFG4: + case CSR_SVPREDCFG5: + case CSR_SVPREDCFG6: + case CSR_SVPREDCFG7: + return 0;// XXX TODO: return correct entry #endif case CSR_FFLAGS: require_fp; diff --git a/riscv/sv.cc b/riscv/sv.cc index 79c2c37..1a16730 100644 --- a/riscv/sv.cc +++ b/riscv/sv.cc @@ -135,10 +135,15 @@ uint64_t sv_insn_t::remap(uint64_t reg, bool intreg, int &voffs, int &newoffs) */ reg_t sv_insn_t::predicate(uint64_t reg, bool intreg, bool &zeroing) { + sv_reg_entry *pr = get_regentry(reg, intreg); + if (!pr->active) + { + return ~0x0; // *REGISTER* not active: return all-1s (unconditional "on") + } sv_pred_entry *r = get_predentry(reg, intreg); if (!r->active) { - return ~0x0; // not active: return all-1s (unconditional "on") + return ~0x0; // *PREDICATION* not active: return all-1s (unconditional "on") } zeroing = r->zero; reg = r->regidx; diff --git a/riscv/sv.h b/riscv/sv.h index 9315dd0..748b9c6 100644 --- a/riscv/sv.h +++ b/riscv/sv.h @@ -5,15 +5,21 @@ #include "decode.h" +// useful macros for constructing SV reg and predicate CSR CAM entries +#define SV_REG_CSR(type, regkey, elwidth, regidx, isvec, packed) \ + (regkey | (elwidth<<5) | (type<<7) | (regidx<<8) | (isvec<<14) | (packed<<15)) +#define SV_PRED_CSR(type, regkey, zero, inv, regidx, active) \ + (regkey | (zero<<5) | (inv<<6) | (type<<7) | (regidx<<8) | (active<<14)) + // this table is for the CSRs (4? for RV32E, 16 for other types) // it's a CAM that's used to generate 2 tables (below) // just as in RV, writing to entries in this CAM *clears* // all entries with a higher index union sv_reg_csr_entry { struct { - unsigned int type : 1; // 1=INT, 0=FP uint64_t regkey : 5; // 5 bits unsigned int elwidth: 2; // 0=8-bit, 1=dflt, 2=dflt/2 3=dflt*2 + unsigned int type : 1; // 1=INT, 0=FP uint64_t regidx : 6; // yes 6 bits unsigned int isvec : 1; // vector=1, scalar=0 unsigned int packed : 1; // Packed SIMD=1 @@ -44,10 +50,10 @@ typedef struct { union sv_pred_csr_entry { struct { - unsigned int type : 1; // 1=INT, 0=FP uint64_t regkey: 5; // 5 bits unsigned int zero : 1; // zeroing=1, skipping=0 unsigned int inv : 1; // inversion=1 + unsigned int type : 1; // 1=INT, 0=FP uint64_t regidx: 6; // 6 bits unsigned int active: 1; // enabled=1, disabled=0 } b; -- 2.30.2