Merge remote-tracking branch 'origin/master' into debug_v013_pr
This commit is contained in:
@ -140,6 +140,8 @@ object CSR
|
||||
val firstHPM = 3
|
||||
val nCtr = 32
|
||||
val nHPM = nCtr - firstHPM
|
||||
|
||||
val maxPMPs = 16
|
||||
}
|
||||
|
||||
class PerfCounterIO(implicit p: Parameters) extends CoreBundle
|
||||
@ -418,10 +420,14 @@ 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
|
||||
if (reg_pmp.nonEmpty) {
|
||||
require(reg_pmp.size <= CSR.maxPMPs)
|
||||
val read_pmp = reg_pmp.padTo(CSR.maxPMPs, 0.U.asTypeOf(new PMP))
|
||||
for (i <- 0 until read_pmp.size by pmpCfgPerCSR)
|
||||
read_mapping += (CSRs.pmpcfg0 + pmpCfgIndex(i)) -> read_pmp.map(_.cfg).slice(i, i + pmpCfgPerCSR).asUInt
|
||||
for ((pmp, i) <- read_pmp zipWithIndex)
|
||||
read_mapping += (CSRs.pmpaddr0 + i) -> pmp.addr
|
||||
}
|
||||
|
||||
for (i <- 0 until nCustomMrwCsrs) {
|
||||
val addr = 0xff0 + i
|
||||
@ -687,7 +693,7 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param
|
||||
}
|
||||
if (reg_pmp.nonEmpty) 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) {
|
||||
when (decoded_addr(CSRs.pmpcfg0 + pmpCfgIndex(i)) && !pmp.cfgLocked) {
|
||||
pmp.cfg := new PMPConfig().fromBits(wdata >> ((i * pmp.cfg.getWidth) % xLen))
|
||||
}
|
||||
when (decoded_addr(CSRs.pmpaddr0 + i) && !pmp.addrLocked(next)) {
|
||||
@ -735,10 +741,11 @@ 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 }
|
||||
for (pmp <- reg_pmp) {
|
||||
pmp.cfg.res := 0
|
||||
when (reset) {
|
||||
pmp.cfg.a := 0
|
||||
pmp.cfg.l := 0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,12 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) {
|
||||
io.cpu.s2_nack := s2_valid && !s2_valid_hit && !(s2_valid_uncached && tl_out.a.ready && !uncachedInFlight.asUInt.andR)
|
||||
when (io.cpu.s2_nack || (s2_valid_hit && s2_update_meta)) { s1_nack := true }
|
||||
|
||||
val s3_valid = Reg(next = s2_valid, init=Bool(false))
|
||||
val s3_uncached = Reg(next = s2_uncached, init=Bool(false))
|
||||
when (s2_valid_cached_miss) {
|
||||
assert( !(s3_valid && s3_uncached) )
|
||||
}
|
||||
|
||||
// exceptions
|
||||
val s1_storegen = new StoreGen(s1_req.typ, s1_req.addr, UInt(0), wordBytes)
|
||||
val no_xcpt = Bool(usingDataScratchpad) && s1_req.phys /* slave port */ && s1_hit_state.isValid()
|
||||
|
@ -9,9 +9,9 @@ import tile._
|
||||
import util._
|
||||
|
||||
class PMPConfig extends Bundle {
|
||||
val p = UInt(width = 2)
|
||||
val l = Bool()
|
||||
val res = UInt(width = 2)
|
||||
val a = UInt(width = 2)
|
||||
val m = Bool()
|
||||
val x = Bool()
|
||||
val w = Bool()
|
||||
val r = Bool()
|
||||
@ -32,8 +32,10 @@ class PMPReg(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
val cfg = new PMPConfig
|
||||
val addr = UInt(width = paddrBits - PMP.lgAlign)
|
||||
|
||||
def locked = cfg.p(1)
|
||||
def addrLocked(next: PMPReg) = locked || next.locked && next.cfg.a(1)
|
||||
def napot = cfg.a(1)
|
||||
def torNotNAPOT = cfg.a(0)
|
||||
def cfgLocked = cfg.l
|
||||
def addrLocked(next: PMPReg) = cfgLocked || next.cfgLocked && next.cfg.a(1)
|
||||
}
|
||||
|
||||
class PMP(implicit p: Parameters) extends PMPReg {
|
||||
@ -99,7 +101,7 @@ class PMP(implicit p: Parameters) extends PMPReg {
|
||||
|
||||
// returns whether this PMP completely contains, or contains none of, a page
|
||||
def homogeneous(x: UInt, pgLevel: UInt, prev: PMP): Bool =
|
||||
!cfg.p(0) || Mux(cfg.a(1), rangeHomogeneous(x, pgLevel, prev), pow2Homogeneous(x, pgLevel))
|
||||
Mux(napot, pow2Homogeneous(x, pgLevel), !torNotNAPOT || rangeHomogeneous(x, pgLevel, prev))
|
||||
|
||||
// returns whether this matching PMP fully contains the access
|
||||
def aligned(x: UInt, lgSize: UInt, lgMaxSize: Int, prev: PMP): Bool = if (lgMaxSize <= lgAlign) true.B else {
|
||||
@ -108,12 +110,12 @@ class PMP(implicit p: Parameters) extends PMPReg {
|
||||
val straddlesUpperBound = ((x >> lgMaxSize) ^ (comparand >> lgMaxSize)) === 0 && (comparand(lgMaxSize-1, 0) & (x(lgMaxSize-1, 0) | lsbMask)) =/= 0
|
||||
val rangeAligned = !(straddlesLowerBound || straddlesUpperBound)
|
||||
val pow2Aligned = (lsbMask & ~mask(lgMaxSize-1, 0)) === 0
|
||||
Mux(cfg.a(1), rangeAligned, pow2Aligned)
|
||||
Mux(napot, pow2Aligned, rangeAligned)
|
||||
}
|
||||
|
||||
// returns whether this PMP matches at least one byte of the access
|
||||
def hit(x: UInt, lgSize: UInt, lgMaxSize: Int, prev: PMP): Bool =
|
||||
cfg.p(0) && Mux(cfg.a(1), rangeMatch(x, lgSize, lgMaxSize, prev), pow2Match(x, lgSize, lgMaxSize))
|
||||
Mux(napot, pow2Match(x, lgSize, lgMaxSize), torNotNAPOT && rangeMatch(x, lgSize, lgMaxSize, prev))
|
||||
}
|
||||
|
||||
class PMPHomogeneityChecker(pmps: Seq[PMP])(implicit p: Parameters) {
|
||||
@ -144,7 +146,7 @@ class PMPChecker(lgMaxSize: Int)(implicit p: Parameters) extends CoreModule()(p)
|
||||
|
||||
val res = (pmp0 /: (io.pmp zip (pmp0 +: io.pmp)).reverse) { case (prev, (pmp, prevPMP)) =>
|
||||
val hit = pmp.hit(io.addr, io.size, lgMaxSize, prevPMP)
|
||||
val ignore = default && !pmp.cfg.m
|
||||
val ignore = default && !pmp.cfg.l
|
||||
val aligned = pmp.aligned(io.addr, io.size, lgMaxSize, prevPMP)
|
||||
val cur = Wire(init = pmp)
|
||||
cur.cfg.r := (aligned && pmp.cfg.r) || ignore
|
||||
|
@ -79,6 +79,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
|
||||
val s1_kill = Reg(next = Bool(false))
|
||||
val resp_valid = Reg(next = Vec.fill(io.requestor.size)(Bool(false)))
|
||||
val ae = Reg(next = io.mem.xcpt.ae.ld)
|
||||
val resp_ae = Reg(Bool())
|
||||
|
||||
val r_req = Reg(new PTWReq)
|
||||
val r_req_dest = Reg(Bits())
|
||||
@ -99,7 +100,6 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(
|
||||
}
|
||||
val traverse = pte.table() && !invalid_paddr && count < pgLevels-1
|
||||
val pte_addr = Cat(r_pte.ppn, vpn_idx) << log2Ceil(xLen/8)
|
||||
val resp_ae = Reg(next = ae || invalid_paddr)
|
||||
|
||||
when (arb.io.out.fire()) {
|
||||
r_req := arb.io.out.bits
|
||||
|
@ -61,6 +61,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
|
||||
val level = UInt(width = log2Ceil(pgLevels))
|
||||
val u = Bool()
|
||||
val g = Bool()
|
||||
val ae = Bool()
|
||||
val sw = Bool()
|
||||
val sx = Bool()
|
||||
val sr = Bool()
|
||||
@ -140,9 +141,13 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
|
||||
newEntry.c := cacheable
|
||||
newEntry.u := pte.u
|
||||
newEntry.g := pte.g
|
||||
newEntry.sr := pte.sr()
|
||||
newEntry.sw := pte.sw()
|
||||
newEntry.sx := pte.sx()
|
||||
// if an access exception occurs during PTW, pretend the page has full
|
||||
// permissions so that a page fault will not occur, but clear the
|
||||
// phyiscal memory permissions, so that an access exception will occur.
|
||||
newEntry.ae := io.ptw.resp.bits.ae
|
||||
newEntry.sr := pte.sr() || io.ptw.resp.bits.ae
|
||||
newEntry.sw := pte.sw() || io.ptw.resp.bits.ae
|
||||
newEntry.sx := pte.sx() || io.ptw.resp.bits.ae
|
||||
newEntry.pr := prot_r && !io.ptw.resp.bits.ae
|
||||
newEntry.pw := prot_w && !io.ptw.resp.bits.ae
|
||||
newEntry.px := prot_x && !io.ptw.resp.bits.ae
|
||||
@ -154,7 +159,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters
|
||||
val plru = new PseudoLRU(normalEntries)
|
||||
val repl_waddr = Mux(!valid(normalEntries-1, 0).andR, PriorityEncoder(~valid(normalEntries-1, 0)), plru.replace)
|
||||
|
||||
val priv_ok = Mux(priv_s, ~Mux(io.ptw.status.sum, UInt(0), entries.map(_.u).asUInt), entries.map(_.u).asUInt)
|
||||
val priv_ok = entries.map(_.ae).asUInt | Mux(priv_s, ~Mux(io.ptw.status.sum, UInt(0), entries.map(_.u).asUInt), entries.map(_.u).asUInt)
|
||||
val r_array = Cat(true.B, priv_ok & (entries.map(_.sr).asUInt | Mux(io.ptw.status.mxr, entries.map(_.sx).asUInt, UInt(0))))
|
||||
val w_array = Cat(true.B, priv_ok & entries.map(_.sw).asUInt)
|
||||
val x_array = Cat(true.B, priv_ok & entries.map(_.sx).asUInt)
|
||||
|
@ -29,9 +29,10 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p
|
||||
|
||||
nDCachePorts += 1 // core TODO dcachePorts += () => module.core.io.dmem ??
|
||||
|
||||
val device = new Device {
|
||||
def ofInt(x: Int) = Seq(ResourceInt(BigInt(x)))
|
||||
def ofStr(x: String) = Seq(ResourceString(x))
|
||||
private def ofInt(x: Int) = Seq(ResourceInt(BigInt(x)))
|
||||
private def ofStr(x: String) = Seq(ResourceString(x))
|
||||
|
||||
val cpuDevice = new Device {
|
||||
def describe(resources: ResourceBindings): Description = {
|
||||
val block = p(CacheBlockBytes)
|
||||
val m = if (rocketParams.core.mulDiv.nonEmpty) "m" else ""
|
||||
@ -85,24 +86,28 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p
|
||||
"compatible" -> ofStr("riscv"),
|
||||
"status" -> ofStr("okay"),
|
||||
"clock-frequency" -> Seq(ResourceInt(rocketParams.core.bootFreqHz)),
|
||||
"riscv,isa" -> ofStr(isa),
|
||||
"interrupt-controller" -> Nil,
|
||||
"#interrupt-cells" -> ofInt(1))
|
||||
"riscv,isa" -> ofStr(isa))
|
||||
++ dcache ++ icache ++ nextlevel ++ mmu ++ itlb ++ dtlb)
|
||||
}
|
||||
}
|
||||
val intcDevice = new Device {
|
||||
def describe(resources: ResourceBindings): Description = {
|
||||
Description(s"cpus/cpu@${hartid}/interrupt-controller", Map(
|
||||
"compatible" -> ofStr("riscv,cpu-intc"),
|
||||
"interrupt-controller" -> Nil,
|
||||
"#interrupt-cells" -> ofInt(1)))
|
||||
}
|
||||
}
|
||||
|
||||
ResourceBinding {
|
||||
Resource(device, "reg").bind(ResourceInt(BigInt(hartid)))
|
||||
|
||||
// debug, msip, mtip, meip, seip offsets in CSRs
|
||||
val intMap = Seq(65535, 3, 7, 11, 9)
|
||||
Resource(cpuDevice, "reg").bind(ResourceInt(BigInt(hartid)))
|
||||
Resource(intcDevice, "reg").bind(ResourceInt(BigInt(hartid)))
|
||||
|
||||
intNode.edgesIn.flatMap(_.source.sources).map { case s =>
|
||||
for (i <- s.range.start until s.range.end) {
|
||||
intMap.lift(i).foreach { j =>
|
||||
csrIntMap.lift(i).foreach { j =>
|
||||
s.resources.foreach { r =>
|
||||
r.bind(device, ResourceInt(j))
|
||||
r.bind(intcDevice, ResourceInt(j))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,7 +127,8 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
|
||||
require(outer.p(PAddrBits) >= outer.masterNode.edgesIn(0).bundle.addressBits)
|
||||
|
||||
val core = Module(p(BuildCore)(outer.p))
|
||||
core.io.hartid := io.hartid
|
||||
decodeCoreInterrupts(core.io.interrupts) // Decode the interrupt vector
|
||||
core.io.hartid := io.hartid // Pass through the hartid
|
||||
outer.frontend.module.io.cpu <> core.io.imem
|
||||
outer.frontend.module.io.resetVector := io.resetVector
|
||||
dcachePorts += core.io.dmem // TODO outer.dcachePorts += () => module.core.io.dmem ??
|
||||
@ -136,12 +142,6 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
|
||||
core.io.rocc.interrupt := lr.module.io.core.interrupt
|
||||
}
|
||||
|
||||
// Decode the interrupt vector
|
||||
core.io.interrupts.debug := io.interrupts(0)(0)
|
||||
core.io.interrupts.msip := io.interrupts(0)(1)
|
||||
core.io.interrupts.mtip := io.interrupts(0)(2)
|
||||
core.io.interrupts.meip := io.interrupts(0)(3)
|
||||
core.io.interrupts.seip.foreach { _ := io.interrupts(0)(4) }
|
||||
|
||||
// TODO eliminate this redundancy
|
||||
val h = dcachePorts.size
|
||||
|
Reference in New Issue
Block a user