aboutsummaryrefslogtreecommitdiff
path: root/VexRiscv/src/test/scala/vexriscv/ip/fpu
diff options
context:
space:
mode:
Diffstat (limited to 'VexRiscv/src/test/scala/vexriscv/ip/fpu')
-rw-r--r--VexRiscv/src/test/scala/vexriscv/ip/fpu/FpuTest.scala1663
-rw-r--r--VexRiscv/src/test/scala/vexriscv/ip/fpu/Playground.scala47
2 files changed, 1710 insertions, 0 deletions
diff --git a/VexRiscv/src/test/scala/vexriscv/ip/fpu/FpuTest.scala b/VexRiscv/src/test/scala/vexriscv/ip/fpu/FpuTest.scala
new file mode 100644
index 0000000..11182ac
--- /dev/null
+++ b/VexRiscv/src/test/scala/vexriscv/ip/fpu/FpuTest.scala
@@ -0,0 +1,1663 @@
+package vexriscv.ip.fpu
+
+import java.io.File
+import java.lang
+import java.util.Scanner
+
+import org.apache.commons.io.FileUtils
+import org.scalatest.funsuite.AnyFunSuite
+import spinal.core.SpinalEnumElement
+import spinal.core.sim._
+import spinal.core._
+import spinal.lib.DoCmd
+import spinal.lib.experimental.math.Floating
+import spinal.lib.sim._
+import spinal.sim.Backend.{isMac, isWindows}
+
+import scala.collection.mutable
+import scala.collection.mutable.ArrayBuffer
+import scala.sys.process.ProcessLogger
+import scala.util.Random
+import org.scalatest.funsuite.AnyFunSuite
+
+//TODO Warning DataCache write aggregation will disable itself
+class FpuTest extends AnyFunSuite{
+
+ val b2f = lang.Float.intBitsToFloat(_)
+ val b2d = lang.Double.longBitsToDouble(_)
+ val f2b = lang.Float.floatToRawIntBits(_)
+ val d2bOffset = BigInt("10000000000000000",16)
+ def d2b(that : Double) = {
+ val l = lang.Double.doubleToRawLongBits(that)
+ var a = BigInt(l)
+ if(l < 0) {
+ a = d2bOffset + a
+ }
+ a
+ }
+
+
+ test("f32f64") {
+ val p = FpuParameter(
+ withDouble = true,
+// withAdd = false,
+// withMul = false,
+// withDivSqrt = false,
+ sim = true
+ )
+ testP(p)
+ }
+ test("f32") {
+ val p = FpuParameter(
+ withDouble = false,
+ sim = true
+ )
+ testP(p)
+ }
+
+ def testP(p : FpuParameter){
+ val portCount = 4
+
+ val config = SimConfig
+ config.allOptimisation
+// config.withFstWave
+ config.compile(new FpuCore(portCount, p){
+ for(i <- 0 until portCount) out(Bits(5 bits)).setName(s"flagAcc$i") := io.port(i).completion.flags.asBits
+ setDefinitionName("FpuCore"+ (if(p.withDouble) "Double" else ""))
+ }).doSim(seed = 42){ dut =>
+ dut.clockDomain.forkStimulus(10)
+ dut.clockDomain.forkSimSpeedPrinter(5.0)
+
+
+ class TestCase(op : String){
+ def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -tininessafter -forever -$op"){
+ def f32_f32_f32 ={
+ val s = new Scanner(next)
+ val a,b,c = (s.nextLong(16).toInt)
+ (b2f(a), b2f(b), b2f(c), s.nextInt(16))
+ }
+
+ def i32_f32 ={
+ val s = new Scanner(next)
+ (s.nextLong(16).toInt, b2f(s.nextLong(16).toInt), s.nextInt(16))
+ }
+
+ def f32_i32 = {
+ val s = new Scanner(next)
+ (b2f(s.nextLong(16).toInt), s.nextLong(16).toInt, s.nextInt(16))
+ }
+
+ def f32_f32_i32 = {
+ val s = new Scanner(next)
+ val a,b,c = (s.nextLong(16).toInt)
+ (b2f(a), b2f(b), c, s.nextInt(16))
+ }
+
+ def f32_f32 = {
+ val s = new Scanner(next)
+ val a,b = (s.nextLong(16).toInt)
+ (b2f(a), b2f(b), s.nextInt(16))
+ }
+
+
+ def nextLong(s : Scanner) : Long = java.lang.Long.parseUnsignedLong( s.next(),16)
+
+ def f64_f64_f64 ={
+ val s = new Scanner(next)
+ val a,b,c = nextLong(s)
+ (b2d(a), b2d(b), b2d(c), s.nextInt(16))
+ }
+
+ def i32_f64 ={
+ val s = new Scanner(next)
+ (s.nextLong(16).toInt, b2d(nextLong(s)), s.nextInt(16))
+ }
+
+ def f64_i32 = {
+ val s = new Scanner(next)
+ (b2d(nextLong(s)), s.nextLong(16).toInt, s.nextInt(16))
+ }
+
+ def f64_f64_i32 = {
+ val str = next
+ val s = new Scanner(str)
+ val a,b = (nextLong(s))
+ (b2d(a), b2d(b), s.nextInt(16), s.nextInt(16))
+ }
+
+ def f64_f64 = {
+ val s = new Scanner(next)
+ val a,b = nextLong(s)
+ (b2d(a), b2d(b), s.nextInt(16))
+ }
+
+
+ def f32_f64_i32 = {
+ val s = new Scanner(next)
+ val a,b = nextLong(s)
+ (b2f(a.toInt), b2d(b), s.nextInt(16))
+ }
+ def f64_f32_i32 = {
+ val s = new Scanner(next)
+ val a,b = nextLong(s)
+ (b2d(a), b2f(b.toInt), s.nextInt(16))
+ }
+ }
+ lazy val RAW = build("")
+ lazy val RNE = build("-rnear_even")
+ lazy val RTZ = build("-rminMag")
+ lazy val RDN = build("-rmin")
+ lazy val RUP = build("-rmax")
+ lazy val RMM = build("-rnear_maxMag")
+ lazy val all = List(RNE, RTZ, RDN, RUP, RMM, RAW)
+ def kill = all.foreach(_.kill)
+ def apply(rounding : FpuRoundMode.E) = rounding match {
+ case FpuRoundMode.RNE => RNE
+ case FpuRoundMode.RTZ => RTZ
+ case FpuRoundMode.RDN => RDN
+ case FpuRoundMode.RUP => RUP
+ case FpuRoundMode.RMM => RMM
+ }
+ }
+
+ class TestVector(f : String) {
+ val add = new TestCase(s"${f}_add")
+ val sub = new TestCase(s"${f}_sub")
+ val mul = new TestCase(s"${f}_mul")
+ val ui2f = new TestCase(s"ui32_to_${f}")
+ val i2f = new TestCase(s"i32_to_${f}")
+ val f2ui = new TestCase(s"${f}_to_ui32 -exact")
+ val f2i = new TestCase(s"${f}_to_i32 -exact")
+ val eq = new TestCase(s"${f}_eq")
+ val lt = new TestCase(s"${f}_lt")
+ val le = new TestCase(s"${f}_le")
+ val min = new TestCase(s"${f}_le")
+ val max = new TestCase(s"${f}_lt")
+ val transfer = new TestCase(s"${f}_eq")
+ val fclass = new TestCase(s"${f}_eq")
+ val sgnj = new TestCase(s"${f}_eq")
+ val sgnjn = new TestCase(s"${f}_eq")
+ val sgnjx = new TestCase(s"${f}_eq")
+ val sqrt = new TestCase(s"${f}_sqrt")
+ val div = new TestCase(s"${f}_div")
+ }
+
+ val f32 = new TestVector("f32"){
+ val f64 = new TestCase(s"f32_eq")
+ val cvt64 = new TestCase(s"f32_to_f64")
+ }
+ val f64 = new TestVector("f64"){
+ val f32 = new TestCase(s"f64_eq")
+ val cvt32 = new TestCase(s"f64_to_f32")
+ }
+
+ val cpus = for(id <- 0 until portCount) yield new {
+ val cmdQueue = mutable.Queue[FpuCmd => Unit]()
+ val commitQueue = mutable.Queue[FpuCommit => Unit]()
+ val rspQueue = mutable.Queue[FpuRsp => Unit]()
+
+ var pendingMiaou = 0
+ var flagAccumulator = 0
+
+ def cmdAdd(body : FpuCmd => Unit): Unit ={
+ pendingMiaou += 1
+ cmdQueue += body
+ }
+
+ def softAssert(cond : Boolean, msg : String) = if(!cond)println(msg)
+ def flagMatch(ref : Int, value : Float, report : String): Unit ={
+ val patch = if(value.abs == 1.17549435E-38f && false) 0x1f & ~2 else 0x1f
+ flagMatch(ref, report, patch)
+ }
+
+ def flagMatch(ref : Int, value : Double, report : String): Unit ={
+ val patch = if(value.abs == b2d(1 << 52) && false) 0x1f & ~2 else 0x1f
+ flagMatch(ref, report, patch)
+ }
+
+ def flagMatch(ref : Int, report : String, mask : Int = 0x1f): Unit ={
+ waitUntil(pendingMiaou == 0)
+ assert((flagAccumulator & mask) == (ref & mask), s"Flag missmatch dut=$flagAccumulator ref=$ref $report")
+ flagAccumulator = 0
+ }
+ def flagClear(): Unit ={
+ waitUntil(pendingMiaou == 0)
+ flagAccumulator = 0
+ }
+
+ val flagAggregated = dut.reflectBaseType(s"flagAcc$id").asInstanceOf[Bits]
+ dut.clockDomain.onSamplings{
+ val c = dut.io.port(id).completion
+ if(c.valid.toBoolean) {
+ pendingMiaou -= 1
+ flagAccumulator |= flagAggregated.toInt
+ }
+ dut.writeback.randomSim.randomize()
+ }
+
+ StreamDriver(dut.io.port(id).cmd ,dut.clockDomain){payload =>
+ if(cmdQueue.isEmpty) false else {
+ cmdQueue.dequeue().apply(payload)
+ true
+ }
+ }
+
+
+ StreamMonitor(dut.io.port(id)rsp, dut.clockDomain){payload =>
+ pendingMiaou -= 1
+ if(payload.NV.toBoolean) flagAccumulator |= 1 << 4
+ if(payload.NX.toBoolean) flagAccumulator |= 1 << 0
+ rspQueue.dequeue().apply(payload)
+ }
+
+ StreamReadyRandomizer(dut.io.port(id).rsp, dut.clockDomain)
+
+
+ StreamDriver(dut.io.port(id).commit ,dut.clockDomain){payload =>
+ if(commitQueue.isEmpty) false else {
+ commitQueue.dequeue().apply(payload)
+ true
+ }
+ }
+
+
+
+
+ def loadRaw(rd : Int, value : BigInt, format : FpuFormat.E): Unit ={
+ cmdAdd {cmd =>
+ cmd.opcode #= cmd.opcode.spinalEnum.LOAD
+ cmd.rs1.randomize()
+ cmd.rs2.randomize()
+ cmd.rs3.randomize()
+ cmd.rd #= rd
+ cmd.arg.randomize()
+ cmd.roundMode.randomize()
+ cmd.format #= format
+ }
+ commitQueue += {cmd =>
+ cmd.write #= true
+ cmd.rd #= rd
+ cmd.value #= value
+ cmd.opcode #= cmd.opcode.spinalEnum.LOAD
+ }
+ }
+
+
+ def load(rd : Int, value : Float): Unit ={
+ loadRaw(rd, f2b(value).toLong & 0xFFFFFFFFl, FpuFormat.FLOAT)
+ }
+
+ def load(rd : Int, value : Double): Unit ={
+ loadRaw(rd, d2b(value), FpuFormat.DOUBLE)
+ }
+
+ def storeRaw(rs : Int, format : FpuFormat.E)(body : FpuRsp => Unit): Unit ={
+ cmdAdd {cmd =>
+ cmd.opcode #= cmd.opcode.spinalEnum.STORE
+ cmd.rs1.randomize()
+ cmd.rs2 #= rs
+ cmd.rs3.randomize()
+ cmd.rd.randomize()
+ cmd.arg.randomize()
+ cmd.roundMode.randomize()
+ cmd.format #= format
+ }
+
+ rspQueue += body
+// waitUntil(rspQueue.isEmpty)
+ }
+
+ def storeFloat(rs : Int)(body : Float => Unit): Unit ={
+ storeRaw(rs, FpuFormat.FLOAT){rsp => body(b2f(rsp.value.toBigInt.toInt))}
+ }
+ def store(rs : Int)(body : Double => Unit): Unit ={
+ storeRaw(rs, FpuFormat.DOUBLE){rsp => body(b2d(rsp.value.toBigInt.toLong))}
+ }
+
+ def fpuF2f(rd : Int, rs1 : Int, rs2 : Int, rs3 : Int, opcode : FpuOpcode.E, arg : Int, rounding : FpuRoundMode.E, format : FpuFormat.E): Unit ={
+ cmdAdd {cmd =>
+ cmd.opcode #= opcode
+ cmd.rs1 #= rs1
+ cmd.rs2 #= rs2
+ cmd.rs3 #= rs3
+ cmd.rd #= rd
+ cmd.arg #= arg
+ cmd.roundMode #= rounding
+ cmd.format #= format
+ }
+ commitQueue += {cmd =>
+ cmd.write #= true
+ cmd.rd #= rd
+ cmd.opcode #= opcode
+ }
+ }
+
+ def fpuF2i(rs1 : Int, rs2 : Int, opcode : FpuOpcode.E, arg : Int, rounding : FpuRoundMode.E, format : FpuFormat.E)(body : FpuRsp => Unit): Unit ={
+ cmdAdd {cmd =>
+ cmd.opcode #= opcode
+ cmd.rs1 #= rs1
+ cmd.rs2 #= rs2
+ cmd.rs3.randomize()
+ cmd.rd.randomize()
+ cmd.arg #= arg
+ cmd.roundMode #= rounding
+ cmd.format #= format
+ }
+ rspQueue += body
+ }
+
+
+ def mul(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E, format : FpuFormat.E): Unit ={
+ fpuF2f(rd, rs1, rs2, Random.nextInt(32), FpuOpcode.MUL, 0, rounding, format)
+ }
+
+ def add(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = FpuRoundMode.RNE, format : FpuFormat.E): Unit ={
+ fpuF2f(rd, rs1, rs2, Random.nextInt(32), FpuOpcode.ADD, 0, rounding, format)
+ }
+
+ def sub(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = FpuRoundMode.RNE, format : FpuFormat.E): Unit ={
+ fpuF2f(rd, rs1, rs2, Random.nextInt(32), FpuOpcode.ADD, 1, rounding, format)
+ }
+
+ def div(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = FpuRoundMode.RNE, format : FpuFormat.E): Unit ={
+ fpuF2f(rd, rs1, rs2, Random.nextInt(32), FpuOpcode.DIV, Random.nextInt(4), rounding, format)
+ }
+
+ def sqrt(rd : Int, rs1 : Int, rounding : FpuRoundMode.E = FpuRoundMode.RNE, format : FpuFormat.E): Unit ={
+ fpuF2f(rd, rs1, Random.nextInt(32), Random.nextInt(32), FpuOpcode.SQRT, Random.nextInt(4), rounding, format)
+ }
+
+ def fma(rd : Int, rs1 : Int, rs2 : Int, rs3 : Int, rounding : FpuRoundMode.E, format : FpuFormat.E): Unit ={
+ fpuF2f(rd, rs1, rs2, rs3, FpuOpcode.FMA, 0, rounding, format)
+ }
+
+ def sgnjRaw(rd : Int, rs1 : Int, rs2 : Int, arg : Int, format : FpuFormat.E): Unit ={
+ fpuF2f(rd, rs1, rs2, Random.nextInt(32), FpuOpcode.SGNJ, arg, FpuRoundMode.elements.randomPick(), format)
+ }
+
+ def sgnj(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = null, format : FpuFormat.E): Unit ={
+ sgnjRaw(rd, rs1, rs2, 0, format)
+ }
+ def sgnjn(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = null, format : FpuFormat.E): Unit ={
+ sgnjRaw(rd, rs1, rs2, 1, format)
+ }
+ def sgnjx(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = null, format : FpuFormat.E): Unit ={
+ sgnjRaw(rd, rs1, rs2, 2, format)
+ }
+
+ def cmp(rs1 : Int, rs2 : Int, arg : Int, format : FpuFormat.E)(body : FpuRsp => Unit): Unit ={
+ fpuF2i(rs1, rs2, FpuOpcode.CMP, arg, FpuRoundMode.elements.randomPick(), format)(body)
+ }
+
+ def f2i(rs1 : Int, signed : Boolean, rounding : FpuRoundMode.E, format : FpuFormat.E)(body : FpuRsp => Unit): Unit ={
+ fpuF2i(rs1, Random.nextInt(32), FpuOpcode.F2I, if(signed) 1 else 0, rounding, format)(body)
+ }
+
+ def i2f(rd : Int, value : Int, signed : Boolean, rounding : FpuRoundMode.E, format : FpuFormat.E): Unit ={
+ cmdAdd {cmd =>
+ cmd.opcode #= cmd.opcode.spinalEnum.I2F
+ cmd.rs1.randomize()
+ cmd.rs2.randomize()
+ cmd.rs3.randomize()
+ cmd.rd #= rd
+ cmd.arg #= (if(signed) 1 else 0)
+ cmd.roundMode #= rounding
+ cmd.format #= format
+ }
+ commitQueue += {cmd =>
+ cmd.write #= true
+ cmd.rd #= rd
+ cmd.opcode #= FpuOpcode.I2F
+ cmd.value #= value.toLong & 0xFFFFFFFFl
+ }
+ }
+
+ def fmv_x_w(rs1 : Int)(body : Float => Unit): Unit ={
+ cmdAdd {cmd =>
+ cmd.opcode #= cmd.opcode.spinalEnum.FMV_X_W
+ cmd.rs1 #= rs1
+ cmd.rs2.randomize()
+ cmd.rs3.randomize()
+ cmd.rd.randomize()
+ cmd.arg #= 0
+ cmd.roundMode.randomize()
+ cmd.format #= FpuFormat.FLOAT
+ }
+ rspQueue += {rsp => body(b2f(rsp.value.toBigInt.toInt))}
+ }
+
+ def fmv_w_x(rd : Int, value : Int): Unit ={
+ cmdAdd {cmd =>
+ cmd.opcode #= cmd.opcode.spinalEnum.FMV_W_X
+ cmd.rs1.randomize()
+ cmd.rs2.randomize()
+ cmd.rs3.randomize()
+ cmd.rd #= rd
+ cmd.arg #= 0
+ cmd.roundMode.randomize()
+ cmd.format #= FpuFormat.FLOAT
+ }
+ commitQueue += {cmd =>
+ cmd.write #= true
+ cmd.rd #= rd
+ cmd.opcode #= FpuOpcode.FMV_W_X
+ cmd.value #= value.toLong & 0xFFFFFFFFl
+ }
+ }
+
+ def minMax(rd : Int, rs1 : Int, rs2 : Int, arg : Int, format : FpuFormat.E): Unit ={
+ cmdAdd {cmd =>
+ cmd.opcode #= cmd.opcode.spinalEnum.MIN_MAX
+ cmd.rs1 #= rs1
+ cmd.rs2 #= rs2
+ cmd.rs3.randomize()
+ cmd.rd #= rd
+ cmd.arg #= arg
+ cmd.roundMode.randomize()
+ cmd.format #= format
+ }
+ commitQueue += {cmd =>
+ cmd.write #= true
+ cmd.rd #= rd
+ cmd.opcode #= FpuOpcode.MIN_MAX
+ }
+ }
+
+
+
+ def fclass(rs1 : Int, format : FpuFormat.E)(body : Int => Unit) : Unit = {
+ cmdAdd {cmd =>
+ cmd.opcode #= FpuOpcode.FCLASS
+ cmd.rs1 #= rs1
+ cmd.rs2.randomize()
+ cmd.rs3.randomize()
+ cmd.rd.randomize()
+ cmd.arg.randomize()
+ cmd.roundMode.randomize()
+ cmd.format #= format
+ }
+ rspQueue += {rsp => body(rsp.value.toBigInt.toInt)}
+ }
+ }
+
+
+
+
+
+ val stim = for(cpu <- cpus) yield fork {
+ import cpu._
+
+ class RegAllocator(){
+ var value = 0
+
+ def allocate(): Int ={
+ while(true){
+ val rand = Random.nextInt(32)
+ val mask = 1 << rand
+ if((value & mask) == 0) {
+ value |= mask
+ return rand
+ }
+ }
+ 0
+ }
+ }
+ def checkFloat(ref : Float, dut : Float): Boolean ={
+ if((f2b(ref) & 0x80000000) != (f2b(dut) & 0x80000000)) return false
+ if(ref == 0.0 && dut == 0.0 && f2b(ref) != f2b(dut)) return false
+ if(ref.isNaN && dut.isNaN) return true
+ if(ref == dut) 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)
+ false
+ }
+
+ def checkDouble(ref : Double, dut : Double): Boolean ={
+ if((d2b(ref) & Long.MinValue) != (d2b(dut) & Long.MinValue)) return false
+ if(ref == 0.0 && dut == 0.0 && d2b(ref) != d2b(dut)) return false
+ if(ref.isNaN && dut.isNaN) return true
+ if(ref == dut) return true
+ if(ref.abs * 1.0001 + Float.MinPositiveValue >= dut.abs*0.9999 && ref.abs * 0.9999 - Double.MinPositiveValue <= dut.abs*1.0001) return true
+ // if(ref + Float.MinPositiveValue*2.0f === dut || dut + Float.MinPositiveValue*2.0f === ref)
+ false
+ }
+ def checkFloatExact(ref : Float, dut : Float): Boolean ={
+ if(ref.signum != dut.signum === dut) return false
+ if(ref.isNaN && dut.isNaN) return true
+ if(ref == dut) return true
+ false
+ }
+
+
+ def randomFloat(): Float ={
+ val exp = Random.nextInt(10)-5
+ (Random.nextDouble() * (Math.pow(2.0, exp)) * (if(Random.nextBoolean()) -1.0 else 1.0)).toFloat
+ }
+
+ def randomDouble(): Double ={
+ val exp = Random.nextInt(10)-5
+ (Random.nextDouble() * (Math.pow(2.0, exp)) * (if(Random.nextBoolean()) -1.0 else 1.0))
+ }
+
+
+ def testBinaryOp(op : (Int,Int,Int,FpuRoundMode.E, FpuFormat.E) => Unit, a : Float, b : Float, ref : Float, flag : Int, rounding : FpuRoundMode.E, opName : String): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2, rs3 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+ load(rs2, b)
+ op(rd,rs1,rs2, rounding, FpuFormat.FLOAT)
+ storeFloat(rd){v =>
+ assert(f2b(v) == f2b(ref), f"## ${a} ${opName} $b = $v, $ref $rounding")
+ }
+
+ flagMatch(flag, ref, f"## ${opName} ${a} $b $ref $rounding")
+ }
+
+
+ def testBinaryOpF64(op : (Int,Int,Int,FpuRoundMode.E, FpuFormat.E) => Unit, a : Double, b : Double, ref : Double, flag : Int, rounding : FpuRoundMode.E, opName : String): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2, rs3 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+ load(rs2, b)
+ op(rd,rs1,rs2, rounding, FpuFormat.DOUBLE)
+ store(rd){v =>
+ assert(d2b(v) == d2b(ref), f"## ${a} ${opName} $b = $v, $ref $rounding, ${d2b(a).toString(16)} ${d2b(b).toString(16)} ${d2b(ref).toString(16)}")
+ }
+
+ flagMatch(flag, ref, f"## ${opName} ${a} $b $ref $rounding")
+ }
+
+
+ def testTransferF32Raw(a : Float, iSrc : Boolean, iDst : Boolean): Unit ={
+ val rd = Random.nextInt(32)
+
+ def handle(v : Float): Unit ={
+ val ref = a
+ assert(f2b(v) == f2b(ref), f"$a = $v, $ref")
+ }
+
+ if(iSrc) fmv_w_x(rd, f2b(a)) else load(rd, a)
+ if(iDst) fmv_x_w(rd)(handle) else storeFloat(rd)(handle)
+
+ flagMatch(0, f"$a")
+ }
+
+
+ def testTransferF64Raw(a : Double): Unit ={
+ val rd = Random.nextInt(32)
+
+ def handle(v : Double): Unit ={
+ val ref = a
+ assert(d2b(v) == d2b(ref), f"$a = $v, $ref")
+ }
+
+ load(rd, a)
+ store(rd)(handle)
+
+ flagMatch(0, f"$a")
+ }
+
+ def testTransferF32F64Raw(a : Float, iSrc : Boolean): Unit ={
+ val rd = Random.nextInt(32)
+ if(iSrc) fmv_w_x(rd, f2b(a)) else load(rd, a)
+ storeRaw(rd, FpuFormat.DOUBLE){rsp =>
+ val v = rsp.value.toBigInt.toLong
+ val ref = (0xFFFFFFFFl << 32) | f2b(a)
+ assert(v == ref, f"$a = $v, $ref")
+ }
+ flagMatch(0, f"$a")
+ }
+
+ def testTransferF64F32Raw(a : Double, iDst : Boolean): Unit ={
+ val rd = Random.nextInt(32)
+ load(rd, a)
+ if(iDst)fmv_x_w(rd){v_ =>
+ val v = f2b(v_).toLong & 0xFFFFFFFFl
+ val ref = d2b(a) & 0xFFFFFFFFl
+ assert(v == ref, f"$a = $v, $ref")
+ }
+ else storeRaw(rd, FpuFormat.FLOAT){rsp =>
+ val v = rsp.value.toBigInt.toLong & 0xFFFFFFFFl
+ val ref = d2b(a) & 0xFFFFFFFFl
+ assert(v == ref, f"$a = $v, $ref")
+ }
+ flagMatch(0, f"$a")
+ }
+
+
+ def testCvtF32F64Raw(a : Float, ref : Double, flag : Int, rounding : FpuRoundMode.E): Unit ={
+ val rs, rd = Random.nextInt(32)
+ load(rs, a)
+ fpuF2f(rd, rs, Random.nextInt(32), Random.nextInt(32), FpuOpcode.FCVT_X_X, Random.nextInt(3), rounding, FpuFormat.FLOAT)
+ store(rd){v =>
+ assert(d2b(v) == d2b(ref), f"testCvtF32F64Raw $a $ref $rounding")
+ }
+ flagMatch(flag,ref, f"testCvtF32F64Raw $a $ref $rounding")
+ }
+
+ def testCvtF64F32Raw(a : Double, ref : Float, flag : Int, rounding : FpuRoundMode.E): Unit ={
+ val rs, rd = Random.nextInt(32)
+ load(rs, a)
+ fpuF2f(rd, rs, Random.nextInt(32), Random.nextInt(32), FpuOpcode.FCVT_X_X, Random.nextInt(3), rounding, FpuFormat.DOUBLE)
+ storeFloat(rd){v =>
+ assert(d2b(v) == d2b(ref), f"testCvtF64F32Raw $a $ref $rounding")
+ }
+ flagMatch(flag, ref, f"testCvtF64F32Raw $a $ref $rounding")
+ }
+
+
+ def testClassRaw(a : Float) : Unit = {
+ val rd = Random.nextInt(32)
+
+
+ load(rd, a)
+ fclass(rd, FpuFormat.FLOAT){v =>
+ val mantissa = f2b(a) & 0x7FFFFF
+ val exp = (f2b(a) >> 23) & 0xFF
+ val sign = (f2b(a) >> 31) & 0x1
+
+ val refBit = if(a.isInfinite) (if(sign == 0) 7 else 0)
+ else if(a.isNaN) (if((mantissa >> 22) != 0) 9 else 8)
+ else if(exp == 0 && mantissa != 0) (if(sign == 0) 5 else 2)
+ else if(exp == 0 && mantissa == 0) (if(sign == 0) 4 else 3)
+ else if(sign == 0) 6 else 1
+
+ val ref = 1 << refBit
+
+ assert(v == ref, f"fclass $a")
+ }
+ }
+
+
+ def testClassF64Raw(a : Double) : Unit = {
+ val rd = Random.nextInt(32)
+
+
+ load(rd, a)
+ fclass(rd, FpuFormat.DOUBLE){v =>
+ val mantissa = d2b(a) & 0x000FFFFFFFFFFFFFl
+ val exp = (d2b(a) >> 52) & 0x7FF
+ val sign = (d2b(a) >> 63) & 0x1
+
+ val refBit = if(a.isInfinite) (if(sign == 0) 7 else 0)
+ else if(a.isNaN) (if((mantissa >> 51) != 0) 9 else 8)
+ else if(exp == 0 && mantissa != 0) (if(sign == 0) 5 else 2)
+ else if(exp == 0 && mantissa == 0) (if(sign == 0) 4 else 3)
+ else if(sign == 0) 6 else 1
+
+ val ref = 1 << refBit
+
+ assert(v == ref, f"fclass $a")
+ }
+ }
+
+
+
+ def testFmaRaw(a : Float, b : Float, c : Float): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2, rs3 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+ load(rs2, b)
+ load(rs3, c)
+
+ fma(rd,rs1,rs2,rs3, FpuRoundMode.RNE, FpuFormat.FLOAT)
+ storeFloat(rd){v =>
+ val ref = a.toDouble * b.toDouble + c.toDouble
+ val mul = a.toDouble * b.toDouble
+ if((mul.abs-c.abs)/mul.abs > 0.1) assert(checkFloat(ref.toFloat, v), f"$a%.20f * $b%.20f + $c%.20f = $v%.20f, $ref%.20f")
+ }
+ }
+
+
+
+ def testFmaF64Raw(a : Double, b : Double, c : Double): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2, rs3 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+ load(rs2, b)
+ load(rs3, c)
+
+ fma(rd,rs1,rs2,rs3, FpuRoundMode.RNE, FpuFormat.DOUBLE)
+ store(rd){v =>
+ val ref = a.toDouble * b.toDouble + c.toDouble
+ val mul = a.toDouble * b.toDouble
+ if((mul.abs-c.abs)/mul.abs > 0.1) assert(checkDouble(ref, v), f"$a%.20f * $b%.20f + $c%.20f = $v%.20f, $ref%.20f")
+ }
+ }
+
+ def testSqrtF64Exact(a : Double, ref : Double, flag : Int, rounding : FpuRoundMode.E): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2, rs3 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+
+ sqrt(rd,rs1, rounding, FpuFormat.DOUBLE)
+
+ store(rd){v =>
+ assert(d2b(v) == d2b(ref), f"## sqrt${a} = $v, $ref $rounding, ${d2b(a).toString(16)} ${d2b(ref).toString(16)}")
+ }
+
+ flagMatch(flag, ref, f"## sqrt${a} $ref $rounding")
+ }
+
+ def testSqrtExact(a : Float, ref : Float, flag : Int, rounding : FpuRoundMode.E): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2, rs3 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+
+ sqrt(rd,rs1, rounding, FpuFormat.FLOAT)
+
+ storeFloat(rd){v =>
+ assert(d2b(v) == d2b(ref), f"## sqrt${a} = $v, $ref $rounding, ${f2b(a).toString()} ${f2b(ref).toString()}")
+ }
+
+ flagMatch(flag, ref, f"## sqrt${a} $ref $rounding")
+ }
+
+
+ def testF2iExact(a : Float, ref : Int, flag : Int, signed : Boolean, rounding : FpuRoundMode.E): Unit ={
+ val rs = new RegAllocator()
+ val rs1 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+ f2i(rs1, signed, rounding, FpuFormat.FLOAT){rsp =>
+ if(signed) {
+ val v = rsp.value.toBigInt.toInt
+ var ref2 = ref
+ if(a >= Int.MaxValue) ref2 = Int.MaxValue
+ if(a <= Int.MinValue) ref2 = Int.MinValue
+ if(a.isNaN) ref2 = Int.MaxValue
+ assert(v == (ref2), f" <= f2i($a) = $v, $ref2, $rounding, $flag")
+ } else {
+ val v = rsp.value.toBigInt.toLong & 0xFFFFFFFFl
+ var ref2 = ref.toLong & 0xFFFFFFFFl
+ if(a < 0) ref2 = 0
+ if(a >= 0xFFFFFFFFl) ref2 = 0xFFFFFFFFl
+ if(a.isNaN) ref2 = 0xFFFFFFFFl
+ assert(v == ref2, f" <= f2ui($a) = $v, $ref2, $rounding $flag")
+ }
+ }
+
+ flagMatch(flag, ref, f" f2${if(signed) "" else "u"}i($a) $ref $flag $rounding")
+ }
+
+
+
+ def testF642iExact(a : Double, ref : Int, flag : Int, signed : Boolean, rounding : FpuRoundMode.E): Unit ={
+ val rs = new RegAllocator()
+ val rs1 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+ f2i(rs1, signed, rounding, FpuFormat.DOUBLE){rsp =>
+ if(signed) {
+ val v = rsp.value.toBigInt.toInt
+ var ref2 = ref
+ if(a >= Int.MaxValue) ref2 = Int.MaxValue
+ if(a <= Int.MinValue) ref2 = Int.MinValue
+ if(a.isNaN) ref2 = Int.MaxValue
+ assert(v == (ref2), f" <= f2i($a) = $v, $ref2, $rounding, $flag")
+ } else {
+ val v = rsp.value.toBigInt.toLong & 0xFFFFFFFFl
+ var ref2 = ref.toLong & 0xFFFFFFFFl
+ if(a < 0) ref2 = 0
+ if(a >= 0xFFFFFFFFl) ref2 = 0xFFFFFFFFl
+ if(a.isNaN) ref2 = 0xFFFFFFFFl
+ assert(v == ref2, f" <= f2ui($a) = $v, $ref2, $rounding $flag")
+ }
+ }
+
+ flagMatch(flag, ref, f" f2${if(signed) "" else "u"}i($a) $ref $flag $rounding")
+ }
+
+
+
+ def testI2fExact(a : Int, ref : Float, f : Int, signed : Boolean, rounding : FpuRoundMode.E): Unit ={
+ val rs = new RegAllocator()
+ val rd = Random.nextInt(32)
+ i2f(rd, a, signed, rounding, FpuFormat.FLOAT)
+ storeFloat(rd){v =>
+ val aLong = if(signed) a.toLong else a.toLong & 0xFFFFFFFFl
+ assert(f2b(v) == f2b(ref), f"i2f($aLong) = $v, $ref $rounding")
+ }
+
+
+ flagMatch(f, ref, f"i2f($a) = $ref")
+ }
+
+
+
+ def testI2f64Exact(a : Int, ref : Double, f : Int, signed : Boolean, rounding : FpuRoundMode.E): Unit ={
+ val rs = new RegAllocator()
+ val rd = Random.nextInt(32)
+ i2f(rd, a, signed, rounding, FpuFormat.DOUBLE)
+ store(rd){v =>
+ val aLong = if(signed) a.toLong else a.toLong & 0xFFFFFFFFl
+ assert(d2b(v) == d2b(ref), f"i2f($aLong) = $v, $ref $rounding")
+ }
+
+
+ flagMatch(f, ref, f"i2f($a) = $ref")
+ }
+
+
+ def testCmpExact(a : Float, b : Float, ref : Int, flag : Int, arg : Int): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2, rs3 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+ load(rs2, b)
+ cmp(rs1, rs2, arg, FpuFormat.FLOAT){rsp =>
+ val v = rsp.value.toBigInt.toInt
+ assert(v === ref, f"cmp($a, $b, $arg) = $v, $ref")
+ }
+ flagMatch(flag,f"$a < $b $ref $flag ${f2b(a).toHexString} ${f2b(b).toHexString}")
+ }
+ def testLeRaw(a : Float, b : Float, ref : Int, flag : Int) = testCmpExact(a,b,ref,flag, 0)
+ def testEqRaw(a : Float, b : Float, ref : Int, flag : Int) = testCmpExact(a,b,ref,flag, 2)
+ def testLtRaw(a : Float, b : Float, ref : Int, flag : Int) = testCmpExact(a,b,ref,flag, 1)
+
+
+ def testCmpF64Exact(a : Double, b : Double, ref : Int, flag : Int, arg : Int): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2, rs3 = rs.allocate()
+ val rd = Random.nextInt(32)
+ load(rs1, a)
+ load(rs2, b)
+ cmp(rs1, rs2, arg, FpuFormat.DOUBLE){rsp =>
+ val v = rsp.value.toBigInt.toInt
+ assert(v === ref, f"cmp($a, $b, $arg) = $v, $ref")
+ }
+ flagMatch(flag,f"$a < $b $ref $flag ${d2b(a)} ${d2b(b)}")
+ }
+ def testLeF64Raw(a : Double, b : Double, ref : Int, flag : Int) = testCmpF64Exact(a,b,ref,flag, 0)
+ def testEqF64Raw(a : Double, b : Double, ref : Int, flag : Int) = testCmpF64Exact(a,b,ref,flag, 2)
+ def testLtF64Raw(a : Double, b : Double, ref : Int, flag : Int) = testCmpF64Exact(a,b,ref,flag, 1)
+
+// def testFmv_x_w(a : Float): Unit ={
+// val rs = new RegAllocator()
+// val rs1, rs2, rs3 = rs.allocate()
+// val rd = Random.nextInt(32)
+// load(rs1, a)tes
+// fmv_x_w(rs1){rsp =>
+// val ref = f2b(a).toLong & 0xFFFFFFFFl
+// val v = rsp.value.toBigInt
+// println(f"fmv_x_w $a = $v, $ref")
+// assert(v === ref)
+// }
+// }
+
+// def testFmv_w_x(a : Int): Unit ={
+// val rs = new RegAllocator()
+// val rs1, rs2, rs3 = rs.allocate()
+// val rd = Random.nextInt(32)
+// fmv_w_x(rd, a)
+// storeFloat(rd){v =>
+// val ref = b2f(a)
+// println(f"fmv_w_x $a = $v, $ref")
+// assert(v === ref)
+// }
+// }
+
+
+
+ def testMinMaxExact(a : Float, b : Float, arg : Int): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2 = rs.allocate()
+ val rd = Random.nextInt(32)
+ val ref = (a,b) match {
+ case _ if a.isNaN && b.isNaN => b2f(0x7FC00000)
+ case _ if a.isNaN => b
+ case _ if b.isNaN => a
+ case _ => if(arg == 0) Math.min(a,b) else Math.max(a,b)
+ }
+ val flag = (a,b) match {
+ case _ if a.isNaN && ((f2b(a) >> 22 ) & 1) == 0 => 16
+ case _ if b.isNaN && ((f2b(b) >> 22 ) & 1) == 0 => 16
+ case _ => 0
+ }
+ load(rs1, a)
+ load(rs2, b)
+
+ minMax(rd,rs1,rs2, arg, FpuFormat.FLOAT)
+ storeFloat(rd){v =>
+ assert(f2b(ref) == f2b(v), f"minMax($a $b $arg) = $v, $ref")
+ }
+ flagMatch(flag, f"minmax($a $b $arg)")
+ }
+
+ def testMinExact(a : Float, b : Float) : Unit = testMinMaxExact(a,b,0)
+ def testMaxExact(a : Float, b : Float) : Unit = testMinMaxExact(a,b,1)
+
+
+ def testMinMaxF64Exact(a : Double, b : Double, arg : Int): Unit ={
+ val rs = new RegAllocator()
+ val rs1, rs2 = rs.allocate()
+ val rd = Random.nextInt(32)
+ val ref = (a,b) match {
+ case _ if a.isNaN && b.isNaN => b2d(0x7ff8000000000000l)
+ case _ if a.isNaN => b
+ case _ if b.isNaN => a
+ case _ => if(arg == 0) Math.min(a,b) else Math.max(a,b)
+ }
+ val flag = (a,b) match {
+ case _ if a.isNaN && ((d2b(a) >> 51 ) & 1) == 0 => 16
+ case _ if b.isNaN && ((d2b(b) >> 51 ) & 1) == 0 => 16
+ case _ => 0
+ }
+ load(rs1, a)
+ load(rs2, b)
+
+ minMax(rd,rs1,rs2, arg, FpuFormat.DOUBLE)
+ store(rd){v =>
+ assert(d2b(ref) == d2b(v), f"minMax($a $b $arg) = $v, $ref")
+ }
+ flagMatch(flag, f"minmax($a $b $arg)")
+ }
+
+ def testMinF64Exact(a : Double, b : Double) : Unit = testMinMaxF64Exact(a,b,0)
+ def testMaxF64Exact(a : Double, b : Double) : Unit = testMinMaxF64Exact(a,b,1)
+
+
+ def testSgnjRaw(a : Float, b : Float): Unit ={
+ var ref = b2f((f2b(a) & ~0x80000000) | f2b(b) & 0x80000000)
+ if(a.isNaN) ref = a
+ testBinaryOp(sgnj,a,b,ref,0, null,"sgnj")
+ }
+ def testSgnjnRaw(a : Float, b : Float): Unit ={
+ var ref = b2f((f2b(a) & ~0x80000000) | ((f2b(b) & 0x80000000) ^ 0x80000000))
+ if(a.isNaN) ref = a
+ testBinaryOp(sgnjn,a,b,ref,0, null,"sgnjn")
+ }
+ def testSgnjxRaw(a : Float, b : Float): Unit ={
+ var ref = b2f(f2b(a) ^ (f2b(b) & 0x80000000))
+ if(a.isNaN) ref = a
+ testBinaryOp(sgnjx,a,b,ref,0, null,"sgnjx")
+ }
+
+ val f64SignMask = 1l << 63
+ def testSgnjF64Raw(a : Double, b : Double): Unit ={
+ var ref = b2d((d2b(a).toLong & ~f64SignMask) | d2b(b).toLong & f64SignMask)
+ if(a.isNaN) ref = a
+ testBinaryOpF64(sgnj,a,b,ref,0, null,"sgnj")
+ }
+ def testSgnjnF64Raw(a : Double, b : Double): Unit ={
+ var ref = b2d((d2b(a).toLong & ~f64SignMask) | ((d2b(b).toLong & f64SignMask) ^ f64SignMask))
+ if(a.isNaN) ref = a
+ testBinaryOpF64(sgnjn,a,b,ref,0, null,"sgnjn")
+ }
+ def testSgnjxF64Raw(a : Double, b : Double): Unit ={
+ var ref = b2d(d2b(a).toLong ^ (d2b(b).toLong & f64SignMask))
+ if(a.isNaN) ref = a
+ testBinaryOpF64(sgnjx,a,b,ref,0, null,"sgnjx")
+ }
+
+
+ def withMinus(that : Seq[Float]) = that.flatMap(f => List(f, -f))
+ val fZeros = withMinus(List(0.0f))
+ val fSubnormals = withMinus(List(b2f(0x00000000+1), b2f(0x00000000+2), b2f(0x00006800), b2f(0x00800000-2), b2f(0x00800000-1)))
+ val fExpSmall = withMinus(List(b2f(0x00800000), b2f(0x00800000+1), b2f(0x00800000 + 2)))
+ val fExpNormal = withMinus(List(b2f(0x3f800000-2), b2f(0x3f800000-1), b2f(0x3f800000), b2f(0x3f800000+1), b2f(0x3f800000+2)))
+ val fExpBig = withMinus(List(b2f(0x7f7fffff-2), b2f(0x7f7fffff-1), b2f(0x7f7fffff)))
+ val fInfinity = withMinus(List(Float.PositiveInfinity))
+ val fNan = List(Float.NaN, b2f(0x7f820000), b2f(0x7fc00000))
+ val fAll = fZeros ++ fSubnormals ++ fExpSmall ++ fExpNormal ++ fExpBig ++ fInfinity ++ fNan
+
+ val iSmall = (0 to 20)
+ val iBigUnsigned = (0 to 20).map(e => 0xFFFFFFFF - e)
+ val iBigSigned = (0 to 20).map(e => 0x7FFFFFFF - e) ++ (0 to 20).map(e => 0x80000000 + e)
+ val iUnsigned = iSmall ++ iBigUnsigned
+ val iSigned = iSmall ++ iSmall.map(-_) ++ iBigSigned
+
+
+ val roundingModes = FpuRoundMode.elements
+ def foreachRounding(body : FpuRoundMode.E => Unit): Unit ={
+ for(rounding <- roundingModes){
+ body(rounding)
+ }
+ }
+
+ def testFmaF32() : Unit = {
+ testFmaRaw(randomFloat(), randomFloat(), randomFloat())
+ flagClear()
+ }
+
+
+ def testFmaF64() : Unit = {
+ testFmaF64Raw(randomDouble(), randomDouble(), randomDouble())
+ flagClear()
+ }
+
+ def testLeF32() : Unit = {
+ val (a,b,i,f) = f32.le.RAW.f32_f32_i32
+ testLeRaw(a,b,i, f)
+ }
+ def testLtF32() : Unit = {
+ val (a,b,i,f) = f32.lt.RAW.f32_f32_i32
+ testLtRaw(a,b,i, f)
+ }
+
+ def testEqF32() : Unit = {
+ val (a,b,i,f) = f32.eq.RAW.f32_f32_i32
+ testEqRaw(a,b,i, f)
+ }
+
+ def testLeF64() : Unit = {
+ val (a,b,i,f) = f64.le.RAW.f64_f64_i32
+ testLeF64Raw(a,b,i, f)
+ }
+ def testLtF64() : Unit = {
+ val (a,b,i,f) = f64.lt.RAW.f64_f64_i32
+ testLtF64Raw(a,b,i, f)
+ }
+
+ def testEqF64() : Unit = {
+ val (a,b,i,f) = f64.eq.RAW.f64_f64_i32
+ testEqF64Raw(a,b,i, f)
+ }
+
+
+ def testF2uiF32() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,f) = f32.f2ui(rounding).f32_i32
+ testF2iExact(a,b, f, false, rounding)
+ }
+
+ def testF2iF32() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,f) = f32.f2i(rounding).f32_i32
+ testF2iExact(a,b, f, true, rounding)
+ }
+
+ def testF2uiF64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,f) = f64.f2ui(rounding).f64_i32
+ testF642iExact(a,b, f, false, rounding)
+ }
+
+ def testF2iF64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,f) = f64.f2i(rounding).f64_i32
+ testF642iExact(a,b, f, true, rounding)
+ }
+
+
+ def testDiv() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,r,f) = f32.div(rounding).f32_f32_f32
+ testBinaryOp(div, a, b, r, f, rounding, "div")
+ }
+
+ def testSqrt() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,r,f) = f32.sqrt(rounding).f32_f32
+ testSqrtExact(a, r, f, rounding)
+ flagClear()
+ }
+
+ def testSgnjF32() : Unit = {
+ testSgnjRaw(b2f(Random.nextInt()), b2f(Random.nextInt()))
+ testSgnjnRaw(b2f(Random.nextInt()), b2f(Random.nextInt()))
+ testSgnjxRaw(b2f(Random.nextInt()), b2f(Random.nextInt()))
+ val (a,b,r,f) = f32.sgnj.RAW.f32_f32_i32
+ testSgnjRaw(a, b)
+ testSgnjnRaw(a, b)
+ testSgnjxRaw(a, b)
+ }
+
+ def testDivF64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,r,f) = f64.div(rounding).f64_f64_f64
+ // testDivF64Exact(a, b, r, f, rounding)
+ testBinaryOpF64(div, a, b, r, f,rounding, "div")
+ flagClear()
+ }
+
+ def testSqrtF64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,r,f) = f64.sqrt(rounding).f64_f64
+ testSqrtF64Exact(a, r, f, rounding)
+ flagClear()
+ }
+
+ def testSgnjF64() : Unit = {
+ testSgnjF64Raw(b2d(Random.nextLong()), b2d(Random.nextLong()))
+ testSgnjnF64Raw(b2d(Random.nextLong()), b2d(Random.nextLong()))
+ testSgnjxF64Raw(b2d(Random.nextLong()), b2d(Random.nextLong()))
+ val (a,b,r,f) = f64.sgnj.RAW.f64_f64_i32
+ testSgnjF64Raw(a, b)
+ testSgnjnF64Raw(a, b)
+ testSgnjxF64Raw(a, b)
+ }
+
+
+ def testTransferF32() : Unit = {
+ val (a,b,r,f) = f32.transfer.RAW.f32_f32_i32
+ testTransferF32Raw(a, Random.nextBoolean(), Random.nextBoolean())
+ }
+
+ def testTransferF64() : Unit = {
+ val (a,b,r,f) = f64.transfer.RAW.f64_f64_i32
+ testTransferF64Raw(a)
+ }
+
+ def testTransferF64F32() : Unit = {
+ val (a,b,r,f) = f64.f32.RAW.f64_f64_i32
+ testTransferF64F32Raw(a, Random.nextBoolean())
+ }
+ def testTransferF32F64() : Unit = {
+ val (a,b,r,f) = f32.f64.RAW.f32_f32_i32
+ testTransferF32F64Raw(a, Random.nextBoolean())
+ }
+
+ def testCvtF32F64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,r,f) = f32.cvt64(rounding).f32_f64_i32
+ testCvtF32F64Raw(a, r, f, rounding)
+ }
+ def testCvtF64F32() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,r,f) = f64.cvt32(rounding).f64_f32_i32
+ testCvtF64F32Raw(a, r, f, rounding)
+ }
+
+ def testClassF32() : Unit = {
+ val (a,b,r,f) = f32.fclass.RAW.f32_f32_i32
+ testClassRaw(a)
+ }
+
+ def testMinF32() : Unit = {
+ val (a,b,r,f) = f32.min.RAW.f32_f32_f32
+ testMinExact(a,b)
+ }
+ def testMaxF32() : Unit = {
+ val (a,b,r,f) = f32.max.RAW.f32_f32_f32
+ testMaxExact(a,b)
+ }
+
+ def testClassF64() : Unit = {
+ val (a,b,r,f) = f64.fclass.RAW.f64_f64_i32
+ testClassF64Raw(a)
+ }
+
+ def testMinF64() : Unit = {
+ val (a,b,r,f) = f64.min.RAW.f64_f64_f64
+ testMinF64Exact(a,b)
+ }
+ def testMaxF64() : Unit = {
+ val (a,b,r,f) = f64.max.RAW.f64_f64_f64
+ testMaxF64Exact(a,b)
+ }
+
+
+ def testUI2f32() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,f) = f32.i2f(rounding).i32_f32
+ testI2fExact(a,b,f, true, rounding)
+ }
+
+ def testI2f32() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,f) = f32.ui2f(rounding).i32_f32
+ testI2fExact(a,b,f, false, rounding)
+ }
+
+ def testUI2f64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,f) = f64.i2f(rounding).i32_f64
+ testI2f64Exact(a,b,f, true, rounding)
+ }
+
+ def testI2f64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,f) = f64.ui2f(rounding).i32_f64
+ testI2f64Exact(a,b,f, false, rounding)
+ }
+
+ def testMulF32() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,c,f) = f32.mul(rounding).f32_f32_f32
+ testBinaryOp(mul,a,b,c,f, rounding,"mul")
+ }
+
+ def testAddF32() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,c,f) = f32.add(rounding).f32_f32_f32
+ testBinaryOp(add,a,b,c,f, rounding,"add")
+ }
+
+ def testSubF32() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,c,f) = f32.sub(rounding).f32_f32_f32
+ testBinaryOp(sub,a,b,c,f, rounding,"sub")
+ }
+
+
+ def testMulF64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,c,f) = f64.mul(rounding).f64_f64_f64
+ testBinaryOpF64(mul,a,b,c,f, rounding,"mul")
+ }
+
+ def testAddF64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,c,f) = f64.add(rounding).f64_f64_f64
+ testBinaryOpF64(add,a,b,c,f, rounding,"add")
+ }
+
+ def testSubF64() : Unit = {
+ val rounding = FpuRoundMode.elements.randomPick()
+ val (a,b,c,f) = f64.sub(rounding).f64_f64_f64
+ testBinaryOpF64(sub,a,b,c,f, rounding,"sub")
+ }
+
+
+ val f32Tests = List[() => Unit](testSubF32, testAddF32, testMulF32, testI2f32, testUI2f32, testMinF32, testMaxF32, testSgnjF32, testTransferF32, testDiv, testSqrt, testF2iF32, testF2uiF32, testLeF32, testEqF32, testLtF32, testClassF32, testFmaF32)
+ val f64Tests = List[() => Unit](testSubF64, testAddF64, testMulF64, testI2f64, testUI2f64, testMinF64, testMaxF64, testSgnjF64, testTransferF64, testDiv, testSqrt, testF2iF64, testF2uiF64, testLeF64, testEqF64, testLtF64, testClassF64, testFmaF64, testCvtF32F64, testCvtF64F32)
+
+ var fxxTests = f32Tests
+ if(p.withDouble) fxxTests ++= f64Tests
+
+//5071920 5225560
+// for(v <- List(-1.17549435082e-38f, 1.17549435082e-38f);
+// rounding <- FpuRoundMode.elements) {
+// for (i <- 0 until 2048) {
+// val b = d2b(v)// 0x0010000000000000l //d2b(1.17549435082e-38)
+// val s = (b - (i.toLong << 21)).toLong
+// val d = b2d(s)
+//// val rounding = FpuRoundMode.RNE
+// testCvtF64F32Raw(d, Clib.math.d2f(d, rounding.position), Clib.math.d2fFlag(d, rounding.position), rounding)
+// }
+// }
+//
+//
+// testCvtF64F32Raw(-1.1754943508051483E-38, -1.17549435E-38f, 1, FpuRoundMode.RNE)
+// testCvtF64F32Raw( 1.1754943157898258E-38, 1.17549435E-38f , 3, FpuRoundMode.RMM)
+// testCvtF64F32Raw( 1.1754942807573643E-38, 1.17549435E-38f , 3, FpuRoundMode.RMM)
+// testCvtF64F32Raw(-1.1754943508051483E-38, -1.17549435E-38f, 1, FpuRoundMode.RMM)
+
+ //-1.1754943508051483E-38 -1.17549435E-38 1 RNE @ 592770
+ // 1.1754943157898258E-38 1.17549435E-38 3 RMM @ 2697440
+ // 1.1754942807573643E-38 1.17549435E-38 3 RMM
+// for(_ <- 0 until 1000000) testCvtF64F32() // 1 did not equal 3 Flag missmatch dut=1 ref=3 testCvtF64F32Raw 1.1754942807573643E-38 1.17549435E-38 RMM
+// println("FCVT_D_S done")
+
+// testBinaryOpF64(div, -2.2250738564511294E-308, 4.294967296003891E9, -5.180654E-318, 1, FpuRoundMode.RDN,"div") // ??? wtf
+
+// testBinaryOp(add,b2f(0x7F800000),b2f(0x1FD << 23),b2f(0x7F800000),0, FpuRoundMode.RNE,"add")
+
+
+
+// testBinaryOp(mul,1.1753509E-38f, 1.0001221f ,1.17549435E-38f,1, FpuRoundMode.RNE,"mul")
+//
+// for(i <- 0 until 10000000){
+// val rounding = FpuRoundMode.elements.randomPick()
+// val (a,b,c,f) = f32.mul(rounding).f32_f32_f32
+// testBinaryOp(mul,a,b,c,f, rounding,"mul")
+// }
+//
+// testBinaryOpF64(mul,2.781342323134002E-309, 7.999999999999999, 2.2250738585072014E-308, 3, FpuRoundMode.RNE,"mul")
+//// for(i <- 0 until 10000000){
+//// val rounding = FpuRoundMode.RNE
+//// val (a,b,c,f) = f64.mul(rounding).f64_f64_f64
+//// testBinaryOpF64(mul,a,b,c,f, rounding,"mul")
+//// }
+// for(_ <- 0 until 100000000) testMulF64()
+// println("f64 Mul done")
+//
+// for(_ <- 0 until 10000) testDivF64()
+// println("f64 div done")
+//
+//
+// for(_ <- 0 until 10000) testDiv()
+// println("f32 div done")
+//
+// for(_ <- 0 until 10000) testAddF32()
+// for(_ <- 0 until 10000) testSubF32()
+//
+// println("Add done")
+//
+//
+// for(_ <- 0 until 10000) testSqrt()
+// println("f32 sqrt done")
+
+
+
+
+
+
+ //TODO test boxing
+ //TODO double <-> simple convertions
+ if(p.withDouble) {
+
+ testSqrtF64Exact(1.25*1.25, 1.25, 0, FpuRoundMode.RNE)
+ testSqrtF64Exact(1.5*1.5, 1.5, 0, FpuRoundMode.RNE)
+
+ for(_ <- 0 until 10000) testSqrtF64()
+ println("f64 sqrt done")
+
+// testDivF64Exact(1.0, 8.0, 0.125, 0, FpuRoundMode.RNE)
+// testDivF64Exact(4.0, 8.0, 0.5, 0, FpuRoundMode.RNE)
+// testDivF64Exact(8.0, 8.0, 1.0, 0, FpuRoundMode.RNE)
+// testDivF64Exact(1.5, 2.0, 0.75, 0, FpuRoundMode.RNE)
+// testDivF64Exact(1.875, 1.5, 1.25, 0, FpuRoundMode.RNE)
+
+ for(_ <- 0 until 10000) testDivF64()
+ println("f64 div done")
+
+ for(_ <- 0 until 10000) testSgnjF64()
+ println("f64 sgnj done")
+
+ for(_ <- 0 until 10000) testSgnjF32()
+ println("f32 sgnj done")
+
+ //380000000001ffef 5fffffffffff9ff 8000000000100000
+// testBinaryOpF64(mul,-5.877471754282472E-39, 8.814425663400984E-280, -5.180654E-318 ,1, FpuRoundMode.RMM,"mul")
+// 5.877471754282472E-39 8.814425663400984E-280 -5.180654E-318 RMM
+
+ for(_ <- 0 until 10000) testCvtF64F32() // 1 did not equal 3 Flag missmatch dut=1 ref=3 testCvtF64F32Raw 1.1754942807573643E-38 1.17549435E-38 RMM
+ println("FCVT_D_S done")
+ for(_ <- 0 until 10000) testCvtF32F64()
+ println("FCVT_S_D done")
+
+ for(_ <- 0 until 10000) testF2iF64()
+ println("f64 f2i done")
+ for(_ <- 0 until 10000) testF2uiF64()
+ println("f64 f2ui done")
+
+
+
+
+
+ for(_ <- 0 until 10000) testMinF64()
+ for(_ <- 0 until 10000) testMaxF64()
+ println("f64 minMax done")
+
+
+
+ for(i <- 0 until 1000) testFmaF64()
+ flagClear()
+ println("f64 fma done") //TODO
+
+
+ for(_ <- 0 until 10000) testLeF64()
+ for(_ <- 0 until 10000) testLtF64()
+ for(_ <- 0 until 10000) testEqF64()
+ println("f64 Cmp done")
+
+
+ for(_ <- 0 until 10000) testClassF64()
+ println("f64 class done")
+//
+
+
+
+
+
+
+
+
+ for(_ <- 0 until 10000) testAddF64()
+ for(_ <- 0 until 10000) testSubF64()
+ println("f64 Add done")
+
+
+ // testI2f64Exact(0x7FFFFFF5, 0x7FFFFFF5, 0, true, FpuRoundMode.RNE)
+ for(_ <- 0 until 10000) testUI2f64()
+ for(_ <- 0 until 10000) testI2f64()
+ println("f64 i2f done")
+
+
+
+// testF2iExact(1.0f,1, 0, false, FpuRoundMode.RTZ)
+// testF2iExact(2.0f,2, 0, false, FpuRoundMode.RTZ)
+// testF2iExact(2.5f,2, 1, false, FpuRoundMode.RTZ)
+
+
+
+
+ testBinaryOpF64(mul,1.0, 1.0, 1.0,0 , FpuRoundMode.RNE,"mul")
+ testBinaryOpF64(mul,1.0, 2.0, 2.0,0 , FpuRoundMode.RNE,"mul")
+ testBinaryOpF64(mul,2.5, 2.0, 5.0,0 , FpuRoundMode.RNE,"mul")
+
+ for(_ <- 0 until 10000) testMulF64()
+ println("f64 Mul done")
+
+ testTransferF64Raw(1.0)
+ testTransferF64Raw(2.0)
+ testTransferF64Raw(2.5)
+ testTransferF64Raw(6.97949770801e-39)
+ testTransferF64Raw(8.72437213501e-40)
+ testTransferF64Raw(5.6E-45)
+
+ testTransferF32F64Raw(b2f(0xFFFF1234), false)
+ testTransferF64F32Raw(b2d(0xFFF123498765463l << 4), false)
+ testTransferF32F64Raw(b2f(0xFFFF1234), true)
+ testTransferF64F32Raw(b2d(0xFFF123498765463l << 4), true)
+
+ for (_ <- 0 until 10000) testTransferF64()
+ println("f64 load/store/rf transfer done")
+
+ for (_ <- 0 until 10000) testTransferF64F32()
+ println("f64 -> f32 load/store/rf transfer done")
+
+ for (_ <- 0 until 10000) testTransferF32F64()
+ println("f32 -> f64 load/store/rf transfer done")
+
+ }
+
+ for(_ <- 0 until 10000) testTransferF32()
+ println("f32 load/store/rf transfer done")
+
+ for(_ <- 0 until 10000) testMulF32()
+ println("Mul done")
+
+
+ for(_ <- 0 until 10000) testUI2f32()
+ for(_ <- 0 until 10000) testI2f32()
+ println("i2f done")
+
+
+ testF2iExact(1.0f,1, 0, false, FpuRoundMode.RTZ)
+ testF2iExact(2.0f,2, 0, false, FpuRoundMode.RTZ)
+ testF2iExact(2.5f,2, 1, false, FpuRoundMode.RTZ)
+
+
+
+
+
+ for(_ <- 0 until 10000) testF2uiF32()
+ for(_ <- 0 until 10000) testF2iF32()
+ println("f2i done")
+
+
+
+// waitUntil(cmdQueue.isEmpty)
+// dut.clockDomain.waitSampling(1000)
+// simSuccess()
+
+
+
+ for(i <- 0 until 1000) testFmaF32()
+ flagClear()
+ println("fma done") //TODO
+
+
+ testF2iExact(-2.14748365E9f, -2147483648, 0, true, FpuRoundMode.RDN)
+
+ testEqRaw(Float.PositiveInfinity,Float.PositiveInfinity,1, 0)
+ testEqRaw(0f, 0f,1, 0)
+
+ for(_ <- 0 until 10000) testLeF32()
+ for(_ <- 0 until 10000) testLtF32()
+ for(_ <- 0 until 10000) testEqF32()
+ println("Cmp done")
+
+
+ for(_ <- 0 until 10000) testDiv()
+ println("f32 div done")
+
+ for(_ <- 0 until 10000) testSqrt()
+ println("f32 sqrt done")
+
+ for(_ <- 0 until 10000) testSgnjF32()
+ println("f32 sgnj done")
+
+
+ for(_ <- 0 until 10000) testClassF32()
+ println("f32 class done")
+
+
+ for(_ <- 0 until 10000) testMinF32()
+ for(_ <- 0 until 10000) testMaxF32()
+ println("minMax done")
+
+
+
+ testBinaryOp(mul,1.469368E-39f, 7.9999995f, 1.17549435E-38f,3, FpuRoundMode.RUP,"mul")
+ testBinaryOp(mul,1.1753509E-38f, 1.0001221f, 1.17549435E-38f ,1, FpuRoundMode.RUP,"mul")
+ testBinaryOp(mul, 1.1754942E-38f, -1.0000001f, -1.17549435E-38f,1, FpuRoundMode.RNE,"mul")
+ testBinaryOp(mul, 1.1754942E-38f, -1.0000001f, -1.17549435E-38f,1, FpuRoundMode.RDN,"mul")
+ testBinaryOp(mul, 1.1754942E-38f, -1.0000001f, -1.17549435E-38f,1, FpuRoundMode.RMM,"mul")
+
+ testBinaryOp(mul, 1.1754945E-38f, 0.9999998f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
+ testBinaryOp(mul, 1.1754945E-38f, -0.9999998f, -1.17549435E-38f, 3, FpuRoundMode.RDN, "mul")
+ testBinaryOp(mul, 1.1754946E-38f, 0.9999997f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
+ testBinaryOp(mul, 1.1754946E-38f, -0.9999997f, -1.17549435E-38f, 3, FpuRoundMode.RDN, "mul")
+ testBinaryOp(mul, 1.1754949E-38f, 0.99999946f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
+ testBinaryOp(mul, 1.1754949E-38f, -0.99999946f, -1.17549435E-38f, 3, FpuRoundMode.RDN, "mul")
+ testBinaryOp(mul, 1.1754955E-38f, 0.999999f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
+
+
+
+
+
+
+ for(_ <- 0 until 10000) testAddF32()
+ for(_ <- 0 until 10000) testSubF32()
+
+ println("Add done")
+
+
+
+
+
+
+
+
+
+
+// waitUntil(cmdQueue.isEmpty)
+// dut.clockDomain.waitSampling(1000)
+// simSuccess()
+
+ for(i <- 0 until 100000) fxxTests.randomPick()()
+ waitUntil(cpu.rspQueue.isEmpty)
+ }
+
+
+
+
+ stim.foreach(_.join())
+ dut.clockDomain.waitSampling(100)
+ }
+ }
+}
+
+
+//object Clib {
+// val java_home = System.getProperty("java.home")
+// assert(java_home != "" && java_home != null, "JAVA_HOME need to be set")
+// val jdk = java_home.replace("/jre","").replace("\\jre","")
+// val jdkIncludes = jdk + "/include"
+// val flags = List("-fPIC", "-m64", "-shared", "-Wno-attributes") //-Wl,--whole-archive
+// val os = new File("/media/data/open/SaxonSoc/berkeley-softfloat-3/build/Linux-x86_64-GCC").listFiles().map(_.getAbsolutePath).filter(_.toString.endsWith(".o"))
+// val cmd = s"gcc -I/media/data/open/SaxonSoc/berkeley-softfloat-3/source/include -I$jdkIncludes -I$jdkIncludes/linux ${flags.mkString(" ")} -o src/test/cpp/fpu/math/fpu_math.so src/test/cpp/fpu/math/fpu_math.c src/test/cpp/fpu/math/softfloat.a" // src/test/cpp/fpu/math/softfloat.a
+// DoCmd.doCmd(cmd)
+// val math = new FpuMath
+//}
+// cd /media/data/open/SaxonSoc/testFloatBuild/berkeley-softfloat-3/build/Linux-x86_64-GCC
+// make clean && SPECIALIZE_TYPE=RISCV make -j$(nproc) && cp softfloat.a /media/data/open/SaxonSoc/artyA7SmpUpdate/SaxonSoc/ext/VexRiscv/src/test/cpp/fpu/math
+//object FpuCompileSo extends App{
+//
+//// val b2f = lang.Float.intBitsToFloat(_)
+//// for(e <- FpuRoundMode.elements) {
+//// println(e)
+//// for (i <- -2 until 50) println(i + " => " + Clib.math.addF32(b2f(0x7f000000), b2f(0x7f000000 + i), e.position))
+//// println("")
+//// }
+// //1 did not equal 3 Flag missmatch dut=1 ref=3 ## mul 0.9994812 -1.1754988E-38 -1.174889E-38 RMM
+// // println(Clib.math.mulF32(0.9994812f, -1.1754988E-38f, FpuRoundMode.RMM.position))
+//// miaou ffffffff 7fffffe0 7f
+//// miaou 0 3ffffff0 70 = 0
+//
+// val b2f = lang.Float.intBitsToFloat(_)
+// val b2d = lang.Double.longBitsToDouble(_)
+// val f2b = lang.Float.floatToRawIntBits(_)
+// val d2bOffset = BigInt("10000000000000000",16)
+// def d2b(that : Double) = {
+// val l = lang.Double.doubleToRawLongBits(that)
+// var a = BigInt(l)
+// if(l < 0) {
+// a = d2bOffset + a
+// }
+// a
+// }
+// val builder =new StringBuilder()
+// for(i <- 0 until 256){
+//// builder ++= (Clib.math.mulF32(1.17548538251e-38f, b2f(f2b(1.0f)+i),0)).toString + "\n"
+// val b = d2b(1.17549435082e-38)
+// val s = (b-(i.toLong << 25)).toLong
+// val d = b2d(s)
+// builder ++= f"$b $s $d => "
+// builder ++= f"${d2b(d)}%x " + (Clib.math.d2fFlag(d,0)).toString + " " + d + " => " + (Clib.math.d2f(d,FpuRoundMode.RMM.position)).toString + "\n"
+// }
+//
+// Thread.sleep(400)
+// println(builder.toString)
+// println(Clib.math.mulF32( 1.1753509E-38f, 1.0001221f, FpuRoundMode.RUP.position))
+// println(Clib.math.mulF32( 1.1754945E-38f, 0.9999998f, FpuRoundMode.RUP.position))
+// testBinaryOp(mul, 1.1753509E-38f, 1.0001221f, 1.17549435E-38f ,1, FpuRoundMode.RUP,"mul")
+// testBinaryOp(mul, 1.1754945E-38f, 0.9999998f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
+// miaou ffffffff 7fffffe0 7f
+// miaou 0 3ffffff0 70 = 0
+// miaou ffffffff 7fffff7e 7f
+// miaou 1 3fffffbf 3f = 1
+
+// println(Clib.math.mulF32( 1.1753509E-38f, 1.0001221f, FpuRoundMode.RUP.position))
+// println(Clib.math.mulF32( 1.469368E-39f, 7.9999995f, FpuRoundMode.RUP.position))
+// println(Clib.math.mulF32( 1.40129846432e-45f, 7.9999995f, FpuRoundMode.RUP.position))
+// println(Clib.math.mulF32( 2.93873587706e-39f, 7.9999995f, FpuRoundMode.RUP.position))
+// println(Clib.math.mulF32( 1f, 7.9999995f, FpuRoundMode.RUP.position))
+
+
+// println(Clib.math.addF32(1.00000011921f, 4.0f, FpuRoundMode.RNE.position))
+// println(Clib.math.addF32(1.00000011921f, 4.0f, FpuRoundMode.RTZ.position))
+// println(Clib.math.addF32(1.00000011921f, 4.0f, FpuRoundMode.RDN.position))
+// println(Clib.math.addF32(1.00000011921f, 4.0f, FpuRoundMode.RUP.position))
+//}
+
+class ProcessStream(cmd : String){
+ import sys.process._
+
+ val buf = mutable.Queue[() => String]()
+ val p = Process(cmd).run(new ProcessLogger {
+ override def out(s: => String): Unit = {
+ while(buf.size > 10000) Thread.sleep(10)
+ buf.enqueue(() => s)
+ }
+ override def err(s: => String): Unit = {}
+ override def buffer[T](f: => T): T = f
+ })
+
+ def kill = p.destroy()
+ def next = {
+ while(buf.isEmpty) { Thread.sleep(10) }
+ buf.dequeue()()
+ }
+}
+
diff --git a/VexRiscv/src/test/scala/vexriscv/ip/fpu/Playground.scala b/VexRiscv/src/test/scala/vexriscv/ip/fpu/Playground.scala
new file mode 100644
index 0000000..a155210
--- /dev/null
+++ b/VexRiscv/src/test/scala/vexriscv/ip/fpu/Playground.scala
@@ -0,0 +1,47 @@
+package vexriscv.ip.fpu
+
+object MiaouDiv extends App{
+ val input = 2.5
+ var output = 1/(input*0.95)
+
+ def y = output
+ def x = input
+
+ for(i <- 0 until 10) {
+ output = 2 * y - x * y * y
+ println(output)
+ }
+
+
+ //output = x*output
+ println(1/input)
+}
+
+object MiaouSqrt extends App{
+ val input = 2.0
+ var output = 1/Math.sqrt(input*0.95)
+ // def x = output
+ // def y = input
+
+ def y = output
+ def x = input
+
+ for(i <- 0 until 10) {
+ output = y * (1.5 - x * y * y / 2)
+ println(output)
+ }
+
+ output = x*output
+ println(output)
+ println(s"ref ${Math.sqrt(input)}")
+}
+
+
+object MiaouNan extends App{
+ println(Float.NaN + 3.0f)
+ println(3.0f + Float.NaN )
+ println(0.0f*Float.PositiveInfinity )
+ println(1.0f/0.0f )
+ println(Float.MaxValue -1 )
+ println(Float.PositiveInfinity - Float.PositiveInfinity)
+} \ No newline at end of file