From b81029f619c0e0a67c27861cfb40ba7c6507f4e9 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 16 May 2023 16:50:38 +0100 Subject: [PATCH] fix fpu underflow rounding (#343) --- src/main/scala/vexriscv/ip/fpu/FpuCore.scala | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vexriscv/ip/fpu/FpuCore.scala b/src/main/scala/vexriscv/ip/fpu/FpuCore.scala index d9dcf69..b78f84f 100644 --- a/src/main/scala/vexriscv/ip/fpu/FpuCore.scala +++ b/src/main/scala/vexriscv/ip/fpu/FpuCore.scala @@ -1547,15 +1547,22 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ val expBase = muxDouble[UInt](input.format)(exponentF64Subnormal + 1)(exponentF32Subnormal + 1) val expDif = expBase -^ input.value.exponent val expSubnormal = !input.value.special && !expDif.msb - var discardCount = (expSubnormal ? expDif.resize(log2Up(p.internalMantissaSize) bits) | U(0)) + var discardCount = (expSubnormal ? expDif | U(0)) if (p.withDouble) when(input.format === FpuFormat.FLOAT) { discardCount \= discardCount + 29 } - val exactMask = (List(True) ++ (0 until p.internalMantissaSize + 1).map(_ < discardCount)).asBits.asUInt - val roundAdjusted = (True ## (manAggregate >> 1)) (discardCount) ## ((manAggregate & exactMask) =/= 0) + val discardCountTrunk = discardCount.resize(log2Up(p.internalMantissaSize) bits) + val exactMask = (List(True) ++ (0 until p.internalMantissaSize + 1).map(_ < discardCountTrunk)).asBits.asUInt + val roundAdjusted = (True ## (manAggregate >> 1)) (discardCountTrunk) ## ((manAggregate & exactMask) =/= 0) + val rneBit = CombInit((U"01" ## (manAggregate >> 2))(discardCountTrunk)) + when(discardCount >= widthOf(manAggregate)){ + rneBit := False + roundAdjusted(1) := False + exactMask := exactMask.maxValue + } val mantissaIncrement = !input.value.special && input.roundMode.mux( - FpuRoundMode.RNE -> (roundAdjusted(1) && (roundAdjusted(0) || (U"01" ## (manAggregate >> 2)) (discardCount))), + FpuRoundMode.RNE -> (roundAdjusted(1) && (roundAdjusted(0) || rneBit)), FpuRoundMode.RTZ -> False, FpuRoundMode.RDN -> (roundAdjusted =/= 0 && input.value.sign), FpuRoundMode.RUP -> (roundAdjusted =/= 0 && !input.value.sign),