WIP on priv-1.10
This commit is contained in:
@ -40,8 +40,7 @@ class DatapathPTWIO(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
}
|
||||
|
||||
class PTE(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
val reserved_for_hardware = Bits(width = 16)
|
||||
val ppn = UInt(width = 38)
|
||||
val ppn = UInt(width = 54)
|
||||
val reserved_for_software = Bits(width = 2)
|
||||
val d = Bool()
|
||||
val a = Bool()
|
||||
@ -53,19 +52,13 @@ class PTE(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
val v = Bool()
|
||||
|
||||
def table(dummy: Int = 0) = v && !r && !w && !x
|
||||
def leaf(dummy: Int = 0) = v && (r || (x && !w))
|
||||
def leaf(dummy: Int = 0) = v && (r || (x && !w)) && a
|
||||
def ur(dummy: Int = 0) = sr() && u
|
||||
def uw(dummy: Int = 0) = sw() && u
|
||||
def ux(dummy: Int = 0) = sx() && u
|
||||
def sr(dummy: Int = 0) = leaf() && r
|
||||
def sw(dummy: Int = 0) = leaf() && w
|
||||
def sw(dummy: Int = 0) = leaf() && w && d
|
||||
def sx(dummy: Int = 0) = leaf() && x
|
||||
|
||||
def access_ok(req: PTWReq) = {
|
||||
val perm_ok = Mux(req.fetch, x, Mux(req.store, w, r || (x && req.mxr)))
|
||||
val priv_ok = Mux(u, !req.pum, req.prv(0))
|
||||
leaf() && priv_ok && perm_ok
|
||||
}
|
||||
}
|
||||
|
||||
class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
|
||||
@ -77,10 +70,11 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
|
||||
|
||||
require(usingAtomics, "PTW requires atomic memory operations")
|
||||
|
||||
val s_ready :: s_req :: s_wait1 :: s_wait2 :: s_set_dirty :: s_wait1_dirty :: s_wait2_dirty :: s_done :: Nil = Enum(UInt(), 8)
|
||||
val s_ready :: s_req :: s_wait1 :: s_wait2 :: Nil = Enum(UInt(), 4)
|
||||
val state = Reg(init=s_ready)
|
||||
val count = Reg(UInt(width = log2Up(pgLevels)))
|
||||
val s1_kill = Reg(next = Bool(false))
|
||||
val resp_valid = Reg(next = Bool(false))
|
||||
|
||||
val r_req = Reg(new PTWReq)
|
||||
val r_req_dest = Reg(Bits())
|
||||
@ -128,23 +122,18 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
|
||||
|
||||
(hit && count < pgLevels-1, Mux1H(hits, data))
|
||||
}
|
||||
|
||||
val pte_wdata = Wire(init=new PTE().fromBits(0))
|
||||
pte_wdata.a := true
|
||||
pte_wdata.d := r_req.store
|
||||
|
||||
io.mem.req.valid := state.isOneOf(s_req, s_set_dirty)
|
||||
io.mem.req.valid := state === s_req
|
||||
io.mem.req.bits.phys := Bool(true)
|
||||
io.mem.req.bits.cmd := Mux(state === s_set_dirty, M_XA_OR, M_XRD)
|
||||
io.mem.req.bits.cmd := M_XRD
|
||||
io.mem.req.bits.typ := log2Ceil(xLen/8)
|
||||
io.mem.req.bits.addr := pte_addr
|
||||
io.mem.s1_data := pte_wdata.asUInt
|
||||
io.mem.s1_kill := s1_kill
|
||||
io.mem.invalidate_lr := Bool(false)
|
||||
|
||||
val resp_ppns = (0 until pgLevels-1).map(i => Cat(pte_addr >> (pgIdxBits + pgLevelBits*(pgLevels-i-1)), r_req.addr(pgLevelBits*(pgLevels-i-1)-1,0))) :+ (pte_addr >> pgIdxBits)
|
||||
for (i <- 0 until io.requestor.size) {
|
||||
io.requestor(i).resp.valid := state === s_done && (r_req_dest === i)
|
||||
io.requestor(i).resp.valid := resp_valid && (r_req_dest === i)
|
||||
io.requestor(i).resp.bits.pte := r_pte
|
||||
io.requestor(i).resp.bits.pte.ppn := resp_ppns(count)
|
||||
io.requestor(i).ptbr := io.dpath.ptbr
|
||||
@ -174,7 +163,8 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
|
||||
state := s_wait2
|
||||
when (io.mem.xcpt.pf.ld) {
|
||||
r_pte.v := false
|
||||
state := s_done
|
||||
state := s_ready
|
||||
resp_valid := true
|
||||
}
|
||||
}
|
||||
is (s_wait2) {
|
||||
@ -182,41 +172,16 @@ class PTW(n: Int)(implicit p: Parameters) extends CoreModule()(p) {
|
||||
state := s_req
|
||||
}
|
||||
when (io.mem.resp.valid) {
|
||||
state := s_done
|
||||
when (pte.access_ok(r_req) && (!pte.a || (r_req.store && !pte.d))) {
|
||||
state := s_set_dirty
|
||||
}.otherwise {
|
||||
r_pte := pte
|
||||
}
|
||||
r_pte := pte
|
||||
when (pte.table() && count < pgLevels-1) {
|
||||
state := s_req
|
||||
count := count + 1
|
||||
}.otherwise {
|
||||
state := s_ready
|
||||
resp_valid := true
|
||||
}
|
||||
}
|
||||
}
|
||||
is (s_set_dirty) {
|
||||
when (io.mem.req.ready) {
|
||||
state := s_wait1_dirty
|
||||
}
|
||||
}
|
||||
is (s_wait1_dirty) {
|
||||
state := s_wait2_dirty
|
||||
when (io.mem.xcpt.pf.st) {
|
||||
r_pte.v := false
|
||||
state := s_done
|
||||
}
|
||||
}
|
||||
is (s_wait2_dirty) {
|
||||
when (io.mem.s2_nack) {
|
||||
state := s_set_dirty
|
||||
}
|
||||
when (io.mem.resp.valid) {
|
||||
state := s_req
|
||||
}
|
||||
}
|
||||
is (s_done) {
|
||||
state := s_ready
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user