fpu min max pass
This commit is contained in:
parent
008fadeaa9
commit
bf0829231d
|
@ -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))
|
||||||
|
|
|
@ -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())})
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue