Skip to content

Commit

Permalink
Got FpuDiv to work
Browse files Browse the repository at this point in the history
  • Loading branch information
Dolu1990 committed Apr 23, 2024
1 parent ea6ad9e commit 9d4e67a
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 49 deletions.
1 change: 1 addition & 0 deletions src/main/scala/vexiiriscv/Param.scala
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ class ParamSimple(){
plugins += new execute.fpu.FpuAddPlugin(early0)
plugins += new execute.fpu.FpuMulPlugin(early0, withFma = !skipFma, fmaFullAccuracy = fpuFmaFullAccuracy)
plugins += new execute.fpu.FpuSqrtPlugin(early0)
plugins += new execute.fpu.FpuDivPlugin(early0)
plugins += new execute.fpu.FpuPackerPlugin(lane0)
// plugins += new execute.fpu.FpuEmbedded()
}
Expand Down
34 changes: 30 additions & 4 deletions src/main/scala/vexiiriscv/execute/DivPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import spinal.core._
import spinal.lib._
import spinal.lib.misc.pipeline._
import vexiiriscv.execute.RsUnsignedPlugin._
import vexiiriscv.misc.{AdderAggregator, DivComp, DivRadix2, DivRadix, MulSpliter}
import vexiiriscv.misc.{AdderAggregator, DivComp, DivRadix, DivRadix2, DivRsp, MulSpliter}
import vexiiriscv.riscv.Riscv._
import vexiiriscv.riscv._

Expand All @@ -17,14 +17,36 @@ object DivPlugin extends AreaObject {
val DIV_REVERT_RESULT = Payload(Bool())
}

trait DivReuse{
def divInject(layer : LaneLayer, at : Int, a : UInt, b : UInt, iterations : UInt) : Unit
def divRsp : DivRsp
def divRadix : Int
}

class DivPlugin(val layer : LaneLayer,
var impl : (Int, Int, Boolean) => DivComp,
var divAt: Int = 0,
var writebackAt : Int = 0,
var radix: Int = 2,
var area: Boolean = true) extends ExecutionUnitElementSimple(layer){
var area: Boolean = true) extends ExecutionUnitElementSimple(layer) with DivReuse {
import DivPlugin._


override def divInject(layer: LaneLayer, at: Int, a: UInt, b: UInt, interations : UInt): Unit = {
assert(layer == this.layer && at == this.divAt)
logic.processing.request := True
val divWidth = logic.processing.div.width
assert(divWidth >= widthOf(a))
assert(divWidth >= widthOf(b))
logic.processing.div.io.cmd.a := a.resized // << (divWidth-widthOf(a))
logic.processing.div.io.cmd.b := b.resized // << (divWidth-widthOf(b))
logic.processing.div.io.cmd.normalized := True
logic.processing.div.io.cmd.iterations := interations
}

override def divRsp: DivRsp = logic.processing.div.io.rsp
override def divRadix: Int = radix

val logic = during setup new Logic {
awaitBuild()

Expand Down Expand Up @@ -59,14 +81,18 @@ class DivPlugin(val layer : LaneLayer,
DIV_REVERT_RESULT := (RS1_REVERT ^ (RS2_REVERT && !REM)) && !(RS2_FORMATED === 0 && RS2_SIGNED && !REM) //RS2_SIGNED == RS1_SIGNED anyway

val cmdSent = RegInit(False) setWhen (div.io.cmd.fire) clearWhen (isReady)
div.io.cmd.valid := isValid && SEL && !cmdSent
val request = isValid && SEL
div.io.cmd.valid := request && !cmdSent
div.io.cmd.a := RS1_UNSIGNED.resized
div.io.cmd.b := RS2_UNSIGNED.resized
div.io.cmd.normalized := False
div.io.cmd.iterations.assignDontCare()
div.io.flush := isReady
div.io.rsp.ready := False


val unscheduleRequest = RegNext(isCancel) clearWhen (isReady) init (False)
val freeze = isValid && SEL && !div.io.rsp.valid & !unscheduleRequest
val freeze = request && !div.io.rsp.valid & !unscheduleRequest
el.freezeWhen(freeze)

val selected = REM ? div.io.rsp.remain otherwise div.io.rsp.result
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/vexiiriscv/execute/fpu/FpuAddPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class FpuAddPlugin(val layer : LaneLayer,
addPort.cmd.roundMode := FpuUtils.ROUNDING
addPort.cmd.hartId := Global.HART_ID
addPort.cmd.uopId := Decode.UOP_ID
addPort.cmd.flags.clearAll()
}

buildBefore.release()
Expand Down
12 changes: 5 additions & 7 deletions src/main/scala/vexiiriscv/execute/fpu/FpuAddSharedPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ case class FpuAddSharedCmd(p1 : FloatUnpackedParam, p2 : FloatUnpackedParam, ats
val roundMode = FpuRoundMode()
val hartId = Global.HART_ID()
val uopId = Decode.UOP_ID()
val flags = FpuFlags()
}

class FpuAddSharedPort(_cmd : FpuAddSharedCmd) extends Area{
Expand All @@ -47,8 +48,7 @@ class FpuAddSharedPlugin(lane: ExecuteLanePlugin,

val logic = during setup new Area{
val fpp = host.find[FpuPackerPlugin](p => p.lane == lane)
val ffwbp = host.find[FpuFlagsWritebackPlugin](p => p.lane == lane)
val buildBefore = retains(lane.pipelineLock, fpp.elaborationLock, ffwbp.elaborationLock)
val buildBefore = retains(lane.pipelineLock, fpp.elaborationLock)
val uopLock = retains(lane.uopLock)
awaitBuild()
val latency = packAt
Expand All @@ -68,7 +68,6 @@ class FpuAddSharedPlugin(lane: ExecuteLanePlugin,

val uopsAt = mutable.LinkedHashMap[Int, ArrayBuffer[UopLayerSpec]]()
for (port <- ports; (uop, at) <- port.uopsAt) uopsAt.getOrElseUpdate(at, ArrayBuffer[UopLayerSpec]()) += uop
val flagsWb = ffwbp.createPort(uopsAt.keys.toList)
val packAts = uopsAt.keys.map(_ + latency).toList
val packPort = fpp.createPort(packAts, packParam)
for ((at, uops) <- uopsAt) {
Expand All @@ -93,6 +92,7 @@ class FpuAddSharedPlugin(lane: ExecuteLanePlugin,
val FORMAT = insert(reader(_.format))
val ROUNDMODE = insert(reader(_.roundMode))
val RDN = insert( ROUNDMODE === FpuRoundMode.RDN)
val FLAGS = insert(reader(_.flags))
Global.HART_ID := reader(_.hartId)
Decode.UOP_ID := reader(_.uopId)
valid := reader.oh.orR
Expand All @@ -117,10 +117,6 @@ class FpuAddSharedPlugin(lane: ExecuteLanePlugin,
val onPack = new pip.Area(packAt) {
val mask = inserter.GROUP_OH.andMask(isValid)

flagsWb.ats := mask
flagsWb.flags.clearAll()
flagsWb.flags.NV.setWhen(adder.result.NV)

packPort.cmd.at := mask
packPort.cmd.value.mode := adder.result.RESULT.mode
packPort.cmd.value.quiet := adder.result.RESULT.quiet
Expand All @@ -131,6 +127,8 @@ class FpuAddSharedPlugin(lane: ExecuteLanePlugin,
packPort.cmd.roundMode := inserter.ROUNDMODE
packPort.cmd.hartId := Global.HART_ID
packPort.cmd.uopId := Decode.UOP_ID
packPort.cmd.flags := inserter.FLAGS
packPort.cmd.flags.NV.setWhen(adder.result.NV)

ready := !lane.isFreezed()
}
Expand Down
109 changes: 109 additions & 0 deletions src/main/scala/vexiiriscv/execute/fpu/FpuDivPlugin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package vexiiriscv.execute.fpu

import spinal.core._
import spinal.lib.misc.pipeline._
import spinal.lib.misc.plugin.FiberPlugin
import vexiiriscv.Global
import vexiiriscv.decode.Decode
import vexiiriscv.execute._
import vexiiriscv.execute.fpu.FpuUtils.FORMAT
import vexiiriscv.riscv._


class FpuDivPlugin(val layer : LaneLayer,
var exeAt : Int = 0,
var packAt : Int = 0) extends FiberPlugin{
val p = FpuUtils

val SEL = Payload(Bool())

val logic = during setup new Area{
val fup = host[FpuUnpackerPlugin]
val fpp = host[FpuPackerPlugin]
val dr = host[DivReuse]
val buildBefore = retains(layer.el.pipelineLock)
val uopLock = retains(layer.el.uopLock, fup.elaborationLock, fpp.elaborationLock)
awaitBuild()

val packParam = FloatUnpackedParam(
exponentMax = p.unpackedConfig.exponentMax-p.unpackedConfig.exponentMin,
exponentMin = p.unpackedConfig.exponentMin-p.unpackedConfig.exponentMax-1,
mantissaWidth = p.unpackedConfig.mantissaWidth+2
)
val packPort = fpp.createPort(List(packAt), packParam)

layer.el.setDecodingDefault(SEL, False)
def add(uop: MicroOp, decodings: (Payload[_ <: BaseType], Any)*) = {
val spec = layer.add(uop)
spec.addDecoding(SEL -> True)
spec.addDecoding(decodings)
uop.resources.foreach {
case RfResource(_, rs: RfRead) => fup.unpack(uop, rs)
case _ =>
}
packPort.uopsAt += spec -> packAt
}

add(Rvfd.FDIV_S, FORMAT -> FpuFormat.FLOAT)
if(Riscv.RVD) {
add(Rvfd.FDIV_D, FORMAT -> FpuFormat.DOUBLE)
}

uopLock.release()


val RS1_FP = fup(RS1)
val RS2_FP = fup(RS2)
val internalMantissaSize = p.mantissaWidth
val iterationsWished = 1+internalMantissaSize+2+1
val drift = iterationsWished % log2Up(dr.divRadix)
val interations = iterationsWished + drift

val onExecute = new layer.Execute(exeAt) {
when(isValid && SEL) {
dr.divInject(layer, exeAt, U(B"1" ## RS1_FP.mantissa.raw), U(B"1" ## RS2_FP.mantissa.raw), interations-1)
}
val DIVIDER_RSP = insert(dr.divRsp.result(drift+1, iterationsWished bits) | U(dr.divRsp.remain.orR || dr.divRsp.result(0, drift+1 bits).orR).resized)
}
import onExecute.DIVIDER_RSP

val onPack = new layer.Execute(packAt) {
val needShift = !DIVIDER_RSP.msb
val mantissa = needShift.mux(DIVIDER_RSP(0, internalMantissaSize+2 bits), DIVIDER_RSP(1, internalMantissaSize+2 bits) | U(DIVIDER_RSP(0)).resized)
val exponent = RS1_FP.exponent - RS2_FP.exponent - AFix(U(needShift))

packPort.cmd.at(0) := isValid && SEL
packPort.cmd.value.setNormal
packPort.cmd.value.quiet := False
packPort.cmd.value.sign := RS1_FP.sign ^ RS2_FP.sign
packPort.cmd.value.exponent := exponent
packPort.cmd.value.mantissa := mantissa
packPort.cmd.format := FORMAT
packPort.cmd.roundMode := FpuUtils.ROUNDING
packPort.cmd.hartId := Global.HART_ID
packPort.cmd.uopId := Decode.UOP_ID

val forceOverflow = RS1_FP.isInfinity || RS2_FP.isZero
val infinitynan = RS1_FP.isZero && RS2_FP.isZero || RS1_FP.isInfinity && RS2_FP.isInfinity
val forceNan = RS1_FP.isNan || RS2_FP.isNan || infinitynan
val forceZero = RS1_FP.isZero || RS2_FP.isInfinity

packPort.cmd.flags.NX := False
packPort.cmd.flags.UF := False
packPort.cmd.flags.OF := False
packPort.cmd.flags.DZ := !forceNan && !RS1_FP.isInfinity && RS2_FP.isZero
packPort.cmd.flags.NV := False

when(forceNan) {
packPort.cmd.value.setNanQuiet
packPort.cmd.flags.NV setWhen((infinitynan || RS1_FP.isNanSignaling || RS2_FP.isNanSignaling))
} elsewhen(forceOverflow) {
packPort.cmd.value.setInfinity
} elsewhen(forceZero) {
packPort.cmd.value.setZero
}
}

buildBefore.release()
}
}
12 changes: 5 additions & 7 deletions src/main/scala/vexiiriscv/execute/fpu/FpuMulPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,11 @@ class FpuMulPlugin(val layer : LaneLayer,
val fup = host[FpuUnpackerPlugin]
val fpp = host[FpuPackerPlugin]
val fasp = host[FpuAddSharedPlugin]
val ffwp = host[FpuFlagsWritebackPlugin]
val mp = host[MulReuse]
val buildBefore = retains(layer.el.pipelineLock, ffwp.elaborationLock)
val buildBefore = retains(layer.el.pipelineLock)
val uopLock = retains(layer.el.uopLock, fup.elaborationLock, fpp.elaborationLock)
awaitBuild()

val flagsWb = ffwp.createPort(List(packAt))

val packParam = FloatUnpackedParam(
exponentMax = p.unpackedConfig.exponentMax * 2 + 1,
exponentMin = p.unpackedConfig.exponentMin * 2,
Expand Down Expand Up @@ -130,13 +127,12 @@ class FpuMulPlugin(val layer : LaneLayer,
import norm._

val onPack = new layer.el.Execute(packAt) {
flagsWb.ats(0) := isValid && SEL
flagsWb.flags.clearAll()
val nv = False

val mode = FloatMode.NORMAL()
when(FORCE_NAN) {
mode := FloatMode.NAN
flagsWb.flags.NV setWhen ((INFINITY_NAN || RS1_FP.isNanSignaling || RS2_FP.isNanSignaling))
nv setWhen ((INFINITY_NAN || RS1_FP.isNanSignaling || RS2_FP.isNanSignaling))
}.elsewhen(FORCE_OVERFLOW) {
mode := FloatMode.INF
}.elsewhen(FORCE_ZERO) {
Expand All @@ -153,6 +149,7 @@ class FpuMulPlugin(val layer : LaneLayer,
packPort.cmd.roundMode := FpuUtils.ROUNDING
packPort.cmd.hartId := Global.HART_ID
packPort.cmd.uopId := Decode.UOP_ID
packPort.cmd.flags.assign(NV = nv)

if(withFma) {
addPort.cmd.at(0) := isValid && SEL && FMA
Expand All @@ -166,6 +163,7 @@ class FpuMulPlugin(val layer : LaneLayer,
addPort.cmd.roundMode := FpuUtils.ROUNDING
addPort.cmd.hartId := Global.HART_ID
addPort.cmd.uopId := Decode.UOP_ID
addPort.cmd.flags.assign(NV = nv)
}
}

Expand Down
14 changes: 8 additions & 6 deletions src/main/scala/vexiiriscv/execute/fpu/FpuPackerPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ case class FpuPackerCmd(p : FloatUnpackedParam, ats : Seq[Int]) extends Bundle{
val roundMode = FpuRoundMode()
val hartId = Global.HART_ID()
val uopId = Decode.UOP_ID()
val flags = FpuFlags()
}

class FpuPackerPort(_cmd : FpuPackerCmd) extends Area{
Expand Down Expand Up @@ -58,7 +59,7 @@ class FpuPackerPlugin(val lane: ExecuteLanePlugin,
val wbPorts = mutable.LinkedHashMap[Int, Flow[Bits]]()
val uopsAt = mutable.LinkedHashMap[Int, ArrayBuffer[UopLayerSpec]]()
for(port <- ports; (uop, at) <- port.uopsAt) uopsAt.getOrElseUpdate(at, ArrayBuffer[UopLayerSpec]()) += uop
val flagsWb = ffwbp.createPort(uopsAt.keys.toList)
val flagsWb = ffwbp.createPort(uopsAt.keys.map(_ + latency).toList)
for((at, uops) <- uopsAt) {
val port = wbp.createPort(at+latency).setName("FpuPackerPlugin_wb_at_" + at)
wbPorts(at) = port
Expand Down Expand Up @@ -89,6 +90,7 @@ class FpuPackerPlugin(val lane: ExecuteLanePlugin,
val VALUE = insert(OhMux.or(reader.oh.asBits, remapped.toSeq))
val FORMAT = insert(reader(_.format))
val ROUNDMODE = insert(reader(_.roundMode))
val FLAGS = insert(reader(_.flags))
Global.HART_ID := reader(_.hartId)
Decode.UOP_ID := reader(_.uopId)
valid := reader.oh.orR
Expand Down Expand Up @@ -248,11 +250,11 @@ class FpuPackerPlugin(val lane: ExecuteLanePlugin,

val csr = host[FpuCsrPlugin]
flagsWb.ats := GROUP_OH.andMask(valid)
flagsWb.flags.NX := nx
flagsWb.flags.UF := uf
flagsWb.flags.OF := of
flagsWb.flags.DZ := False
flagsWb.flags.NV := False
flagsWb.flags.NX := FLAGS.NX || nx
flagsWb.flags.UF := FLAGS.UF || uf
flagsWb.flags.OF := FLAGS.OF || of
flagsWb.flags.DZ := FLAGS.DZ
flagsWb.flags.NV := FLAGS.NV


p.whenDouble(FORMAT) {
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/vexiiriscv/execute/fpu/FpuSqrtPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ class FpuSqrtPlugin(val layer : LaneLayer,
packPort.cmd.roundMode := FpuUtils.ROUNDING
packPort.cmd.hartId := Global.HART_ID
packPort.cmd.uopId := Decode.UOP_ID

packPort.cmd.value.setNormal
packPort.cmd.value.quiet := False
packPort.cmd.value.sign := RS1_FP.sign
Expand All @@ -89,7 +88,7 @@ class FpuSqrtPlugin(val layer : LaneLayer,
packPort.cmd.value.setInfinity
}

val NV = False //TODO FPU FLAG
val NV = False
when(negative) {
packPort.cmd.value.setNanQuiet
NV := True
Expand All @@ -101,6 +100,8 @@ class FpuSqrtPlugin(val layer : LaneLayer,
when(RS1_FP.isZero) {
packPort.cmd.value.setZero
}

packPort.cmd.flags.assign(NV = NV)
}

buildBefore.release()
Expand Down
9 changes: 9 additions & 0 deletions src/main/scala/vexiiriscv/execute/fpu/Interface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ case class FpuFlags() extends Bundle{
List(NX, UF, OF, DZ, NV).foreach(_ := False)
}

def assign(NX : Bool = False, UF : Bool = False, OF : Bool = False, DZ : Bool = False, NV : Bool = False) = {
this.NX := NX
this.UF := UF
this.OF := OF
this.DZ := DZ
this.NV := NV
this
}

def |(that : FpuFlags) = {
val ret = FpuFlags()
ret.NX := this.NX | that.NX
Expand Down
Loading

0 comments on commit 9d4e67a

Please sign in to comment.