mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
fpu i2f rounding ok
This commit is contained in:
parent
c51b0fcafe
commit
a87cb202b1
2 changed files with 63 additions and 79 deletions
|
@ -336,16 +336,6 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
output.roundMode := input.roundMode
|
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 s1 = new Area{
|
||||||
val input = s0.output.stage()
|
val input = s0.output.stage()
|
||||||
val busy = False
|
val busy = False
|
||||||
|
@ -414,7 +404,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
|
|
||||||
|
|
||||||
val i2fSign = fsm.patched
|
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()
|
val recoded = p.internalFloating()
|
||||||
recoded.mantissa := f32Mantissa
|
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.exponent := (U(exponentOne+31) - fsm.manTop).resized
|
||||||
output.value.mantissa := U(i2fShifted)
|
output.value.mantissa := U(i2fShifted)
|
||||||
output.value.setNormal
|
output.value.setNormal
|
||||||
|
output.round := i2fRound
|
||||||
when(fsm.i2fZero) { output.value.setZero }
|
when(fsm.i2fZero) { output.value.setZero }
|
||||||
//TODO ROUND
|
//TODO ROUND
|
||||||
}
|
}
|
||||||
|
@ -977,7 +970,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
val round = new Area{
|
val round = new Area{
|
||||||
val input = merge.commited.combStage
|
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 manAggregate = input.value.mantissa @@ input.round
|
||||||
val expDif = (exponentOne-126) - input.value.exponent
|
val expDif = (exponentOne-126) - input.value.exponent
|
||||||
val discardCount = expDif.msb ? U(0) | expDif.resize(log2Up(p.internalMantissaSize) bits)
|
val discardCount = expDif.msb ? U(0) | expDif.resize(log2Up(p.internalMantissaSize) bits)
|
||||||
|
|
|
@ -39,17 +39,23 @@ class FpuTest extends FunSuite{
|
||||||
// config.withFstWave
|
// config.withFstWave
|
||||||
config.compile(new FpuCore(portCount, p)).doSim(seed = 42){ dut =>
|
config.compile(new FpuCore(portCount, p)).doSim(seed = 42){ dut =>
|
||||||
dut.clockDomain.forkStimulus(10)
|
dut.clockDomain.forkStimulus(10)
|
||||||
dut.clockDomain.forkSimSpeedPrinter()
|
dut.clockDomain.forkSimSpeedPrinter(5.0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestCase(t : String, op : String){
|
class TestCase(op : String){
|
||||||
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -forever -${t}_$op"){
|
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -forever -$op"){
|
||||||
def f32_2 ={
|
def f32_2 ={
|
||||||
val l = next
|
val l = next
|
||||||
val s = new Scanner(l)
|
val s = new Scanner(l)
|
||||||
(b2f(s.nextLong(16).toInt), b2f(s.nextLong(16).toInt), b2f(s.nextLong(16).toInt), s.nextInt(16))
|
(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 RNE = build("-rnear_even")
|
||||||
val RTZ = build("-rminMag")
|
val RTZ = build("-rminMag")
|
||||||
|
@ -68,8 +74,11 @@ class FpuTest extends FunSuite{
|
||||||
}
|
}
|
||||||
|
|
||||||
val f32 = new {
|
val f32 = new {
|
||||||
val add = new TestCase("f32", "add")
|
val add = new TestCase("f32_add")
|
||||||
val mul = new TestCase("f32", "mul")
|
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 {
|
val cpus = for(id <- 0 until portCount) yield new {
|
||||||
|
@ -240,7 +249,7 @@ class FpuTest extends FunSuite{
|
||||||
rspQueue += body
|
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 =>
|
cmdQueue += {cmd =>
|
||||||
cmd.opcode #= cmd.opcode.spinalEnum.I2F
|
cmd.opcode #= cmd.opcode.spinalEnum.I2F
|
||||||
cmd.rs1.randomize()
|
cmd.rs1.randomize()
|
||||||
|
@ -248,6 +257,7 @@ class FpuTest extends FunSuite{
|
||||||
cmd.rs3.randomize()
|
cmd.rs3.randomize()
|
||||||
cmd.rd #= rd
|
cmd.rd #= rd
|
||||||
cmd.arg #= (if(signed) 1 else 0)
|
cmd.arg #= (if(signed) 1 else 0)
|
||||||
|
cmd.roundMode #= rounding
|
||||||
}
|
}
|
||||||
commitQueue += {cmd =>
|
commitQueue += {cmd =>
|
||||||
cmd.write #= true
|
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 ={
|
def testCmp(a : Float, b : Float): Unit ={
|
||||||
val rs = new RegAllocator()
|
val rs = new RegAllocator()
|
||||||
val rs1, rs2, rs3 = rs.allocate()
|
val rs1, rs2, rs3 = rs.allocate()
|
||||||
|
@ -624,78 +647,46 @@ class FpuTest extends FunSuite{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(i <- 0 until 64){
|
// for(i <- 0 until 64){
|
||||||
val rounding = FpuRoundMode.RMM
|
// val rounding = FpuRoundMode.RMM
|
||||||
val a = 24f
|
// val a = 24f
|
||||||
val b = b2f(0x3f800000+i)
|
// val b = b2f(0x3f800000+i)
|
||||||
val c = Clib.math.mulF32(a, b, rounding.position)
|
// val c = Clib.math.mulF32(a, b, rounding.position)
|
||||||
val f = 0
|
// 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)
|
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")
|
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 100000){
|
||||||
for(_ <- 0 until 1000000){
|
|
||||||
val rounding = FpuRoundMode.elements.randomPick()
|
val rounding = FpuRoundMode.elements.randomPick()
|
||||||
val (a,b,c,f) = f32.add(rounding).f32_2
|
val (a,b,c,f) = f32.add(rounding).f32_2
|
||||||
// if(a.isNaN) println("Nan")
|
testAddExact(a,b,c,f, rounding)
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println("Add done")
|
||||||
|
|
||||||
waitUntil(cmdQueue.isEmpty)
|
waitUntil(cmdQueue.isEmpty)
|
||||||
dut.clockDomain.waitSampling(1000)
|
dut.clockDomain.waitSampling(1000)
|
||||||
simSuccess()
|
simSuccess()
|
||||||
|
|
Loading…
Reference in a new issue