WIP on PMP
This commit is contained in:
parent
b1b405404d
commit
aace526857
@ -185,6 +185,7 @@ class CSRFileIO(implicit p: Parameters) extends CoreBundle
|
||||
val interrupt = Bool(OUTPUT)
|
||||
val interrupt_cause = UInt(OUTPUT, xLen)
|
||||
val bp = Vec(nBreakpoints, new BP).asOutput
|
||||
val pmp = Vec(nPMPs, new PMP).asOutput
|
||||
val counters = Vec(nPerfCounters, new PerfCounterIO)
|
||||
}
|
||||
|
||||
@ -237,6 +238,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
||||
|
||||
val reg_tselect = Reg(UInt(width = log2Up(nBreakpoints)))
|
||||
val reg_bp = Reg(Vec(1 << log2Up(nBreakpoints), new BP))
|
||||
val reg_pmp = Reg(Vec(nPMPs, new PMP))
|
||||
|
||||
val reg_mie = Reg(UInt(width = xLen))
|
||||
val reg_mideleg = Reg(UInt(width = xLen))
|
||||
@ -286,6 +288,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
||||
io.interrupt := all_interrupts.orR && !reg_debug && !io.singleStep || reg_singleStepped
|
||||
io.interrupt_cause := interruptCause
|
||||
io.bp := reg_bp take nBreakpoints
|
||||
io.pmp := reg_pmp
|
||||
|
||||
// debug interrupts are only masked by being in debug mode
|
||||
when (Bool(usingDebug) && reg_dcsr.debugint && !reg_debug) {
|
||||
@ -395,6 +398,13 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
||||
}
|
||||
}
|
||||
|
||||
val pmpCfgPerCSR = xLen / new PMPConfig().getWidth
|
||||
def pmpCfgIndex(i: Int) = (xLen / 32) * (i / pmpCfgPerCSR)
|
||||
for (i <- 0 until reg_pmp.size by pmpCfgPerCSR)
|
||||
read_mapping += (CSRs.pmpcfg0 + pmpCfgIndex(i)) -> reg_pmp.map(_.cfg).slice(i, i + pmpCfgPerCSR).asUInt
|
||||
for ((pmp, i) <- reg_pmp zipWithIndex)
|
||||
read_mapping += (CSRs.pmpaddr0 + i) -> pmp.addr
|
||||
|
||||
for (i <- 0 until nCustomMrwCsrs) {
|
||||
val addr = 0xff0 + i
|
||||
require(addr < (1 << CSR.ADDRSZ))
|
||||
@ -653,6 +663,15 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
||||
when (decoded_addr(CSRs.tdata2)) { bp.address := wdata }
|
||||
}
|
||||
}
|
||||
for (((pmp, next), i) <- (reg_pmp zip (reg_pmp.tail :+ reg_pmp.last)) zipWithIndex) {
|
||||
require(xLen % pmp.cfg.getWidth == 0)
|
||||
when (decoded_addr(CSRs.pmpcfg0 + pmpCfgIndex(i)) && !pmp.locked) {
|
||||
pmp.cfg := new PMPConfig().fromBits(wdata >> ((i * pmp.cfg.getWidth) % xLen))
|
||||
}
|
||||
when (decoded_addr(CSRs.pmpaddr0 + i) && !pmp.addrLocked(next)) {
|
||||
pmp.addr := wdata
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reg_mip <> io.interrupts
|
||||
@ -691,6 +710,12 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
||||
}
|
||||
for (bp <- reg_bp drop nBreakpoints)
|
||||
bp := new BP().fromBits(0)
|
||||
if (reg_pmp.nonEmpty) {
|
||||
for (pmp <- reg_pmp) {
|
||||
if (!usingUser) pmp.cfg.m := true
|
||||
when (reset) { pmp.cfg.p := 0 }
|
||||
}
|
||||
}
|
||||
|
||||
def legalizePrivilege(priv: UInt): UInt =
|
||||
if (usingVM) Mux(priv === PRV.H, PRV.U, priv)
|
||||
|
@ -302,6 +302,26 @@ object CSRs {
|
||||
val mcause = 0x342
|
||||
val mbadaddr = 0x343
|
||||
val mip = 0x344
|
||||
val pmpcfg0 = 0x3a0
|
||||
val pmpcfg1 = 0x3a1
|
||||
val pmpcfg2 = 0x3a2
|
||||
val pmpcfg3 = 0x3a3
|
||||
val pmpaddr0 = 0x3b0
|
||||
val pmpaddr1 = 0x3b1
|
||||
val pmpaddr2 = 0x3b2
|
||||
val pmpaddr3 = 0x3b3
|
||||
val pmpaddr4 = 0x3b4
|
||||
val pmpaddr5 = 0x3b5
|
||||
val pmpaddr6 = 0x3b6
|
||||
val pmpaddr7 = 0x3b7
|
||||
val pmpaddr8 = 0x3b8
|
||||
val pmpaddr9 = 0x3b9
|
||||
val pmpaddr10 = 0x3ba
|
||||
val pmpaddr11 = 0x3bb
|
||||
val pmpaddr12 = 0x3bc
|
||||
val pmpaddr13 = 0x3bd
|
||||
val pmpaddr14 = 0x3be
|
||||
val pmpaddr15 = 0x3bf
|
||||
val tselect = 0x7a0
|
||||
val tdata1 = 0x7a1
|
||||
val tdata2 = 0x7a2
|
||||
@ -495,6 +515,26 @@ object CSRs {
|
||||
res += mcause
|
||||
res += mbadaddr
|
||||
res += mip
|
||||
res += pmpcfg0
|
||||
res += pmpcfg1
|
||||
res += pmpcfg2
|
||||
res += pmpcfg3
|
||||
res += pmpaddr0
|
||||
res += pmpaddr1
|
||||
res += pmpaddr2
|
||||
res += pmpaddr3
|
||||
res += pmpaddr4
|
||||
res += pmpaddr5
|
||||
res += pmpaddr6
|
||||
res += pmpaddr7
|
||||
res += pmpaddr8
|
||||
res += pmpaddr9
|
||||
res += pmpaddr10
|
||||
res += pmpaddr11
|
||||
res += pmpaddr12
|
||||
res += pmpaddr13
|
||||
res += pmpaddr14
|
||||
res += pmpaddr15
|
||||
res += tselect
|
||||
res += tdata1
|
||||
res += tdata2
|
||||
|
66
src/main/scala/rocket/PMP.scala
Normal file
66
src/main/scala/rocket/PMP.scala
Normal file
@ -0,0 +1,66 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package rocket
|
||||
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import config._
|
||||
import tile._
|
||||
import util._
|
||||
|
||||
class PMPConfig extends Bundle {
|
||||
val p = UInt(width = 2)
|
||||
val a = UInt(width = 2)
|
||||
val m = Bool()
|
||||
val x = Bool()
|
||||
val w = Bool()
|
||||
val r = Bool()
|
||||
}
|
||||
|
||||
class PMP(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
val cfg = new PMPConfig
|
||||
val addr = UInt(width = paddrBits - lgAlign)
|
||||
|
||||
def enabled(prv: UInt) = cfg.p.orR && (cfg.m || prv <= PRV.S)
|
||||
def locked = cfg.p.andR
|
||||
def addrLocked(next: PMP) = locked || next.locked && next.cfg.a(1)
|
||||
|
||||
private def lgAlign = 2
|
||||
private def mask = (0 until paddrBits - lgAlign).scanLeft(cfg.a(0))((m, i) => m && addr(i)).asUInt
|
||||
|
||||
def pow2AddressMatch(x: UInt, lgSize: UInt, lgMaxSize: Int) = {
|
||||
val m = mask
|
||||
def checkOne(a: UInt) = (~(a >> lgAlign) | m) === (~addr | m)
|
||||
var res = checkOne(x)
|
||||
for (i <- (1 << lgAlign) until (1 << lgMaxSize) by (1 << lgAlign))
|
||||
res = res || (lgSize > log2Ceil(i) && checkOne(x | i))
|
||||
res
|
||||
}
|
||||
|
||||
def hit(prv: UInt, x: UInt, lgSize: UInt, lgMaxSize: Int) = {
|
||||
enabled(prv) && pow2AddressMatch(x, lgSize, lgMaxSize)
|
||||
}
|
||||
}
|
||||
|
||||
class PMPChecker(lgMaxSize: Int)(implicit p: Parameters) extends CoreModule()(p)
|
||||
with HasRocketCoreParameters {
|
||||
val io = new Bundle {
|
||||
val prv = UInt(INPUT, PRV.SZ)
|
||||
val pmp = Vec(nPMPs, new PMP).asInput
|
||||
val addr = UInt(INPUT, paddrBits)
|
||||
val size = UInt(INPUT, log2Ceil(lgMaxSize + 1))
|
||||
val xcpt_if = Bool(OUTPUT)
|
||||
val xcpt_ld = Bool(OUTPUT)
|
||||
val xcpt_st = Bool(OUTPUT)
|
||||
}
|
||||
|
||||
def hits = io.pmp.map(_.hit(io.prv, io.addr, io.size, lgMaxSize))
|
||||
val default = io.prv > PRV.S
|
||||
val (r, w, x, _) = ((default, default, default, 0.U) /: (io.pmp zip hits).reverse) { case ((r, w, x, pri), (pmp, hit)) =>
|
||||
MuxT(hit && pmp.cfg.p >= pri, (pmp.cfg.r, pmp.cfg.w, pmp.cfg.x, pmp.cfg.p), (r, w, x, pri))
|
||||
}
|
||||
|
||||
io.xcpt_if := !x
|
||||
io.xcpt_ld := !r
|
||||
io.xcpt_st := !w
|
||||
}
|
@ -26,17 +26,21 @@ class PTWResp(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
val level = UInt(width = log2Ceil(pgLevels))
|
||||
}
|
||||
|
||||
class TLBPTWIO(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
class TLBPTWIO(implicit p: Parameters) extends CoreBundle()(p)
|
||||
with HasRocketCoreParameters {
|
||||
val req = Decoupled(new PTWReq)
|
||||
val resp = Valid(new PTWResp).flip
|
||||
val ptbr = new PTBR().asInput
|
||||
val status = new MStatus().asInput
|
||||
val pmp = Vec(nPMPs, new PMP).asInput
|
||||
}
|
||||
|
||||
class DatapathPTWIO(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
class DatapathPTWIO(implicit p: Parameters) extends CoreBundle()(p)
|
||||
with HasRocketCoreParameters {
|
||||
val ptbr = new PTBR().asInput
|
||||
val invalidate = Bool(INPUT)
|
||||
val status = new MStatus().asInput
|
||||
val pmp = Vec(nPMPs, new PMP).asInput
|
||||
}
|
||||
|
||||
class PTE(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
@ -138,6 +142,7 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
|
||||
io.requestor(i).resp.bits.pte.ppn := pte_addr >> pgIdxBits
|
||||
io.requestor(i).ptbr := io.dpath.ptbr
|
||||
io.requestor(i).status := io.dpath.status
|
||||
io.requestor(i).pmp := io.dpath.pmp
|
||||
}
|
||||
|
||||
// control state machine
|
||||
|
@ -18,6 +18,7 @@ case class RocketCoreParams(
|
||||
useAtomics: Boolean = true,
|
||||
useCompressed: Boolean = true,
|
||||
nBreakpoints: Int = 1,
|
||||
nPMPs: Int = 16,
|
||||
nPerfCounters: Int = 0,
|
||||
nCustomMRWCSRs: Int = 0,
|
||||
mtvecInit: Option[BigInt] = Some(BigInt(0)),
|
||||
@ -42,6 +43,7 @@ trait HasRocketCoreParameters extends HasCoreParameters {
|
||||
val fastLoadByte = rocketParams.fastLoadByte
|
||||
val fastJAL = rocketParams.fastJAL
|
||||
val nBreakpoints = rocketParams.nBreakpoints
|
||||
val nPMPs = rocketParams.nPMPs
|
||||
val nPerfCounters = rocketParams.nPerfCounters
|
||||
val nCustomMrwCsrs = rocketParams.nCustomMRWCSRs
|
||||
val mtvecInit = rocketParams.mtvecInit
|
||||
@ -483,6 +485,7 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p)
|
||||
csr.io.badaddr := encodeVirtualAddress(wb_reg_wdata, wb_reg_wdata)
|
||||
io.ptw.ptbr := csr.io.ptbr
|
||||
io.ptw.status := csr.io.status
|
||||
io.ptw.pmp := csr.io.pmp
|
||||
csr.io.rw.addr := wb_reg_inst(31,20)
|
||||
csr.io.rw.cmd := Mux(wb_reg_valid, wb_ctrl.csr, CSR.N)
|
||||
csr.io.rw.wdata := wb_reg_wdata
|
||||
|
@ -74,12 +74,17 @@ class TLB(entries: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreMod
|
||||
val mpu_ppn = Mux(do_refill, refill_ppn,
|
||||
Mux(vm_enabled, ppns.last, vpn(ppnBits-1, 0)))
|
||||
val mpu_physaddr = Cat(mpu_ppn, io.req.bits.vaddr(pgIdxBits-1, 0))
|
||||
val pmp = Module(new PMPChecker(8))
|
||||
pmp.io.addr := mpu_physaddr
|
||||
pmp.io.size := 2
|
||||
pmp.io.pmp := io.ptw.pmp
|
||||
pmp.io.prv := priv
|
||||
val legal_address = edge.manager.findSafe(mpu_physaddr).reduce(_||_)
|
||||
def fastCheck(member: TLManagerParameters => Boolean) =
|
||||
legal_address && Mux1H(edge.manager.findFast(mpu_physaddr), edge.manager.managers.map(m => Bool(member(m))))
|
||||
val prot_r = fastCheck(_.supportsGet)
|
||||
val prot_w = fastCheck(_.supportsPutFull)
|
||||
val prot_x = fastCheck(_.executable)
|
||||
val prot_r = fastCheck(_.supportsGet) && !pmp.io.xcpt_ld
|
||||
val prot_w = fastCheck(_.supportsPutFull) && !pmp.io.xcpt_st
|
||||
val prot_x = fastCheck(_.executable) && !pmp.io.xcpt_if
|
||||
val cacheable = fastCheck(_.supportsAcquireB)
|
||||
val isSpecial = {
|
||||
val homogeneous = Wire(init = false.B)
|
||||
|
@ -43,7 +43,7 @@ trait HasCoreParameters extends HasTileParameters {
|
||||
|
||||
val coreInstBits = coreParams.instBits
|
||||
val coreInstBytes = coreInstBits/8
|
||||
val coreDataBits = xLen
|
||||
val coreDataBits = xLen max fLen
|
||||
val coreDataBytes = coreDataBits/8
|
||||
|
||||
val coreDCacheReqTagBits = 6
|
||||
|
Loading…
Reference in New Issue
Block a user