Skip to content

Commit

Permalink
Got the FPU to work in mixed modes (XLEN != FLEN)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dolu1990 committed Sep 19, 2024
1 parent 8abcd9b commit ccb0e1d
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/main/scala/vexiiriscv/Param.scala
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ class ParamSimple(){
plugins += new LsuL1Plugin(
lane = lane0,
memDataWidth = lsuMemDataWidth,
cpuDataWidth = xlen,
cpuDataWidth = xlen max withRvd.mux(64, 0),
refillCount = lsuL1RefillCount,
writebackCount = lsuL1WritebackCount,
setCount = lsuL1Sets,
Expand Down
22 changes: 19 additions & 3 deletions src/main/scala/vexiiriscv/execute/DivPlugin.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package vexiiriscv.execute

import spinal.core._
import spinal.core.fiber.Retainer
import spinal.lib._
import spinal.lib.misc.pipeline._
import vexiiriscv.execute.RsUnsignedPlugin._
Expand All @@ -20,6 +21,8 @@ trait DivReuse{
def divInject(layer : LaneLayer, at : Int, a : UInt, b : UInt, iterations : UInt) : Unit
def divRsp : DivRsp
def divRadix : Int
def divInjectWidth(a : Int, b : Int, iterations : Int)
val divRetainer = Retainer()
}

class DivPlugin(val layer : LaneLayer,
Expand Down Expand Up @@ -47,6 +50,16 @@ class DivPlugin(val layer : LaneLayer,
override def divRsp: DivRsp = logic.processing.div.io.rsp
override def divRadix: Int = radix

override def divInjectWidth(a: Int, b: Int, result: Int): Unit = {
injectApi.a = injectApi.a max a
injectApi.b = injectApi.b max b
injectApi.result = injectApi.result max result
}

val injectApi = new Area {
var a, b, result = 0
}

val logic = during setup new Logic {
awaitBuild()

Expand Down Expand Up @@ -74,15 +87,18 @@ class DivPlugin(val layer : LaneLayer,
}

uopRetainer.release()
divRetainer.await()

val processing = new el.Execute(divAt) {
val div = impl(Riscv.XLEN, radix, area)
val abWidthRaw = Riscv.XLEN.get max injectApi.a max injectApi.b
val abWidth = (abWidthRaw+4-1)/4*4
val div = impl(abWidth, radix, area)

val divRevertResult = RegNext((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)
val request = isValid && SEL
val a, b = UInt(Riscv.XLEN bits)
val a, b = UInt(abWidth bits)
a := RS1_UNSIGNED.resized
b := RS2_UNSIGNED.resized
div.io.cmd.valid := request && !cmdSent
Expand All @@ -103,7 +119,7 @@ class DivPlugin(val layer : LaneLayer,
val freeze = request && !div.io.rsp.valid & !unscheduleRequest
el.freezeWhen(freeze)

val selected = REM ? div.io.rsp.remain otherwise div.io.rsp.result
val selected = REM ? div.io.rsp.remain.resize(XLEN) otherwise div.io.rsp.result.resize(XLEN)

def twoComplement(that: Bits, enable: Bool): UInt = (Mux(enable, ~that, that).asUInt + enable.asUInt)
DIV_RESULT := twoComplement(B(selected), divRevertResult).asBits.resized
Expand Down
21 changes: 16 additions & 5 deletions src/main/scala/vexiiriscv/execute/MulPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import spinal.lib.misc.pipeline._
import vexiiriscv.riscv.{IntRegFile, RS1, RS2, Riscv, Rvi}
import Riscv._
import RsUnsignedPlugin._
import spinal.core.fiber.Retainer
import vexiiriscv.misc.{AdderAggregator, MulSpliter}

import scala.collection.mutable.ArrayBuffer
Expand All @@ -21,6 +22,8 @@ trait MulReuse{
def inject(a : Bits, b : Bits) : Unit
def rspAt : Int
def rsp : Bits
def injectWidth(a : Int, b : Int, result : Int) : Unit
val mulLock = Retainer()
}

class MulPlugin(val layer : LaneLayer,
Expand Down Expand Up @@ -51,6 +54,14 @@ class MulPlugin(val layer : LaneLayer,

override def rspAt: Int = writebackAt
override def rsp: Bits = logic.writeback.result.asBits
override def injectWidth(a: Int, b: Int, result : Int): Unit = {
injectApi.a = injectApi.a max a
injectApi.b = injectApi.b max b
injectApi.result = injectApi.result max result
}
val injectApi = new Area{
var a,b,result = 0
}

val logic = during setup new Logic {
if(Riscv.RVM.isEmpty) Riscv.RVM.set(true)
Expand Down Expand Up @@ -87,9 +98,9 @@ class MulPlugin(val layer : LaneLayer,
}
}
uopRetainer.release()

val finalWidth = XLEN*2
val SRC_WIDTH = XLEN.get + (!useRsUnsignedPlugin).toInt
mulLock.await()
val finalWidth = XLEN*2 max injectApi.result
val SRC_WIDTH = (XLEN.get + (!useRsUnsignedPlugin).toInt) max injectApi.a max injectApi.b
val keys = new AreaRoot{
val MUL_SRC1 = Payload(Bits(SRC_WIDTH bits))
val MUL_SRC2 = Payload(Bits(SRC_WIDTH bits))
Expand All @@ -102,8 +113,8 @@ class MulPlugin(val layer : LaneLayer,
val rs2 = node(el(IntRegFile, RS2))
useRsUnsignedPlugin match {
case false => {
MUL_SRC1 := (RS1_SIGNED && rs1.msb) ## (rs1)
MUL_SRC2 := (RS2_SIGNED && rs2.msb) ## (rs2)
MUL_SRC1 := ((RS1_SIGNED && rs1.msb) ## (rs1)).asSInt.resize(SRC_WIDTH).asBits
MUL_SRC2 := ((RS2_SIGNED && rs2.msb) ## (rs2)).asSInt.resize(SRC_WIDTH).asBits
if(keepMulSrc) {
KeepAttribute(apply(MUL_SRC1))
KeepAttribute(apply(MUL_SRC2))
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/vexiiriscv/execute/fpu/FpuDivPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ class FpuDivPlugin(val layer : LaneLayer,
val fpp = host[FpuPackerPlugin]
val dr = host[DivReuse]
val buildBefore = retains(layer.lane.pipelineLock)
val uopLock = retains(layer.lane.uopLock, fup.elaborationLock, fpp.elaborationLock)
val uopLock = retains(layer.lane.uopLock, fup.elaborationLock, fpp.elaborationLock, dr.divRetainer)
awaitBuild()
dr.divInjectWidth(p.unpackedConfig.mantissaWidth+1, p.unpackedConfig.mantissaWidth+1, p.unpackedConfig.mantissaWidth+1)

val packParam = FloatUnpackedParam(
exponentMax = p.unpackedConfig.exponentMax-p.unpackedConfig.exponentMin,
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/vexiiriscv/execute/fpu/FpuMulPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ class FpuMulPlugin(val layer : LaneLayer,
val fasp = host[FpuAddSharedPlugin]
val mp = host[MulReuse]
val buildBefore = retains(layer.lane.pipelineLock)
val uopLock = retains(layer.lane.uopLock, fup.elaborationLock, fpp.elaborationLock)
val uopLock = retains(layer.lane.uopLock, fup.elaborationLock, fpp.elaborationLock, mp.mulLock)
awaitBuild()
mp.injectWidth(p.unpackedConfig.mantissaWidth + 2, p.unpackedConfig.mantissaWidth + 2, 2 * (p.unpackedConfig.mantissaWidth + 2))

val packParam = FloatUnpackedParam(
exponentMax = p.unpackedConfig.exponentMax * 2 + 1,
Expand Down Expand Up @@ -117,7 +118,6 @@ class FpuMulPlugin(val layer : LaneLayer,
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)
}
}
Expand Down
13 changes: 9 additions & 4 deletions src/main/scala/vexiiriscv/execute/fpu/FpuMvPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ class FpuMvPlugin(val layer : LaneLayer,

add(Rvfd.FMV_W_X, f32, SEL_FLOAT -> True)
add(Rvfd.FMV_X_W, f32, SEL_INT -> True)
if (Riscv.RVD && Riscv.XLEN.get == 64) {
add(Rvfd.FMV_D_X, f64, SEL_FLOAT -> True)
add(Rvfd.FMV_X_D, f64, SEL_INT -> True)
if (Riscv.XLEN.get == 64) {
iwbp.signExtend(iwb, layer(Rvfd.FMV_X_W), 32)
if (Riscv.RVD) {
add(Rvfd.FMV_D_X, f64, SEL_FLOAT -> True)
add(Rvfd.FMV_X_D, f64, SEL_INT -> True)
}
}

uopLock.release()
Expand All @@ -70,7 +72,10 @@ class FpuMvPlugin(val layer : LaneLayer,
fwb.valid := SEL_FLOAT
fwb.payload(31 downto 0) := up(layer.lane(IntRegFile, RS1))(31 downto 0)
if(Riscv.RVD.get) {
fwb.payload(63 downto 32) := muxDouble(FORMAT)(up(layer.lane(IntRegFile, RS1))(63 downto 32))(B"xFFFFFFFF")
fwb.payload(63 downto 32) := (Riscv.XLEN.get == 32).mux(
B"xFFFFFFFF",
muxDouble(FORMAT)(up(layer.lane(IntRegFile, RS1))(63 downto 32))(B"xFFFFFFFF")
)
}
}

Expand Down
15 changes: 8 additions & 7 deletions src/main/scala/vexiiriscv/execute/lsu/LsuPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,8 @@ class LsuPlugin(var layer : LaneLayer,



val writeData = CombInit[Bits](elp(IntRegFile, riscv.RS2))
val writeData = Bits(Riscv.LSLEN bits)
writeData := elp(IntRegFile, riscv.RS2).resized
if(Riscv.withFpu) when(FLOAT){
val value = elp(FloatRegFile, riscv.RS2)
writeData(value.bitsRange) := value
Expand Down Expand Up @@ -522,7 +523,7 @@ class LsuPlugin(var layer : LaneLayer,
val srcZipped = splited.zipWithIndex.filter { case (v, b) => b % (wordBytes / srcSize) == i }
val src = srcZipped.map(_._1)
val range = log2Up(wordBytes) - 1 downto log2Up(wordBytes) - log2Up(srcSize)
val sel = srcp.ADD_SUB(range).asUInt
val sel = l1.MIXED_ADDRESS(range)
shited(i * 8, 8 bits) := src.read(sel)
}
val RESULT = insert(shited)
Expand All @@ -544,7 +545,7 @@ class LsuPlugin(var layer : LaneLayer,
l1.lockPort.address := 0
}
val rva = Riscv.RVA.get generate new Area {
val srcBuffer = RegNext[Bits](loadData.RESULT)
val srcBuffer = RegNext[Bits](loadData.RESULT.resize(XLEN bits))
val alu = new AtomicAlu(
op = UOP(29, 3 bits),
swap = UOP(27),
Expand All @@ -555,7 +556,7 @@ class LsuPlugin(var layer : LaneLayer,
val aluBuffer = RegNext(alu.result)

when(preCtrl.IS_AMO) {
writeData := aluBuffer
writeData(aluBuffer.bitsRange) := aluBuffer
}

val delay = History(!elp.isFreezed(), 1 to 2)
Expand Down Expand Up @@ -772,7 +773,7 @@ class LsuPlugin(var layer : LaneLayer,
assert(dbusAccesses.size == 1)
val rsp = dbusAccesses.head.rsp
rsp.valid := l1.SEL && FROM_ACCESS && !elp.isFreezed()
rsp.data := l1.READ_DATA
rsp.data := loadData.RESULT.resized //loadData.RESULT instead of l1.READ_DATA (because it rv32fd
rsp.error := l1.FAULT
rsp.redo := traps.l1Failed
rsp.waitSlot := 0
Expand Down Expand Up @@ -811,7 +812,7 @@ class LsuPlugin(var layer : LaneLayer,

val onWb = new elp.Execute(wbAt){
iwb.valid := SEL && !FLOAT
iwb.payload := onCtrl.loadData.RESULT
iwb.payload := onCtrl.loadData.RESULT.resized

if (withRva) when(l1.ATOMIC && !l1.LOAD) {
iwb.payload(0) := onCtrl.SC_MISS
Expand All @@ -820,7 +821,7 @@ class LsuPlugin(var layer : LaneLayer,

fpwb.foreach{p =>
p.valid := SEL && FLOAT
p.payload := onCtrl.loadData.RESULT
p.payload := onCtrl.loadData.RESULT.resized
if(Riscv.RVD) when(SIZE === 2) {
p.payload(63 downto 32).setAll()
}
Expand Down
5 changes: 4 additions & 1 deletion src/main/scala/vexiiriscv/test/WhiteboxerPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,10 @@ class WhiteboxerPlugin(withOutputs : Boolean) extends FiberPlugin{
uopId := c(Decode.UOP_ID)
size := c(AguPlugin.SIZE).resized
address := c(LsuL1.PHYSICAL_ADDRESS)
data := host.find[IntFormatPlugin](_.lane == p.layer.lane).logic.stages.find(_.ctrlLink == c.ctrlLink).get.wb.payload
data := host.find[IntFormatPlugin](_.lane == p.layer.lane).logic.stages.find(_.ctrlLink == c.ctrlLink).get.wb.payload.resized
if(p.logic.fpwb.nonEmpty) when(p.logic.fpwb.get.valid){
data := p.logic.fpwb.get.payload.asSInt.resize(widthOf(data)).asBits
}
})
}

Expand Down
16 changes: 13 additions & 3 deletions src/test/scala/vexiiriscv/tester/Regression.scala
Original file line number Diff line number Diff line change
Expand Up @@ -373,19 +373,29 @@ class RegressionSingle(compiled : SimCompiled[VexiiRiscv],


val freertos = List(
"sp_flop", "blocktim", "integer", "countsem", "EventGroupsDemo", "flop", "QPeek",
"integer", "countsem", "EventGroupsDemo", "flop", "QPeek",
"QueueSet", "recmutex", "semtest", "TaskNotify", "dynamic",
"GenQTest", "PollQ", "QueueOverwrite", "QueueSetPolling", "test1"
)
if(rvm) for(name <- freertos.take(config.freertosCount)){
val args = newArgs()
args.loadElf(new File(nsf, f"baremetal/freertosDemo/build/${name}/${arch + (arch.endsWith("im").mux("a",""))}/freertosDemo.elf"))
var freertosArch = arch
if(xlen == 64 && rvf && !rvd) freertosArch = "rv64ima"
args.loadElf(new File(nsf, f"baremetal/freertosDemo/build/${name}/${freertosArch + (freertosArch.endsWith("im").mux("a",""))}/freertosDemo.elf"))
args.failAfter(300000000)
args.name(s"freertos/$name")
}

if(config.buildroot && rvm && rva && mmu.nonEmpty) priv.filter(_.p.withSupervisor).foreach{ _ =>
val path = s"ext/NaxSoftware/buildroot/images/$archLinux"
var arch = s"rv${xlen}ima"
xlen match{
case 32 => if(rvc) arch += "c"
case 64 => {
if(rvf && rvd && rvc) arch += "fdc"
else if (rvc) arch += "c"
}
}
val path = s"ext/NaxSoftware/buildroot/images/$arch"
val args = newArgs()
args.failAfter(10000000000l)
args.name("buildroot")
Expand Down

0 comments on commit ccb0e1d

Please sign in to comment.