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 value = p.writeFloating()
|
||||||
val scrap = Bool()
|
val scrap = Bool()
|
||||||
val roundMode = FpuRoundMode()
|
val roundMode = FpuRoundMode()
|
||||||
|
val allowException = Bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
case class RoundOutput() extends Bundle{
|
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
|
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 fsm = new Area{
|
||||||
val f2iShift = input.rs1.exponent - U(exponentOne)
|
val f2iShift = input.rs1.exponent - U(exponentOne)
|
||||||
val isF2i = input.opcode === FpuOpcode.F2I
|
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 fclassResult = B(0, 32 bits)
|
||||||
val decoded = input.rs1.decode()
|
val decoded = input.rs1.decode()
|
||||||
fclassResult(0) := input.rs1.sign && decoded.isInfinity
|
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(2) := input.rs1.sign && isSubnormal //TODO
|
||||||
fclassResult(3) := input.rs1.sign && decoded.isZero
|
fclassResult(3) := input.rs1.sign && decoded.isZero
|
||||||
fclassResult(4) := !input.rs1.sign && decoded.isZero
|
fclassResult(4) := !input.rs1.sign && decoded.isZero
|
||||||
fclassResult(5) := !input.rs1.sign && isSubnormal //TODO
|
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(7) := !input.rs1.sign && decoded.isInfinity
|
||||||
fclassResult(8) := decoded.isNan && !decoded.isQuiet
|
fclassResult(8) := decoded.isNan && !decoded.isQuiet
|
||||||
fclassResult(9) := 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.sign := sgnjResult
|
||||||
rfOutput.value.exponent := input.rs1.exponent
|
rfOutput.value.exponent := input.rs1.exponent
|
||||||
rfOutput.value.mantissa := input.rs1.mantissa @@ U"0"
|
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 le = new TestCase("f32_le")
|
||||||
val min = new TestCase("f32_le")
|
val min = new TestCase("f32_le")
|
||||||
val max = new TestCase("f32_lt")
|
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 {
|
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)
|
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 ={
|
def cmp(rs1 : Int, rs2 : Int, arg : Int = 1)(body : FpuRsp => Unit): Unit ={
|
||||||
fpuF2i(rs1, rs2, FpuOpcode.CMP, arg, FpuRoundMode.elements.randomPick())(body)
|
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 =>
|
cmdAdd {cmd =>
|
||||||
cmd.opcode #= cmd.opcode.spinalEnum.FMV_X_W
|
cmd.opcode #= cmd.opcode.spinalEnum.FMV_X_W
|
||||||
cmd.rs1 #= rs1
|
cmd.rs1 #= rs1
|
||||||
|
@ -307,7 +325,7 @@ class FpuTest extends FunSuite{
|
||||||
cmd.rd.randomize()
|
cmd.rd.randomize()
|
||||||
cmd.arg #= 0
|
cmd.arg #= 0
|
||||||
}
|
}
|
||||||
rspQueue += body
|
rspQueue += {rsp => body(b2f(rsp.value.toLong.toInt))}
|
||||||
}
|
}
|
||||||
|
|
||||||
def fmv_w_x(rd : Int, value : Int): Unit ={
|
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 =>
|
cmdAdd {cmd =>
|
||||||
cmd.opcode #= cmd.opcode.spinalEnum.SGNJ
|
cmd.opcode #= FpuOpcode.FCLASS
|
||||||
cmd.rs1 #= rs1
|
cmd.rs1 #= rs1
|
||||||
cmd.rs2 #= rs2
|
cmd.rs2.randomize()
|
||||||
cmd.rs3.randomize()
|
cmd.rs3.randomize()
|
||||||
cmd.rd #= rd
|
cmd.rd.randomize()
|
||||||
cmd.arg #= 0
|
cmd.arg.randomize()
|
||||||
}
|
|
||||||
commitQueue += {cmd =>
|
|
||||||
cmd.write #= true
|
|
||||||
cmd.sync #= false
|
|
||||||
}
|
}
|
||||||
|
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)
|
val rd = Random.nextInt(32)
|
||||||
load(rd, a)
|
|
||||||
storeFloat(rd){v =>
|
def handle(v : Float): Unit ={
|
||||||
val refUnclamped = a
|
val refUnclamped = a
|
||||||
val ref = a
|
val ref = a
|
||||||
println(f"$a = $v, $ref")
|
assert(f2b(v) == f2b(ref), f"$a = $v, $ref")
|
||||||
assert(f2b(v) == f2b(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 ={
|
def testMul(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()
|
||||||
|
@ -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 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 testLt(a : Float, b : Float, ref : Int, flag : Int) = testCmpExact(a,b,ref,flag, 1)
|
||||||
|
|
||||||
def testFmv_x_w(a : Float): Unit ={
|
// def testFmv_x_w(a : Float): Unit ={
|
||||||
val rs = new RegAllocator()
|
// val rs = new RegAllocator()
|
||||||
val rs1, rs2, rs3 = rs.allocate()
|
// val rs1, rs2, rs3 = rs.allocate()
|
||||||
val rd = Random.nextInt(32)
|
// val rd = Random.nextInt(32)
|
||||||
load(rs1, a)
|
// load(rs1, a)
|
||||||
fmv_x_w(rs1){rsp =>
|
// fmv_x_w(rs1){rsp =>
|
||||||
val ref = f2b(a).toLong & 0xFFFFFFFFl
|
// val ref = f2b(a).toLong & 0xFFFFFFFFl
|
||||||
val v = rsp.value.toBigInt
|
// val v = rsp.value.toBigInt
|
||||||
println(f"fmv_x_w $a = $v, $ref")
|
// println(f"fmv_x_w $a = $v, $ref")
|
||||||
assert(v === ref)
|
// assert(v === ref)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
def testFmv_w_x(a : Int): Unit ={
|
// def testFmv_w_x(a : Int): Unit ={
|
||||||
val rs = new RegAllocator()
|
// val rs = new RegAllocator()
|
||||||
val rs1, rs2, rs3 = rs.allocate()
|
// val rs1, rs2, rs3 = rs.allocate()
|
||||||
val rd = Random.nextInt(32)
|
// val rd = Random.nextInt(32)
|
||||||
fmv_w_x(rd, a)
|
// fmv_w_x(rd, a)
|
||||||
storeFloat(rd){v =>
|
// storeFloat(rd){v =>
|
||||||
val ref = b2f(a)
|
// val ref = b2f(a)
|
||||||
println(f"fmv_w_x $a = $v, $ref")
|
// println(f"fmv_w_x $a = $v, $ref")
|
||||||
assert(v === ref)
|
// assert(v === ref)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -710,18 +753,16 @@ class FpuTest extends FunSuite{
|
||||||
|
|
||||||
|
|
||||||
def testSgnj(a : Float, b : Float): Unit ={
|
def testSgnj(a : Float, b : Float): Unit ={
|
||||||
val rs = new RegAllocator()
|
val ref = b2f((f2b(a) & ~0x80000000) | f2b(b) & 0x80000000)
|
||||||
val rs1, rs2, rs3 = rs.allocate()
|
testBinaryOp(sgnj,a,b,ref,0, null,"sgnj")
|
||||||
val rd = Random.nextInt(32)
|
}
|
||||||
load(rs1, a)
|
def testSgnjn(a : Float, b : Float): Unit ={
|
||||||
load(rs2, b)
|
val ref = b2f((f2b(a) & ~0x80000000) | ((f2b(b) & 0x80000000) ^ 0x80000000))
|
||||||
|
testBinaryOp(sgnjn,a,b,ref,0, null,"sgnjn")
|
||||||
sgnj(rd,rs1,rs2)
|
}
|
||||||
storeFloat(rd){v =>
|
def testSgnjx(a : Float, b : Float): Unit ={
|
||||||
val ref = a * a.signum * b.signum
|
val ref = b2f(f2b(a) ^ (f2b(b) & 0x80000000))
|
||||||
println(f"sgnf $a $b = $v, $ref")
|
testBinaryOp(sgnjx,a,b,ref,0, null,"sgnjx")
|
||||||
assert(ref == v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -762,6 +803,41 @@ 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){
|
||||||
|
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){
|
for(_ <- 0 until 10000){
|
||||||
val (a,b,r,f) = f32.min.RAW.f32_f32_f32
|
val (a,b,r,f) = f32.min.RAW.f32_f32_f32
|
||||||
testMin(a,b)
|
testMin(a,b)
|
||||||
|
@ -890,9 +966,9 @@ class FpuTest extends FunSuite{
|
||||||
for(_ <- 0 until 1000) testAdd(randomFloat(), randomFloat())
|
for(_ <- 0 until 1000) testAdd(randomFloat(), randomFloat())
|
||||||
|
|
||||||
|
|
||||||
testLoadStore(1.17549435082e-38f)
|
// testTransfer(1.17549435082e-38f)
|
||||||
testLoadStore(1.4E-45f)
|
// testTransfer(1.4E-45f)
|
||||||
testLoadStore(3.44383110592e-41f)
|
// testTransfer(3.44383110592e-41f)
|
||||||
|
|
||||||
//TODO bring back those tests and test overflow / underflow (F2I)
|
//TODO bring back those tests and test overflow / underflow (F2I)
|
||||||
// testF2i(16.0f , false)
|
// testF2i(16.0f , false)
|
||||||
|
@ -918,7 +994,7 @@ class FpuTest extends FunSuite{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
testLoadStore(1.2f)
|
// testTransfer(1.2f)
|
||||||
testMul(1.2f, 2.5f)
|
testMul(1.2f, 2.5f)
|
||||||
testMul(b2f(0x00400000), 16.0f)
|
testMul(b2f(0x00400000), 16.0f)
|
||||||
testMul(b2f(0x00100000), 16.0f)
|
testMul(b2f(0x00100000), 16.0f)
|
||||||
|
@ -941,8 +1017,8 @@ class FpuTest extends FunSuite{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
testLoadStore(1.765f)
|
// testTransfer(1.765f)
|
||||||
testFmv_w_x(f2b(7.234f))
|
// testFmv_w_x(f2b(7.234f))
|
||||||
testI2f(64, false)
|
testI2f(64, false)
|
||||||
for(i <- iUnsigned) testI2f(i, false)
|
for(i <- iUnsigned) testI2f(i, false)
|
||||||
for(i <- iSigned) testI2f(i, true)
|
for(i <- iSigned) testI2f(i, true)
|
||||||
|
@ -985,8 +1061,8 @@ class FpuTest extends FunSuite{
|
||||||
// dut.clockDomain.waitSampling(10000000)
|
// dut.clockDomain.waitSampling(10000000)
|
||||||
|
|
||||||
|
|
||||||
testFmv_x_w(1.246f)
|
// testFmv_x_w(1.246f)
|
||||||
testFmv_w_x(f2b(7.234f))
|
// testFmv_w_x(f2b(7.234f))
|
||||||
|
|
||||||
testSgnj(1.0f, 2.0f)
|
testSgnj(1.0f, 2.0f)
|
||||||
testSgnj(1.5f, 2.0f)
|
testSgnj(1.5f, 2.0f)
|
||||||
|
@ -1091,8 +1167,8 @@ class FpuTest extends FunSuite{
|
||||||
tests += (() =>{testDiv(randomFloat(), randomFloat())})
|
tests += (() =>{testDiv(randomFloat(), randomFloat())})
|
||||||
tests += (() =>{testSqrt(randomFloat().abs)})
|
tests += (() =>{testSqrt(randomFloat().abs)})
|
||||||
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