Skip to content

Commit

Permalink
Add pmp support for cacheless configs
Browse files Browse the repository at this point in the history
Add pmp regression test
  • Loading branch information
Dolu1990 committed Nov 22, 2024
1 parent 2f918b0 commit eeadda3
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 13 deletions.
29 changes: 25 additions & 4 deletions src/main/scala/vexiiriscv/Param.scala
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,25 @@ class ParamSimple(){
withNapot = true
)

var fetchPmpParam = new PmpPortParameter(
var fetchNoL1PmpParam = new PmpPortParameter(
napotMatchAt = 0,
napotHitsAt = 1,
torCmpAt = 0,
torHitsAt = 1,
hitsAt = 1,
rspAt = 1
)

var lsuNoL1PmpParam = new PmpPortParameter(
napotMatchAt = 0,
napotHitsAt = 0,
torCmpAt = 0,
torHitsAt = 0,
hitsAt = 0,
rspAt = 0
)

var fetchL1PmpParam = new PmpPortParameter(
napotMatchAt = 1,
napotHitsAt = 1,
torCmpAt = 1,
Expand All @@ -181,7 +199,7 @@ class ParamSimple(){
rspAt = 2
)

var lsuPmpParam = new PmpPortParameter(
var lsuL1PmpParam = new PmpPortParameter(
napotMatchAt = 1,
napotHitsAt = 1,
torCmpAt = 1,
Expand Down Expand Up @@ -497,6 +515,7 @@ class ParamSimple(){
opt[Unit]("with-dispatcher-buffer") action { (v, c) => withDispatcherBuffer = true }
opt[Unit]("with-supervisor") action { (v, c) => privParam.withSupervisor = true; privParam.withUser = true; withMmu = true }
opt[Unit]("with-user") action { (v, c) => privParam.withUser = true }
opt[Unit]("without-mmu") action { (v, c) => withMmu = false }
opt[Unit]("without-mul") action { (v, c) => withMul = false }
opt[Unit]("without-div") action { (v, c) => withDiv = false }
opt[Unit]("with-mul") action { (v, c) => withMul = true }
Expand Down Expand Up @@ -616,6 +635,7 @@ class ParamSimple(){
forkAt = fetchForkAt,
joinAt = fetchForkAt+1, //You can for instance allow the external memory to have more latency by changing this
wordWidth = fetchMemDataWidth,
pmpPortParameter = fetchNoL1PmpParam,
translationStorageParameter = fetchTsp,
translationPortParameter = withMmu match {
case false => null
Expand Down Expand Up @@ -644,7 +664,7 @@ class ParamSimple(){
case false => null
case true => fetchTpp
},
pmpPortParameter = fetchPmpParam
pmpPortParameter = fetchL1PmpParam
)

fetchL1Prefetch match {
Expand Down Expand Up @@ -711,6 +731,7 @@ class ParamSimple(){
forkAt = lsuForkAt+0,
joinAt = lsuForkAt+1,
wbAt = 2, //TODO
pmpPortParameter = lsuNoL1PmpParam,
translationStorageParameter = lsuTsp,
translationPortParameter = withMmu match {
case false => null
Expand All @@ -730,7 +751,7 @@ class ParamSimple(){
storeBufferSlots = lsuStoreBufferSlots,
storeBufferOps = lsuStoreBufferOps,
softwarePrefetch = lsuSoftwarePrefetch,
pmpPortParameter = fetchPmpParam,
pmpPortParameter = fetchL1PmpParam,
translationStorageParameter = lsuTsp,
translationPortParameter = withMmu match {
case false => null
Expand Down
20 changes: 17 additions & 3 deletions src/main/scala/vexiiriscv/execute/lsu/LsuCachelessPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import spinal.core.fiber.{Handle, Retainer}
import spinal.core.sim.SimDataPimper
import vexiiriscv.decode.Decode
import vexiiriscv.fetch.FetchPipelinePlugin
import vexiiriscv.memory.{AddressTranslationPortUsage, AddressTranslationService, DBusAccessService, PmaLoad, PmaLogic, PmaPort, PmaStore}
import vexiiriscv.memory.{AddressTranslationPortUsage, AddressTranslationService, DBusAccessService, PmaLoad, PmaLogic, PmaPort, PmaStore, PmpService}
import vexiiriscv.misc.{AddressToMask, LsuTriggerService, PerformanceCounterService, TrapArg, TrapReason, TrapService}
import vexiiriscv.riscv.Riscv.{FLEN, LSLEN, XLEN}
import spinal.lib.misc.pipeline._
Expand All @@ -27,6 +27,7 @@ class LsuCachelessPlugin(var layer : LaneLayer,
var withSpeculativeLoadFlush : Boolean, //WARNING, the fork cmd may be flushed out of existance before firing if any plugin doesn't flush from the first cycle after !freeze
var translationStorageParameter: Any,
var translationPortParameter: Any,
var pmpPortParameter : Any,
var addressAt: Int = 0,
var triggerAt: Int = 0,
var pmaAt : Int = 0,
Expand Down Expand Up @@ -55,9 +56,10 @@ class LsuCachelessPlugin(var layer : LaneLayer,
val fpwbp = host.findOption[WriteBackPlugin](p => p.lane == layer.lane && p.rf == FloatRegFile)
val srcp = host.find[SrcPlugin](_.layer == layer)
val ats = host[AddressTranslationService]
val ps = host[PmpService]
val ts = host[TrapService]
val ss = host[ScheduleService]
val buildBefore = retains(elp.pipelineLock, ats.portsLock)
val buildBefore = retains(elp.pipelineLock, ats.portsLock, ps.portsLock)
val atsStorageLock = retains(ats.storageLock)
val retainer = retains(List(elp.uopLock, srcp.elaborationLock, ifp.elaborationLock, ts.trapLock, ss.elaborationLock) ++ fpwbp.map(_.elaborationLock))
awaitBuild()
Expand Down Expand Up @@ -138,6 +140,8 @@ class LsuCachelessPlugin(var layer : LaneLayer,
}
}



val onAddress = new addressCtrl.Area{
val RAW_ADDRESS = insert(srcp.ADD_SUB.asUInt)

Expand All @@ -152,6 +156,16 @@ class LsuCachelessPlugin(var layer : LaneLayer,
val MISS_ALIGNED = insert((1 to log2Up(LSLEN / 8)).map(i => SIZE === i && RAW_ADDRESS(i - 1 downto 0) =/= 0).orR) //TODO remove from speculLoad and handle it with trap
}
val tpk = onAddress.translationPort.keys
val pmpPort = ps.createPmpPort(
nodes = List.tabulate(forkAt+1)(elp.execute(_).down),
physicalAddress = tpk.TRANSLATED,
forceCheck = _ => False,
read = _(LOAD),
write = _(STORE),
execute = _ => False,
portSpec = pmpPortParameter,
storageSpec = null
)

val onPma = new elp.Execute(pmaAt){
val port = new PmaPort(Global.PHYSICAL_WIDTH, (0 to log2Up(Riscv.LSLEN / 8)).map(1 << _), List(PmaLoad, PmaStore))
Expand Down Expand Up @@ -233,7 +247,7 @@ class LsuCachelessPlugin(var layer : LaneLayer,
trapPort.code := TrapReason.REDO
}

when(tpk.ACCESS_FAULT || onPma.RSP.fault) {
when(tpk.ACCESS_FAULT || onPma.RSP.fault || pmpPort.ACCESS_FAULT) {
skip := True
trapPort.exception := True
trapPort.code := CSR.MCAUSE_ENUM.LOAD_ACCESS_FAULT
Expand Down
19 changes: 16 additions & 3 deletions src/main/scala/vexiiriscv/fetch/FetchCachelessPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import spinal.lib.bus.tilelink.DebugId
import spinal.lib.system.tag.{MappedTransfers, PmaRegion}
import vexiiriscv._
import vexiiriscv.Global._
import vexiiriscv.memory.{AddressTranslationPortUsage, AddressTranslationService, PmaLoad, PmaLogic, PmaPort}
import vexiiriscv.memory.{AddressTranslationPortUsage, AddressTranslationService, PmaLoad, PmaLogic, PmaPort, PmpService}
import vexiiriscv.misc.{PerformanceCounterService, TrapArg, TrapReason, TrapService}
import vexiiriscv.riscv.CSR

Expand All @@ -27,6 +27,7 @@ object FetchCachelessPlugin{
class FetchCachelessPlugin(var wordWidth : Int,
var translationStorageParameter: Any,
var translationPortParameter: Any,
var pmpPortParameter : Any,
var addressAt: Int = 0,
var pmaAt: Int = 0,
var forkAt : Int = 0,
Expand All @@ -36,9 +37,10 @@ class FetchCachelessPlugin(var wordWidth : Int,

val logic = during setup new Area{
val pp = host[FetchPipelinePlugin]
val ps = host[PmpService]
val ts = host[TrapService]
val ats = host[AddressTranslationService]
val buildBefore = retains(pp.elaborationLock, ats.portsLock)
val buildBefore = retains(pp.elaborationLock, ats.portsLock, ps.portsLock)
val atsStorageLock = retains(ats.storageLock)
val trapLock = ts.trapLock()
awaitBuild()
Expand Down Expand Up @@ -93,6 +95,17 @@ class FetchCachelessPlugin(var wordWidth : Int,
}
val tpk = onAddress.translationPort.keys

val pmpPort = ps.createPmpPort(
nodes = List.tabulate(joinAt+1)(pp.fetch(_).down),
physicalAddress = tpk.TRANSLATED,
forceCheck = _ => False,
read = _ => False,
write = _ => False,
execute = _ => True,
portSpec = pmpPortParameter,
storageSpec = null
)

val onPma = new pp.Fetch(pmaAt) {
val port = new PmaPort(Global.PHYSICAL_WIDTH, List(Fetch.WORD_WIDTH / 8), List(PmaLoad))
port.cmd.address := tpk.TRANSLATED
Expand Down Expand Up @@ -152,7 +165,7 @@ class FetchCachelessPlugin(var wordWidth : Int,
trapPort.code.assignDontCare()
trapPort.arg.allowOverride() := 0

when(rsp.error || fork.PMA_FAULT){
when(rsp.error || fork.PMA_FAULT || pmpPort.ACCESS_FAULT){
TRAP := True
trapPort.exception := True
trapPort.code := CSR.MCAUSE_ENUM.INSTRUCTION_ACCESS_FAULT
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/vexiiriscv/memory/PmpPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class PmpPlugin(val p : PmpParam) extends FiberPlugin with PmpService{

val isNapot = RegNext(cfg.kind(1))
val isTor = RegNext(cfg.kind === 1)
val napot = Napot(address.dropHigh(1)).dropLow(extraBit.toInt) //TODO drop high ?
val napot = Napot(address.dropHigh(1)).dropLow(extraBit.toInt)
if(granularity == 4) when(!cfgNext.kind(0)){ napot.setAll() }
val mask = RegNext(napot)

Expand Down
1 change: 1 addition & 0 deletions src/main/scala/vexiiriscv/tester/TestBench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class TestOptions{
probe.enabled = withProbe
probe.trace = false

// delayed(1000){ simFailure() }
// Things to enable when we want to collect traces
val tracerFile = traceRvlsLog.option(new FileBackend(new File(currentTestPath(), "tracer.log")))
onTrace {
Expand Down
5 changes: 4 additions & 1 deletion src/test/scala/vexiiriscv/tester/Regression.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import spinal.core._
import spinal.core.sim._
import spinal.lib.misc.plugin.Hostable
import spinal.lib.misc.test.{AsyncJob, MultithreadedFunSuite}
import vexiiriscv.memory.MmuPlugin
import vexiiriscv.memory.{MmuPlugin, PmpPlugin}
import vexiiriscv.misc.{EmbeddedRiscvJtag, PrivilegedPlugin}
import vexiiriscv.riscv.Riscv
import vexiiriscv.{Global, ParamSimple, VexiiRiscv}
Expand Down Expand Up @@ -52,6 +52,7 @@ class RegressionSingle(compiled : SimCompiled[VexiiRiscv],
val xlen = dut.database(Riscv.XLEN)
val priv = dut.host.get[PrivilegedPlugin]
val mmu = dut.host.get[MmuPlugin]
val pmp = dut.host.get[PmpPlugin]

val rvm = dut.database(Riscv.RVM)
val rvc = dut.database(Riscv.RVC)
Expand Down Expand Up @@ -351,6 +352,7 @@ class RegressionSingle(compiled : SimCompiled[VexiiRiscv],

priv.filter(_.p.withSupervisor).foreach(_ => regulars ++= List("supervisor"))
if(mmu.nonEmpty) regulars ++= List(s"mmu_sv${if(xlen == 32) 32 else 39}")
if(pmp.get.p.pmpSize > 4 && priv.get.p.withSupervisor) regulars ++= List(s"pmp")

if(config.regular) for(name <- regulars){
val args = newArgs()
Expand Down Expand Up @@ -627,6 +629,7 @@ class Regression extends MultithreadedFunSuite(sys.env.getOrElse("VEXIIRISCV_REG
return List("", "--with-rvf", "--with-rvf --with-rvd").randomPick(random)
}
}
addDim("pmp", List("", "--pmp-size=8"))


// addTest(default)
Expand Down

0 comments on commit eeadda3

Please sign in to comment.