fpu sgnj / fclass / fmv pass
This commit is contained in:
parent
bf0829231d
commit
bf6a64b6b5
|
@ -105,6 +105,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
|||
val value = p.writeFloating()
|
||||
val scrap = Bool()
|
||||
val roundMode = FpuRoundMode()
|
||||
val allowException = Bool()
|
||||
}
|
||||
|
||||
case class RoundOutput() extends Bundle{
|
||||
|
@ -463,7 +464,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
|||
}
|
||||
recodedResult := recoded.sign ## f32.exp ## f32.man
|
||||
|
||||
val isSubnormal = !recoded.special && recoded.exponent <= exponentOne - 127
|
||||
val expInSubnormalRange = recoded.exponent <= exponentOne - 127
|
||||
val isSubnormal = !recoded.special && expInSubnormalRange
|
||||
val isNormal = !recoded.special && !expInSubnormalRange
|
||||
val fsm = new Area{
|
||||
val f2iShift = input.rs1.exponent - U(exponentOne)
|
||||
val isF2i = input.opcode === FpuOpcode.F2I
|
||||
|
@ -584,12 +587,12 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
|||
val fclassResult = B(0, 32 bits)
|
||||
val decoded = input.rs1.decode()
|
||||
fclassResult(0) := input.rs1.sign && decoded.isInfinity
|
||||
fclassResult(1) := input.rs1.sign && decoded.isNormal
|
||||
fclassResult(1) := input.rs1.sign && isNormal
|
||||
fclassResult(2) := input.rs1.sign && isSubnormal //TODO
|
||||
fclassResult(3) := input.rs1.sign && decoded.isZero
|
||||
fclassResult(4) := !input.rs1.sign && decoded.isZero
|
||||
fclassResult(5) := !input.rs1.sign && isSubnormal //TODO
|
||||
fclassResult(6) := !input.rs1.sign && decoded.isNormal
|
||||
fclassResult(6) := !input.rs1.sign && isNormal
|
||||
fclassResult(7) := !input.rs1.sign && decoded.isInfinity
|
||||
fclassResult(8) := decoded.isNan && !decoded.isQuiet
|
||||
fclassResult(9) := decoded.isNan && decoded.isQuiet
|
||||
|
@ -623,7 +626,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
|||
rfOutput.value.sign := sgnjResult
|
||||
rfOutput.value.exponent := input.rs1.exponent
|
||||
rfOutput.value.mantissa := input.rs1.mantissa @@ U"0"
|
||||
rfOutput.value.special := False //TODO
|
||||
rfOutput.value.special := input.rs1.special
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,11 @@ class FpuTest extends FunSuite{
|
|||
val le = new TestCase("f32_le")
|
||||
val min = new TestCase("f32_le")
|
||||
val max = new TestCase("f32_lt")
|
||||
val transfer = new TestCase("f32_eq")
|
||||
val fclass = new TestCase("f32_eq")
|
||||
val sgnj = new TestCase("f32_eq")
|
||||
val sgnjn = new TestCase("f32_eq")
|
||||
val sgnjx = new TestCase("f32_eq")
|
||||
}
|
||||
|
||||
val cpus = for(id <- 0 until portCount) yield new {
|
||||
|
@ -272,6 +277,19 @@ class FpuTest extends FunSuite{
|
|||
fpuF2f(rd, rs1, rs2, rs3, FpuOpcode.FMA, 0, rounding)
|
||||
}
|
||||
|
||||
def sgnjRaw(rd : Int, rs1 : Int, rs2 : Int, arg : Int): Unit ={
|
||||
fpuF2f(rd, rs1, rs2, Random.nextInt(32), FpuOpcode.SGNJ, arg, FpuRoundMode.elements.randomPick())
|
||||
}
|
||||
|
||||
def sgnj(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = null): Unit ={
|
||||
sgnjRaw(rd, rs1, rs2, 0)
|
||||
}
|
||||
def sgnjn(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = null): Unit ={
|
||||
sgnjRaw(rd, rs1, rs2, 1)
|
||||
}
|
||||
def sgnjx(rd : Int, rs1 : Int, rs2 : Int, rounding : FpuRoundMode.E = null): Unit ={
|
||||
sgnjRaw(rd, rs1, rs2, 2)
|
||||
}
|
||||
|
||||
def cmp(rs1 : Int, rs2 : Int, arg : Int = 1)(body : FpuRsp => Unit): Unit ={
|
||||
fpuF2i(rs1, rs2, FpuOpcode.CMP, arg, FpuRoundMode.elements.randomPick())(body)
|
||||
|
@ -298,7 +316,7 @@ class FpuTest extends FunSuite{
|
|||
}
|
||||
}
|
||||
|
||||
def fmv_x_w(rs1 : Int)(body : FpuRsp => Unit): Unit ={
|
||||
def fmv_x_w(rs1 : Int)(body : Float => Unit): Unit ={
|
||||
cmdAdd {cmd =>
|
||||
cmd.opcode #= cmd.opcode.spinalEnum.FMV_X_W
|
||||
cmd.rs1 #= rs1
|
||||
|
@ -307,7 +325,7 @@ class FpuTest extends FunSuite{
|
|||
cmd.rd.randomize()
|
||||
cmd.arg #= 0
|
||||
}
|
||||
rspQueue += body
|
||||
rspQueue += {rsp => body(b2f(rsp.value.toLong.toInt))}
|
||||
}
|
||||
|
||||
def fmv_w_x(rd : Int, value : Int): Unit ={
|
||||
|
@ -342,19 +360,17 @@ class FpuTest extends FunSuite{
|
|||
}
|
||||
|
||||
|
||||
def sgnj(rd : Int, rs1 : Int, rs2 : Int): Unit ={
|
||||
|
||||
def fclass(rs1 : Int)(body : Int => Unit) : Unit = {
|
||||
cmdAdd {cmd =>
|
||||
cmd.opcode #= cmd.opcode.spinalEnum.SGNJ
|
||||
cmd.opcode #= FpuOpcode.FCLASS
|
||||
cmd.rs1 #= rs1
|
||||
cmd.rs2 #= rs2
|
||||
cmd.rs2.randomize()
|
||||
cmd.rs3.randomize()
|
||||
cmd.rd #= rd
|
||||
cmd.arg #= 0
|
||||
}
|
||||
commitQueue += {cmd =>
|
||||
cmd.write #= true
|
||||
cmd.sync #= false
|
||||
cmd.rd.randomize()
|
||||
cmd.arg.randomize()
|
||||
}
|
||||
rspQueue += {rsp => body(rsp.value.toLong.toInt)}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,16 +476,43 @@ class FpuTest extends FunSuite{
|
|||
}
|
||||
}
|
||||
|
||||
def testLoadStore(a : Float): Unit ={
|
||||
def testTransfer(a : Float, iSrc : Boolean, iDst : Boolean): Unit ={
|
||||
val rd = Random.nextInt(32)
|
||||
load(rd, a)
|
||||
storeFloat(rd){v =>
|
||||
|
||||
def handle(v : Float): Unit ={
|
||||
val refUnclamped = a
|
||||
val ref = a
|
||||
println(f"$a = $v, $ref")
|
||||
assert(f2b(v) == f2b(ref))
|
||||
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 testClass(a : Float) : Unit = {
|
||||
val rd = Random.nextInt(32)
|
||||
|
||||
|
||||
load(rd, a)
|
||||
fclass(rd){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 testMul(a : Float, b : Float): Unit ={
|
||||
val rs = new RegAllocator()
|
||||
val rs1, rs2, rs3 = rs.allocate()
|
||||
|
@ -653,30 +696,30 @@ class FpuTest extends FunSuite{
|
|||
def testEq(a : Float, b : Float, ref : Int, flag : Int) = testCmpExact(a,b,ref,flag, 2)
|
||||
def testLt(a : Float, b : Float, ref : Int, flag : Int) = testCmpExact(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)
|
||||
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_x_w(a : Float): Unit ={
|
||||
// val rs = new RegAllocator()
|
||||
// val rs1, rs2, rs3 = rs.allocate()
|
||||
// val rd = Random.nextInt(32)
|
||||
// load(rs1, a)
|
||||
// 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 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)
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
@ -710,18 +753,16 @@ class FpuTest extends FunSuite{
|
|||
|
||||
|
||||
def testSgnj(a : Float, b : Float): Unit ={
|
||||
val rs = new RegAllocator()
|
||||
val rs1, rs2, rs3 = rs.allocate()
|
||||
val rd = Random.nextInt(32)
|
||||
load(rs1, a)
|
||||
load(rs2, b)
|
||||
|
||||
sgnj(rd,rs1,rs2)
|
||||
storeFloat(rd){v =>
|
||||
val ref = a * a.signum * b.signum
|
||||
println(f"sgnf $a $b = $v, $ref")
|
||||
assert(ref == v)
|
||||
val ref = b2f((f2b(a) & ~0x80000000) | f2b(b) & 0x80000000)
|
||||
testBinaryOp(sgnj,a,b,ref,0, null,"sgnj")
|
||||
}
|
||||
def testSgnjn(a : Float, b : Float): Unit ={
|
||||
val ref = b2f((f2b(a) & ~0x80000000) | ((f2b(b) & 0x80000000) ^ 0x80000000))
|
||||
testBinaryOp(sgnjn,a,b,ref,0, null,"sgnjn")
|
||||
}
|
||||
def testSgnjx(a : Float, b : Float): Unit ={
|
||||
val ref = b2f(f2b(a) ^ (f2b(b) & 0x80000000))
|
||||
testBinaryOp(sgnjx,a,b,ref,0, null,"sgnjx")
|
||||
}
|
||||
|
||||
|
||||
|
@ -762,6 +803,41 @@ class FpuTest extends FunSuite{
|
|||
|
||||
val binaryOps = List[(Int,Int,Int,FpuRoundMode.E) => Unit](add, sub, mul)
|
||||
|
||||
|
||||
|
||||
for(_ <- 0 until 10000){
|
||||
testSgnj(b2f(Random.nextInt()), b2f(Random.nextInt()))
|
||||
testSgnjn(b2f(Random.nextInt()), b2f(Random.nextInt()))
|
||||
testSgnjx(b2f(Random.nextInt()), b2f(Random.nextInt()))
|
||||
val (a,b,r,f) = f32.sgnj.RAW.f32_f32_i32
|
||||
testSgnj(a, b)
|
||||
testSgnjn(a, b)
|
||||
testSgnjx(a, b)
|
||||
}
|
||||
println("f32 sgnj done")
|
||||
|
||||
for(_ <- 0 until 10000){
|
||||
testTransfer(b2f(Random.nextInt()), Random.nextBoolean(), Random.nextBoolean())
|
||||
}
|
||||
for(_ <- 0 until 10000){
|
||||
val (a,b,r,f) = f32.transfer.RAW.f32_f32_i32
|
||||
testTransfer(a, Random.nextBoolean(), Random.nextBoolean())
|
||||
}
|
||||
|
||||
println("f32 load/store/rf transfer done")
|
||||
|
||||
|
||||
for(_ <- 0 until 10000){
|
||||
testClass(b2f(Random.nextInt()))
|
||||
}
|
||||
for(_ <- 0 until 10000){
|
||||
val (a,b,r,f) = f32.fclass.RAW.f32_f32_i32
|
||||
testClass(a)
|
||||
}
|
||||
|
||||
println("f32 class done")
|
||||
|
||||
|
||||
for(_ <- 0 until 10000){
|
||||
val (a,b,r,f) = f32.min.RAW.f32_f32_f32
|
||||
testMin(a,b)
|
||||
|
@ -890,9 +966,9 @@ class FpuTest extends FunSuite{
|
|||
for(_ <- 0 until 1000) testAdd(randomFloat(), randomFloat())
|
||||
|
||||
|
||||
testLoadStore(1.17549435082e-38f)
|
||||
testLoadStore(1.4E-45f)
|
||||
testLoadStore(3.44383110592e-41f)
|
||||
// testTransfer(1.17549435082e-38f)
|
||||
// testTransfer(1.4E-45f)
|
||||
// testTransfer(3.44383110592e-41f)
|
||||
|
||||
//TODO bring back those tests and test overflow / underflow (F2I)
|
||||
// testF2i(16.0f , false)
|
||||
|
@ -918,7 +994,7 @@ class FpuTest extends FunSuite{
|
|||
|
||||
|
||||
|
||||
testLoadStore(1.2f)
|
||||
// testTransfer(1.2f)
|
||||
testMul(1.2f, 2.5f)
|
||||
testMul(b2f(0x00400000), 16.0f)
|
||||
testMul(b2f(0x00100000), 16.0f)
|
||||
|
@ -941,8 +1017,8 @@ class FpuTest extends FunSuite{
|
|||
|
||||
|
||||
|
||||
testLoadStore(1.765f)
|
||||
testFmv_w_x(f2b(7.234f))
|
||||
// testTransfer(1.765f)
|
||||
// testFmv_w_x(f2b(7.234f))
|
||||
testI2f(64, false)
|
||||
for(i <- iUnsigned) testI2f(i, false)
|
||||
for(i <- iSigned) testI2f(i, true)
|
||||
|
@ -985,8 +1061,8 @@ class FpuTest extends FunSuite{
|
|||
// dut.clockDomain.waitSampling(10000000)
|
||||
|
||||
|
||||
testFmv_x_w(1.246f)
|
||||
testFmv_w_x(f2b(7.234f))
|
||||
// testFmv_x_w(1.246f)
|
||||
// testFmv_w_x(f2b(7.234f))
|
||||
|
||||
testSgnj(1.0f, 2.0f)
|
||||
testSgnj(1.5f, 2.0f)
|
||||
|
@ -1091,8 +1167,8 @@ class FpuTest extends FunSuite{
|
|||
tests += (() =>{testDiv(randomFloat(), randomFloat())})
|
||||
tests += (() =>{testSqrt(randomFloat().abs)})
|
||||
tests += (() =>{testCmp(randomFloat(), randomFloat())})
|
||||
tests += (() =>{testFmv_x_w(randomFloat())})
|
||||
tests += (() =>{testFmv_w_x(f2b(randomFloat()))})
|
||||
// tests += (() =>{testFmv_x_w(randomFloat())})
|
||||
// tests += (() =>{testFmv_w_x(f2b(randomFloat()))})
|
||||
// tests += (() =>{testMin(randomFloat(), randomFloat())})
|
||||
tests += (() =>{testSgnj(randomFloat(), randomFloat())})
|
||||
|
||||
|
|
Loading…
Reference in New Issue