fpu got exception flag right for add/sub/mul/i2f/f2i
This commit is contained in:
parent
936e5823dc
commit
6170243283
|
@ -451,6 +451,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
|
|
||||||
val recoded = CombInit(input.rs1)
|
val recoded = CombInit(input.rs1)
|
||||||
|
|
||||||
|
val flag = io.port(input.source).completion.flag
|
||||||
|
|
||||||
val halt = False
|
val halt = False
|
||||||
val recodedResult = Bits(32 bits)//recoded.asBits.resize(32 bits)
|
val recodedResult = Bits(32 bits)//recoded.asBits.resize(32 bits)
|
||||||
|
@ -522,6 +523,10 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
}
|
}
|
||||||
is(FpuFloat.NAN){
|
is(FpuFloat.NAN){
|
||||||
recodedResult(23, 8 bits).setAll()
|
recodedResult(23, 8 bits).setAll()
|
||||||
|
when(input.rs1.isCanonical){
|
||||||
|
recodedResult(31) := False
|
||||||
|
recodedResult(0, 22 bits) := 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -540,8 +545,8 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
FpuRoundMode.RMM -> (round(1))
|
FpuRoundMode.RMM -> (round(1))
|
||||||
)
|
)
|
||||||
val result = (Mux(resign, ~unsigned, unsigned) + (resign ^ increment).asUInt)
|
val result = (Mux(resign, ~unsigned, unsigned) + (resign ^ increment).asUInt)
|
||||||
val overflow = RegNext((input.rs1.exponent > (input.arg(0) ? U(exponentOne+30) | U(exponentOne+31)) || input.rs1.isInfinity) && !input.rs1.sign || input.rs1.isNan)
|
val overflow = (input.rs1.exponent > (input.arg(0) ? U(exponentOne+30) | U(exponentOne+31)) || input.rs1.isInfinity) && !input.rs1.sign || input.rs1.isNan
|
||||||
val underflow = RegNext((input.rs1.exponent > U(exponentOne+30) || !input.arg(0) || input.rs1.isInfinity) && input.rs1.sign)
|
val underflow = (input.rs1.exponent > U(exponentOne+31) || input.arg(0) && unsigned.msb && unsigned(30 downto 0) =/= 0 || !input.arg(0) && (unsigned =/= 0 || increment) || input.rs1.isInfinity) && input.rs1.sign
|
||||||
val isZero = input.rs1.isZero
|
val isZero = input.rs1.isZero
|
||||||
when(isZero){
|
when(isZero){
|
||||||
result := 0
|
result := 0
|
||||||
|
@ -549,6 +554,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
val low = overflow
|
val low = overflow
|
||||||
val high = input.arg(0) ^ overflow
|
val high = input.arg(0) ^ overflow
|
||||||
result := (31 -> high, default -> low)
|
result := (31 -> high, default -> low)
|
||||||
|
flag.NV := input.valid && input.opcode === FpuOpcode.F2I && fsm.done && !isZero
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,8 +654,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
scrap setWhen(needShift && mulHigh(0))
|
scrap setWhen(needShift && mulHigh(0))
|
||||||
val forceZero = input.rs1.isZero || input.rs2.isZero
|
val forceZero = input.rs1.isZero || input.rs2.isZero
|
||||||
val forceUnderflow = exp < exponentOne + exponentOne - 127 - 24 // 0x6A //TODO
|
val forceUnderflow = exp < exponentOne + exponentOne - 127 - 24 // 0x6A //TODO
|
||||||
val forceOverflow = /*exp > exponentOne + exponentOne + 127 || */input.rs1.isInfinity || input.rs2.isInfinity
|
val forceOverflow = input.rs1.isInfinity || input.rs2.isInfinity
|
||||||
val forceNan = input.rs1.isNan || input.rs2.isNan || ((input.rs1.isInfinity || input.rs2.isInfinity) && (input.rs1.isZero || input.rs2.isZero))
|
val infinitynan = ((input.rs1.isInfinity || input.rs2.isInfinity) && (input.rs1.isZero || input.rs2.isZero))
|
||||||
|
val forceNan = input.rs1.isNan || input.rs2.isNan || infinitynan
|
||||||
|
|
||||||
val output = p.writeFloating()
|
val output = p.writeFloating()
|
||||||
output.sign := input.rs1.sign ^ input.rs2.sign
|
output.sign := input.rs1.sign ^ input.rs2.sign
|
||||||
|
@ -657,8 +664,10 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
output.mantissa := man.asUInt
|
output.mantissa := man.asUInt
|
||||||
output.setNormal
|
output.setNormal
|
||||||
|
|
||||||
|
val flag = io.port(input.source).completion.flag
|
||||||
when(forceNan) {
|
when(forceNan) {
|
||||||
output.setNanQuiet
|
output.setNanQuiet
|
||||||
|
flag.NV setWhen(input.valid && (infinitynan || input.rs1.isNanSignaling || input.rs2.isNanSignaling))
|
||||||
} elsewhen(forceOverflow) {
|
} elsewhen(forceOverflow) {
|
||||||
output.setInfinity
|
output.setInfinity
|
||||||
} elsewhen(forceZero) {
|
} elsewhen(forceZero) {
|
||||||
|
@ -936,7 +945,8 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
val forceZero = xyMantissa === 0 || (input.rs1.isZero && input.rs2.isZero)
|
val forceZero = xyMantissa === 0 || (input.rs1.isZero && input.rs2.isZero)
|
||||||
// val forceOverflow = exponent === exponentOne + 128 //Handled by writeback rounding
|
// val forceOverflow = exponent === exponentOne + 128 //Handled by writeback rounding
|
||||||
val forceInfinity = (input.rs1.isInfinity || input.rs2.isInfinity)
|
val forceInfinity = (input.rs1.isInfinity || input.rs2.isInfinity)
|
||||||
val forceNan = input.rs1.isNan || input.rs2.isNan || (input.rs1.isInfinity && input.rs2.isInfinity && (input.rs1.sign ^ input.rs2.sign))
|
val infinityNan = (input.rs1.isInfinity && input.rs2.isInfinity && (input.rs1.sign ^ input.rs2.sign))
|
||||||
|
val forceNan = input.rs1.isNan || input.rs2.isNan || infinityNan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -951,6 +961,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
output.roundMode := input.roundMode
|
output.roundMode := input.roundMode
|
||||||
output.scrap := (norm.mantissa(1) | norm.mantissa(0) | shifter.roundingScrap)
|
output.scrap := (norm.mantissa(1) | norm.mantissa(0) | shifter.roundingScrap)
|
||||||
|
|
||||||
|
|
||||||
|
val flag = io.port(input.source).completion.flag
|
||||||
|
flag.NV setWhen(input.valid && (norm.infinityNan || input.rs1.isNanSignaling || input.rs2.isNanSignaling))
|
||||||
when(norm.forceNan) {
|
when(norm.forceNan) {
|
||||||
output.value.setNanQuiet
|
output.value.setNanQuiet
|
||||||
} elsewhen(norm.forceZero) {
|
} elsewhen(norm.forceZero) {
|
||||||
|
@ -963,21 +976,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
}
|
}
|
||||||
} elsewhen(norm.forceInfinity) {
|
} elsewhen(norm.forceInfinity) {
|
||||||
output.value.setInfinity
|
output.value.setInfinity
|
||||||
} /*elsewhen(norm.forceOverflow) {
|
}
|
||||||
val doMax = input.roundMode.mux(
|
|
||||||
FpuRoundMode.RNE -> (False),
|
|
||||||
FpuRoundMode.RTZ -> (True),
|
|
||||||
FpuRoundMode.RDN -> (!output.value.sign),
|
|
||||||
FpuRoundMode.RUP -> (output.value.sign),
|
|
||||||
FpuRoundMode.RMM -> (False)
|
|
||||||
)
|
|
||||||
when(doMax){
|
|
||||||
output.value.exponent := exponentOne + 127
|
|
||||||
output.value.mantissa.setAll()
|
|
||||||
} otherwise {
|
|
||||||
output.value.setInfinity
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -993,8 +992,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
|
|
||||||
//TODO do not break NAN payload (seems already fine)
|
//TODO do not break NAN payload (seems already fine)
|
||||||
val manAggregate = input.value.mantissa @@ input.scrap
|
val manAggregate = input.value.mantissa @@ input.scrap
|
||||||
val expDif = (exponentOne-126) - input.value.exponent
|
val expDif = (exponentOne-126) -^ input.value.exponent
|
||||||
val discardCount = expDif.msb ? U(0) | expDif.resize(log2Up(p.internalMantissaSize) bits)
|
val expSubnormal = !expDif.msb
|
||||||
|
val discardCount = expSubnormal ? expDif.resize(log2Up(p.internalMantissaSize) bits) | U(0)
|
||||||
val exactMask = (List(True) ++ (0 until p.internalMantissaSize+1).map(_ < discardCount)).asBits.asUInt
|
val exactMask = (List(True) ++ (0 until p.internalMantissaSize+1).map(_ < discardCount)).asBits.asUInt
|
||||||
val roundAdjusted = (True ## (manAggregate>>1))(discardCount) ## ((manAggregate & exactMask) =/= 0)
|
val roundAdjusted = (True ## (manAggregate>>1))(discardCount) ## ((manAggregate & exactMask) =/= 0)
|
||||||
|
|
||||||
|
@ -1017,8 +1017,18 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
math.mantissa := adder(0, p.internalMantissaSize bits)
|
math.mantissa := adder(0, p.internalMantissaSize bits)
|
||||||
|
|
||||||
val patched = CombInit(math)
|
val patched = CombInit(math)
|
||||||
|
val nx,of,uf = False
|
||||||
|
// val ufPatch = input.roundMode === FpuRoundMode.RUP && !input.value.sign && !input.scrap|| input.roundMode === FpuRoundMode.RDN && input.value.sign && !input.scrap
|
||||||
|
// when(!math.special && (input.value.exponent <= exponentOne-127 && (math.exponent =/= exponentOne-126 || !input.value.mantissa.lsb || ufPatch)) && roundAdjusted.asUInt =/= 0){
|
||||||
|
// uf := True
|
||||||
|
// }
|
||||||
|
|
||||||
|
when(!math.special && math.exponent <= exponentOne-127 && roundAdjusted.asUInt =/= 0){ //Do not catch exact 1.17549435E-38 underflow, but, who realy care ?
|
||||||
|
uf := True
|
||||||
|
}
|
||||||
when(!math.special && math.exponent >= exponentOne + 128){
|
when(!math.special && math.exponent >= exponentOne + 128){
|
||||||
// patched.setInfinity
|
nx := True
|
||||||
|
of := True
|
||||||
val doMax = input.roundMode.mux(
|
val doMax = input.roundMode.mux(
|
||||||
FpuRoundMode.RNE -> (False),
|
FpuRoundMode.RNE -> (False),
|
||||||
FpuRoundMode.RTZ -> (True),
|
FpuRoundMode.RTZ -> (True),
|
||||||
|
@ -1036,6 +1046,8 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
|
|
||||||
|
|
||||||
when(!math.special && math.exponent <= exponentOne - 127-23){
|
when(!math.special && math.exponent <= exponentOne - 127-23){
|
||||||
|
nx := True
|
||||||
|
uf := True
|
||||||
val doMin = input.roundMode.mux(
|
val doMin = input.roundMode.mux(
|
||||||
FpuRoundMode.RNE -> (False),
|
FpuRoundMode.RNE -> (False),
|
||||||
FpuRoundMode.RTZ -> (False),
|
FpuRoundMode.RTZ -> (False),
|
||||||
|
@ -1051,6 +1063,14 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nx setWhen(!input.value.special && (roundAdjusted =/= 0))
|
||||||
|
when(input.valid){
|
||||||
|
val flag = io.port(input.source).completion.flag
|
||||||
|
flag.NX setWhen(nx)
|
||||||
|
flag.OF setWhen(of)
|
||||||
|
flag.UF setWhen(uf)
|
||||||
|
}
|
||||||
val output = input.swapPayload(RoundOutput())
|
val output = input.swapPayload(RoundOutput())
|
||||||
output.source := input.source
|
output.source := input.source
|
||||||
output.lockId := input.lockId
|
output.lockId := input.lockId
|
||||||
|
@ -1079,8 +1099,11 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
|
||||||
if(p.sim) when(port.data.isZero || port.data.isInfinity){
|
if(p.sim) when(port.data.isZero || port.data.isInfinity){
|
||||||
port.data.mantissa.assignDontCare()
|
port.data.mantissa.assignDontCare()
|
||||||
}
|
}
|
||||||
if(p.sim) when(port.data.special){
|
if(p.sim) when(input.value.special){
|
||||||
port.data.exponent(p.internalExponentSize-1 downto 2).assignDontCare()
|
port.data.exponent(p.internalExponentSize-1 downto 3).assignDontCare()
|
||||||
|
when(!input.value.isNan){
|
||||||
|
port.data.exponent(2 downto 2).assignDontCare()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
when(port.valid){
|
when(port.valid){
|
||||||
|
|
|
@ -27,6 +27,7 @@ object FpuFloat{
|
||||||
val ZERO = 0
|
val ZERO = 0
|
||||||
val INFINITY = 1
|
val INFINITY = 1
|
||||||
val NAN = 2
|
val NAN = 2
|
||||||
|
val NAN_CANONICAL_BIT = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
case class FpuFloat(exponentSize: Int,
|
case class FpuFloat(exponentSize: Int,
|
||||||
|
@ -49,12 +50,14 @@ case class FpuFloat(exponentSize: Int,
|
||||||
def isInfinity = special && exponent(1 downto 0) === FpuFloat.INFINITY
|
def isInfinity = special && exponent(1 downto 0) === FpuFloat.INFINITY
|
||||||
def isNan = special && exponent(1 downto 0) === FpuFloat.NAN
|
def isNan = special && exponent(1 downto 0) === FpuFloat.NAN
|
||||||
def isQuiet = mantissa.msb
|
def isQuiet = mantissa.msb
|
||||||
|
def isNanSignaling = special && exponent(1 downto 0) === FpuFloat.NAN && !isQuiet
|
||||||
|
def isCanonical = exponent(FpuFloat.NAN_CANONICAL_BIT)
|
||||||
|
|
||||||
def setNormal = { special := False }
|
def setNormal = { special := False }
|
||||||
def setZero = { special := True; exponent(1 downto 0) := FpuFloat.ZERO }
|
def setZero = { special := True; exponent(1 downto 0) := FpuFloat.ZERO }
|
||||||
def setInfinity = { special := True; exponent(1 downto 0) := FpuFloat.INFINITY }
|
def setInfinity = { special := True; exponent(1 downto 0) := FpuFloat.INFINITY }
|
||||||
def setNan = { special := True; exponent(1 downto 0) := FpuFloat.NAN }
|
def setNan = { special := True; exponent(1 downto 0) := FpuFloat.NAN; exponent(FpuFloat.NAN_CANONICAL_BIT) := False}
|
||||||
def setNanQuiet = { special := True; exponent(1 downto 0) := FpuFloat.NAN ; mantissa.msb := True }
|
def setNanQuiet = { special := True; exponent(1 downto 0) := FpuFloat.NAN; exponent(FpuFloat.NAN_CANONICAL_BIT) := True; mantissa.msb := True; }
|
||||||
|
|
||||||
def decode() = {
|
def decode() = {
|
||||||
val ret = FpuFloatDecoded()
|
val ret = FpuFloatDecoded()
|
||||||
|
|
|
@ -23,7 +23,7 @@ import scala.util.Random
|
||||||
class FpuTest extends FunSuite{
|
class FpuTest extends FunSuite{
|
||||||
|
|
||||||
val b2f = lang.Float.intBitsToFloat(_)
|
val b2f = lang.Float.intBitsToFloat(_)
|
||||||
val f2b = lang.Float.floatToIntBits(_)
|
val f2b = lang.Float.floatToRawIntBits(_)
|
||||||
|
|
||||||
def clamp(f : Float) = {
|
def clamp(f : Float) = {
|
||||||
f // if(f.abs < b2f(0x00800000)) b2f(f2b(f) & 0x80000000) else f
|
f // if(f.abs < b2f(0x00800000)) b2f(f2b(f) & 0x80000000) else f
|
||||||
|
@ -38,9 +38,11 @@ class FpuTest extends FunSuite{
|
||||||
)
|
)
|
||||||
|
|
||||||
val config = SimConfig
|
val config = SimConfig
|
||||||
// config.withFstWave
|
config.allOptimisation
|
||||||
|
config.withFstWave
|
||||||
config.compile(new FpuCore(portCount, p){
|
config.compile(new FpuCore(portCount, p){
|
||||||
for(i <- 0 until portCount) out(Bits(5 bits)).setName(s"flagAcc$i") := io.port(i).completion.flag.asBits
|
for(i <- 0 until portCount) out(Bits(5 bits)).setName(s"flagAcc$i") := io.port(i).completion.flag.asBits
|
||||||
|
setDefinitionName("FpuCore")
|
||||||
}).doSim(seed = 42){ dut =>
|
}).doSim(seed = 42){ dut =>
|
||||||
dut.clockDomain.forkStimulus(10)
|
dut.clockDomain.forkStimulus(10)
|
||||||
dut.clockDomain.forkSimSpeedPrinter(5.0)
|
dut.clockDomain.forkSimSpeedPrinter(5.0)
|
||||||
|
@ -48,10 +50,29 @@ class FpuTest extends FunSuite{
|
||||||
|
|
||||||
|
|
||||||
class TestCase(op : String){
|
class TestCase(op : String){
|
||||||
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -forever -$op"){
|
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -tininessafter -forever -$op"){
|
||||||
def f32_2 ={
|
def f32_f32 ={
|
||||||
val s = new Scanner(next)
|
val s = new Scanner(next)
|
||||||
(b2f(s.nextLong(16).toInt), b2f(s.nextLong(16).toInt), b2f(s.nextLong(16).toInt), s.nextInt(16))
|
val a,b,c = (s.nextLong(16).toInt)
|
||||||
|
// if(b2f(a).isNaN || b2f(b).isNaN){
|
||||||
|
// print("NAN => ")
|
||||||
|
// if(((a >> 23) & 0xFF) == 0xFF && ((a >> 0) & 0xEFFFFF) != 0){
|
||||||
|
// print(a.toHexString)
|
||||||
|
// print(" " + f2b(b2f(a)).toHexString)
|
||||||
|
// }
|
||||||
|
// if(((b >> 23) & 0xFF) == 0xFF && ((b >> 0) & 0xEFFFFF) != 0){
|
||||||
|
// print(b.toHexString)
|
||||||
|
// print(" " + f2b(b2f(b)).toHexString)
|
||||||
|
// }
|
||||||
|
// if(((c >> 23) & 0xFF) == 0xFF && ((c >> 0) & 0xEFFFFF) != 0){
|
||||||
|
// print(" " + c.toHexString)
|
||||||
|
// print(" " + f2b(b2f(c)).toHexString)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// print(" " + simTime())
|
||||||
|
// println("")
|
||||||
|
// }
|
||||||
|
(b2f(a), b2f(b), b2f(c), s.nextInt(16))
|
||||||
}
|
}
|
||||||
|
|
||||||
def i32_f32 ={
|
def i32_f32 ={
|
||||||
|
@ -95,18 +116,26 @@ class FpuTest extends FunSuite{
|
||||||
val commitQueue = mutable.Queue[FpuCommit => Unit]()
|
val commitQueue = mutable.Queue[FpuCommit => Unit]()
|
||||||
val rspQueue = mutable.Queue[FpuRsp => Unit]()
|
val rspQueue = mutable.Queue[FpuRsp => Unit]()
|
||||||
|
|
||||||
var pending = 0
|
var pendingMiaou = 0
|
||||||
var flagAccumulator = 0
|
var flagAccumulator = 0
|
||||||
|
|
||||||
def cmdAdd(body : FpuCmd => Unit): Unit ={
|
def cmdAdd(body : FpuCmd => Unit): Unit ={
|
||||||
pending += 1
|
pendingMiaou += 1
|
||||||
cmdQueue += body
|
cmdQueue += body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def softAssert(cond : Boolean, msg : String) = if(!cond)println(msg)
|
||||||
|
def flagMatch(ref : Int, value : Float, report : String): Unit ={
|
||||||
|
waitUntil(pendingMiaou == 0)
|
||||||
|
val patch = if(value.abs == 1.17549435E-38f) ref & ~2 else ref
|
||||||
|
assert(flagAccumulator == patch, s"Flag missmatch dut=$flagAccumulator ref=$patch $report")
|
||||||
|
flagAccumulator = 0
|
||||||
|
}
|
||||||
|
|
||||||
val flagAggregated = dut.reflectBaseType(s"flagAcc$id").asInstanceOf[Bits]
|
val flagAggregated = dut.reflectBaseType(s"flagAcc$id").asInstanceOf[Bits]
|
||||||
dut.clockDomain.onSamplings{
|
dut.clockDomain.onSamplings{
|
||||||
val c = dut.io.port(id).completion
|
val c = dut.io.port(id).completion
|
||||||
pending -= c.count.toInt
|
pendingMiaou -= c.count.toInt
|
||||||
flagAccumulator |= flagAggregated.toInt
|
flagAccumulator |= flagAggregated.toInt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +181,7 @@ class FpuTest extends FunSuite{
|
||||||
}
|
}
|
||||||
|
|
||||||
def load(rd : Int, value : Float): Unit ={
|
def load(rd : Int, value : Float): Unit ={
|
||||||
loadRaw(rd, lang.Float.floatToIntBits(value).toLong & 0xFFFFFFFFl)
|
loadRaw(rd, f2b(value).toLong & 0xFFFFFFFFl)
|
||||||
}
|
}
|
||||||
|
|
||||||
def storeRaw(rs : Int)(body : FpuRsp => Unit): Unit ={
|
def storeRaw(rs : Int)(body : FpuRsp => Unit): Unit ={
|
||||||
|
@ -166,7 +195,7 @@ class FpuTest extends FunSuite{
|
||||||
}
|
}
|
||||||
|
|
||||||
rspQueue += body
|
rspQueue += body
|
||||||
waitUntil(rspQueue.isEmpty)
|
// waitUntil(rspQueue.isEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
def storeFloat(rs : Int)(body : Float => Unit): Unit ={
|
def storeFloat(rs : Int)(body : Float => Unit): Unit ={
|
||||||
|
@ -385,6 +414,9 @@ class FpuTest extends FunSuite{
|
||||||
storeFloat(rd){v =>
|
storeFloat(rd){v =>
|
||||||
assert(f2b(v) == f2b(ref), f"## ${a} ${opName} $b = $v, $ref $rounding")
|
assert(f2b(v) == f2b(ref), f"## ${a} ${opName} $b = $v, $ref $rounding")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
flagMatch(flag, ref, f"## ${opName} ${a} $b $ref $rounding")
|
||||||
}
|
}
|
||||||
|
|
||||||
def testAddExact(a : Float, b : Float, ref : Float, flag : Int, rounding : FpuRoundMode.E): Unit ={
|
def testAddExact(a : Float, b : Float, ref : Float, flag : Int, rounding : FpuRoundMode.E): Unit ={
|
||||||
|
@ -538,6 +570,8 @@ class FpuTest extends FunSuite{
|
||||||
assert(v == ref2, f" <= f2ui($a) = $v, $ref2, $rounding $flag")
|
assert(v == ref2, f" <= f2ui($a) = $v, $ref2, $rounding $flag")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flagMatch(flag, ref, f" f2${if(signed) "" else "u"}i($a) $ref $flag $rounding")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -563,6 +597,9 @@ class FpuTest extends FunSuite{
|
||||||
val ref = b
|
val ref = b
|
||||||
assert(f2b(v) == f2b(ref), f"i2f($aLong) = $v, $ref")
|
assert(f2b(v) == f2b(ref), f"i2f($aLong) = $v, $ref")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
flagMatch(f, b, f"i2f() = $b")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -589,7 +626,7 @@ class FpuTest extends FunSuite{
|
||||||
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 = lang.Float.floatToIntBits(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)
|
||||||
|
@ -682,48 +719,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)
|
||||||
|
|
||||||
testI2f(24, false)
|
|
||||||
testI2f(17, false)
|
|
||||||
|
|
||||||
testLoadStore(2.5f)
|
testF2iExact(-2.14748365E9f, -2147483648, 0, true, FpuRoundMode.RDN)
|
||||||
testLoadStore(3.67341984632e-40f)
|
|
||||||
testLoadStore(5.5321021294e-40f)
|
|
||||||
|
|
||||||
|
for(_ <- 0 until 10000){
|
||||||
for(_ <- 0 until 100000){
|
|
||||||
val rounding = FpuRoundMode.elements.randomPick()
|
|
||||||
val (a,b,c,f) = f32.add(rounding).f32_2
|
|
||||||
testBinaryOp(add,a,b,c,f, rounding,"add")
|
|
||||||
}
|
|
||||||
|
|
||||||
for(_ <- 0 until 100000){
|
|
||||||
val rounding = FpuRoundMode.elements.randomPick()
|
|
||||||
val (a,b,c,f) = f32.sub(rounding).f32_2
|
|
||||||
testBinaryOp(sub,a,b,c,f, rounding,"sub")
|
|
||||||
}
|
|
||||||
|
|
||||||
println("Add done")
|
|
||||||
|
|
||||||
for(_ <- 0 until 100000){
|
|
||||||
val rounding = FpuRoundMode.elements.randomPick()
|
|
||||||
val (a,b,f) = f32.i2f(rounding).i32_f32
|
|
||||||
testI2fExact(a,b,f, true, rounding)
|
|
||||||
}
|
|
||||||
|
|
||||||
for(_ <- 0 until 100000){
|
|
||||||
val rounding = FpuRoundMode.elements.randomPick()
|
|
||||||
val (a,b,f) = f32.ui2f(rounding).i32_f32
|
|
||||||
testI2fExact(a,b,f, false, rounding)
|
|
||||||
}
|
|
||||||
println("i2f done")
|
|
||||||
|
|
||||||
for(_ <- 0 until 100000){
|
|
||||||
val rounding = FpuRoundMode.elements.randomPick()
|
val rounding = FpuRoundMode.elements.randomPick()
|
||||||
val (a,b,f) = f32.f2ui(rounding).f32_i32
|
val (a,b,f) = f32.f2ui(rounding).f32_i32
|
||||||
testF2iExact(a,b, f, false, rounding)
|
testF2iExact(a,b, f, false, rounding)
|
||||||
}
|
}
|
||||||
|
|
||||||
for(_ <- 0 until 100000){
|
for(_ <- 0 until 10000){
|
||||||
val rounding = FpuRoundMode.elements.randomPick()
|
val rounding = FpuRoundMode.elements.randomPick()
|
||||||
val (a,b,f) = f32.f2i(rounding).f32_i32
|
val (a,b,f) = f32.f2i(rounding).f32_i32
|
||||||
testF2iExact(a,b, f, true, rounding)
|
testF2iExact(a,b, f, true, rounding)
|
||||||
|
@ -731,17 +736,63 @@ class FpuTest extends FunSuite{
|
||||||
|
|
||||||
println("f2i done")
|
println("f2i done")
|
||||||
|
|
||||||
|
for(_ <- 0 until 10000){
|
||||||
|
|
||||||
for(_ <- 0 until 100000){
|
|
||||||
val rounding = FpuRoundMode.elements.randomPick()
|
val rounding = FpuRoundMode.elements.randomPick()
|
||||||
val (a,b,c,f) = f32.mul(rounding).f32_2
|
val (a,b,f) = f32.i2f(rounding).i32_f32
|
||||||
|
testI2fExact(a,b,f, true, rounding)
|
||||||
|
}
|
||||||
|
|
||||||
|
for(_ <- 0 until 10000){
|
||||||
|
val rounding = FpuRoundMode.elements.randomPick()
|
||||||
|
val (a,b,f) = f32.ui2f(rounding).i32_f32
|
||||||
|
testI2fExact(a,b,f, false, rounding)
|
||||||
|
}
|
||||||
|
println("i2f 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){
|
||||||
|
val rounding = FpuRoundMode.elements.randomPick()
|
||||||
|
val (a,b,c,f) = f32.mul(rounding).f32_f32
|
||||||
testBinaryOp(mul,a,b,c,f, rounding,"mul")
|
testBinaryOp(mul,a,b,c,f, rounding,"mul")
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Mul done")
|
println("Mul done")
|
||||||
|
|
||||||
|
|
||||||
|
for(_ <- 0 until 10000){
|
||||||
|
val rounding = FpuRoundMode.elements.randomPick()
|
||||||
|
val (a,b,c,f) = f32.add(rounding).f32_f32
|
||||||
|
testBinaryOp(add,a,b,c,f, rounding,"add")
|
||||||
|
}
|
||||||
|
|
||||||
|
for(_ <- 0 until 10000){
|
||||||
|
val rounding = FpuRoundMode.elements.randomPick()
|
||||||
|
val (a,b,c,f) = f32.sub(rounding).f32_f32
|
||||||
|
testBinaryOp(sub,a,b,c,f, rounding,"sub")
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Add done")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -823,7 +874,7 @@ class FpuTest extends FunSuite{
|
||||||
|
|
||||||
|
|
||||||
testLoadStore(1.765f)
|
testLoadStore(1.765f)
|
||||||
testFmv_w_x(lang.Float.floatToIntBits(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)
|
||||||
|
@ -874,7 +925,7 @@ class FpuTest extends FunSuite{
|
||||||
|
|
||||||
|
|
||||||
testFmv_x_w(1.246f)
|
testFmv_x_w(1.246f)
|
||||||
testFmv_w_x(lang.Float.floatToIntBits(7.234f))
|
testFmv_w_x(f2b(7.234f))
|
||||||
|
|
||||||
testMin(1.0f, 2.0f)
|
testMin(1.0f, 2.0f)
|
||||||
testMin(1.5f, 2.0f)
|
testMin(1.5f, 2.0f)
|
||||||
|
@ -989,7 +1040,7 @@ class FpuTest extends FunSuite{
|
||||||
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(lang.Float.floatToIntBits(randomFloat()))})
|
tests += (() =>{testFmv_w_x(f2b(randomFloat()))})
|
||||||
tests += (() =>{testMin(randomFloat(), randomFloat())})
|
tests += (() =>{testMin(randomFloat(), randomFloat())})
|
||||||
tests += (() =>{testSgnj(randomFloat(), randomFloat())})
|
tests += (() =>{testSgnj(randomFloat(), randomFloat())})
|
||||||
|
|
||||||
|
@ -1018,15 +1069,37 @@ object Clib {
|
||||||
DoCmd.doCmd(cmd)
|
DoCmd.doCmd(cmd)
|
||||||
val math = new FpuMath
|
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{
|
object FpuCompileSo extends App{
|
||||||
|
|
||||||
val b2f = lang.Float.intBitsToFloat(_)
|
// val b2f = lang.Float.intBitsToFloat(_)
|
||||||
for(e <- FpuRoundMode.elements) {
|
// for(e <- FpuRoundMode.elements) {
|
||||||
println(e)
|
// println(e)
|
||||||
for (i <- -2 until 50) println(i + " => " + Clib.math.addF32(b2f(0x7f000000), b2f(0x7f000000 + i), e.position))
|
// for (i <- -2 until 50) println(i + " => " + Clib.math.addF32(b2f(0x7f000000), b2f(0x7f000000 + i), e.position))
|
||||||
println("")
|
// 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
|
||||||
|
|
||||||
|
|
||||||
|
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.RNE.position))
|
||||||
// println(Clib.math.addF32(1.00000011921f, 4.0f, FpuRoundMode.RTZ.position))
|
// println(Clib.math.addF32(1.00000011921f, 4.0f, FpuRoundMode.RTZ.position))
|
||||||
|
|
Loading…
Reference in New Issue