fpu i2f rounding ok

This commit is contained in:
Dolu1990 2021-02-01 16:12:38 +01:00
parent c51b0fcafe
commit a87cb202b1
2 changed files with 63 additions and 79 deletions

View File

@ -336,16 +336,6 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
output.roundMode := input.roundMode
}
// val i2fSign = input.arg(0) && input.value.msb
// val i2fUnsigned = input.value.asUInt.twoComplement(i2fSign).resize(32 bits)
// val i2fLog2 = OHToUInt(OHMasking.last(i2fUnsigned))
// val i2fShifted = (i2fUnsigned << p.internalMantissaSize) >> i2fLog2
// rfOutput.value.sign := i2fSign
// rfOutput.value.exponent := i2fLog2 +^ exponentOne
// rfOutput.value.mantissa := U(i2fShifted).resized
// rfOutput.value.special := False //TODO
val s1 = new Area{
val input = s0.output.stage()
val busy = False
@ -414,7 +404,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val i2fSign = fsm.patched
val i2fShifted = input.value.takeHigh(23)
val (i2fHigh, i2fLow) = input.value.splitAt(widthOf(input.value)-24)
val i2fShifted = i2fHigh >> 1
val i2fRound = U(i2fHigh.lsb ## (i2fLow =/= 0))
val recoded = p.internalFloating()
recoded.mantissa := f32Mantissa
@ -437,6 +429,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
output.value.exponent := (U(exponentOne+31) - fsm.manTop).resized
output.value.mantissa := U(i2fShifted)
output.value.setNormal
output.round := i2fRound
when(fsm.i2fZero) { output.value.setZero }
//TODO ROUND
}
@ -977,7 +970,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val round = new Area{
val input = merge.commited.combStage
//TODO do not break NAN payload
//TODO do not break NAN payload (seems already fine)
val manAggregate = input.value.mantissa @@ input.round
val expDif = (exponentOne-126) - input.value.exponent
val discardCount = expDif.msb ? U(0) | expDif.resize(log2Up(p.internalMantissaSize) bits)

View File

@ -39,17 +39,23 @@ class FpuTest extends FunSuite{
// config.withFstWave
config.compile(new FpuCore(portCount, p)).doSim(seed = 42){ dut =>
dut.clockDomain.forkStimulus(10)
dut.clockDomain.forkSimSpeedPrinter()
dut.clockDomain.forkSimSpeedPrinter(5.0)
class TestCase(t : String, op : String){
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -forever -${t}_$op"){
class TestCase(op : String){
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -forever -$op"){
def f32_2 ={
val l = next
val s = new Scanner(l)
(b2f(s.nextLong(16).toInt), b2f(s.nextLong(16).toInt), b2f(s.nextLong(16).toInt), s.nextInt(16))
}
def i32_f32 ={
val l = next
val s = new Scanner(l)
(s.nextLong(16).toInt, b2f(s.nextLong(16).toInt), s.nextInt(16))
}
}
val RNE = build("-rnear_even")
val RTZ = build("-rminMag")
@ -68,8 +74,11 @@ class FpuTest extends FunSuite{
}
val f32 = new {
val add = new TestCase("f32", "add")
val mul = new TestCase("f32", "mul")
val add = new TestCase("f32_add")
val mul = new TestCase("f32_mul")
val ui2f = new TestCase("ui32_to_f32")
val i2f = new TestCase("i32_to_f32")
val f2ui = new TestCase("f32_to_ui32")
}
val cpus = for(id <- 0 until portCount) yield new {
@ -240,7 +249,7 @@ class FpuTest extends FunSuite{
rspQueue += body
}
def i2f(rd : Int, value : Int, signed : Boolean): Unit ={
def i2f(rd : Int, value : Int, signed : Boolean, rounding : FpuRoundMode.E = FpuRoundMode.RNE): Unit ={
cmdQueue += {cmd =>
cmd.opcode #= cmd.opcode.spinalEnum.I2F
cmd.rs1.randomize()
@ -248,6 +257,7 @@ class FpuTest extends FunSuite{
cmd.rs3.randomize()
cmd.rd #= rd
cmd.arg #= (if(signed) 1 else 0)
cmd.roundMode #= rounding
}
commitQueue += {cmd =>
cmd.write #= true
@ -520,6 +530,19 @@ class FpuTest extends FunSuite{
}
}
def testI2fExact(a : Int, b : Float, f : Int, signed : Boolean, rounding : FpuRoundMode.E): Unit ={
val rs = new RegAllocator()
val rd = Random.nextInt(32)
i2f(rd, a, signed, rounding)
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))
}
}
def testCmp(a : Float, b : Float): Unit ={
val rs = new RegAllocator()
val rs1, rs2, rs3 = rs.allocate()
@ -624,78 +647,46 @@ class FpuTest extends FunSuite{
}
for(i <- 0 until 64){
val rounding = FpuRoundMode.RMM
val a = 24f
val b = b2f(0x3f800000+i)
val c = Clib.math.mulF32(a, b, rounding.position)
val f = 0
// for(i <- 0 until 64){
// val rounding = FpuRoundMode.RMM
// val a = 24f
// val b = b2f(0x3f800000+i)
// val c = Clib.math.mulF32(a, b, rounding.position)
// val f = 0
// testMulExact(a,b,c,f, rounding)
// }
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 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 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.mul(rounding).f32_2
testMulExact(a,b,c,f, rounding)
}
// simSuccess()
for(_ <- 0 until 1000000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.mul(rounding).f32_2
// if(!(c.abs < 1e-35f && c.abs > 0f)) testMulExact(a,b,c,f, rounding)
/*if(! (a.toDouble*b.toDouble.abs <= 2E-45)) */testMulExact(a,b,c,f, rounding)
}
// roundingModes.foreach(rounding => println(Clib.math.addF32(0.0f, 0.0f, rounding.position)))
// roundingModes.foreach(rounding => println(Clib.math.addF32(1.0f,-1.0f, rounding.position)))
println("Mul done")
for(i <- 0 until 20) println(Clib.math.addF32(b2f(0x7f000000), b2f(0x7f000000-10+i), 0))
// simSuccess()
foreachRounding(r => println(Clib.math.addF32(b2f(0x7f7fffff), b2f(0x7f7fffff),r.position)))
println("")
foreachRounding(r => println(Clib.math.addF32(2.5787021E38f, 3.4027196E38f,r.position)))
println("")
// println(Clib.math.addF32(8.0f, b2f(0xBf800000), 0))
// println(Clib.math.addF32(8.0f, b2f(0xBf800001), 0))
// println(Clib.math.addF32(8.0f, b2f(0xBf800002), 0))
// println(Clib.math.addF32(8.0f, b2f(0xBf800003), 0))
// println(Clib.math.addF32(8.0f, b2f(0xBf800004), 0))
// println(Clib.math.addF32(8.0f, b2f(0xBf800005), 0))
// println(Clib.math.addF32(8.0f, b2f(0xBf800006), 0))
// println(Clib.math.addF32(8.0f, b2f(0xBf800007), 0))
// println(Clib.math.addF32(8.0f, b2f(0xBf800008), 0))
testAdd(-5.3687091E8f, 16.249022f, FpuRoundMode.RNE)
testAdd(-5.3687091E8f, 16.0f, FpuRoundMode.RNE)
testAdd(-5.3687091E8f, 15.0f, FpuRoundMode.RNE)
for(i <- 0 until 20) testAdd(4.0f, b2f(0xBf800000 + i), FpuRoundMode.RNE)
for(i <- 0 until 64) testAdd(12.0f, b2f(0xBf801000 + i), FpuRoundMode.RNE)
for(i <- 0 until 64) testAdd(8.0f, b2f(0xBf801000 + i), FpuRoundMode.RNE)
for(i <- 0 until 64) testAdd(12.0f, b2f(0x3f801000 + i), FpuRoundMode.RNE)
for(i <- 0 until 64) testAdd(8.0f, b2f(0x3f801000 + i), FpuRoundMode.RNE)
for(i <- 0 until 20) testAdd(b2f(0x40800000+3), b2f(0xBf800000 + i+1), FpuRoundMode.RNE)
for(i <- 0 until 20) testAdd(8.0f, b2f(0xBf800000 + i), FpuRoundMode.RNE)
for(i <- 0 until 20) testAdd(16.0f, b2f(0xBf800000 + i), FpuRoundMode.RNE)
// testAdd(8.0f, b2f(0xBf800001), FpuRoundMode.RNE)
// testAdd(8.0f, b2f(0xBf800002), FpuRoundMode.RNE)
// testAdd(8.0f, b2f(0xBf800003), FpuRoundMode.RNE)
// testAdd(8.0f, b2f(0xBf800004), FpuRoundMode.RNE)
// testAddExact(-256.2578f,1.8905041f ,-254.36731f,0, FpuRoundMode.RNE)
for(_ <- 0 until 1000000){
for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.add(rounding).f32_2
// if(a.isNaN) println("Nan")
// if(b.isNaN) println("Nan")
// if(a.isInfinity) println("Inf")
// if(b.isInfinity) println("Inf")
// if(a == 0f) println("Zero")
// if(b == 0f) println("Zero")
/*if(/*a > 0 && b < 0 && */!c.isInfinity) */testAddExact(a,b,c,f, rounding)
testAddExact(a,b,c,f, rounding)
}
println("Add done")
waitUntil(cmdQueue.isEmpty)
dut.clockDomain.waitSampling(1000)
simSuccess()