fpu min max pass

This commit is contained in:
Dolu1990 2021-02-06 14:08:21 +01:00
parent 008fadeaa9
commit bf0829231d
2 changed files with 49 additions and 43 deletions

View File

@ -571,11 +571,13 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
0 -> rs1AbsSmaller, 0 -> rs1AbsSmaller,
1 -> False, 1 -> False,
2 -> True, 2 -> True,
3 -> (!rs1AbsSmaller && !rs1Equal) 3 -> !rs1AbsSmaller
) )
val minMaxResult = ((rs1Smaller ^ input.arg(0)) && !input.rs1.isNan || input.rs2.isNan) ? input.rs1 | input.rs2 val minMaxResult = ((rs1Smaller ^ input.arg(0)) && !input.rs1.isNan || input.rs2.isNan) ? input.rs1 | input.rs2
when(input.rs1.isNan && input.rs2.isNan) { minMaxResult.setNanQuiet }
// when(input.rs1.isZero && input.rs2.isZero && input.rs1.sign =/= input.rs2.sign){ minMaxResult.sign := !input.arg(0) }
val cmpResult = B(rs1Smaller && !bothZero && !input.arg(1) || (rs1Equal || bothZero) && !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 } 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)
@ -612,6 +614,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
rfOutput.value.assignDontCare() rfOutput.value.assignDontCare()
switch(input.opcode){ switch(input.opcode){
is(FpuOpcode.MIN_MAX){ is(FpuOpcode.MIN_MAX){
rfOutput.value.sign := minMaxResult.sign
rfOutput.value.exponent := minMaxResult.exponent rfOutput.value.exponent := minMaxResult.exponent
rfOutput.value.mantissa := minMaxResult.mantissa @@ U"0" rfOutput.value.mantissa := minMaxResult.mantissa @@ U"0"
rfOutput.value.special := minMaxResult.special rfOutput.value.special := minMaxResult.special
@ -624,15 +627,12 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
} }
} }
val signalQuiet = input.opcode === FpuOpcode.CMP && input.arg =/= 2
// val useRs1 = List(FpuOpcode.CMP).map(input.opcode === _).orR
// val useRs2 = List(FpuOpcode.CMP).map(input.opcode === _).orR
val onlySignalingNan = input.arg === 2
val rs1Nan = input.rs1.isNan val rs1Nan = input.rs1.isNan
val rs2Nan = input.rs2.isNan val rs2Nan = input.rs2.isNan
val rs1NanNv = input.rs1.isNan && !(onlySignalingNan && input.rs1.isQuiet) val rs1NanNv = input.rs1.isNan && (!input.rs1.isQuiet || signalQuiet)
val rs2NanNv = input.rs2.isNan && !(onlySignalingNan && input.rs2.isQuiet) val rs2NanNv = input.rs2.isNan && (!input.rs2.isQuiet || signalQuiet)
val nv = input.opcode === FpuOpcode.CMP && (rs1NanNv || rs2NanNv) val nv = (input.opcode === FpuOpcode.CMP || input.opcode === FpuOpcode.MIN_MAX) && (rs1NanNv || rs2NanNv)
flag.NV setWhen(input.valid && nv) flag.NV setWhen(input.valid && nv)
input.ready := !halt && (toFpuRf ? rfOutput.ready | io.port.map(_.rsp.ready).read(input.source)) input.ready := !halt && (toFpuRf ? rfOutput.ready | io.port.map(_.rsp.ready).read(input.source))

View File

@ -51,7 +51,7 @@ class FpuTest extends FunSuite{
class TestCase(op : String){ class TestCase(op : String){
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -tininessafter -forever -$op"){ def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -tininessafter -forever -$op"){
def f32_f32 ={ def f32_f32_f32 ={
val s = new Scanner(next) val s = new Scanner(next)
val a,b,c = (s.nextLong(16).toInt) val a,b,c = (s.nextLong(16).toInt)
// if(b2f(a).isNaN || b2f(b).isNaN){ // if(b2f(a).isNaN || b2f(b).isNaN){
@ -120,6 +120,8 @@ class FpuTest extends FunSuite{
val eq = new TestCase("f32_eq") val eq = new TestCase("f32_eq")
val lt = new TestCase("f32_lt") val lt = new TestCase("f32_lt")
val le = new TestCase("f32_le") val le = new TestCase("f32_le")
val min = new TestCase("f32_le")
val max = new TestCase("f32_lt")
} }
val cpus = for(id <- 0 until portCount) yield new { val cpus = for(id <- 0 until portCount) yield new {
@ -138,7 +140,7 @@ class FpuTest extends FunSuite{
def softAssert(cond : Boolean, msg : String) = if(!cond)println(msg) def softAssert(cond : Boolean, msg : String) = if(!cond)println(msg)
def flagMatch(ref : Int, value : Float, report : String): Unit ={ def flagMatch(ref : Int, value : Float, report : String): Unit ={
val patch = if(value.abs == 1.17549435E-38f) ref & ~2 else ref val patch = if(value.abs == 1.17549435E-38f) ref & ~2 else ref
flagMatch(ref, patch, report) flagMatch(patch, report)
} }
def flagMatch(ref : Int, report : String): Unit ={ def flagMatch(ref : Int, report : String): Unit ={
waitUntil(pendingMiaou == 0) waitUntil(pendingMiaou == 0)
@ -324,14 +326,14 @@ class FpuTest extends FunSuite{
} }
} }
def min(rd : Int, rs1 : Int, rs2 : Int): Unit ={ def minMax(rd : Int, rs1 : Int, rs2 : Int, arg : Int = 0): Unit ={
cmdAdd {cmd => cmdAdd {cmd =>
cmd.opcode #= cmd.opcode.spinalEnum.MIN_MAX cmd.opcode #= cmd.opcode.spinalEnum.MIN_MAX
cmd.rs1 #= rs1 cmd.rs1 #= rs1
cmd.rs2 #= rs2 cmd.rs2 #= rs2
cmd.rs3.randomize() cmd.rs3.randomize()
cmd.rd #= rd cmd.rd #= rd
cmd.arg #= 0 cmd.arg #= arg
} }
commitQueue += {cmd => commitQueue += {cmd =>
cmd.write #= true cmd.write #= true
@ -678,25 +680,35 @@ class FpuTest extends FunSuite{
def testMin(a : Float, b : Float): Unit ={ def testMinMaxExact(a : Float, b : Float, arg : Int): Unit ={
val rs = new RegAllocator() val rs = new RegAllocator()
val rs1, rs2, rs3 = rs.allocate() val rs1, rs2 = rs.allocate()
val rd = Random.nextInt(32) 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(rs1, a)
load(rs2, b) load(rs2, b)
min(rd,rs1,rs2) minMax(rd,rs1,rs2, arg)
storeFloat(rd){v => storeFloat(rd){v =>
val ref = (a,b) match { assert(f2b(ref) == f2b(v), f"minMax($a $b $arg) = $v, $ref")
case _ if a.isNaN => b
case _ if b.isNaN => a
case _ => Math.min(a,b)
}
println(f"min $a $b = $v, $ref")
assert(f2b(ref) == f2b(v))
} }
flagMatch(flag, f"minmax($a $b $arg)")
} }
def testMin(a : Float, b : Float) = testMinMaxExact(a,b,0)
def testMax(a : Float, b : Float) = testMinMaxExact(a,b,1)
def testSgnj(a : Float, b : Float): Unit ={ def testSgnj(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()
@ -750,6 +762,16 @@ class FpuTest extends FunSuite{
val binaryOps = List[(Int,Int,Int,FpuRoundMode.E) => Unit](add, sub, mul) val binaryOps = List[(Int,Int,Int,FpuRoundMode.E) => Unit](add, sub, mul)
for(_ <- 0 until 10000){
val (a,b,r,f) = f32.min.RAW.f32_f32_f32
testMin(a,b)
}
for(_ <- 0 until 10000){
val (a,b,r,f) = f32.max.RAW.f32_f32_f32
testMax(a,b)
}
println("minMax done")
for(_ <- 0 until 100000){ for(_ <- 0 until 100000){
val (a,b,i,f) = f32.le.RAW.f32_f32_i32 val (a,b,i,f) = f32.le.RAW.f32_f32_i32
testLe(a,b,i, f) testLe(a,b,i, f)
@ -812,7 +834,7 @@ class FpuTest extends FunSuite{
for(_ <- 0 until 10000){ for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick() val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.mul(rounding).f32_f32 val (a,b,c,f) = f32.mul(rounding).f32_f32_f32
testBinaryOp(mul,a,b,c,f, rounding,"mul") testBinaryOp(mul,a,b,c,f, rounding,"mul")
} }
@ -821,13 +843,13 @@ class FpuTest extends FunSuite{
for(_ <- 0 until 10000){ for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick() val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.add(rounding).f32_f32 val (a,b,c,f) = f32.add(rounding).f32_f32_f32
testBinaryOp(add,a,b,c,f, rounding,"add") testBinaryOp(add,a,b,c,f, rounding,"add")
} }
for(_ <- 0 until 10000){ for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick() val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.sub(rounding).f32_f32 val (a,b,c,f) = f32.sub(rounding).f32_f32_f32
testBinaryOp(sub,a,b,c,f, rounding,"sub") testBinaryOp(sub,a,b,c,f, rounding,"sub")
} }
@ -936,14 +958,7 @@ class FpuTest extends FunSuite{
for(a <- fAll; b <- fAll) testCmp(a, b) for(a <- fAll; b <- fAll) testCmp(a, b)
for(_ <- 0 until 1000) testCmp(randomFloat(), randomFloat()) for(_ <- 0 until 1000) testCmp(randomFloat(), randomFloat())
testMin(0.0f, 1.2f )
testMin(1.2f, 0.0f )
testMin(0.0f, -0.0f )
testMin(-0.0f, 0.0f )
for(a <- fAll; _ <- 0 until 50) testMin(a, 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(1.2f)
testSqrt(0.0f) testSqrt(0.0f)
@ -973,15 +988,6 @@ class FpuTest extends FunSuite{
testFmv_x_w(1.246f) testFmv_x_w(1.246f)
testFmv_w_x(f2b(7.234f)) testFmv_w_x(f2b(7.234f))
testMin(1.0f, 2.0f)
testMin(1.5f, 2.0f)
testMin(1.5f, 3.5f)
testMin(1.5f, 1.5f)
testMin(1.5f, -1.5f)
testMin(-1.5f, 1.5f)
testMin(-1.5f, -1.5f)
testMin(1.5f, -3.5f)
testSgnj(1.0f, 2.0f) testSgnj(1.0f, 2.0f)
testSgnj(1.5f, 2.0f) testSgnj(1.5f, 2.0f)
testSgnj(1.5f, 3.5f) testSgnj(1.5f, 3.5f)
@ -1087,7 +1093,7 @@ class FpuTest extends FunSuite{
tests += (() =>{testCmp(randomFloat(), randomFloat())}) tests += (() =>{testCmp(randomFloat(), randomFloat())})
tests += (() =>{testFmv_x_w(randomFloat())}) tests += (() =>{testFmv_x_w(randomFloat())})
tests += (() =>{testFmv_w_x(f2b(randomFloat()))}) tests += (() =>{testFmv_w_x(f2b(randomFloat()))})
tests += (() =>{testMin(randomFloat(), randomFloat())}) // tests += (() =>{testMin(randomFloat(), randomFloat())})
tests += (() =>{testSgnj(randomFloat(), randomFloat())}) tests += (() =>{testSgnj(randomFloat(), randomFloat())})