From 195e4c422dc2891b71a7bbefc7dbc8c23be46b46 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Wed, 27 Jan 2021 12:11:30 +0100 Subject: [PATCH] fpu now integrate f2i shifter withing the subnormal shifter --- src/main/scala/vexriscv/ip/fpu/FpuCore.scala | 48 ++++++++++++++++---- src/test/scala/vexriscv/ip/fpu/FpuTest.scala | 39 ++++++++++++++-- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/src/main/scala/vexriscv/ip/fpu/FpuCore.scala b/src/main/scala/vexriscv/ip/fpu/FpuCore.scala index baa0bdd..cfe6e1c 100644 --- a/src/main/scala/vexriscv/ip/fpu/FpuCore.scala +++ b/src/main/scala/vexriscv/ip/fpu/FpuCore.scala @@ -54,11 +54,13 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ case class ShortPipInput() extends Bundle{ val source = Source() val opcode = p.Opcode() - val rs1, rs2 = p.internalFloating() + val rs2 = p.internalFloating() + val rs1Raw = Bits(widthOf(rs2) bits) val lockId = lockIdType() val rd = p.rfAddress() val value = Bits(32 bits) val arg = Bits(2 bits) + def rs1 = rs1Raw.as(p.internalFloating) } case class MulInput() extends Bundle{ @@ -242,6 +244,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ input.ready setWhen(shortPipHit && shortPip.ready) shortPip.valid := input.valid && shortPipHit shortPip.payload.assignSomeByName(read.output.payload) + shortPip.rs1Raw := read.output.rs1.asBits val divSqrtHit = input.opcode === p.Opcode.DIV || input.opcode === p.Opcode.SQRT val divSqrt = Stream(DivSqrtInput()) @@ -437,18 +440,41 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ recodedResult := recoded.sign ## f32.exp ## f32.man val isSubnormal = !recoded.special && recoded.exponent <= exponentOne - 127 - val subnormal = new Area{ - val needRecoding = List(FpuOpcode.FMV_X_W, FpuOpcode.STORE).map(_ === input.opcode).orR + val fsm = new Area{ + val f2iShift = input.rs1.exponent - U(exponentOne) + val isF2i = input.opcode === FpuOpcode.F2I + val needRecoding = List(FpuOpcode.FMV_X_W, FpuOpcode.STORE).map(_ === input.opcode).orR && isSubnormal val manTop = Reg(UInt(log2Up(p.internalMantissaSize) bits)) val counter = Reg(UInt(log2Up(p.internalMantissaSize+1) bits)) val done, boot = Reg(Bool()) - when(input.valid && needRecoding && isSubnormal && !done){ + val isZero = input.rs1.isZero// || input.rs1.exponent < exponentOne-1 + val overflow = input.rs1.exponent > (input.arg(0) ? U(exponentOne+30) | U(exponentOne+31)) && !input.rs1.sign + val underflow = input.rs1.exponent > (input.arg(0) ? U(exponentOne+30) | U(exponentOne-1)) && input.rs1.sign // && !(input.arg(0) && input.rs1.exponent === exponentOne-31 && input.rs) + + when(input.valid && (needRecoding || isF2i) && !done){ halt := True when(boot){ - manTop := (U(exponentOne - 127) - recoded.exponent).resized + when(isF2i){ + when(underflow || overflow){ + done := True + val low = overflow + val high = input.arg(0) ^ overflow + input.rs1Raw.getDrivingReg(0, 32 bits) := (31 -> high, default -> low) + } otherwise { + manTop := (U(exponentOne + 31) - input.rs1.exponent).resized //TODO merge + input.rs1Raw.getDrivingReg(0, 32 bits) := input.rs1Raw(0, 23 bits) << 9 + } + } otherwise { + manTop := (U(exponentOne - 127) - recoded.exponent).resized + } boot := False + } otherwise { - recoded.mantissa.getDrivingReg := (U(counter === 0) @@ recoded.mantissa) >> 1 + when(isF2i){ + input.rs1Raw.getDrivingReg(0, 32 bits) := (B(counter === 0 && !isZero) ## input.rs1Raw(0, 32 bits)) >> 1 + } otherwise { + input.rs1Raw.getDrivingReg(0, 23 bits) := (B(counter === 0) ## input.rs1Raw(0, 23 bits)) >> 1 + } counter := counter + 1 when(counter === manTop) { done := True @@ -483,9 +509,11 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ } - val f2iShift = input.rs1.exponent - U(exponentOne) - val f2iShifted = (U"1" @@ input.rs1.mantissa) << (f2iShift.resize(5 bits)) - val f2iUnsigned = f2iShifted >> p.internalMantissaSize +// val f2iShift = input.rs1.exponent - U(exponentOne) +// val f2iShifted = (U"1" @@ input.rs1.mantissa) << (f2iShift.resize(5 bits)) +// val f2iUnsigned = f2iShifted >> p.internalMantissaSize +// val f2iResult = (f2iUnsigned.twoComplement(input.arg(0) && input.rs1.sign)).asBits.resize(32 bits) + val f2iUnsigned = input.rs1Raw(0, 32 bits).asUInt val f2iResult = (f2iUnsigned.twoComplement(input.arg(0) && input.rs1.sign)).asBits.resize(32 bits) val bothZero = input.rs1.isZero && input.rs2.isZero @@ -839,7 +867,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ val xSigned = xMantissa.twoComplement(xSign) // val ySigned = (yMantissa +^ (yMantissa.lsb && !ySign).asUInt).twoComplement(ySign) - val ySigned = ((ySign ## Mux(ySign, ~yMantissa, yMantissa)).asUInt +^ (ySign || yMantissa.lsb).asUInt).asSInt + val ySigned = ((ySign ## Mux(ySign, ~yMantissa, yMantissa)).asUInt +^ (ySign || yMantissa.lsb).asUInt).asSInt //rounding here val xyMantissa = U(xSigned + ySigned).trim(1 bits) } diff --git a/src/test/scala/vexriscv/ip/fpu/FpuTest.scala b/src/test/scala/vexriscv/ip/fpu/FpuTest.scala index 0bfeb4c..05f27f5 100644 --- a/src/test/scala/vexriscv/ip/fpu/FpuTest.scala +++ b/src/test/scala/vexriscv/ip/fpu/FpuTest.scala @@ -422,10 +422,19 @@ class FpuTest extends FunSuite{ val rd = Random.nextInt(32) load(rs1, a) f2i(rs1, signed){rsp => - val ref = a.toInt - val v = (rsp.value.toBigInt & 0xFFFFFFFF).toInt - println(f"f2i($a) = $v, $ref") - assert(v === ref) + if(signed) { + val ref = a.toInt + val v = (rsp.value.toBigInt & 0xFFFFFFFFl).toInt + println(f"f2i($a) = $v, $ref") + if (a.abs < 1024 * 1024) assert(v == ref) + assert(checkFloat(v, ref)) + } else { + val ref = a.toLong.min(0xFFFFFFFFl) + val v = (rsp.value.toBigInt & 0xFFFFFFFFl).toLong + println(f"f2i($a) = $v, $ref") + if (a.abs < 1024 * 1024) assert(v == ref) + assert(checkFloat(v, ref)) + } } } @@ -542,6 +551,28 @@ class FpuTest extends FunSuite{ testLoadStore(1.4E-45f) testLoadStore(3.44383110592e-41f) +//TODO bring back those tests and test overflow / underflow (F2I) +// testF2i(16.0f , false) +// testF2i(18.0f , false) +// testF2i(1200.0f, false) +// testF2i(1.0f , false) +// testF2i(0.0f , false) +// testF2i(1024*1024*1024*2l , false) +// testF2i(1024*1024*4095l , false) +// testF2i(1024*1024*5000l , false) +// +// val f2iUnsigned = ((0l to 32l) ++ (4060 to 4095).map(_*1024*1024l)).map(_.toFloat) ++ List(-0.0f) +// val f2iSigned = ((-32 to 32) ++ ((2030 to 2047)++(-2047 to -2030)).map(_*1024*1024)).map(_.toFloat) ++ List(-0.0f) +// for(f <- f2iUnsigned) testF2i(f, false) +// for(f <- f2iSigned) testF2i(f, true) +// for(f <- fAll) testF2i(f, false) +// for(f <- fAll) testF2i(f, true) +// for(_ <- 0 until 1000) testF2i(Random.nextFloat(), Random.nextBoolean()) + + + + + testAdd(b2f(0x3f800000), b2f(0x3f800000-1)) testAdd(1.1f, 2.3f) testAdd(1.2f, -1.2f)