Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(PMA, CSR): support PMA CSR configurable #4233

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rocket-chip
85 changes: 85 additions & 0 deletions src/main/scala/xiangshan/backend/fu/NewCSR/CSRPMA.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package xiangshan.backend.fu.NewCSR

import chisel3._
import chisel3.util._
import freechips.rocketchip.rocket.CSRs
import freechips.rocketchip.tile.XLen
import org.chipsalliance.cde.config.Parameters
import xiangshan.backend.fu.NewCSR.CSRDefines.{CSRRWField => RW, CSRWARLField => WARL}
import xiangshan.backend.fu.NewCSR.CSRFunc._
import xiangshan.backend.fu.PMAConfigEntry
import xiangshan.{HasPMParameters, PMParameKey}
import CSRConfig._
import system.SoCParamsKey

import scala.collection.immutable.SeqMap

trait CSRPMA { self: NewCSR =>
val pmacfg: Seq[CSRModule[_]] = Range(0, p(PMParameKey).NumPMA/8+1, 2).map(num =>
Module(new CSRModule(s"Pmacfg$num") with HasPMACfgRSink {
// read condition
regOut := cfgRData(64*(num/2+1)-1, 64*num/2)
})
.setAddr(CSRs.pmacfg0 + num)
)

// every pmacfg has 8 cfgs
val pmacfgs: Seq[CSRModule[_]] = Range(0, p(PMParameKey).NumPMA).map(num =>
Module(new CSRModule(s"Pma$num"+"cfg", new PMACfgInitBundle(num)))
)

val pmaaddr: Seq[CSRModule[_]] = Range(0, p(PMParameKey).NumPMA).map(num =>
Module(new CSRModule(s"Pmaaddr$num") with HasPMAAddrSink {
// read condition
regOut := addrRData(num)
})
.setAddr(CSRs.pmaaddr0 + num)
)

val pmaCSRMods: Seq[CSRModule[_]] = pmacfg ++ pmaaddr

val pmaCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from(
pmaCSRMods.map(csr => csr.addr -> (csr.w -> csr.rdata)).iterator
)

val pmaCSROutMap: SeqMap[Int, UInt] = SeqMap.from(
pmpCSRMods.map(csr => csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt).iterator
)

private val pmaCfgRead = Cat(pmacfgs.map(_.rdata(7, 0)).reverse)

pmaCSRMods.foreach { mod =>
mod match {
case m: HasPMACfgRSink =>
m.cfgRData := pmaCfgRead
case _ =>
}
}
}

class PMACfgInitBundle(num: Int)(implicit val p: Parameters) extends PMACfgBundle with PMAInit {
override val R = WARL(0, wNoFilter).withReset(pmaInit(num).r.B)
override val W = WARL(1, wNoFilter).withReset(pmaInit(num).w.B)
override val X = WARL(2, wNoFilter).withReset(pmaInit(num).x.B)
override val A = PMPCfgAField(4, 3, wNoFilter).withReset(if (pmaInit(num).a > 0) pmaInit(num).a.U else 0.U)
override val ATOMIC = WARL(5, wNoFilter).withReset(pmaInit(num).atomic.B)
override val C = WARL(6, wNoFilter).withReset(pmaInit(num).c.B)
override val L = PMPCfgLField(7, wNoFilter).withReset(pmaInit(num).l.B)
}

class PMACfgBundle extends PMPCfgBundle {
override val ATOMIC = WARL(5, wNoFilter).withReset(false.B)
override val C = WARL(6, wNoFilter).withReset(false.B)
}

trait HasPMACfgRSink { self: CSRModule[_] =>
val cfgRData = IO(Input(UInt((p(PMParameKey).NumPMA/8 * p(XLen)).W)))
}

trait HasPMAAddrSink { self: CSRModule[_] =>
val addrRData = IO(Input(Vec(p(PMParameKey).NumPMA, UInt(64.W))))
}

trait PMAInit extends HasPMParameters with PMAReadWrite {
def pmaInit: Seq[PMAConfigEntry] = (PMAConfigs ++ Seq.fill(NumPMA-PMAConfigs.length)(PMAConfigEntry(0))).reverse
}
4 changes: 2 additions & 2 deletions src/main/scala/xiangshan/backend/fu/NewCSR/CSRPMP.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ trait CSRPMP { self: NewCSR =>
)

// every pmpcfg has 8 cfgs
val cfgs: Seq[CSRModule[_]] = Range(0, p(PMParameKey).NumPMP).map(num =>
val pmpcfgs: Seq[CSRModule[_]] = Range(0, p(PMParameKey).NumPMP).map(num =>
Module(new CSRModule(s"Pmp$num"+"cfg", new PMPCfgBundle) {
when (w.wen && (!(!w.wdata(0).asBool && w.wdata(1).asBool))) { // when R=0 W=1, reserved
reg.W := w.wdata(1).asBool
Expand Down Expand Up @@ -51,7 +51,7 @@ trait CSRPMP { self: NewCSR =>
pmpCSRMods.map(csr => csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt).iterator
)

private val pmpCfgRead = Cat(cfgs.map(_.rdata(7, 0)).reverse)
private val pmpCfgRead = Cat(pmpcfgs.map(_.rdata(7, 0)).reverse)

pmpCSRMods.foreach { mod =>
mod match {
Expand Down
38 changes: 30 additions & 8 deletions src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class NewCSR(implicit val p: Parameters) extends Module
with DebugLevel
with CSRCustom
with CSRPMP
with CSRPMA
with HasCriticalErrors
with IpIeAliasConnect
{
Expand Down Expand Up @@ -319,7 +320,8 @@ class NewCSR(implicit val p: Parameters) extends Module
debugCSRMap ++
aiaCSRMap ++
customCSRMap ++
pmpCSRMap
pmpCSRMap ++
pmaCSRMap

val csrMods: Seq[CSRModule[_]] =
machineLevelCSRMods ++
Expand All @@ -330,7 +332,8 @@ class NewCSR(implicit val p: Parameters) extends Module
debugCSRMods ++
aiaCSRMods ++
customCSRMods ++
pmpCSRMods
pmpCSRMods ++
pmaCSRMods

var csrOutMap: SeqMap[Int, UInt] =
machineLevelCSROutMap ++
Expand All @@ -341,7 +344,8 @@ class NewCSR(implicit val p: Parameters) extends Module
debugCSROutMap ++
aiaCSROutMap ++
customCSROutMap ++
pmpCSROutMap
pmpCSROutMap ++
pmaCSROutMap

// interrupt
val nmip = RegInit(new NonMaskableIRPendingBundle, (new NonMaskableIRPendingBundle).init)
Expand Down Expand Up @@ -430,13 +434,21 @@ class NewCSR(implicit val p: Parameters) extends Module

// PMP
val pmpEntryMod = Module(new PMPEntryHandleModule)
pmpEntryMod.io.in.pmpCfg := cfgs.map(_.regOut.asInstanceOf[PMPCfgBundle])
pmpEntryMod.io.in.pmpCfg := pmpcfgs.map(_.regOut.asInstanceOf[PMPCfgBundle])
pmpEntryMod.io.in.pmpAddr := pmpaddr.map(_.regOut.asInstanceOf[PMPAddrBundle])
pmpEntryMod.io.in.ren := ren
pmpEntryMod.io.in.wen := wenLegalReg
pmpEntryMod.io.in.addr := addr
pmpEntryMod.io.in.wdata := wdata

// PMA
val pmaEntryMod = Module(new PMAEntryHandleModule)
pmaEntryMod.io.in.pmaCfg := pmacfgs.map(_.regOut.asInstanceOf[PMACfgBundle])
pmaEntryMod.io.in.ren := ren
pmaEntryMod.io.in.wen := wenLegalReg
pmaEntryMod.io.in.addr := addr
pmaEntryMod.io.in.wdata := wdata

// Todo: all wen and wdata of CSRModule assigned in this for loop
for ((id, (wBundle, _)) <- csrRwMap) {
if (vsMapS.contains(id)) {
Expand Down Expand Up @@ -534,16 +546,21 @@ class NewCSR(implicit val p: Parameters) extends Module

mhartid.hartid := this.io.fromTop.hartId

cfgs.zipWithIndex.foreach { case (mod, i) =>
mod.w.wen := wenLegalReg && (addr === (0x3A0 + i / 8 * 2).U)
pmpcfgs.zipWithIndex.foreach { case (mod, i) =>
mod.w.wen := wenLegalReg && (addr === (CSRs.pmpcfg0 + i / 8 * 2).U)
mod.w.wdata := pmpEntryMod.io.out.pmpCfgWData(8*((i%8)+1)-1,8*(i%8))
}

pmpaddr.zipWithIndex.foreach{ case(mod, i) =>
mod.w.wen := wenLegalReg && (addr === (0x3B0 + i).U)
pmpaddr.zipWithIndex.foreach { case (mod, i) =>
mod.w.wen := wenLegalReg && (addr === (CSRs.pmpaddr0 + i).U)
mod.w.wdata := pmpEntryMod.io.out.pmpAddrWData(i)
}

pmacfgs.zipWithIndex.foreach { case (mod, i) =>
mod.w.wen := wenLegalReg && (addr === (CSRs.pmacfg0 + i / 8 * 2).U)
mod.w.wdata := pmaEntryMod.io.out.pmaCfgWdata(8*((i%8)+1)-1,8*(i%8))
}

csrMods.foreach { mod =>
mod match {
case m: HypervisorBundle =>
Expand Down Expand Up @@ -660,6 +677,11 @@ class NewCSR(implicit val p: Parameters) extends Module
m.addrRData := pmpEntryMod.io.out.pmpAddrRData
case _ =>
}
mod match {
case m: HasPMAAddrSink =>
m.addrRData := pmaEntryMod.io.out.pmaAddrRData
case _ =>
}
mod match {
case m: HasMHPMSink =>
// cycle from mcycle
Expand Down
177 changes: 177 additions & 0 deletions src/main/scala/xiangshan/backend/fu/NewCSR/PMAEntryModule.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package xiangshan.backend.fu.NewCSR

import chisel3._
import chisel3.util._
import freechips.rocketchip.rocket.CSRs
import org.chipsalliance.cde.config.Parameters
import xiangshan.backend.fu.PMAConfigEntry
import xiangshan.{HasPMParameters, PMParameKey}
import CSRConfig._

trait PMAConst extends PMPConst

abstract class PMABundle(implicit val p: Parameters) extends Bundle with PMAConst
abstract class PMAModule(implicit val p: Parameters) extends Module with PMAConst

class PMAEntryHandleModule(implicit p: Parameters) extends PMAModule with PMAInit with PMAReadWrite {
val io = IO(new PMAEntryHandleIOBundle)

val pmaCfg = io.in.pmaCfg

val ren = io.in.ren
val wen = io.in.wen
val addr = io.in.addr
val wdata = io.in.wdata

require(NumPMA >= 16, "The number of PMA should be greater than or equal to 16.")

val pmaAddrInit = VecInit(Seq.fill(p(PMParameKey).NumPMA)(0.U((PMPAddrWidth-PMPOffBits).W)))
val pmaMaskInit = VecInit(Seq.fill(p(PMParameKey).NumPMA)(0.U(PMPAddrWidth.W)))

pmaAddrInit.zip(pmaMaskInit).zip(pmaInit).foreach { case ((addr, mask), init) =>
addr := genAddr(init).U((PMPAddrWidth-PMPOffBits).W)
mask := genMask(init.a, genAddr(init))
}

val pmaAddr = RegInit(pmaAddrInit)
val pmaMask = RegInit(pmaMaskInit)

val pmaEntry = Wire(Vec(p(PMParameKey).NumPMA, new PMAEntry))

for (i <- pmaEntry.indices) {
pmaEntry(i).gen(pmaCfg(i), pmaAddr(i), pmaMask(i))
}

// write pmaCfg
val cfgVec = WireInit(VecInit(Seq.fill(8)(0.U.asTypeOf(new PMACfgBundle))))
for (i <- 0 until (p(PMParameKey).NumPMA/8+1) by 2) {
when (wen && (addr === (CSRs.pmacfg0 + i).U)) {
for (j <- cfgVec.indices) {
val cfgOldTmp = pmaEntry(8*i/2+j).cfg
val cfgNewTmp = Wire(new PMACfgBundle)
cfgNewTmp := wdata(8*(j+1)-1, 8*j)
cfgVec(j) := cfgOldTmp
when (!cfgOldTmp.L.asBool) {
cfgVec(j) := cfgNewTmp
cfgVec(j).W := cfgNewTmp.W.asBool && cfgNewTmp.R.asBool
if (CoarserGrain) {
cfgVec(j).A := Cat(cfgNewTmp.A.asUInt(1), cfgNewTmp.A.asUInt.orR)
}
when (PMPCfgAField.isNa4OrNapot(cfgVec(j))) {
pmaMask(8*i/2+j) := pmaEntry(8*i/2+j).matchMask(cfgVec(j), pmaEntry(8*i/2+j).addr)
}
}
}
}
}

io.out.pmaCfgWdata := Cat(cfgVec.map(_.asUInt).reverse)


val pmaAddrR = Wire(Vec(p(PMParameKey).NumPMA, UInt(64.W)))

for (i <- 0 until p(PMParameKey).NumPMA) {
pmaAddrR(i) := pmaEntry(i).addr
// write pmaAddr
when (wen && (addr === (CSRs.pmaaddr0 + i).U)) {
if (i != (p(PMParameKey).NumPMA - 1)) {
val addrNextLocked: Bool = PMPCfgLField.addrLocked(pmaEntry(i).cfg, pmaEntry(i + 1).cfg)
pmaMask(i) := Mux(!addrNextLocked, pmaEntry(i).matchMask(wdata), pmaEntry(i).mask)
pmaAddr(i) := Mux(!addrNextLocked, wdata, pmaEntry(i).addr)
} else {
val addrLocked: Bool = PMPCfgLField.addrLocked(pmaEntry(i).cfg)
pmaMask(i) := Mux(!addrLocked, pmaEntry(i).matchMask(wdata), pmaEntry(i).mask)
pmaAddr(i) := Mux(!addrLocked, wdata, pmaEntry(i).addr)
}
}
// read pmaAddr
when (ren && (addr === (CSRs.pmaaddr0 + i).U)) {
pmaAddrR(i) := pmaEntry(i).readAddr(pmaEntry(i).cfg, pmaEntry(i).addr)
}
}

io.out.pmaAddrRData := pmaAddrR

}

class PMAEntryHandleIOBundle(implicit p: Parameters) extends PMABundle {
val in = Input(new Bundle {
val wen = Bool()
val ren = Bool()
val addr = UInt(12.W)
val wdata = UInt(64.W)
val pmaCfg = Vec(NumPMA, new PMACfgBundle)
})

val out = Output(new Bundle {
val pmaCfgWdata = UInt(PMXLEN.W)
val pmaAddrRData = Vec(NumPMA, UInt(64.W))
})
}

trait PMAReadWrite extends PMAConst with PMPReadWrite {
def shift_addr(addr: BigInt): BigInt = {
addr >> 2
}

def get_napot(base: BigInt, range: BigInt): BigInt = {
val PlatformGrainBytes = 1 << PlatformGrain
if ((base % PlatformGrainBytes) != 0) {
println("base: %x", base)
}
if ((range % PlatformGrainBytes) != 0) {
println("range: %x", range)
}
require((base % PlatformGrainBytes) == 0)
require((range % PlatformGrainBytes) == 0)

(base + (range/2 - 1)) >> PMPOffBits
}

def matchMask(cfgA0: Bool, paddr: UInt): UInt = {
val matchMaskCAddr = Cat(paddr, cfgA0) | (((1 << PlatformGrain) - 1) >> PMPOffBits).U((paddr.getWidth + 1).W)
Cat(matchMaskCAddr & (~(matchMaskCAddr + 1.U)).asUInt, ((1 << PMPOffBits) - 1).U(PMPOffBits.W))
}

def readAddr(cfg: PMACfgBundle, addr: UInt): UInt = {
val G = PlatformGrain - PMPOffBits
require(G >= 0)
if (G == 0) {
addr
} else if (G >= 2) {
Mux(PMPCfgAField.isNa4OrNapot(cfg), setLowBits(addr, G-1), clearLowBits(addr, G))
} else {
Mux(PMPCfgAField.isOffOrTor(cfg), clearLowBits(addr, G), addr)
}
}

def genAddr(init: PMAConfigEntry): BigInt = {
if (init.a < 2) {
shift_addr(init.base_addr)
} else {
get_napot(init.base_addr, init.range)
}
}

def genMask(a: BigInt, initAddr: BigInt) = {
val matchMaskAddr = (initAddr << 1) | (a & 0x1) | (((1 << PlatformGrain) - 1) >> PMPOffBits)
val mask = ((matchMaskAddr & ~(matchMaskAddr + 1)) << PMPOffBits) | ((1 << PMPOffBits) - 1)
mask.U(PMPAddrWidth.W)
}
}

class PMAEntry(implicit p: Parameters) extends PMABundle with PMAReadWrite {
val cfg = new PMACfgBundle
val addr = UInt((PMPAddrWidth-PMPOffBits).W)
val mask = UInt(PMPAddrBits.W)

def gen(cfg: PMACfgBundle, addr: UInt, mask: UInt) = {
this.cfg := cfg
this.addr := addr
this.mask := mask
}

def matchMask(paddr: UInt): UInt = {
matchMask(cfg.A.asUInt(0), paddr)
}
}
Loading
Loading