1
0

move to new version of hardfloat

This commit is contained in:
Yunsup Lee 2015-11-14 14:49:17 -08:00
parent 19daee10f0
commit 3c3c946755

View File

@ -182,6 +182,31 @@ class FPInput extends FPUCtrlSigs {
val in3 = Bits(width = 65) val in3 = Bits(width = 65)
} }
object ClassifyRecFN {
def apply(expWidth: Int, sigWidth: Int, in: UInt) = {
val sign = in(sigWidth + expWidth)
val exp = in(sigWidth + expWidth - 1, sigWidth - 1)
val sig = in(sigWidth - 2, 0)
val code = exp(expWidth,expWidth-2)
val codeHi = code(2, 1)
val isSpecial = codeHi === UInt(3)
val isHighSubnormalIn = exp(expWidth-2, 0) < UInt(2)
val isSubnormal = code === UInt(1) || codeHi === UInt(1) && isHighSubnormalIn
val isNormal = codeHi === UInt(1) && !isHighSubnormalIn || codeHi === UInt(2)
val isZero = code === UInt(0)
val isInf = isSpecial && !exp(expWidth-2)
val isNaN = code.andR
val isSNaN = isNaN && !sig(sigWidth-2)
val isQNaN = isNaN && sig(sigWidth-2)
Cat(isQNaN, isSNaN, isInf && !sign, isNormal && !sign,
isSubnormal && !sign, isZero && !sign, isZero && sign,
isSubnormal && sign, isNormal && sign, isInf && sign)
}
}
class FPToInt extends Module class FPToInt extends Module
{ {
val io = new Bundle { val io = new Bundle {
@ -197,30 +222,59 @@ class FPToInt extends Module
val in = Reg(new FPInput) val in = Reg(new FPInput)
val valid = Reg(next=io.in.valid) val valid = Reg(next=io.in.valid)
def upconvert(x: UInt) = {
val s2d = Module(new hardfloat.RecFNToRecFN(8, 24, 11, 53))
s2d.io.in := x
s2d.io.roundingMode := UInt(0)
s2d.io.out
}
val in1_upconvert = upconvert(io.in.bits.in1)
val in2_upconvert = upconvert(io.in.bits.in2)
when (io.in.valid) { when (io.in.valid) {
def upconvert(x: UInt) = hardfloat.recodedFloatNToRecodedFloatM(x, Bits(0), 23, 9, 52, 12)._1
in := io.in.bits in := io.in.bits
when (io.in.bits.single && !io.in.bits.ldst && io.in.bits.cmd != FCMD_MV_XF) { when (io.in.bits.single && !io.in.bits.ldst && io.in.bits.cmd != FCMD_MV_XF &&
in.in1 := upconvert(io.in.bits.in1) // need to also check toint because CVT_IF and SQRT overlap
in.in2 := upconvert(io.in.bits.in2) !(io.in.bits.cmd === FCMD_CVT_IF && io.in.bits.toint)) {
in.in1 := in1_upconvert
in.in2 := in2_upconvert
} }
} }
val unrec_s = hardfloat.recodedFloatNToFloatN(in.in1, 23, 9) val unrec_s = hardfloat.fNFromRecFN(8, 24, in.in1)
val unrec_d = hardfloat.recodedFloatNToFloatN(in.in1, 52, 12) val unrec_d = hardfloat.fNFromRecFN(11, 53, in.in1)
val unrec_out = Mux(in.single, Cat(Fill(32, unrec_s(31)), unrec_s), unrec_d) val unrec_out = Mux(in.single, Cat(Fill(32, unrec_s(31)), unrec_s), unrec_d)
val classify_s = hardfloat.recodedFloatNClassify(in.in1, 23, 9) val classify_s = ClassifyRecFN(8, 24, in.in1)
val classify_d = hardfloat.recodedFloatNClassify(in.in1, 52, 12) val classify_d = ClassifyRecFN(11, 53, in.in1)
val classify_out = Mux(in.single, classify_s, classify_d) val classify_out = Mux(in.single, classify_s, classify_d)
val dcmp = Module(new hardfloat.recodedFloatNCompare(52, 12)) val dcmp = Module(new hardfloat.CompareRecFN(11, 53))
dcmp.io.a := in.in1 dcmp.io.a := in.in1
dcmp.io.b := in.in2 dcmp.io.b := in.in2
val dcmp_out = (~in.rm & Cat(dcmp.io.a_lt_b, dcmp.io.a_eq_b)).orR dcmp.io.signaling := Bool(true)
val dcmp_exc = (~in.rm & Cat(dcmp.io.a_lt_b_invalid, dcmp.io.a_eq_b_invalid)).orR << 4 val dcmp_out = (~in.rm & Cat(dcmp.io.lt, dcmp.io.eq)).orR
val dcmp_exc = dcmp.io.exceptionFlags
val d2i = hardfloat.recodedFloatNToAny(in.in1, in.rm, in.typ ^ 1, 52, 12, 64) val s2l = Module(new hardfloat.RecFNToIN(8, 24, 64))
val s2w = Module(new hardfloat.RecFNToIN(8, 24, 32))
s2l.io.in := in.in1
s2l.io.roundingMode := in.rm
s2l.io.signedOut := in.typ(0) ^ 1
s2w.io.in := in.in1
s2w.io.roundingMode := in.rm
s2w.io.signedOut := in.typ(0) ^ 1
val d2l = Module(new hardfloat.RecFNToIN(11, 53, 64))
val d2w = Module(new hardfloat.RecFNToIN(11, 53, 32))
d2l.io.in := in.in1
d2l.io.roundingMode := in.rm
d2l.io.signedOut := in.typ(0) ^ 1
d2w.io.in := in.in1
d2w.io.roundingMode := in.rm
d2w.io.signedOut := in.typ(0) ^ 1
io.out.bits.toint := Mux(in.rm(0), classify_out, unrec_out) io.out.bits.toint := Mux(in.rm(0), classify_out, unrec_out)
io.out.bits.store := unrec_out io.out.bits.store := unrec_out
@ -231,12 +285,19 @@ class FPToInt extends Module
io.out.bits.exc := dcmp_exc io.out.bits.exc := dcmp_exc
} }
when (in.cmd === FCMD_CVT_IF) { when (in.cmd === FCMD_CVT_IF) {
io.out.bits.toint := Mux(in.typ(1), d2i._1, d2i._1(31,0).toSInt).toUInt when (in.single) {
io.out.bits.exc := d2i._2 io.out.bits.toint := Mux(in.typ(1), s2l.io.out, s2w.io.out.toSInt).toUInt
val sflags = Mux(in.typ(1), s2l.io.intExceptionFlags, s2w.io.intExceptionFlags)
io.out.bits.exc := Cat(sflags(2, 1).orR, UInt(0, 3), sflags(0))
} .otherwise {
io.out.bits.toint := Mux(in.typ(1), d2l.io.out, d2w.io.out.toSInt).toUInt
val dflags = Mux(in.typ(1), d2l.io.intExceptionFlags, d2w.io.intExceptionFlags)
io.out.bits.exc := Cat(dflags(2, 1).orR, UInt(0, 3), dflags(0))
}
} }
io.out.valid := valid io.out.valid := valid
io.out.bits.lt := dcmp.io.a_lt_b io.out.bits.lt := dcmp.io.lt
io.as_double := in io.as_double := in
} }
@ -251,20 +312,36 @@ class IntToFP(val latency: Int) extends Module
val mux = Wire(new FPResult) val mux = Wire(new FPResult)
mux.exc := Bits(0) mux.exc := Bits(0)
mux.data := hardfloat.floatNToRecodedFloatN(in.bits.in1, 52, 12) mux.data := hardfloat.recFNFromFN(11, 53, in.bits.in1)
when (in.bits.single) { when (in.bits.single) {
mux.data := Cat(SInt(-1, 32), hardfloat.floatNToRecodedFloatN(in.bits.in1, 23, 9)) mux.data := Cat(SInt(-1, 32), hardfloat.recFNFromFN(8, 24, in.bits.in1))
} }
val l2s = Module(new hardfloat.INToRecFN(64, 8, 24))
val w2s = Module(new hardfloat.INToRecFN(32, 8, 24))
l2s.io.signedIn := in.bits.typ(0) ^ 1
l2s.io.in := in.bits.in1
l2s.io.roundingMode := in.bits.rm
w2s.io.signedIn := in.bits.typ(0) ^ 1
w2s.io.in := in.bits.in1
w2s.io.roundingMode := in.bits.rm
val l2d = Module(new hardfloat.INToRecFN(64, 11, 53))
val w2d = Module(new hardfloat.INToRecFN(32, 11, 53))
l2d.io.signedIn := in.bits.typ(0) ^ 1
l2d.io.in := in.bits.in1
l2d.io.roundingMode := in.bits.rm
w2d.io.signedIn := in.bits.typ(0) ^ 1
w2d.io.in := in.bits.in1
w2d.io.roundingMode := in.bits.rm
when (in.bits.cmd === FCMD_CVT_FI) { when (in.bits.cmd === FCMD_CVT_FI) {
when (in.bits.single) { when (in.bits.single) {
val u = hardfloat.anyToRecodedFloatN(in.bits.in1(63,0), in.bits.rm, in.bits.typ ^ 1, 23, 9, 64) mux.data := Cat(SInt(-1, 32), Mux(in.bits.typ(1), l2s.io.out, w2s.io.out))
mux.data := Cat(SInt(-1, 32), u._1) mux.exc := Mux(in.bits.typ(1), l2s.io.exceptionFlags, w2s.io.exceptionFlags)
mux.exc := u._2
}.otherwise { }.otherwise {
val u = hardfloat.anyToRecodedFloatN(in.bits.in1(63,0), in.bits.rm, in.bits.typ ^ 1, 52, 12, 64) mux.data := Mux(in.bits.typ(1), l2d.io.out, w2d.io.out)
mux.data := u._1 mux.exc := Mux(in.bits.typ(1), l2d.io.exceptionFlags, w2d.io.exceptionFlags)
mux.exc := u._2
} }
} }
@ -289,8 +366,12 @@ class FPToFP(val latency: Int) extends Module
val sign_d = fsgnjSign(in.bits.in1, in.bits.in2, 64, !in.bits.single && isSgnj, in.bits.rm) val sign_d = fsgnjSign(in.bits.in1, in.bits.in2, 64, !in.bits.single && isSgnj, in.bits.rm)
val fsgnj = Cat(sign_d, in.bits.in1(63,33), sign_s, in.bits.in1(31,0)) val fsgnj = Cat(sign_d, in.bits.in1(63,33), sign_s, in.bits.in1(31,0))
val s2d = hardfloat.recodedFloatNToRecodedFloatM(in.bits.in1, in.bits.rm, 23, 9, 52, 12) val s2d = Module(new hardfloat.RecFNToRecFN(8, 24, 11, 53))
val d2s = hardfloat.recodedFloatNToRecodedFloatM(in.bits.in1, in.bits.rm, 52, 12, 23, 9) val d2s = Module(new hardfloat.RecFNToRecFN(11, 53, 8, 24))
s2d.io.in := in.bits.in1
s2d.io.roundingMode := in.bits.rm
d2s.io.in := in.bits.in1
d2s.io.roundingMode := in.bits.rm
val isnan1 = Mux(in.bits.single, in.bits.in1(31,29).andR, in.bits.in1(63,61).andR) val isnan1 = Mux(in.bits.single, in.bits.in1(31,29).andR, in.bits.in1(63,61).andR)
val isnan2 = Mux(in.bits.single, in.bits.in2(31,29).andR, in.bits.in2(63,61).andR) val isnan2 = Mux(in.bits.single, in.bits.in2(31,29).andR, in.bits.in2(63,61).andR)
@ -308,18 +389,18 @@ class FPToFP(val latency: Int) extends Module
when (isSgnj || isLHS) { mux.data := fsgnj } when (isSgnj || isLHS) { mux.data := fsgnj }
when (in.bits.cmd === FCMD_CVT_FF) { when (in.bits.cmd === FCMD_CVT_FF) {
when (in.bits.single) { when (in.bits.single) {
mux.data := Cat(SInt(-1, 32), d2s._1) mux.data := Cat(SInt(-1, 32), d2s.io.out)
mux.exc := d2s._2 mux.exc := d2s.io.exceptionFlags
}.otherwise { }.otherwise {
mux.data := s2d._1 mux.data := s2d.io.out
mux.exc := s2d._2 mux.exc := s2d.io.exceptionFlags
} }
} }
io.out <> Pipe(in.valid, mux, latency-1) io.out <> Pipe(in.valid, mux, latency-1)
} }
class FPUFMAPipe(val latency: Int, sigWidth: Int, expWidth: Int) extends Module class FPUFMAPipe(val latency: Int, expWidth: Int, sigWidth: Int) extends Module
{ {
val io = new Bundle { val io = new Bundle {
val in = Valid(new FPInput).flip val in = Valid(new FPInput).flip
@ -341,7 +422,7 @@ class FPUFMAPipe(val latency: Int, sigWidth: Int, expWidth: Int) extends Module
unless (cmd_fma || cmd_addsub) { in.in3 := zero } unless (cmd_fma || cmd_addsub) { in.in3 := zero }
} }
val fma = Module(new hardfloat.mulAddSubRecodedFloatN(sigWidth, expWidth)) val fma = Module(new hardfloat.MulAddRecFN(expWidth, sigWidth))
fma.io.op := in.cmd fma.io.op := in.cmd
fma.io.roundingMode := in.rm fma.io.roundingMode := in.rm
fma.io.a := in.in1 fma.io.a := in.in1
@ -377,8 +458,8 @@ class FPU(implicit p: Parameters) extends CoreModule()(p) {
val load_wb_single = RegEnable(io.dmem_resp_type === MT_W || io.dmem_resp_type === MT_WU, io.dmem_resp_val) val load_wb_single = RegEnable(io.dmem_resp_type === MT_W || io.dmem_resp_type === MT_WU, io.dmem_resp_val)
val load_wb_data = RegEnable(io.dmem_resp_data, io.dmem_resp_val) val load_wb_data = RegEnable(io.dmem_resp_data, io.dmem_resp_val)
val load_wb_tag = RegEnable(io.dmem_resp_tag, io.dmem_resp_val) val load_wb_tag = RegEnable(io.dmem_resp_tag, io.dmem_resp_val)
val rec_s = hardfloat.floatNToRecodedFloatN(load_wb_data, 23, 9) val rec_s = hardfloat.recFNFromFN(8, 24, load_wb_data)
val rec_d = hardfloat.floatNToRecodedFloatN(load_wb_data, 52, 12) val rec_d = hardfloat.recFNFromFN(11, 53, load_wb_data)
val load_wb_data_recoded = Mux(load_wb_single, Cat(SInt(-1, 32), rec_s), rec_d) val load_wb_data_recoded = Mux(load_wb_single, Cat(SInt(-1, 32), rec_s), rec_d)
// regfile // regfile
@ -415,11 +496,11 @@ class FPU(implicit p: Parameters) extends CoreModule()(p) {
req.in3 := ex_rs3 req.in3 := ex_rs3
req.typ := ex_reg_inst(21,20) req.typ := ex_reg_inst(21,20)
val sfma = Module(new FPUFMAPipe(p(SFMALatency), 23, 9)) val sfma = Module(new FPUFMAPipe(p(SFMALatency), 8, 24))
sfma.io.in.valid := ex_reg_valid && ex_ctrl.fma && ex_ctrl.single sfma.io.in.valid := ex_reg_valid && ex_ctrl.fma && ex_ctrl.single
sfma.io.in.bits := req sfma.io.in.bits := req
val dfma = Module(new FPUFMAPipe(p(DFMALatency), 52, 12)) val dfma = Module(new FPUFMAPipe(p(DFMALatency), 11, 53))
dfma.io.in.valid := ex_reg_valid && ex_ctrl.fma && !ex_ctrl.single dfma.io.in.valid := ex_reg_valid && ex_ctrl.fma && !ex_ctrl.single
dfma.io.in.bits := req dfma.io.in.bits := req
@ -490,8 +571,8 @@ class FPU(implicit p: Parameters) extends CoreModule()(p) {
when (wen(0) || divSqrt_wen) { when (wen(0) || divSqrt_wen) {
regfile(waddr) := wdata regfile(waddr) := wdata
if (enableCommitLog) { if (enableCommitLog) {
val wdata_unrec_s = hardfloat.recodedFloatNToFloatN(wdata(64,0), 23, 9) val wdata_unrec_s = hardfloat.fNFromRecFN(8, 24, wdata(64,0))
val wdata_unrec_d = hardfloat.recodedFloatNToFloatN(wdata(64,0), 52, 12) val wdata_unrec_d = hardfloat.fNFromRecFN(11, 53, wdata(64,0))
val wb_single = (winfo(0) >> 5)(0) val wb_single = (winfo(0) >> 5)(0)
printf ("f%d p%d 0x%x\n", waddr, waddr+ UInt(32), printf ("f%d p%d 0x%x\n", waddr, waddr+ UInt(32),
Mux(wb_single, Cat(UInt(0,32), wdata_unrec_s), wdata_unrec_d)) Mux(wb_single, Cat(UInt(0,32), wdata_unrec_s), wdata_unrec_d))
@ -525,7 +606,7 @@ class FPU(implicit p: Parameters) extends CoreModule()(p) {
val divSqrt_flags_double = Reg(Bits()) val divSqrt_flags_double = Reg(Bits())
val divSqrt_wdata_double = Reg(Bits()) val divSqrt_wdata_double = Reg(Bits())
val divSqrt = Module(new hardfloat.divSqrtRecodedFloat64) val divSqrt = Module(new hardfloat.DivSqrtRecF64)
divSqrt_inReady := Mux(divSqrt.io.sqrtOp, divSqrt.io.inReady_sqrt, divSqrt.io.inReady_div) divSqrt_inReady := Mux(divSqrt.io.sqrtOp, divSqrt.io.inReady_sqrt, divSqrt.io.inReady_div)
val divSqrt_outValid = divSqrt.io.outValid_div || divSqrt.io.outValid_sqrt val divSqrt_outValid = divSqrt.io.outValid_div || divSqrt.io.outValid_sqrt
divSqrt.io.inValid := mem_reg_valid && (mem_ctrl.div || mem_ctrl.sqrt) divSqrt.io.inValid := mem_reg_valid && (mem_ctrl.div || mem_ctrl.sqrt)
@ -549,8 +630,10 @@ class FPU(implicit p: Parameters) extends CoreModule()(p) {
divSqrt_flags_double := divSqrt.io.exceptionFlags divSqrt_flags_double := divSqrt.io.exceptionFlags
} }
val divSqrt_toSingle = hardfloat.recodedFloatNToRecodedFloatM(divSqrt_wdata_double, ex_rm, 52, 12, 23, 9) val divSqrt_toSingle = Module(new hardfloat.RecFNToRecFN(11, 53, 8, 24))
divSqrt_wdata := Mux(divSqrt_single, divSqrt_toSingle._1, divSqrt_wdata_double) divSqrt_toSingle.io.in := divSqrt_wdata_double
divSqrt_flags := divSqrt_flags_double | Mux(divSqrt_single, divSqrt_toSingle._2, Bits(0)) divSqrt_toSingle.io.roundingMode := ex_rm
divSqrt_wdata := Mux(divSqrt_single, divSqrt_toSingle.io.out, divSqrt_wdata_double)
divSqrt_flags := divSqrt_flags_double | Mux(divSqrt_single, divSqrt_toSingle.io.exceptionFlags, Bits(0))
} }
} }