Skip to content

Commit

Permalink
Got internal FPU to run mul/sqrt/load/store
Browse files Browse the repository at this point in the history
  • Loading branch information
Dolu1990 committed Apr 18, 2024
1 parent c5d3d28 commit f47a6ba
Show file tree
Hide file tree
Showing 14 changed files with 409 additions and 116 deletions.
8 changes: 6 additions & 2 deletions src/main/scala/vexiiriscv/Param.scala
Original file line number Diff line number Diff line change
Expand Up @@ -652,8 +652,12 @@ class ParamSimple(){
)

// plugins += new execute.fpu.FpuExecute(early0, 0)
plugins += new WriteBackPlugin("lane0", FloatRegFile, writeAt = 2, allowBypassFrom = allowBypassFrom)
plugins += new execute.fpu.FpuCsr()
plugins += new WriteBackPlugin("lane0", FloatRegFile, writeAt = 8, allowBypassFrom = allowBypassFrom)
plugins += new execute.fpu.FpuCsr(List(lane0))
plugins += new execute.fpu.FpuUnpackerPlugin(early0)
plugins += new execute.fpu.FpuMulPlugin(early0)
plugins += new execute.fpu.FpuSqrtPlugin(early0)
plugins += new execute.fpu.FpuPackerPlugin(lane0)
// plugins += new execute.fpu.FpuEmbedded()
}

Expand Down
30 changes: 23 additions & 7 deletions src/main/scala/vexiiriscv/execute/MulPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ object MulPlugin extends AreaObject {
val RESULT_IS_SIGNED = Payload(Bool())
}

trait MulReuse{
def cmdAt : Int
def inject(a : Bits, b : Bits) : Unit
def rspAt : Int
def rsp : Bits
}

class MulPlugin(val layer : LaneLayer,
var srcAt : Int = 0,
var cmdAt : Int = 0,
var mulAt: Int = 0,
var sumAt: Int = 1,
var sumsSpec: List[(Int, Int)] = List((44, 8), (1000, 1000)),
Expand All @@ -26,9 +33,18 @@ class MulPlugin(val layer : LaneLayer,
var splitWidthA : Int = 17,
var splitWidthB : Int = 17,
var useRsUnsignedPlugin : Boolean = false,
var bufferedHigh : Option[Boolean] = None) extends ExecutionUnitElementSimple(layer){
var bufferedHigh : Option[Boolean] = None) extends ExecutionUnitElementSimple(layer) with MulReuse {
import MulPlugin._


override def inject(src1: Bits, src2: Bits): Unit = {
logic.src(logic.keys.MUL_SRC1) := src1
logic.src(logic.keys.MUL_SRC2) := src2
}

override def rspAt: Int = writebackAt
override def rsp: Bits = logic.writeback.result.asBits

val logic = during setup new Logic {
if(Riscv.RVM.isEmpty) Riscv.RVM.set(true)
awaitBuild()
Expand All @@ -48,8 +64,8 @@ class MulPlugin(val layer : LaneLayer,

if(!useRsUnsignedPlugin){
for(uop <- List(Rvi.MUL,Rvi.MULH, Rvi.MULHSU, Rvi.MULHU); spec = layer(uop)){
spec.addRsSpec(RS1, srcAt)
spec.addRsSpec(RS2, srcAt)
spec.addRsSpec(RS1, cmdAt)
spec.addRsSpec(RS2, cmdAt)
}
}

Expand All @@ -58,8 +74,8 @@ class MulPlugin(val layer : LaneLayer,
for (op <- List(Rvi.MULW); spec = layer(op)) {
ifp.signExtend(formatBus, layer(op), 32)
if (!useRsUnsignedPlugin) {
spec.addRsSpec(RS1, srcAt)
spec.addRsSpec(RS2, srcAt)
spec.addRsSpec(RS1, cmdAt)
spec.addRsSpec(RS2, cmdAt)
}
}
}
Expand All @@ -73,7 +89,7 @@ class MulPlugin(val layer : LaneLayer,
}
import keys._

val src = new el.Execute(srcAt) {
val src = new el.Execute(cmdAt) {
val rs1 = up(el(IntRegFile, RS1))
val rs2 = up(el(IntRegFile, RS2))
useRsUnsignedPlugin match {
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/vexiiriscv/execute/Service.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class LaneLayer(val name : String, val el : ExecuteLaneService, var priority : I
def doChecks(): Unit = {
for(uop <- uops.values) uop.doCheck()
}
class Execute(id: Int) extends CtrlLaneMirror(el.execute(id))
}

class UopLayerSpec(val uop: MicroOp, val elImpl : LaneLayer, val el : ExecuteLaneService) {
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/vexiiriscv/execute/WriteBackPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class WriteBackPlugin(val laneName : String,
def createPort(at : Int): Flow[Bits] = {
val port = Flow(Bits(rf.width bits))
portToSpec(port) = Spec(port, at)
assert(at <= writeAt, "WriteBackPlugin.createPort target is behond writeback range")
port
}
def addMicroOp(port: Flow[Bits], layer : LaneLayer, uop: Seq[MicroOp]): Unit = addMicroOp(port, uop.map(layer.apply))
Expand Down
11 changes: 7 additions & 4 deletions src/main/scala/vexiiriscv/execute/fpu/FpuCsr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,15 @@ import vexiiriscv.regfile.{RegFileWriter, RegFileWriterService, RegfileService}
import vexiiriscv.riscv._


class FpuCsr() extends FiberPlugin{


class FpuCsr(lanes : Seq[ExecuteLaneService]) extends FiberPlugin{
val api = during build new Area{
val rm = Reg(Bits(3 bits)) init (0)
val flags = Reg(FpuFlags())
}

val logic = during setup new Area{
val cp = host[CsrService]
val buildBefore = retains(cp.csrLock)
val buildBefore = retains(lanes.map(_.pipelineLock) :+ cp.csrLock)
awaitBuild()

assert(Global.HART_COUNT.get == 1)
Expand All @@ -36,6 +34,11 @@ class FpuCsr() extends FiberPlugin{
cp.readWrite(CSR.FRM, 0 -> api.rm)
cp.readWrite(CSR.FFLAGS, 0 -> api.flags)

for(lane <- lanes) new lane.Execute(0){
val instrRounding = Decode.UOP(Const.funct3Range)
FpuUtils.ROUNDING.assignFromBits((instrRounding === B"111").mux(api.rm, instrRounding))
}

buildBefore.release()
}
}
94 changes: 85 additions & 9 deletions src/main/scala/vexiiriscv/execute/fpu/FpuMulPlugin.scala
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
package vexiiriscv.execute.fpu

import spinal.core._
import spinal.core.{out, _}
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.Riscv.XLEN
import vexiiriscv.riscv._


class FpuMulPlugin(layer : LaneLayer, unpackAt : Int, packAt : Int) extends FiberPlugin{
class FpuMulPlugin(val layer : LaneLayer,
var expAt : Int = 0,
var normAt: Int = 3,
var packAt : Int = 4) extends FiberPlugin{
val p = FpuUtils

val SEL = Payload(Bool())

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

val packParam = FloatUnpackedParam(
exponentMax = ???,
exponentMin = ???,
mantissaWidth = ???
exponentMax = p.unpackedConfig.exponentMax*2+1,
exponentMin = p.unpackedConfig.exponentMin*2,
mantissaWidth = p.unpackedConfig.mantissaWidth+2
)
val wb = fpp.createPort(packAt, packParam)

Expand All @@ -35,17 +43,85 @@ class FpuMulPlugin(layer : LaneLayer, unpackAt : Int, packAt : Int) extends Fibe
case RfResource(_, rs: RfRead) => fup.unpack(uop, rs)
case _ =>
}
wb.uops += uop
wb.uops += spec
}

add(Rvfd.FMUL_S)
val f64 = FORMAT -> FpuFormat.DOUBLE
val f32 = FORMAT -> FpuFormat.FLOAT

add(Rvfd.FMUL_S, f32)
if(Riscv.RVD) {
add(Rvfd.FMUL_D)
add(Rvfd.FMUL_D, f64)
}

uopLock.release()



val RS1_FP = fup(RS1)
val RS2_FP = fup(RS2)

val calc = new layer.Execute(expAt){
val EXP_ADD = insert(RS1_FP.exponent + RS2_FP.exponent)
val SIGN = insert(RS1_FP.sign ^ RS2_FP.sign)
val FORCE_ZERO = insert(RS1_FP.isZero || RS2_FP.isZero)
val FORCE_OVERFLOW = insert(RS1_FP.isInfinity || RS2_FP.isInfinity)
val INFINITY_NAN = insert(((RS1_FP.isInfinity || RS2_FP.isInfinity) && (RS1_FP.isZero || RS2_FP.isZero)))
val FORCE_NAN = insert(RS1_FP.isNan || RS2_FP.isNan || INFINITY_NAN)
}

import calc._


val mulCmd = new layer.Execute(mp.cmdAt){
val m1 = B"1" ## RS1_FP.mantissa.raw.asUInt
val m2 = B"1" ## RS2_FP.mantissa.raw.asUInt
when(SEL) {
assert(!(Riscv.RVD && XLEN.get == 32))
mp.inject(m1.resized, m2.resized)
}
}

val mulRsp = new layer.Execute(mp.rspAt){
val MUL_RESULT = insert(mp.rsp.take(widthOf(mulCmd.m1) + widthOf(mulCmd.m2)))
}
import mulRsp.MUL_RESULT

val norm = new layer.Execute(normAt){
val needShift = MUL_RESULT.msb
val EXP = insert(EXP_ADD + AFix(U(needShift)))
val MAN = insert(AFix(U(needShift ? MUL_RESULT.dropHigh(1) | (MUL_RESULT.dropHigh(2) << 1)), 1-widthOf(MUL_RESULT) exp))
}
import norm._

val onPack = new layer.el.Execute(packAt) {
val RESULT = Payload(FloatUnpacked(packParam))

RESULT.sign := SIGN
RESULT.exponent := EXP
RESULT.mantissa := MAN.rounded(RoundType.SCRAP)
RESULT.mode := FloatMode.NORMAL
RESULT.quiet := True

val NV = insert(False)

when(FORCE_NAN) {
RESULT.setNanQuiet
NV setWhen (INFINITY_NAN || RS1_FP.isNanSignaling || RS2_FP.isNanSignaling)
}.elsewhen(FORCE_OVERFLOW) {
RESULT.setInfinity
}.elsewhen(FORCE_ZERO) {
RESULT.setZero
}

wb.cmd.valid := isValid && SEL
wb.cmd.value := RESULT
wb.cmd.format := FORMAT
wb.cmd.roundMode := FpuUtils.ROUNDING
wb.cmd.hartId := Global.HART_ID
wb.cmd.uopId := Decode.UOP_ID
}



buildBefore.release()
}
Expand Down
Loading

0 comments on commit f47a6ba

Please sign in to comment.