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 = Bool(OUTPUT)
|
||||||
val interrupt_cause = UInt(OUTPUT, xLen)
|
val interrupt_cause = UInt(OUTPUT, xLen)
|
||||||
val bp = Vec(nBreakpoints, new BP).asOutput
|
val bp = Vec(nBreakpoints, new BP).asOutput
|
||||||
|
val pmp = Vec(nPMPs, new PMP).asOutput
|
||||||
val counters = Vec(nPerfCounters, new PerfCounterIO)
|
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_tselect = Reg(UInt(width = log2Up(nBreakpoints)))
|
||||||
val reg_bp = Reg(Vec(1 << log2Up(nBreakpoints), new BP))
|
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_mie = Reg(UInt(width = xLen))
|
||||||
val reg_mideleg = 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 := all_interrupts.orR && !reg_debug && !io.singleStep || reg_singleStepped
|
||||||
io.interrupt_cause := interruptCause
|
io.interrupt_cause := interruptCause
|
||||||
io.bp := reg_bp take nBreakpoints
|
io.bp := reg_bp take nBreakpoints
|
||||||
|
io.pmp := reg_pmp
|
||||||
|
|
||||||
// debug interrupts are only masked by being in debug mode
|
// debug interrupts are only masked by being in debug mode
|
||||||
when (Bool(usingDebug) && reg_dcsr.debugint && !reg_debug) {
|
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) {
|
for (i <- 0 until nCustomMrwCsrs) {
|
||||||
val addr = 0xff0 + i
|
val addr = 0xff0 + i
|
||||||
require(addr < (1 << CSR.ADDRSZ))
|
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 }
|
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
|
reg_mip <> io.interrupts
|
||||||
@ -691,6 +710,12 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
|||||||
}
|
}
|
||||||
for (bp <- reg_bp drop nBreakpoints)
|
for (bp <- reg_bp drop nBreakpoints)
|
||||||
bp := new BP().fromBits(0)
|
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 =
|
def legalizePrivilege(priv: UInt): UInt =
|
||||||
if (usingVM) Mux(priv === PRV.H, PRV.U, priv)
|
if (usingVM) Mux(priv === PRV.H, PRV.U, priv)
|
||||||
|
@ -302,6 +302,26 @@ object CSRs {
|
|||||||
val mcause = 0x342
|
val mcause = 0x342
|
||||||
val mbadaddr = 0x343
|
val mbadaddr = 0x343
|
||||||
val mip = 0x344
|
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 tselect = 0x7a0
|
||||||
val tdata1 = 0x7a1
|
val tdata1 = 0x7a1
|
||||||
val tdata2 = 0x7a2
|
val tdata2 = 0x7a2
|
||||||
@ -495,6 +515,26 @@ object CSRs {
|
|||||||
res += mcause
|
res += mcause
|
||||||
res += mbadaddr
|
res += mbadaddr
|
||||||
res += mip
|
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 += tselect
|
||||||
res += tdata1
|
res += tdata1
|
||||||
res += tdata2
|
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))
|
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 req = Decoupled(new PTWReq)
|
||||||
val resp = Valid(new PTWResp).flip
|
val resp = Valid(new PTWResp).flip
|
||||||
val ptbr = new PTBR().asInput
|
val ptbr = new PTBR().asInput
|
||||||
val status = new MStatus().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 ptbr = new PTBR().asInput
|
||||||
val invalidate = Bool(INPUT)
|
val invalidate = Bool(INPUT)
|
||||||
val status = new MStatus().asInput
|
val status = new MStatus().asInput
|
||||||
|
val pmp = Vec(nPMPs, new PMP).asInput
|
||||||
}
|
}
|
||||||
|
|
||||||
class PTE(implicit p: Parameters) extends CoreBundle()(p) {
|
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).resp.bits.pte.ppn := pte_addr >> pgIdxBits
|
||||||
io.requestor(i).ptbr := io.dpath.ptbr
|
io.requestor(i).ptbr := io.dpath.ptbr
|
||||||
io.requestor(i).status := io.dpath.status
|
io.requestor(i).status := io.dpath.status
|
||||||
|
io.requestor(i).pmp := io.dpath.pmp
|
||||||
}
|
}
|
||||||
|
|
||||||
// control state machine
|
// control state machine
|
||||||
|
@ -18,6 +18,7 @@ case class RocketCoreParams(
|
|||||||
useAtomics: Boolean = true,
|
useAtomics: Boolean = true,
|
||||||
useCompressed: Boolean = true,
|
useCompressed: Boolean = true,
|
||||||
nBreakpoints: Int = 1,
|
nBreakpoints: Int = 1,
|
||||||
|
nPMPs: Int = 16,
|
||||||
nPerfCounters: Int = 0,
|
nPerfCounters: Int = 0,
|
||||||
nCustomMRWCSRs: Int = 0,
|
nCustomMRWCSRs: Int = 0,
|
||||||
mtvecInit: Option[BigInt] = Some(BigInt(0)),
|
mtvecInit: Option[BigInt] = Some(BigInt(0)),
|
||||||
@ -42,6 +43,7 @@ trait HasRocketCoreParameters extends HasCoreParameters {
|
|||||||
val fastLoadByte = rocketParams.fastLoadByte
|
val fastLoadByte = rocketParams.fastLoadByte
|
||||||
val fastJAL = rocketParams.fastJAL
|
val fastJAL = rocketParams.fastJAL
|
||||||
val nBreakpoints = rocketParams.nBreakpoints
|
val nBreakpoints = rocketParams.nBreakpoints
|
||||||
|
val nPMPs = rocketParams.nPMPs
|
||||||
val nPerfCounters = rocketParams.nPerfCounters
|
val nPerfCounters = rocketParams.nPerfCounters
|
||||||
val nCustomMrwCsrs = rocketParams.nCustomMRWCSRs
|
val nCustomMrwCsrs = rocketParams.nCustomMRWCSRs
|
||||||
val mtvecInit = rocketParams.mtvecInit
|
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)
|
csr.io.badaddr := encodeVirtualAddress(wb_reg_wdata, wb_reg_wdata)
|
||||||
io.ptw.ptbr := csr.io.ptbr
|
io.ptw.ptbr := csr.io.ptbr
|
||||||
io.ptw.status := csr.io.status
|
io.ptw.status := csr.io.status
|
||||||
|
io.ptw.pmp := csr.io.pmp
|
||||||
csr.io.rw.addr := wb_reg_inst(31,20)
|
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.cmd := Mux(wb_reg_valid, wb_ctrl.csr, CSR.N)
|
||||||
csr.io.rw.wdata := wb_reg_wdata
|
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,
|
val mpu_ppn = Mux(do_refill, refill_ppn,
|
||||||
Mux(vm_enabled, ppns.last, vpn(ppnBits-1, 0)))
|
Mux(vm_enabled, ppns.last, vpn(ppnBits-1, 0)))
|
||||||
val mpu_physaddr = Cat(mpu_ppn, io.req.bits.vaddr(pgIdxBits-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(_||_)
|
val legal_address = edge.manager.findSafe(mpu_physaddr).reduce(_||_)
|
||||||
def fastCheck(member: TLManagerParameters => Boolean) =
|
def fastCheck(member: TLManagerParameters => Boolean) =
|
||||||
legal_address && Mux1H(edge.manager.findFast(mpu_physaddr), edge.manager.managers.map(m => Bool(member(m))))
|
legal_address && Mux1H(edge.manager.findFast(mpu_physaddr), edge.manager.managers.map(m => Bool(member(m))))
|
||||||
val prot_r = fastCheck(_.supportsGet)
|
val prot_r = fastCheck(_.supportsGet) && !pmp.io.xcpt_ld
|
||||||
val prot_w = fastCheck(_.supportsPutFull)
|
val prot_w = fastCheck(_.supportsPutFull) && !pmp.io.xcpt_st
|
||||||
val prot_x = fastCheck(_.executable)
|
val prot_x = fastCheck(_.executable) && !pmp.io.xcpt_if
|
||||||
val cacheable = fastCheck(_.supportsAcquireB)
|
val cacheable = fastCheck(_.supportsAcquireB)
|
||||||
val isSpecial = {
|
val isSpecial = {
|
||||||
val homogeneous = Wire(init = false.B)
|
val homogeneous = Wire(init = false.B)
|
||||||
|
@ -43,7 +43,7 @@ trait HasCoreParameters extends HasTileParameters {
|
|||||||
|
|
||||||
val coreInstBits = coreParams.instBits
|
val coreInstBits = coreParams.instBits
|
||||||
val coreInstBytes = coreInstBits/8
|
val coreInstBytes = coreInstBits/8
|
||||||
val coreDataBits = xLen
|
val coreDataBits = xLen max fLen
|
||||||
val coreDataBytes = coreDataBits/8
|
val coreDataBytes = coreDataBits/8
|
||||||
|
|
||||||
val coreDCacheReqTagBits = 6
|
val coreDCacheReqTagBits = 6
|
||||||
|
Loading…
Reference in New Issue
Block a user