From 02b5b9b05c94babac800c3a40cab61e822978ee7 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Wed, 3 Feb 2021 16:48:09 +0100 Subject: [PATCH] fpu load subnormal and i2f now use single cycle shifter --- src/main/scala/vexriscv/ip/fpu/FpuCore.scala | 45 +++++++++++--------- src/test/scala/vexriscv/ip/fpu/FpuTest.scala | 44 ++++++++++--------- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/src/main/scala/vexriscv/ip/fpu/FpuCore.scala b/src/main/scala/vexriscv/ip/fpu/FpuCore.scala index 4614370..c16791c 100644 --- a/src/main/scala/vexriscv/ip/fpu/FpuCore.scala +++ b/src/main/scala/vexriscv/ip/fpu/FpuCore.scala @@ -354,13 +354,22 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ val isQuiet = f32Mantissa.msb val fsm = new Area{ - val manTop = Reg(UInt(log2Up(p.internalMantissaSize) bits)) - val shift = CombInit(manTop) - val counter = Reg(UInt(log2Up(p.internalMantissaSize+1) bits)) val done, boot, patched = Reg(Bool()) val ohInput = CombInit(input.value(0, 32 max p.internalMantissaSize bits)) when(!input.i2f) { ohInput(9, 23 bits) := input.value(0, 23 bits) } val i2fZero = Reg(Bool) + + val shift = new Area{ + val by = Reg(UInt(log2Up(p.internalMantissaSize max 32) bits)) + val input = UInt(p.internalMantissaSize max 32 bits).assignDontCare() + var logic = input + for(i <- by.range){ + logic \= by(i) ? (logic |<< (BigInt(1) << i)) | logic + } + val output = RegNextWhen(logic, !done) + } + shift.input := input.value.asUInt |<< 1 + when(input.valid && (input.i2f || isSubnormal) && !done){ busy := True when(boot){ @@ -368,31 +377,27 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ input.value.getDrivingReg(0, 32 bits) := B(input.value.asUInt.twoComplement(True).resize(32 bits)) patched := True } otherwise { - manTop := OHToUInt(OHMasking.first((ohInput).reversed)) + shift.by := OHToUInt(OHMasking.first((ohInput).reversed)) + (input.i2f ? U(0) | U(9)) boot := False i2fZero := input.value(31 downto 0) === 0 } } otherwise { - when(input.i2f){ - input.value.getDrivingReg(0, 32 bits) := input.value(0, 32 bits) |<< 1 - } otherwise { - input.value.getDrivingReg(0, 23 bits) := input.value(0, 23 bits) |<< 1 - } - counter := counter + 1 - when(counter === shift) { - done := True - } +// when(input.i2f){ +// input.value.getDrivingReg(0, 32 bits) := input.value(0, 32 bits) |<< 1 +// } otherwise { +// input.value.getDrivingReg(0, 23 bits) := input.value(0, 23 bits) |<< 1 +// } + done := True } } val expOffset = (UInt(p.internalExponentSize bits)) expOffset := 0 when(isSubnormal){ - expOffset := manTop.resized + expOffset := (shift.by-9).resized } when(!input.isStall){ - counter := 0 done := False boot := True patched := False @@ -401,7 +406,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ val i2fSign = fsm.patched - val (i2fHigh, i2fLow) = input.value.splitAt(widthOf(input.value)-24) + val (i2fHigh, i2fLow) = fsm.shift.output.splitAt(widthOf(input.value)-24) val scrap = i2fLow =/= 0 val recoded = p.internalFloating() @@ -425,12 +430,14 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ output.scrap := False when(input.i2f){ output.value.sign := i2fSign - output.value.exponent := (U(exponentOne+31) - fsm.manTop).resized - output.value.mantissa := U(i2fHigh) + output.value.exponent := (U(exponentOne+31) - fsm.shift.by).resized output.value.setNormal output.scrap := scrap when(fsm.i2fZero) { output.value.setZero } - //TODO ROUND + } + + when(input.i2f || isSubnormal){ + output.value.mantissa := U(i2fHigh) } } } diff --git a/src/test/scala/vexriscv/ip/fpu/FpuTest.scala b/src/test/scala/vexriscv/ip/fpu/FpuTest.scala index e3a6125..c0b58b8 100644 --- a/src/test/scala/vexriscv/ip/fpu/FpuTest.scala +++ b/src/test/scala/vexriscv/ip/fpu/FpuTest.scala @@ -541,7 +541,6 @@ class FpuTest extends FunSuite{ storeFloat(rd){v => val aLong = if(signed) a.toLong else a.toLong & 0xFFFFFFFFl val ref = b -// println(f"i2f($aLong) = $v, $ref") assert(f2b(v) == f2b(ref), f"i2f($aLong) = $v, $ref") } } @@ -663,28 +662,48 @@ class FpuTest extends FunSuite{ val binaryOps = List[(Int,Int,Int,FpuRoundMode.E) => Unit](add, sub, mul) + testI2f(24, false) + testI2f(17, false) + + testLoadStore(2.5f) + testLoadStore(3.67341984632e-40f) + testLoadStore(5.5321021294e-40f) - for(_ <- 0 until 10000){ + for(_ <- 0 until 100000){ + val rounding = FpuRoundMode.elements.randomPick() + val (a,b,c,f) = f32.add(rounding).f32_2 + testBinaryOp(add,a,b,c,f, rounding,"add") + } + + for(_ <- 0 until 100000){ + val rounding = FpuRoundMode.elements.randomPick() + val (a,b,c,f) = f32.sub(rounding).f32_2 + testBinaryOp(sub,a,b,c,f, rounding,"sub") + } + + println("Add done") + + for(_ <- 0 until 100000){ val rounding = FpuRoundMode.elements.randomPick() val (a,b,f) = f32.i2f(rounding).i32_f32 testI2fExact(a,b,f, true, rounding) } - for(_ <- 0 until 10000){ + for(_ <- 0 until 100000){ val rounding = FpuRoundMode.elements.randomPick() val (a,b,f) = f32.ui2f(rounding).i32_f32 testI2fExact(a,b,f, false, rounding) } println("i2f done") - for(_ <- 0 until 10000){ + for(_ <- 0 until 100000){ val rounding = FpuRoundMode.elements.randomPick() val (a,b,f) = f32.f2ui(rounding).f32_i32 testF2iExact(a,b, f, false, rounding) } - for(_ <- 0 until 10000){ + for(_ <- 0 until 100000){ val rounding = FpuRoundMode.elements.randomPick() val (a,b,f) = f32.f2i(rounding).f32_i32 testF2iExact(a,b, f, true, rounding) @@ -693,21 +712,8 @@ class FpuTest extends FunSuite{ println("f2i done") - for(_ <- 0 until 10000){ - val rounding = FpuRoundMode.elements.randomPick() - val (a,b,c,f) = f32.add(rounding).f32_2 - testBinaryOp(add,a,b,c,f, rounding,"add") - } - for(_ <- 0 until 10000){ - val rounding = FpuRoundMode.elements.randomPick() - val (a,b,c,f) = f32.sub(rounding).f32_2 - testBinaryOp(sub,a,b,c,f, rounding,"sub") - } - - println("Add done") - - for(_ <- 0 until 10000){ + for(_ <- 0 until 100000){ val rounding = FpuRoundMode.elements.randomPick() val (a,b,c,f) = f32.mul(rounding).f32_2 testBinaryOp(mul,a,b,c,f, rounding,"mul")