1
0

WIP on PMP

This commit is contained in:
Andrew Waterman 2017-03-15 01:18:39 -07:00
parent b1b405404d
commit aace526857
7 changed files with 150 additions and 6 deletions

View File

@ -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)

View File

@ -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

View 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
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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