fpu now integrate f2i shifter withing the subnormal shifter

This commit is contained in:
Dolu1990 2021-01-27 12:11:30 +01:00
parent 444bcdba0a
commit 195e4c422d
2 changed files with 73 additions and 14 deletions

View File

@ -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
boot := False
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 {
recoded.mantissa.getDrivingReg := (U(counter === 0) @@ recoded.mantissa) >> 1
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 {
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)
}

View File

@ -422,10 +422,19 @@ class FpuTest extends FunSuite{
val rd = Random.nextInt(32)
load(rs1, a)
f2i(rs1, signed){rsp =>
if(signed) {
val ref = a.toInt
val v = (rsp.value.toBigInt & 0xFFFFFFFF).toInt
val v = (rsp.value.toBigInt & 0xFFFFFFFFl).toInt
println(f"f2i($a) = $v, $ref")
assert(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)