addition bug fixes

This commit is contained in:
Blaise Tine
2022-02-05 09:14:35 -05:00
parent 140124b423
commit bda77760c8
3 changed files with 313 additions and 297 deletions

View File

@@ -33,7 +33,7 @@ jobs:
script: cp -r $PWD ../build_coverage && cd ../build_coverage && ./ci/travis_run.py ./ci/regression.sh -coverage script: cp -r $PWD ../build_coverage && cd ../build_coverage && ./ci/travis_run.py ./ci/regression.sh -coverage
- stage: test - stage: test
name: coverage64 name: coverage64
script: cp -r $PWD ../build_coverage && cd ../build_coverage && ./ci/travis_run.py ./ci/regression64.sh -coverage script: cp -r $PWD ../build_coverage64 && cd ../build_coverage64 && ./ci/travis_run.py ./ci/regression64.sh -coverage
- stage: test - stage: test
name: tex name: tex
script: cp -r $PWD ../build_tex && cd ../build_tex && ./ci/travis_run.py ./ci/regression.sh -tex script: cp -r $PWD ../build_tex && cd ../build_tex && ./ci/travis_run.py ./ci/regression.sh -tex

View File

@@ -48,16 +48,49 @@ inline uint32_t get_fpu_rm(uint32_t func3, Core* core, uint32_t tid, uint32_t wi
return (func3 == 0x7) ? core->get_csr(CSR_FRM, tid, wid) : func3; return (func3 == 0x7) ? core->get_csr(CSR_FRM, tid, wid) : func3;
} }
inline void update_fcrs(uint32_t fflags, Core* core, uint32_t tid, uint32_t wid) { static void update_fcrs(uint32_t fflags, Core* core, uint32_t tid, uint32_t wid) {
if (fflags) { if (fflags) {
core->set_csr(CSR_FCSR, core->get_csr(CSR_FCSR, tid, wid) | fflags, tid, wid); core->set_csr(CSR_FCSR, core->get_csr(CSR_FCSR, tid, wid) | fflags, tid, wid);
core->set_csr(CSR_FFLAGS, core->get_csr(CSR_FFLAGS, tid, wid) | fflags, tid, wid); core->set_csr(CSR_FFLAGS, core->get_csr(CSR_FFLAGS, tid, wid) | fflags, tid, wid);
} }
} }
inline uint64_t nan_box(uint32_t word) { inline uint64_t nan_box(uint32_t value) {
uint64_t mask = 0xffffffff00000000; uint64_t mask = 0xffffffff00000000;
return word | mask; return value | mask;
}
inline bool is_nan_boxed(uint64_t value) {
return (uint32_t(value >> 32) == 0xffffffff);
}
static bool checkBoxedArgs(FWord* out, FWord a, FWord b, uint32_t* fflags) {
bool xa = is_nan_boxed(a);
bool xb = is_nan_boxed(b);
if (xa && xb)
return true;
if (xa) {
// a is NaN boxed but b isn't
*out = nan_box((uint32_t)a);
} else if (xb) {
// b is NaN boxed but a isn't
*out = nan_box(0xffc00000);
} else {
// Both a and b aren't NaN boxed
*out = nan_box(0x7fc00000);
}
*fflags = 0;
return false;
}
static bool checkBoxedCmpArgs(Word* out, FWord a, FWord b, uint32_t* fflags) {
bool xa = is_nan_boxed(a);
bool xb = is_nan_boxed(b);
if (xa && xb)
return true;
*out = 0;
*fflags = 0;
return false;
} }
void Warp::execute(const Instr &instr, pipeline_trace_t *trace) { void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
@@ -845,41 +878,11 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
continue; continue;
uint32_t frm = get_fpu_rm(func3, core_, t, id_); uint32_t frm = get_fpu_rm(func3, core_, t, id_);
uint32_t fflags = 0; uint32_t fflags = 0;
bool fvalid = true;
switch (func7) {
case 0x00: // RV32F: FADD.S
case 0x04: // RV32F: FSUB.S
case 0x08: // RV32F: FMUL.S
case 0x0c: // RV32F: FDIV.S
case 0x2c: // RV32F: FSQRT.S
case 0x10: // RV32F: FSGNJ.S / FSGNJN.S / FSGNJX.S
case 0x14: // RV32F: FMAX.S / FMIN.S
case 0x50: {
// RV32F: FLE.S / FLT.S / FEQ.S
uint64_t a = rsdata[t][0].f;
uint64_t b = rsdata[t][1].f;
// Both a and b aren't NaN boxed
if ((a >> 32 != 0xffffffff) && (b >> 32 != 0xffffffff)) {
rddata[t].f = nan_box(0x7fc00000);
fvalid = false;
}
// a is NaN boxed but b isn't
else if (b >> 32 != 0xffffffff) {
rddata[t].f = nan_box((uint32_t)a);
fvalid = false;
}
// b is NaN boxed but a isn't
else if (a >> 32 != 0xffffffff) {
rddata[t].f = nan_box(0xffc00000);
fvalid = false;
}
break;
}
}
if (fvalid){
switch (func7) { switch (func7) {
case 0x00: { // RV32F: FADD.S case 0x00: { // RV32F: FADD.S
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
rddata[t].f = nan_box(rv_fadd_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags)); rddata[t].f = nan_box(rv_fadd_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
}
trace->fpu.type = FpuType::FMA; trace->fpu.type = FpuType::FMA;
trace->used_fregs.set(rsrc0); trace->used_fregs.set(rsrc0);
trace->used_fregs.set(rsrc1); trace->used_fregs.set(rsrc1);
@@ -893,7 +896,9 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
break; break;
} }
case 0x04: { // RV32F: FSUB.S case 0x04: { // RV32F: FSUB.S
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
rddata[t].f = nan_box(rv_fsub_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags)); rddata[t].f = nan_box(rv_fsub_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
}
trace->fpu.type = FpuType::FMA; trace->fpu.type = FpuType::FMA;
trace->used_fregs.set(rsrc0); trace->used_fregs.set(rsrc0);
trace->used_fregs.set(rsrc1); trace->used_fregs.set(rsrc1);
@@ -907,7 +912,9 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
break; break;
} }
case 0x08: { // RV32F: FMUL.S case 0x08: { // RV32F: FMUL.S
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
rddata[t].f = nan_box(rv_fmul_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags)); rddata[t].f = nan_box(rv_fmul_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
}
trace->fpu.type = FpuType::FMA; trace->fpu.type = FpuType::FMA;
trace->used_fregs.set(rsrc0); trace->used_fregs.set(rsrc0);
trace->used_fregs.set(rsrc1); trace->used_fregs.set(rsrc1);
@@ -921,7 +928,9 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
break; break;
} }
case 0x0c: { // RV32F: FDIV.S case 0x0c: { // RV32F: FDIV.S
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
rddata[t].f = nan_box(rv_fdiv_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags)); rddata[t].f = nan_box(rv_fdiv_s(rsdata[t][0].f, rsdata[t][1].f, frm, &fflags));
}
trace->fpu.type = FpuType::FDIV; trace->fpu.type = FpuType::FDIV;
trace->used_fregs.set(rsrc0); trace->used_fregs.set(rsrc0);
trace->used_fregs.set(rsrc1); trace->used_fregs.set(rsrc1);
@@ -935,7 +944,9 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
break; break;
} }
case 0x2c: { // RV32F: FSQRT.S case 0x2c: { // RV32F: FSQRT.S
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
rddata[t].f = nan_box(rv_fsqrt_s(rsdata[t][0].f, frm, &fflags)); rddata[t].f = nan_box(rv_fsqrt_s(rsdata[t][0].f, frm, &fflags));
}
trace->fpu.type = FpuType::FSQRT; trace->fpu.type = FpuType::FSQRT;
trace->used_fregs.set(rsrc0); trace->used_fregs.set(rsrc0);
break; break;
@@ -947,6 +958,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
break; break;
} }
case 0x10: { case 0x10: {
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
switch (func3) { switch (func3) {
case 0: // RV32F: FSGNJ.S case 0: // RV32F: FSGNJ.S
rddata[t].f = nan_box(rv_fsgnj_s(rsdata[t][0].f, rsdata[t][1].f)); rddata[t].f = nan_box(rv_fsgnj_s(rsdata[t][0].f, rsdata[t][1].f));
@@ -958,6 +970,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
rddata[t].f = nan_box(rv_fsgnjx_s(rsdata[t][0].f, rsdata[t][1].f)); rddata[t].f = nan_box(rv_fsgnjx_s(rsdata[t][0].f, rsdata[t][1].f));
break; break;
} }
}
trace->fpu.type = FpuType::FNCP; trace->fpu.type = FpuType::FNCP;
trace->used_fregs.set(rsrc0); trace->used_fregs.set(rsrc0);
trace->used_fregs.set(rsrc1); trace->used_fregs.set(rsrc1);
@@ -981,6 +994,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
break; break;
} }
case 0x14: { case 0x14: {
if (checkBoxedArgs(&rddata[t].f, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
if (func3) { if (func3) {
// RV32F: FMAX.S // RV32F: FMAX.S
rddata[t].f = nan_box(rv_fmax_s(rsdata[t][0].f, rsdata[t][1].f, &fflags)); rddata[t].f = nan_box(rv_fmax_s(rsdata[t][0].f, rsdata[t][1].f, &fflags));
@@ -988,6 +1002,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
// RV32F: FMIN.S // RV32F: FMIN.S
rddata[t].f = nan_box(rv_fmin_s(rsdata[t][0].f, rsdata[t][1].f, &fflags)); rddata[t].f = nan_box(rv_fmin_s(rsdata[t][0].f, rsdata[t][1].f, &fflags));
} }
}
trace->fpu.type = FpuType::FNCP; trace->fpu.type = FpuType::FNCP;
trace->used_fregs.set(rsrc0); trace->used_fregs.set(rsrc0);
trace->used_fregs.set(rsrc1); trace->used_fregs.set(rsrc1);
@@ -1049,11 +1064,11 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
switch (rsrc1) { switch (rsrc1) {
case 0: case 0:
// RV32D: FCVT.W.D // RV32D: FCVT.W.D
rddata[t].i = sext(rv_ftoi_d(rsdata[t][0].f, frm, &fflags), 32); rddata[t].i = sext((uint64_t)rv_ftoi_d(rsdata[t][0].f, frm, &fflags), 32);
break; break;
case 1: case 1:
// RV32D: FCVT.WU.D // RV32D: FCVT.WU.D
rddata[t].i = sext(rv_ftou_d(rsdata[t][0].f, frm, &fflags), 32); rddata[t].i = sext((uint64_t)rv_ftou_d(rsdata[t][0].f, frm, &fflags), 32);
break; break;
case 2: case 2:
// RV64D: FCVT.L.D // RV64D: FCVT.L.D
@@ -1094,6 +1109,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
break; break;
} }
case 0x50: { case 0x50: {
if (checkBoxedCmpArgs(&rddata[t].i, rsdata[t][0].f, rsdata[t][1].f, &fflags)) {
switch (func3) { switch (func3) {
case 0: case 0:
// RV32F: FLE.S // RV32F: FLE.S
@@ -1108,6 +1124,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
rddata[t].i = rv_feq_s(rsdata[t][0].f, rsdata[t][1].f, &fflags); rddata[t].i = rv_feq_s(rsdata[t][0].f, rsdata[t][1].f, &fflags);
break; break;
} }
}
trace->fpu.type = FpuType::FNCP; trace->fpu.type = FpuType::FNCP;
trace->used_fregs.set(rsrc0); trace->used_fregs.set(rsrc0);
trace->used_fregs.set(rsrc1); trace->used_fregs.set(rsrc1);
@@ -1192,7 +1209,6 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
break; break;
} }
} }
}
update_fcrs(fflags, core_, t, id_); update_fcrs(fflags, core_, t, id_);
} }
rd_write = true; rd_write = true;

View File

@@ -40,7 +40,7 @@ run-simx-64imfd:
run-simx-32: run-simx-32imfd run-simx-32: run-simx-32imfd
run-simx-64: run-simx-64imfd run-simx-64: run-simx-32imfd run-simx-64imfd
run-simx: run-simx-$(XLEN) run-simx: run-simx-$(XLEN)