fpu added more tests for min max sqrt div

This commit is contained in:
Dolu1990 2021-01-26 12:50:23 +01:00
parent f818fb3ba4
commit 3334364f5f
3 changed files with 77 additions and 56 deletions

View File

@ -10,6 +10,7 @@ object FpuDivSqrtIterationState extends SpinalEnum{
val IDLE, YY, XYY, Y2_XYY, DIV, _15_XYY2, Y_15_XYY2, Y_15_XYY2_RESULT, SQRT = newElement() val IDLE, YY, XYY, Y2_XYY, DIV, _15_XYY2, Y_15_XYY2, Y_15_XYY2_RESULT, SQRT = newElement()
} }
//TODO cleanup rounding
case class FpuCore( portCount : Int, p : FpuParameter) extends Component{ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val io = new Bundle { val io = new Bundle {
val port = Vec(slave(FpuPort(p)), portCount) val port = Vec(slave(FpuPort(p)), portCount)
@ -396,13 +397,14 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
} }
recodedResult := recoded.sign ## f32.exp ## f32.man recodedResult := recoded.sign ## f32.exp ## f32.man
val isSubnormal = !recoded.special && recoded.exponent <= exponentOne - 127
val subnormal = new Area{ val subnormal = new Area{
val isSubnormal = !recoded.special && recoded.exponent <= exponentOne - 127 val needRecoding = List(FpuOpcode.FMV_X_W, FpuOpcode.STORE).map(_ === input.opcode).orR
val manTop = Reg(UInt(log2Up(p.internalMantissaSize) bits)) val manTop = Reg(UInt(log2Up(p.internalMantissaSize) bits))
val shift = isSubnormal ? manTop | U(0) val shift = isSubnormal ? manTop | U(0)
val counter = Reg(UInt(log2Up(p.internalMantissaSize+1) bits)) val counter = Reg(UInt(log2Up(p.internalMantissaSize+1) bits))
val done, boot = Reg(Bool()) val done, boot = Reg(Bool())
when(isSubnormal && !done){ when(needRecoding && isSubnormal && !done){
halt := True halt := True
when(boot){ when(boot){
manTop := (U(exponentOne - 127) - recoded.exponent).resized manTop := (U(exponentOne - 127) - recoded.exponent).resized
@ -453,8 +455,13 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val i2fLog2 = OHToUInt(OHMasking.last(i2fUnsigned)) val i2fLog2 = OHToUInt(OHMasking.last(i2fUnsigned))
val i2fShifted = (i2fUnsigned << p.internalMantissaSize) >> i2fLog2 val i2fShifted = (i2fUnsigned << p.internalMantissaSize) >> i2fLog2
val bothZero = input.rs1.isZero && input.rs2.isZero
val rs1Equal = input.rs1 === input.rs2 val rs1Equal = input.rs1 === input.rs2
val rs1AbsSmaller = (input.rs1.exponent @@ input.rs1.mantissa) < (input.rs2.exponent @@ input.rs2.mantissa) val rs1AbsSmaller = (input.rs1.exponent @@ input.rs1.mantissa) < (input.rs2.exponent @@ input.rs2.mantissa)
rs1AbsSmaller.setWhen(input.rs2.isInfinity)
rs1AbsSmaller.setWhen(input.rs1.isZero)
rs1AbsSmaller.clearWhen(input.rs2.isZero)
rs1AbsSmaller.clearWhen(input.rs1.isInfinity)
val rs1Smaller = (input.rs1.sign ## input.rs2.sign).mux( val rs1Smaller = (input.rs1.sign ## input.rs2.sign).mux(
0 -> rs1AbsSmaller, 0 -> rs1AbsSmaller,
1 -> False, 1 -> False,
@ -462,45 +469,19 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
3 -> (!rs1AbsSmaller && !rs1Equal) 3 -> (!rs1AbsSmaller && !rs1Equal)
) )
//TODO
// val rawToFpu = new Area{
// val f32Mantissa = input.value(0, 23 bits).asUInt
// val f32Exponent = input.value(23, 8 bits).asUInt
// val f32Sign = input.value(31)
//
// val expZero = f32Exponent === 0
// val expOne = f32Exponent === 255
// val manZero = f32Mantissa === 0
//
// val isZero = expZero && manZero
// val isSubnormal = expZero && !manZero
// val isNormal = !expOne && !expZero
// val isInfinity = expOne && manZero
// val isNan = expOne && !manZero
// val isQuiet = f32Mantissa.msb
//
// val recoded = p.internalFloating()
// recoded.mantissa := f32Mantissa
// recoded.exponent := f32Exponent
// recoded.sign := f32Sign
// recoded.setNormal
// when(isZero){recoded.setZero}
// when(isSubnormal){recoded.setSubnormal}
// when(isInfinity){recoded.setInfinity}
// when(isNan){recoded.setNan}
// }
val minMaxResult = (rs1Smaller ^ input.arg(0)) ? input.rs1 | input.rs2 val minMaxResult = ((rs1Smaller ^ input.arg(0)) && !input.rs1.isNan || input.rs2.isNan) ? input.rs1 | input.rs2
val cmpResult = B(rs1Smaller && !input.arg(1) || rs1Equal && !input.arg(0)) val cmpResult = B(rs1Smaller && !bothZero && !input.arg(1) || (rs1Equal || bothZero) && !input.arg(0))
when(input.rs1.isNan || input.rs2.isNan) { cmpResult := 0 }
val sgnjResult = (input.rs1.sign && input.arg(1)) ^ input.rs2.sign ^ input.arg(0) val sgnjResult = (input.rs1.sign && input.arg(1)) ^ input.rs2.sign ^ input.arg(0)
val fclassResult = B(0, 32 bits) val fclassResult = B(0, 32 bits)
val decoded = input.rs1.decode() val decoded = input.rs1.decode()
fclassResult(0) := input.rs1.sign && decoded.isInfinity fclassResult(0) := input.rs1.sign && decoded.isInfinity
fclassResult(1) := input.rs1.sign && decoded.isNormal fclassResult(1) := input.rs1.sign && decoded.isNormal
// fclassResult(2) := input.rs1.sign && decoded.isSubnormal //TODO fclassResult(2) := input.rs1.sign && isSubnormal //TODO
fclassResult(3) := input.rs1.sign && decoded.isZero fclassResult(3) := input.rs1.sign && decoded.isZero
fclassResult(4) := !input.rs1.sign && decoded.isZero fclassResult(4) := !input.rs1.sign && decoded.isZero
// fclassResult(5) := !input.rs1.sign && decoded.isSubnormal //TODO fclassResult(5) := !input.rs1.sign && isSubnormal //TODO
fclassResult(6) := !input.rs1.sign && decoded.isNormal fclassResult(6) := !input.rs1.sign && decoded.isNormal
fclassResult(7) := !input.rs1.sign && decoded.isInfinity fclassResult(7) := !input.rs1.sign && decoded.isInfinity
fclassResult(8) := decoded.isNan && !decoded.isQuiet fclassResult(8) := decoded.isNan && !decoded.isQuiet
@ -735,6 +716,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
decode.divSqrtToMul.rs2.sign := input.rs2.sign decode.divSqrtToMul.rs2.sign := input.rs2.sign
decode.divSqrtToMul.rs2.exponent := divExp.value + iterationValue.msb.asUInt decode.divSqrtToMul.rs2.exponent := divExp.value + iterationValue.msb.asUInt
decode.divSqrtToMul.rs2.mantissa := (iterationValue << 1).resized decode.divSqrtToMul.rs2.mantissa := (iterationValue << 1).resized
val zero = input.rs2.isInfinity
val overflow = input.rs2.isZeroOrSubnormal val overflow = input.rs2.isZeroOrSubnormal
val nan = input.rs2.isNan || (input.rs1.isZeroOrSubnormal && input.rs2.isZeroOrSubnormal) val nan = input.rs2.isNan || (input.rs1.isZeroOrSubnormal && input.rs2.isZeroOrSubnormal)
@ -742,6 +724,8 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
decode.divSqrtToMul.rs2.setNanQuiet decode.divSqrtToMul.rs2.setNanQuiet
} elsewhen(overflow) { } elsewhen(overflow) {
decode.divSqrtToMul.rs2.setInfinity decode.divSqrtToMul.rs2.setInfinity
} elsewhen(zero) {
decode.divSqrtToMul.rs2.setZero
} }
when(decode.divSqrtToMul.ready) { when(decode.divSqrtToMul.ready) {
state := IDLE state := IDLE
@ -781,6 +765,13 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
decode.divSqrtToMul.rs2.sign := False decode.divSqrtToMul.rs2.sign := False
decode.divSqrtToMul.rs2.exponent := sqrtExp.value + iterationValue.msb.asUInt decode.divSqrtToMul.rs2.exponent := sqrtExp.value + iterationValue.msb.asUInt
decode.divSqrtToMul.rs2.mantissa := (iterationValue << 1).resized decode.divSqrtToMul.rs2.mantissa := (iterationValue << 1).resized
val nan = input.rs1.sign && !input.rs1.isZero
when(nan){
decode.divSqrtToMul.rs2.setNanQuiet
}
when(decode.divSqrtToMul.ready) { when(decode.divSqrtToMul.ready) {
state := IDLE state := IDLE
input.ready := True input.ready := True
@ -985,14 +976,14 @@ object FpuSynthesisBench extends App{
val rtls = ArrayBuffer[Rtl]() val rtls = ArrayBuffer[Rtl]()
// rtls += new Fpu( rtls += new Fpu(
// "32", "32",
// portCount = 1, portCount = 1,
// FpuParameter( FpuParameter(
// internalMantissaSize = 23, internalMantissaSize = 23,
// withDouble = false withDouble = false
// ) )
// ) )
// rtls += new Fpu( // rtls += new Fpu(
// "64", // "64",
// portCount = 1, // portCount = 1,
@ -1010,10 +1001,10 @@ object FpuSynthesisBench extends App{
// rtls += new Rotate(32) // rtls += new Rotate(32)
// rtls += new Rotate(52) // rtls += new Rotate(52)
// rtls += new Rotate(64) // rtls += new Rotate(64)
rtls += new Rotate3(24) // rtls += new Rotate3(24)
rtls += new Rotate3(32) // rtls += new Rotate3(32)
rtls += new Rotate3(52) // rtls += new Rotate3(52)
rtls += new Rotate3(64) // rtls += new Rotate3(64)
val targets = XilinxStdTargets()// ++ AlteraStdTargets() val targets = XilinxStdTargets()// ++ AlteraStdTargets()

View File

@ -65,7 +65,6 @@ case class FpuFloat(exponentSize: Int,
def decode() = { def decode() = {
val ret = FpuFloatDecoded() val ret = FpuFloatDecoded()
ret.isZero := isZero ret.isZero := isZero
//ret.isSubnormal := isSubnormal
ret.isNormal := isNormal ret.isNormal := isNormal
ret.isInfinity := isInfinity ret.isInfinity := isInfinity
ret.isNan := isNan ret.isNan := isNan

View File

@ -314,7 +314,7 @@ class FpuTest extends FunSuite{
if(ref == 0.0 && dut == 0.0 && f2b(ref) != f2b(dut)) return false if(ref == 0.0 && dut == 0.0 && f2b(ref) != f2b(dut)) return false
if(ref.isNaN && dut.isNaN) return true if(ref.isNaN && dut.isNaN) return true
if(ref == dut) return true if(ref == dut) return true
if(ref.abs * 1.0001 + Float.MinPositiveValue >= dut.abs && ref.abs * 0.9999 - Float.MinPositiveValue <= dut.abs) return true if(ref.abs * 1.0001f + Float.MinPositiveValue >= dut.abs*0.9999f && ref.abs * 0.9999f - Float.MinPositiveValue <= dut.abs*1.0001f) return true
// if(ref + Float.MinPositiveValue*2.0f === dut || dut + Float.MinPositiveValue*2.0f === ref) // if(ref + Float.MinPositiveValue*2.0f === dut || dut + Float.MinPositiveValue*2.0f === ref)
false false
} }
@ -460,7 +460,10 @@ class FpuTest extends FunSuite{
load(rs1, a) load(rs1, a)
load(rs2, b) load(rs2, b)
cmp(rs1, rs2){rsp => cmp(rs1, rs2){rsp =>
val ref = if(a < b) 1 else 0 var ref = if(a < b) 1 else 0
if(a.isNaN || b.isNaN){
ref = 0
}
val v = rsp.value.toBigInt val v = rsp.value.toBigInt
println(f"$a < $b = $v, $ref") println(f"$a < $b = $v, $ref")
assert(v === ref) assert(v === ref)
@ -503,9 +506,13 @@ class FpuTest extends FunSuite{
min(rd,rs1,rs2) min(rd,rs1,rs2)
storeFloat(rd){v => storeFloat(rd){v =>
val ref = a min b val ref = (a,b) match {
case _ if a.isNaN => b
case _ if b.isNaN => a
case _ => Math.min(a,b)
}
println(f"min $a $b = $v, $ref") println(f"min $a $b = $v, $ref")
assert(ref == v) assert(f2b(ref) == f2b(v))
} }
} }
@ -535,13 +542,37 @@ class FpuTest extends FunSuite{
val fNan = List(Float.NaN, b2f(0x7f820000), b2f(0x7fc00000)) val fNan = List(Float.NaN, b2f(0x7f820000), b2f(0x7fc00000))
val fAll = fZeros ++ fSubnormals ++ fExpSmall ++ fExpNormal ++ fExpBig ++ fInfinity ++ fNan val fAll = fZeros ++ fSubnormals ++ fExpSmall ++ fExpNormal ++ fExpBig ++ fInfinity ++ fNan
testCmp(0.0f, 1.2f )
testCmp(1.2f, 0.0f )
testCmp(0.0f, -0.0f )
testCmp(-0.0f, 0.0f )
for(a <- fAll; _ <- 0 until 50) testCmp(a, randomFloat())
for(b <- fAll; _ <- 0 until 50) testCmp(randomFloat(), b)
for(a <- fAll; b <- fAll) testCmp(a, b)
for(_ <- 0 until 1000) testCmp(randomFloat(), randomFloat())
// testDiv(0.0f, 1.2f ) testMin(0.0f, 1.2f )
// testDiv(1.2f, 0.0f ) testMin(1.2f, 0.0f )
// testDiv(0.0f, 0.0f ) testMin(0.0f, -0.0f )
// for(a <- fAll; _ <- 0 until 50) testDiv(a, randomFloat()) testMin(-0.0f, 0.0f )
// for(a <- fAll; b <- fAll) testDiv(a, b) for(a <- fAll; _ <- 0 until 50) testMin(a, randomFloat())
// for(_ <- 0 until 1000) testDiv(randomFloat(), randomFloat()) for(b <- fAll; _ <- 0 until 50) testMin(randomFloat(), b)
for(a <- fAll; b <- fAll) testMin(a, b)
for(_ <- 0 until 1000) testMin(randomFloat(), randomFloat())
testSqrt(1.2f)
testSqrt(0.0f)
for(a <- fAll) testSqrt(a)
for(_ <- 0 until 1000) testSqrt(randomFloat())
testDiv(0.0f, 1.2f )
testDiv(1.2f, 0.0f )
testDiv(0.0f, 0.0f )
for(a <- fAll; _ <- 0 until 50) testDiv(a, randomFloat())
for(b <- fAll; _ <- 0 until 50) testDiv(randomFloat(), b)
for(a <- fAll; b <- fAll) testDiv(a, b)
for(_ <- 0 until 1000) testDiv(randomFloat(), randomFloat())