Improve code quality in FP->FP and Int->FP units
This commit is contained in:
parent
84c4ae775f
commit
7504b47bbe
@ -232,10 +232,11 @@ object FType {
|
|||||||
|
|
||||||
trait HasFPUParameters {
|
trait HasFPUParameters {
|
||||||
val fLen: Int
|
val fLen: Int
|
||||||
|
val xLen: Int
|
||||||
val minXLen = 32
|
val minXLen = 32
|
||||||
val (sExpWidth, sSigWidth) = (FType.S.exp, FType.S.sig)
|
val nIntTypes = log2Ceil(xLen/minXLen) + 1
|
||||||
val (dExpWidth, dSigWidth) = (FType.D.exp, FType.D.sig)
|
|
||||||
val floatTypes = FType.all.filter(_.ieeeWidth <= fLen)
|
val floatTypes = FType.all.filter(_.ieeeWidth <= fLen)
|
||||||
|
val minType = floatTypes.head
|
||||||
val maxType = floatTypes.last
|
val maxType = floatTypes.last
|
||||||
def prevType(t: FType) = floatTypes(typeTag(t) - 1)
|
def prevType(t: FType) = floatTypes(typeTag(t) - 1)
|
||||||
val maxExpWidth = maxType.exp
|
val maxExpWidth = maxType.exp
|
||||||
@ -379,11 +380,10 @@ class FPToInt(implicit p: Parameters) extends FPUModule()(p) {
|
|||||||
dcmp.io.b := in.in2
|
dcmp.io.b := in.in2
|
||||||
dcmp.io.signaling := !in.rm(1)
|
dcmp.io.signaling := !in.rm(1)
|
||||||
|
|
||||||
val tag = !in.singleOut
|
val tag = !in.singleOut // TODO typeTag
|
||||||
val store = ieee(in.in1)
|
val store = ieee(in.in1)
|
||||||
val toint = Wire(init = store)
|
val toint = Wire(init = store)
|
||||||
val intType = Wire(init = tag)
|
val intType = Wire(init = tag)
|
||||||
val nIntTypes = log2Ceil(xLen/minXLen) + 1
|
|
||||||
io.out.bits.store := ((0 until nIntTypes).map(i => Fill(1 << (nIntTypes - i - 1), store((minXLen << i) - 1, 0))): Seq[UInt])(tag)
|
io.out.bits.store := ((0 until nIntTypes).map(i => Fill(1 << (nIntTypes - i - 1), store((minXLen << i) - 1, 0))): Seq[UInt])(tag)
|
||||||
io.out.bits.toint := ((0 until nIntTypes).map(i => toint((minXLen << i) - 1, 0).sextTo(xLen)): Seq[UInt])(intType)
|
io.out.bits.toint := ((0 until nIntTypes).map(i => toint((minXLen << i) - 1, 0).sextTo(xLen)): Seq[UInt])(intType)
|
||||||
io.out.bits.exc := Bits(0)
|
io.out.bits.exc := Bits(0)
|
||||||
@ -440,17 +440,17 @@ class IntToFP(val latency: Int)(implicit p: Parameters) extends FPUModule()(p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val in = Pipe(io.in)
|
val in = Pipe(io.in)
|
||||||
|
val tag = !in.bits.singleIn // TODO typeTag
|
||||||
|
|
||||||
val mux = Wire(new FPResult)
|
val mux = Wire(new FPResult)
|
||||||
mux.exc := Bits(0)
|
mux.exc := Bits(0)
|
||||||
mux.data := recode(in.bits.in1, !in.bits.singleIn)
|
mux.data := recode(in.bits.in1, !in.bits.singleIn)
|
||||||
|
|
||||||
val intValue = {
|
val intValue = {
|
||||||
val n = log2Ceil(xLen/minXLen) + 1
|
|
||||||
val res = Wire(init = in.bits.in1.asSInt)
|
val res = Wire(init = in.bits.in1.asSInt)
|
||||||
for (i <- 0 until n-1) {
|
for (i <- 0 until nIntTypes-1) {
|
||||||
val smallInt = in.bits.in1((minXLen << i) - 1, 0)
|
val smallInt = in.bits.in1((minXLen << i) - 1, 0)
|
||||||
when (in.bits.typ.extract(log2Ceil(n), 1) === i) {
|
when (in.bits.typ.extract(log2Ceil(nIntTypes), 1) === i) {
|
||||||
res := Mux(in.bits.typ(0), smallInt.zext, smallInt.asSInt)
|
res := Mux(in.bits.typ(0), smallInt.zext, smallInt.asSInt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,28 +458,21 @@ class IntToFP(val latency: Int)(implicit p: Parameters) extends FPUModule()(p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
when (in.bits.wflags) { // fcvt
|
when (in.bits.wflags) { // fcvt
|
||||||
val l2s = Module(new hardfloat.INToRecFN(xLen, sExpWidth, sSigWidth))
|
// could be improved for RVD/RVQ with a single variable-position rounding
|
||||||
l2s.io.signedIn := ~in.bits.typ(0)
|
// unit, rather than N fixed-position ones
|
||||||
l2s.io.in := intValue
|
val i2fResults = for (t <- floatTypes) yield {
|
||||||
l2s.io.roundingMode := in.bits.rm
|
val i2f = Module(new hardfloat.INToRecFN(xLen, t.exp, t.sig))
|
||||||
l2s.io.detectTininess := hardfloat.consts.tininess_afterRounding
|
i2f.io.signedIn := ~in.bits.typ(0)
|
||||||
mux.data := sanitizeNaN(l2s.io.out, FType.S)
|
i2f.io.in := intValue
|
||||||
mux.exc := l2s.io.exceptionFlags
|
i2f.io.roundingMode := in.bits.rm
|
||||||
|
i2f.io.detectTininess := hardfloat.consts.tininess_afterRounding
|
||||||
|
(sanitizeNaN(i2f.io.out, t), i2f.io.exceptionFlags)
|
||||||
|
}
|
||||||
|
|
||||||
fLen match {
|
val (data, exc) = i2fResults.unzip
|
||||||
case 32 =>
|
val dataPadded = data.init.map(d => Cat(data.last >> d.getWidth, d)) :+ data.last
|
||||||
case 64 =>
|
mux.data := dataPadded(tag)
|
||||||
val l2d = Module(new hardfloat.INToRecFN(xLen, dExpWidth, dSigWidth))
|
mux.exc := exc(tag)
|
||||||
l2d.io.signedIn := ~in.bits.typ(0)
|
|
||||||
l2d.io.in := intValue
|
|
||||||
l2d.io.roundingMode := in.bits.rm
|
|
||||||
l2d.io.detectTininess := hardfloat.consts.tininess_afterRounding
|
|
||||||
mux.data := Cat(l2d.io.out >> l2s.io.out.getWidth, l2s.io.out)
|
|
||||||
when (!in.bits.singleIn) {
|
|
||||||
mux.data := sanitizeNaN(l2d.io.out, FType.D)
|
|
||||||
mux.exc := l2d.io.exceptionFlags
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
io.out <> Pipe(in.valid, mux, latency-1)
|
io.out <> Pipe(in.valid, mux, latency-1)
|
||||||
@ -511,32 +504,33 @@ class FPToFP(val latency: Int)(implicit p: Parameters) extends FPUModule()(p) {
|
|||||||
fsgnjMux.data := Mux(isNaNOut, maxType.qNaN, Mux(isLHS, in.bits.in1, in.bits.in2))
|
fsgnjMux.data := Mux(isNaNOut, maxType.qNaN, Mux(isLHS, in.bits.in1, in.bits.in2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val inTag = !in.bits.singleIn // TODO typeTag
|
||||||
|
val outTag = !in.bits.singleOut // TODO typeTag
|
||||||
val mux = Wire(init = fsgnjMux)
|
val mux = Wire(init = fsgnjMux)
|
||||||
fLen match {
|
for (t <- floatTypes.init) {
|
||||||
case 32 =>
|
when (outTag === typeTag(t)) {
|
||||||
case 64 =>
|
mux.data := Cat(fsgnjMux.data >> t.recodedWidth, maxType.unsafeConvert(fsgnjMux.data, t))
|
||||||
val fsgnjSingle = maxType.unsafeConvert(fsgnjMux.data, FType.S)
|
}
|
||||||
when (in.bits.singleOut) { mux.data := Cat(fsgnjMux.data >> fsgnjSingle.getWidth, fsgnjSingle) }
|
}
|
||||||
|
|
||||||
when (in.bits.wflags && !in.bits.ren2) { // fcvt
|
when (in.bits.wflags && !in.bits.ren2) { // fcvt
|
||||||
val d2s = Module(new hardfloat.RecFNToRecFN(dExpWidth, dSigWidth, sExpWidth, sSigWidth))
|
if (floatTypes.size > 1) {
|
||||||
d2s.io.in := in.bits.in1
|
// widening conversions simply canonicalize NaN operands
|
||||||
d2s.io.roundingMode := in.bits.rm
|
val widened = Mux(maxType.isNaN(in.bits.in1), maxType.qNaN, in.bits.in1)
|
||||||
d2s.io.detectTininess := hardfloat.consts.tininess_afterRounding
|
fsgnjMux.data := widened
|
||||||
val d2sOut = sanitizeNaN(d2s.io.out, FType.S)
|
fsgnjMux.exc := maxType.isSNaN(in.bits.in1) << 4
|
||||||
|
|
||||||
val s2d = Module(new hardfloat.RecFNToRecFN(sExpWidth, sSigWidth, dExpWidth, dSigWidth))
|
// narrowing conversions require rounding (for RVQ, this could be
|
||||||
s2d.io.in := maxType.unsafeConvert(in.bits.in1, FType.S)
|
// optimized to use a single variable-position rounding unit, rather
|
||||||
s2d.io.roundingMode := in.bits.rm
|
// than two fixed-position ones)
|
||||||
s2d.io.detectTininess := hardfloat.consts.tininess_afterRounding
|
for (outType <- floatTypes.init) when (outTag === typeTag(outType) && (typeTag(outType) == 0 || outTag < inTag)) {
|
||||||
val s2dOut = sanitizeNaN(s2d.io.out, FType.D)
|
val narrower = Module(new hardfloat.RecFNToRecFN(maxType.exp, maxType.sig, outType.exp, outType.sig))
|
||||||
|
narrower.io.in := in.bits.in1
|
||||||
when (in.bits.singleOut) {
|
narrower.io.roundingMode := in.bits.rm
|
||||||
mux.data := Cat(s2dOut >> d2sOut.getWidth, d2sOut)
|
narrower.io.detectTininess := hardfloat.consts.tininess_afterRounding
|
||||||
mux.exc := d2s.io.exceptionFlags
|
val narrowed = sanitizeNaN(narrower.io.out, outType)
|
||||||
}.otherwise {
|
mux.data := Cat(fsgnjMux.data >> narrowed.getWidth, narrowed)
|
||||||
mux.data := s2dOut
|
mux.exc := narrower.io.exceptionFlags
|
||||||
mux.exc := s2d.io.exceptionFlags
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user