diff options
author | Dave.Wen <dave.wen@sifive.com> | 2019-04-25 01:50:46 -0700 |
---|---|---|
committer | Dave.Wen <dave.wen@sifive.com> | 2019-04-25 01:50:46 -0700 |
commit | f6ecc5bb21a690ef3c3a5c3b95259307ff5da938 (patch) | |
tree | 930871fd50c26ffe9c144171bda2a4ef9a7077d6 /riscv | |
parent | 4265438d34183efeccb377cbe5a2a444c7507827 (diff) | |
download | spike-f6ecc5bb21a690ef3c3a5c3b95259307ff5da938.zip spike-f6ecc5bb21a690ef3c3a5c3b95259307ff5da938.tar.gz spike-f6ecc5bb21a690ef3c3a5c3b95259307ff5da938.tar.bz2 |
rvv: fix vsmulv[vx]
Diffstat (limited to 'riscv')
-rw-r--r-- | riscv/decode.h | 14 | ||||
-rw-r--r-- | riscv/insns/vsmul_vv.h | 60 | ||||
-rw-r--r-- | riscv/insns/vsmul_vx.h | 59 | ||||
-rw-r--r-- | riscv/processor.h | 4 |
4 files changed, 76 insertions, 61 deletions
diff --git a/riscv/decode.h b/riscv/decode.h index 885fd09..2ccaf69 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -921,20 +921,22 @@ enum VMUNARY0{ #define INT_ROUNDING(result, xrm, sew) \ switch(xrm){\ case VRM::RNU:\ - result += (1 << (sew - 2));\ - break;\ + result += ((uint64_t)1 << (sew - 1));\ + break;\ case VRM::RNE:\ - assert(true);\ + if ((result & ((uint64_t)1 << (sew + 1))) == 0){\ + result += ((uint64_t)1 << (sew - 1));\ + }\ break;\ case VRM::RDN:\ result = (result >> (sew - 1)) << (sew - 1);\ break;\ case VRM::ROD:\ - if ((result & (1 << ((sew -1) - 1 ))) > 0){\ - result = ((result >> (sew - 1)) + 1) << (sew - 1);\ + if ((result & ((uint64_t)1 << (sew + 1))) == 1){\ + result += ((uint64_t)1 << (sew - 1));\ }\ break;\ - case VRM::INVALID_RM:\ + case VRM::INVALID_RM:\ assert(true);\ } // Seems that 0x0 doesn't work. diff --git a/riscv/insns/vsmul_vv.h b/riscv/insns/vsmul_vv.h index ba5243d..395a1b3 100644 --- a/riscv/insns/vsmul_vv.h +++ b/riscv/insns/vsmul_vv.h @@ -1,31 +1,39 @@ // vsmul: Signed saturating and rounding fractional multiply -int64_t round = 0; -VRM vrm = STATE.VU.get_vround_mode(); +VRM xrm = STATE.VU.get_vround_mode(); +int64_t int_max = (1 << STATE.VU.vsew) - 1; +int64_t int_min = - (1 << (STATE.VU.vsew - 1)); +int64_t val_mask = ((1 << (STATE.VU.vsew - 1)) - 1); +int64_t sign_mask = ((1 << (STATE.VU.vsew - 1))); + VI_VV_LOOP ({ - int64_t result = vsext(vs1 * vs2, sew * 2); - // rounding - switch(vrm){ - case VRM::RNU: - result += (1 << (sew - 1) ); - break; - case VRM::RNE: - assert(true); - break; - case VRM::RDN: - result = (result >> (sew - 1)) << (sew - 1); - break; - case VRM::ROD: - if ((result & (1 << ((sew -1) - 1 ))) > 0){ - result = ((result >> (sew - 1)) + 1) << (sew - 1); - } - break; - case VRM::INVALID_RM: - assert(true); - }; - + int64_t vs1_sign; + int64_t vs2_sign; + int64_t result_sign; + + vs1_sign = vs1 & sign_mask; + vs2_sign = vs2 & sign_mask; + vs1 = vs1 & val_mask; + vs2 = vs2 & val_mask; + uint64_t result = vzext((uint64_t)vs1 * (uint64_t)vs2, sew * 2); + result_sign = vs1_sign ^ vs2_sign; + // rounding + INT_ROUNDING(result, xrm, sew); + // checking the overflow + uint64_t overflow = result & ((uint64_t)-1 << ((sew - 1) * 2)); + // unsigned shifting to rs1 + result = result >> (sew - 1); + result &= val_mask; + result |= result_sign; + // saturation - if (result >= (int64_t)(2^(sew - 1))) - result = (2^(sew - 1)) - 1; - + if (overflow){ + if (result_sign == 0){ // positive + result = int_max; + }else{ + result = int_min; + } + STATE.VU.vxsat = 1; + } + vd = result; }) diff --git a/riscv/insns/vsmul_vx.h b/riscv/insns/vsmul_vx.h index 5cebfa7..7998868 100644 --- a/riscv/insns/vsmul_vx.h +++ b/riscv/insns/vsmul_vx.h @@ -1,31 +1,38 @@ // vsmul -int64_t round = 0; -VRM vrm = STATE.VU.get_vround_mode(); +VRM xrm = STATE.VU.get_vround_mode(); +int64_t int_max = (1 << STATE.VU.vsew) - 1; +int64_t int_min = - (1 << (STATE.VU.vsew - 1)); +int64_t val_mask = ((1 << (STATE.VU.vsew - 1)) - 1); +int64_t sign_mask = ((1 << (STATE.VU.vsew - 1))); + VI_VX_LOOP ({ - int64_t result = vsext(rs1 * vs2, sew * 2); - // rounding - switch(vrm){ - case VRM::RNU: - result += (1 << (sew - 1) ); - break; - case VRM::RNE: - assert(true); - break; - case VRM::RDN: - result = (result >> (sew - 1)) << (sew - 1); - break; - case VRM::ROD: - if ((result & (1 << ((sew -1) - 1 ))) > 0){ - result = ((result >> (sew - 1)) + 1) << (sew - 1); - } - break; - case VRM::INVALID_RM: - assert(true); - }; - + int64_t rs1_sign; + int64_t vs2_sign; + int64_t result_sign; + + rs1_sign = rs1 & sign_mask; + vs2_sign = vs2 & sign_mask; + rs1 = rs1 & val_mask; + vs2 = vs2 & val_mask; + uint64_t result = vzext((uint64_t)rs1 * (uint64_t)vs2, sew * 2); + result_sign = rs1_sign ^ vs2_sign; + // rounding + INT_ROUNDING(result, xrm, sew); + // checking the overflow + uint64_t overflow = result & ((uint64_t)-1 << ((sew - 1) * 2)); + result = result >> (sew - 1); + result &= val_mask; + result |= result_sign; + // saturation - if (result >= (int64_t)(2^(sew - 1))) - result = (2^(sew - 1)) - 1; - + if (overflow){ + if (result_sign == 0){ // positive + result = int_max; + }else{ + result = int_min; + } + STATE.VU.vxsat = 1; + } + vd = result; }) diff --git a/riscv/processor.h b/riscv/processor.h index eae4581..ae15cc7 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -200,9 +200,7 @@ struct vectorUnit_t { reg_t get_slen() { return SLEN; } VRM get_vround_mode() { - uint32_t rm = BITS(vxrm, 0, 2); - assert( rm < VRM::INVALID_RM ); - return (VRM)rm; + return (VRM)vxrm; } }; |