Skip to content

Commit

Permalink
Added AMO support, not tested, but generation is ok
Browse files Browse the repository at this point in the history
  • Loading branch information
Dolu1990 committed Jan 11, 2024
1 parent bfe190d commit e2564a2
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 39 deletions.
4 changes: 4 additions & 0 deletions src/main/scala/vexiiriscv/Param.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ParamSimple(){
var withLateAlu = false
var withMul = true
var withDiv = true
var withAmo = false
var privParam = PrivilegedParam.base
var relaxedBranch = false
var relaxedShift = false
Expand Down Expand Up @@ -59,6 +60,7 @@ class ParamSimple(){
privParam.withSupervisor = true
privParam.withUser = true
withMmu = true
withAmo = true
}


Expand All @@ -76,6 +78,7 @@ class ParamSimple(){
if (withLateAlu) r += "la"
if (withMul) r += "m"
if (withDiv) r += "d"
if (withAmo) r += "a"
if (relaxedBranch) r += "rbra"
if (relaxedShift) r += "rsft"
if (relaxedSrc) r += "rsrc"
Expand Down Expand Up @@ -226,6 +229,7 @@ class ParamSimple(){
plugins += new BranchPlugin(layer=early0, aluAt=0, jumpAt=relaxedBranch.toInt, wbAt=0)
plugins += new LsuCachelessPlugin(
layer = early0,
withAmo = withAmo,
withSpeculativeLoadFlush = true,
addressAt = 0,
forkAt = 0,
Expand Down
33 changes: 22 additions & 11 deletions src/main/scala/vexiiriscv/execute/Agu.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import spinal.lib.misc.pipeline._
import spinal.lib.misc.plugin.{FiberPlugin, PluginHost}
import vexiiriscv.Global
import vexiiriscv.decode.Decode
import vexiiriscv.riscv.{Const, Rvfd, Rvi}
import vexiiriscv.riscv.{Const, MicroOp, Rvfd, Rvi}
import vexiiriscv.riscv.Riscv._

import scala.collection.mutable.ArrayBuffer
Expand Down Expand Up @@ -33,29 +33,40 @@ class AguFrontend(

layer.el.setDecodingDefault(SEL, False)

val loads = ArrayBuffer(Rvi.LB, Rvi.LH, Rvi.LW, Rvi.LBU, Rvi.LHU)
val loads = ArrayBuffer[MicroOp](Rvi.LB, Rvi.LH, Rvi.LW, Rvi.LBU, Rvi.LHU)
if (XLEN.get == 64) loads ++= List(Rvi.LD, Rvi.LWU)
if (RVF) loads ++= List(Rvfd.FLW)
if (RVD) loads ++= List(Rvfd.FLD)
for (op <- loads) add(op).srcs(sk.Op.ADD, sk.SRC1.RF, sk.SRC2.I).decode(LR -> False, LOAD -> True)

// Store stuff
val storeOps = List(sk.Op.ADD, sk.SRC1.RF, sk.SRC2.S)
val stores = ArrayBuffer(Rvi.SB, Rvi.SH, Rvi.SW)
val stores = ArrayBuffer[MicroOp](Rvi.SB, Rvi.SH, Rvi.SW)
if (XLEN.get == 64) stores ++= List(Rvi.SD)
for (store <- stores) add(store).srcs(storeOps).decode(AMO -> False, SC -> False, LOAD -> False, FLOAT -> False)
if (RVF) add(Rvfd.FSW).srcs(storeOps).decode(AMO -> False, SC -> False, LOAD -> False, FLOAT -> True)
if (RVD) add(Rvfd.FSD).srcs(storeOps).decode(AMO -> False, SC -> False, LOAD -> False, FLOAT -> True)

// Atomic stuff
if (RVA) {
val amos = List(
Rvi.AMOSWAP, Rvi.AMOADD, Rvi.AMOXOR, Rvi.AMOAND, Rvi.AMOOR,
Rvi.AMOMIN, Rvi.AMOMAX, Rvi.AMOMINU, Rvi.AMOMAXU
val amos = RVA.get generate new Area {
val uops = ArrayBuffer[MicroOp]()
uops ++= List(
Rvi.AMOSWAPW, Rvi.AMOADDW, Rvi.AMOXORW, Rvi.AMOANDW, Rvi.AMOORW,
Rvi.AMOMINW, Rvi.AMOMAXW, Rvi.AMOMINUW, Rvi.AMOMAXUW
)
for (amo <- amos) add(amo).srcs(sk.Op.SRC1, sk.SRC1.RF).decode(AMO -> True, SC -> False, LOAD -> False, FLOAT -> False)
add(Rvi.SC).srcs(sk.Op.SRC1, sk.SRC1.RF).decode(AMO -> False, SC -> True, LOAD -> False, FLOAT -> False)
add(Rvi.LR).srcs(sk.Op.SRC1, sk.SRC1.RF).decode(LR -> True, LOAD -> True)
assert(false, "Rvi.LR and atomic may need reformat info, CachelessPlugin may use loads list for it, need to add to loads. Also store completion need to be handled")
if(XLEN.get == 64) uops ++= List(
Rvi.AMOSWAPD, Rvi.AMOADDD, Rvi.AMOXORD, Rvi.AMOANDD, Rvi.AMOORD,
Rvi.AMOMIND, Rvi.AMOMAXD, Rvi.AMOMINUD, Rvi.AMOMAXUD
)
for (amo <- uops) add(amo).srcs(sk.Op.SRC1, sk.SRC1.RF).decode(AMO -> True, SC -> False, LOAD -> False, FLOAT -> False)
stores += add(Rvi.SCW).srcs(sk.Op.SRC1, sk.SRC1.RF).decode(AMO -> False, SC -> True, LOAD -> False, FLOAT -> False).uop
loads += Rvi.SCW
loads += add(Rvi.LRW).srcs(sk.Op.SRC1, sk.SRC1.RF).decode(LR -> True, LOAD -> True).uop
if(XLEN.get == 64){
stores += add(Rvi.SCD).srcs(sk.Op.SRC1, sk.SRC1.RF).decode(AMO -> False, SC -> True, LOAD -> False, FLOAT -> False).uop
loads += Rvi.SCD
loads += add(Rvi.LRD).srcs(sk.Op.SRC1, sk.SRC1.RF).decode(LR -> True, LOAD -> True).uop
}
// assert(false, "Rvi.LR and atomic may need reformat info, CachelessPlugin may use loads list for it, need to add to loads. Also store completion need to be handled")
}
}
4 changes: 4 additions & 0 deletions src/main/scala/vexiiriscv/execute/CsrAccessPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class CsrAccessPlugin(layer : LaneLayer,
override def onDecodeHartId: UInt = apiIo.onDecodeHartId
override def onDecodeAddress: UInt = apiIo.onDecodeAddress
override def onDecodeTrapCode: Bits = apiIo.onDecodeTrapCode
def onDecodeTrap(code : Int) : Unit = {
onDecodeTrap()
onDecodeTrapCode := code
}


override def isReading: Bool = apiIo.isReading
Expand Down
9 changes: 4 additions & 5 deletions src/main/scala/vexiiriscv/execute/CsrService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,11 @@ case class CsrRamWrite(addressWidth : Int, dataWidth : Int, priority : Int) exte


object CsrRamService{
//Priorities are arranged in a way to improve ports.ready timings
val priority = new {
val INIT = 0
val TRAP = 1
val COUNTER = 2
val CSR = 3 //This is the very critical path
val INIT = 0
val CSR = 1
val TRAP = 2
val COUNTER = 3
}
}
//usefull for, for instance, mscratch scratch mtvec stvec mepc sepc mtval stval satp pmp stuff
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ object ExecuteUnitElementSimple{

val uopList = ArrayBuffer[MicroOp]()
def add(microOp: MicroOp) = new {
val uop = microOp
uopList += microOp
val impl = layer.add(microOp)
val spec = layer(microOp)
Expand Down
29 changes: 22 additions & 7 deletions src/main/scala/vexiiriscv/execute/LsuCachelessPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import vexiiriscv.memory.{AddressTranslationPortUsage, AddressTranslationService
import vexiiriscv.misc.{AddressToMask, TrapArg, TrapReason, TrapService}
import vexiiriscv.riscv.Riscv.{LSLEN, XLEN}
import spinal.lib.misc.pipeline._
import vexiiriscv.decode.Decode.INSTRUCTION_SLICE_COUNT_WIDTH
import vexiiriscv.decode.Decode.{INSTRUCTION_SLICE_COUNT_WIDTH, UOP}
import vexiiriscv.schedule.{ReschedulePlugin, ScheduleService}

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

case class CachelessBusParam(addressWidth : Int, dataWidth : Int, hartIdWidth : Int){
case class CachelessBusParam(addressWidth : Int, dataWidth : Int, hartIdWidth : Int, withAmo : Boolean){

}

Expand All @@ -32,6 +32,8 @@ case class CachelessCmd(p : CachelessBusParam) extends Bundle{
val io = Bool() //This is for verification purposes, allowing RVLS to track stuff
val fromHart = Bool() //This is for verification purposes, allowing RVLS to track stuff
val hartId = UInt(p.hartIdWidth bits)
val amoEnable = p.withAmo generate Bool()
val amoOp = p.withAmo generate Bits(5 bits)
}

case class CachelessRsp(p : CachelessBusParam) extends Bundle{
Expand All @@ -50,6 +52,7 @@ case class CachelessBus(p : CachelessBusParam) extends Bundle with IMasterSlave
}

class LsuCachelessPlugin(var layer : LaneLayer,
var withAmo : Boolean,
var withSpeculativeLoadFlush : Boolean, //WARNING, the fork cmd may be flushed out of existance before firing
var translationStorageParameter: Any,
var translationPortParameter: Any,
Expand All @@ -73,6 +76,7 @@ class LsuCachelessPlugin(var layer : LaneLayer,
val atsStorageLock = retains(ats.storageLock)
val retainer = retains(elp.uopLock, srcp.elaborationLock, ifp.elaborationLock, ts.trapLock, ss.elaborationLock)
awaitBuild()
Riscv.RVA.set(withAmo)

val translationStorage = ats.newStorage(translationStorageParameter)
atsStorageLock.release()
Expand All @@ -83,7 +87,8 @@ class LsuCachelessPlugin(var layer : LaneLayer,

// IntFormatPlugin specification
val iwb = ifp.access(wbAt)
for(load <- frontend.loads){
val amos = Riscv.RVA.get.option(frontend.amos.uops).toList.flatten
for(load <- frontend.loads ++ amos){
val spec = Rvi.loadSpec(load)
val op = layer(load)
ifp.addMicroOp(iwb, op)
Expand All @@ -97,16 +102,16 @@ class LsuCachelessPlugin(var layer : LaneLayer,
}
}

for(store <- frontend.stores){
for(store <- frontend.stores ++ amos){
val op = layer(store)
op.addRsSpec(RS2, forkAt)
op.dontFlushFrom(forkAt+1)
}

layer.add(Rvi.FENCE) //TODO

layer(Rvi.FENCE).setCompletion(joinAt)
for(uop <- frontend.stores) layer(uop).setCompletion(joinAt)

for(uop <- frontend.stores if layer(uop).completion.isEmpty) layer(uop).setCompletion(joinAt)

retainer.release()

Expand All @@ -121,7 +126,12 @@ class LsuCachelessPlugin(var layer : LaneLayer,
val joinCtrl = elp.execute(joinAt)
val wbCtrl = elp.execute(wbAt)

val busParam = CachelessBusParam(addressWidth = Global.PHYSICAL_WIDTH, dataWidth = Riscv.LSLEN, hartIdWidth = Global.HART_ID_WIDTH)
val busParam = CachelessBusParam(
addressWidth = Global.PHYSICAL_WIDTH,
dataWidth = Riscv.LSLEN,
hartIdWidth = Global.HART_ID_WIDTH,
withAmo = withAmo
)
val bus = master(CachelessBus(busParam))

accessRetainer.await()
Expand Down Expand Up @@ -161,6 +171,11 @@ class LsuCachelessPlugin(var layer : LaneLayer,
bus.cmd.io := tpk.IO
bus.cmd.fromHart := True
bus.cmd.hartId := Global.HART_ID
if(withAmo) {
bus.cmd.amoEnable := LR || SC || AMO
bus.cmd.amoOp := UOP(31 downto 27)
}
//TODO amo AQ/RL

elp.freezeWhen(bus.cmd.isStall)

Expand Down
4 changes: 1 addition & 3 deletions src/main/scala/vexiiriscv/memory/MmuPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,9 @@ class MmuPlugin(var spec : MmuSpec,
csr.readWrite(CSR.SATP, satp.modeOffset -> satp.mode/*, 22 -> satp.asid*/, 0 -> satp.ppn)
val satpModeWrite = csr.onWriteBits(satp.modeOffset, satp.modeWidth bits)
csr.writeCancel(CSR.SATP, satpModeWrite =/= 0 && satpModeWrite =/= spec.satpMode)
// csr.readWriteRam(CSR.SATP) not suported by writeCancel

csr.onDecode(CSR.SATP){
csr.onDecodeTrap()
csr.onDecodeTrapCode := TrapReason.SFENCE_VMA
csr.onDecodeTrap(TrapReason.SFENCE_VMA)
}

csr.trapNextOnWrite += CsrListFilter(List(CSR.MSTATUS, CSR.SSTATUS))
Expand Down
1 change: 0 additions & 1 deletion src/main/scala/vexiiriscv/riscv/RiscvPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class RiscvPlugin(var xlen : Int,
if(Riscv.RVM.isEmpty) Riscv.RVM.set(false)
if(Riscv.RVF.isEmpty) Riscv.RVF.set(false)
if(Riscv.RVD.isEmpty) Riscv.RVD.set(false)
if(Riscv.RVA.isEmpty) Riscv.RVA.set(false)
Riscv.XLEN.set(xlen)
Riscv.FLEN.set(List(Riscv.RVF.get.toInt*32, Riscv.RVD.get.toInt*64).max)
Riscv.LSLEN.set(List(Riscv.XLEN.get, Riscv.FLEN.get).max)
Expand Down
64 changes: 52 additions & 12 deletions src/main/scala/vexiiriscv/riscv/Rvi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,32 @@ object Rvi extends AreaObject {
val SW = TypeSSQ(M"-----------------010-----0100011")
val SD = TypeSSQ(M"-----------------011-----0100011")

val LR = if(Riscv.XLEN.get == 64) TypeILQ(M"00010--00000-----01------0101111") else TypeILQ(M"00010--00000-----010-----0101111")
val SC = if(Riscv.XLEN.get == 64) TypeASQ(M"00011------------01------0101111") else TypeASQ(M"00011------------010-----0101111")

val AMOSWAP = if(Riscv.XLEN.get == 64) TypeASQ(M"00001------------01------0101111") else TypeASQ(M"00001------------010-----0101111")
val AMOADD = if(Riscv.XLEN.get == 64) TypeASQ(M"00000------------01------0101111") else TypeASQ(M"00000------------010-----0101111")
val AMOXOR = if(Riscv.XLEN.get == 64) TypeASQ(M"00100------------01------0101111") else TypeASQ(M"00100------------010-----0101111")
val AMOAND = if(Riscv.XLEN.get == 64) TypeASQ(M"01100------------01------0101111") else TypeASQ(M"01100------------010-----0101111")
val AMOOR = if(Riscv.XLEN.get == 64) TypeASQ(M"01000------------01------0101111") else TypeASQ(M"01000------------010-----0101111")
val AMOMIN = if(Riscv.XLEN.get == 64) TypeASQ(M"10000------------01------0101111") else TypeASQ(M"10000------------010-----0101111")
val AMOMAX = if(Riscv.XLEN.get == 64) TypeASQ(M"10100------------01------0101111") else TypeASQ(M"10100------------010-----0101111")
val AMOMINU = if(Riscv.XLEN.get == 64) TypeASQ(M"11000------------01------0101111") else TypeASQ(M"11000------------010-----0101111")
val AMOMAXU = if(Riscv.XLEN.get == 64) TypeASQ(M"11100------------01------0101111") else TypeASQ(M"11100------------010-----0101111")
val LRW = TypeILQ(M"00010--00000-----010-----0101111")
val SCW = TypeASQ(M"00011------------010-----0101111")

val LRD = TypeILQ(M"00010--00000-----011-----0101111")
val SCD = TypeASQ(M"00011------------011-----0101111")

val AMOSWAPW = TypeASQ(M"00001------------010-----0101111")
val AMOADDW = TypeASQ(M"00000------------010-----0101111")
val AMOXORW = TypeASQ(M"00100------------010-----0101111")
val AMOANDW = TypeASQ(M"01100------------010-----0101111")
val AMOORW = TypeASQ(M"01000------------010-----0101111")
val AMOMINW = TypeASQ(M"10000------------010-----0101111")
val AMOMAXW = TypeASQ(M"10100------------010-----0101111")
val AMOMINUW = TypeASQ(M"11000------------010-----0101111")
val AMOMAXUW = TypeASQ(M"11100------------010-----0101111")


val AMOSWAPD = TypeASQ(M"00001------------011-----0101111")
val AMOADDD = TypeASQ(M"00000------------011-----0101111")
val AMOXORD = TypeASQ(M"00100------------011-----0101111")
val AMOANDD = TypeASQ(M"01100------------011-----0101111")
val AMOORD = TypeASQ(M"01000------------011-----0101111")
val AMOMIND = TypeASQ(M"10000------------011-----0101111")
val AMOMAXD = TypeASQ(M"10100------------011-----0101111")
val AMOMINUD = TypeASQ(M"11000------------011-----0101111")
val AMOMAXUD = TypeASQ(M"11100------------011-----0101111")

val MUL = TypeR(M"0000001----------000-----0110011")
val MULH = TypeR(M"0000001----------001-----0110011")
Expand Down Expand Up @@ -135,6 +149,32 @@ object Rvi extends AreaObject {
loadSpec(LBU) = LoadSpec( 8, false)
loadSpec(LHU) = LoadSpec(16, false)
loadSpec(LWU) = LoadSpec(32, false)

loadSpec(LRW) = LoadSpec(32, true)
loadSpec(SCW) = LoadSpec(32, true)

loadSpec(LRD) = LoadSpec(64, true)
loadSpec(SCD) = LoadSpec(64, true)

loadSpec(AMOSWAPW) = LoadSpec(32, true)
loadSpec(AMOADDW) = LoadSpec(32, true)
loadSpec(AMOXORW) = LoadSpec(32, true)
loadSpec(AMOANDW) = LoadSpec(32, true)
loadSpec(AMOORW) = LoadSpec(32, true)
loadSpec(AMOMINW) = LoadSpec(32, true)
loadSpec(AMOMAXW) = LoadSpec(32, true)
loadSpec(AMOMINUW) = LoadSpec(32, false)
loadSpec(AMOMAXUW) = LoadSpec(32, false)

loadSpec(AMOSWAPD) = LoadSpec(64, true)
loadSpec(AMOADDD) = LoadSpec(64, true)
loadSpec(AMOXORD) = LoadSpec(64, true)
loadSpec(AMOANDD) = LoadSpec(64, true)
loadSpec(AMOORD) = LoadSpec(64, true)
loadSpec(AMOMIND) = LoadSpec(64, true)
loadSpec(AMOMAXD) = LoadSpec(64, true)
loadSpec(AMOMINUD) = LoadSpec(64, false)
loadSpec(AMOMAXUD) = LoadSpec(64, false)
}


Expand Down

0 comments on commit e2564a2

Please sign in to comment.