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 isQuiet = f32Mantissa.msb
val fsm = new Area{ 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 done, boot, patched = Reg(Bool())
val ohInput = CombInit(input.value(0, 32 max p.internalMantissaSize bits)) val ohInput = CombInit(input.value(0, 32 max p.internalMantissaSize bits))
when(!input.i2f) { ohInput(9, 23 bits) := input.value(0, 23 bits) } when(!input.i2f) { ohInput(9, 23 bits) := input.value(0, 23 bits) }
val i2fZero = Reg(Bool) 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){ when(input.valid && (input.i2f || isSubnormal) && !done){
busy := True busy := True
when(boot){ 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)) input.value.getDrivingReg(0, 32 bits) := B(input.value.asUInt.twoComplement(True).resize(32 bits))
patched := True patched := True
} otherwise { } otherwise {
manTop := OHToUInt(OHMasking.first((ohInput).reversed)) shift.by := OHToUInt(OHMasking.first((ohInput).reversed)) + (input.i2f ? U(0) | U(9))
boot := False boot := False
i2fZero := input.value(31 downto 0) === 0 i2fZero := input.value(31 downto 0) === 0
} }
} otherwise { } otherwise {
when(input.i2f){ // when(input.i2f){
input.value.getDrivingReg(0, 32 bits) := input.value(0, 32 bits) |<< 1 // input.value.getDrivingReg(0, 32 bits) := input.value(0, 32 bits) |<< 1
} otherwise { // } otherwise {
input.value.getDrivingReg(0, 23 bits) := input.value(0, 23 bits) |<< 1 // input.value.getDrivingReg(0, 23 bits) := input.value(0, 23 bits) |<< 1
} // }
counter := counter + 1
when(counter === shift) {
done := True done := True
} }
} }
}
val expOffset = (UInt(p.internalExponentSize bits)) val expOffset = (UInt(p.internalExponentSize bits))
expOffset := 0 expOffset := 0
when(isSubnormal){ when(isSubnormal){
expOffset := manTop.resized expOffset := (shift.by-9).resized
} }
when(!input.isStall){ when(!input.isStall){
counter := 0
done := False done := False
boot := True boot := True
patched := False patched := False
@ -401,7 +406,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val i2fSign = fsm.patched 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 scrap = i2fLow =/= 0
val recoded = p.internalFloating() val recoded = p.internalFloating()
@ -425,12 +430,14 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
output.scrap := False output.scrap := False
when(input.i2f){ when(input.i2f){
output.value.sign := i2fSign output.value.sign := i2fSign
output.value.exponent := (U(exponentOne+31) - fsm.manTop).resized output.value.exponent := (U(exponentOne+31) - fsm.shift.by).resized
output.value.mantissa := U(i2fHigh)
output.value.setNormal output.value.setNormal
output.scrap := scrap output.scrap := scrap
when(fsm.i2fZero) { output.value.setZero } 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 => storeFloat(rd){v =>
val aLong = if(signed) a.toLong else a.toLong & 0xFFFFFFFFl val aLong = if(signed) a.toLong else a.toLong & 0xFFFFFFFFl
val ref = b val ref = b
// println(f"i2f($aLong) = $v, $ref")
assert(f2b(v) == f2b(ref), 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) 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 rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.i2f(rounding).i32_f32 val (a,b,f) = f32.i2f(rounding).i32_f32
testI2fExact(a,b,f, true, rounding) testI2fExact(a,b,f, true, rounding)
} }
for(_ <- 0 until 10000){ for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick() val rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.ui2f(rounding).i32_f32 val (a,b,f) = f32.ui2f(rounding).i32_f32
testI2fExact(a,b,f, false, rounding) testI2fExact(a,b,f, false, rounding)
} }
println("i2f done") println("i2f done")
for(_ <- 0 until 10000){ 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 10000){ for(_ <- 0 until 100000){
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)
@ -693,21 +712,8 @@ class FpuTest extends FunSuite{
println("f2i done") 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){ 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 10000){
val rounding = FpuRoundMode.elements.randomPick() val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.mul(rounding).f32_2 val (a,b,c,f) = f32.mul(rounding).f32_2
testBinaryOp(mul,a,b,c,f, rounding,"mul") testBinaryOp(mul,a,b,c,f, rounding,"mul")