Improve code quality in FP->FP and Int->FP units
This commit is contained in:
		
				
					committed by
					
						 Wesley W. Terpstra
						Wesley W. Terpstra
					
				
			
			
				
	
			
			
			
						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 |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user