fpu load subnormal and i2f now use single cycle shifter

This commit is contained in:
Dolu1990 2021-02-03 16:48:09 +01:00
parent 8e7e736e3e
commit 02b5b9b05c
2 changed files with 51 additions and 38 deletions

View File

@ -354,13 +354,22 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val isQuiet = f32Mantissa.msb
val fsm = new Area{
val manTop = Reg(UInt(log2Up(p.internalMantissaSize) bits))
val shift = CombInit(manTop)
val counter = Reg(UInt(log2Up(p.internalMantissaSize+1) bits))
val done, boot, patched = Reg(Bool())
val ohInput = CombInit(input.value(0, 32 max p.internalMantissaSize bits))
when(!input.i2f) { ohInput(9, 23 bits) := input.value(0, 23 bits) }
val i2fZero = Reg(Bool)
val shift = new Area{
val by = Reg(UInt(log2Up(p.internalMantissaSize max 32) bits))
val input = UInt(p.internalMantissaSize max 32 bits).assignDontCare()
var logic = input
for(i <- by.range){
logic \= by(i) ? (logic |<< (BigInt(1) << i)) | logic
}
val output = RegNextWhen(logic, !done)
}
shift.input := input.value.asUInt |<< 1
when(input.valid && (input.i2f || isSubnormal) && !done){
busy := True
when(boot){
@ -368,31 +377,27 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
input.value.getDrivingReg(0, 32 bits) := B(input.value.asUInt.twoComplement(True).resize(32 bits))
patched := True
} otherwise {
manTop := OHToUInt(OHMasking.first((ohInput).reversed))
shift.by := OHToUInt(OHMasking.first((ohInput).reversed)) + (input.i2f ? U(0) | U(9))
boot := False
i2fZero := input.value(31 downto 0) === 0
}
} otherwise {
when(input.i2f){
input.value.getDrivingReg(0, 32 bits) := input.value(0, 32 bits) |<< 1
} otherwise {
input.value.getDrivingReg(0, 23 bits) := input.value(0, 23 bits) |<< 1
}
counter := counter + 1
when(counter === shift) {
done := True
}
// when(input.i2f){
// input.value.getDrivingReg(0, 32 bits) := input.value(0, 32 bits) |<< 1
// } otherwise {
// input.value.getDrivingReg(0, 23 bits) := input.value(0, 23 bits) |<< 1
// }
done := True
}
}
val expOffset = (UInt(p.internalExponentSize bits))
expOffset := 0
when(isSubnormal){
expOffset := manTop.resized
expOffset := (shift.by-9).resized
}
when(!input.isStall){
counter := 0
done := False
boot := True
patched := False
@ -401,7 +406,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val i2fSign = fsm.patched
val (i2fHigh, i2fLow) = input.value.splitAt(widthOf(input.value)-24)
val (i2fHigh, i2fLow) = fsm.shift.output.splitAt(widthOf(input.value)-24)
val scrap = i2fLow =/= 0
val recoded = p.internalFloating()
@ -425,12 +430,14 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
output.scrap := False
when(input.i2f){
output.value.sign := i2fSign
output.value.exponent := (U(exponentOne+31) - fsm.manTop).resized
output.value.mantissa := U(i2fHigh)
output.value.exponent := (U(exponentOne+31) - fsm.shift.by).resized
output.value.setNormal
output.scrap := scrap
when(fsm.i2fZero) { output.value.setZero }
//TODO ROUND
}
when(input.i2f || isSubnormal){
output.value.mantissa := U(i2fHigh)
}
}
}

View File

@ -541,7 +541,6 @@ class FpuTest extends FunSuite{
storeFloat(rd){v =>
val aLong = if(signed) a.toLong else a.toLong & 0xFFFFFFFFl
val ref = b
// println(f"i2f($aLong) = $v, $ref")
assert(f2b(v) == f2b(ref), f"i2f($aLong) = $v, $ref")
}
}
@ -663,28 +662,48 @@ class FpuTest extends FunSuite{
val binaryOps = List[(Int,Int,Int,FpuRoundMode.E) => Unit](add, sub, mul)
testI2f(24, false)
testI2f(17, false)
testLoadStore(2.5f)
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 10000){
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 10000){
for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.f2ui(rounding).f32_i32
testF2iExact(a,b, f, false, rounding)
}
for(_ <- 0 until 10000){
for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.f2i(rounding).f32_i32
testF2iExact(a,b, f, true, rounding)
@ -693,21 +712,8 @@ class FpuTest extends FunSuite{
println("f2i done")
for(_ <- 0 until 10000){
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 10000){
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 10000){
for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.mul(rounding).f32_2
testBinaryOp(mul,a,b,c,f, rounding,"mul")