增加lsu的例外处理
This commit is contained in:
parent
7a3a3417c7
commit
b16eff1ba7
|
@ -110,7 +110,8 @@ class Core(implicit val cpuConfig: CpuConfig) extends Module {
|
|||
csr.ext_int := io.ext_int
|
||||
|
||||
memoryUnit.dataMemory.in.rdata := io.data.rdata
|
||||
memoryUnit.dataMemory.in.acc_err := io.data.access_fault
|
||||
memoryUnit.dataMemory.in.access_fault := io.data.access_fault
|
||||
memoryUnit.dataMemory.in.page_fault := io.data.page_fault
|
||||
memoryUnit.dataMemory.in.ready := io.data.dcache_ready
|
||||
io.data.en := memoryUnit.dataMemory.out.en
|
||||
io.data.rlen := memoryUnit.dataMemory.out.rlen
|
||||
|
|
|
@ -261,9 +261,11 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
|
|||
io.axi.b.ready := true.B
|
||||
|
||||
val access_fault = RegInit(false.B)
|
||||
val page_fault = RegInit(false.B)
|
||||
val addr_err = io.cpu.addr(XLEN - 1, VADDR_WID).orR
|
||||
|
||||
io.cpu.access_fault := access_fault
|
||||
io.cpu.page_fault := page_fault
|
||||
|
||||
// write buffer
|
||||
when(writeFifo_axi_busy) {
|
||||
|
@ -294,7 +296,8 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
|
|||
|
||||
switch(state) {
|
||||
is(s_idle) {
|
||||
access_fault := false.B // 在idle时清除acc_err
|
||||
access_fault := false.B // 在idle时清除access_fault
|
||||
page_fault := false.B // 在idle时清除page_fault
|
||||
when(io.cpu.en) {
|
||||
when(addr_err) {
|
||||
access_fault := true.B
|
||||
|
@ -496,6 +499,17 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
|
|||
}
|
||||
is(s_tlb_refill) {
|
||||
io.cpu.tlb.ptw.vpn.ready := ptw_state === s_handshake
|
||||
when(io.cpu.tlb.access_fault) {
|
||||
access_fault := true.B
|
||||
state := s_wait
|
||||
}.elsewhen(io.cpu.tlb.page_fault) {
|
||||
page_fault := true.B
|
||||
state := s_wait
|
||||
}.otherwise {
|
||||
when(io.cpu.tlb.hit) {
|
||||
state := s_idle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,7 +517,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
|
|||
// 实现页表访问,回填tlb
|
||||
val satp = io.cpu.tlb.csr.satp.asTypeOf(satpBundle)
|
||||
val mstatus = io.cpu.tlb.csr.mstatus.asTypeOf(new Mstatus)
|
||||
val mode = io.cpu.tlb.csr.mode
|
||||
val mode = Mux(io.cpu.tlb.access_type === AccessType.fetch, io.cpu.tlb.csr.imode, io.cpu.tlb.csr.dmode)
|
||||
val sum = mstatus.sum
|
||||
val mxr = mstatus.mxr
|
||||
val vpn = io.cpu.tlb.ptw.vpn.bits.asTypeOf(vpnBundle)
|
||||
|
|
|
@ -211,7 +211,7 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
|
|||
|
||||
switch(state) {
|
||||
is(s_idle) {
|
||||
access_fault := false.B // 在idle时清除acc_err
|
||||
access_fault := false.B // 在idle时清除access_fault
|
||||
page_fault := false.B // 在idle时清除page_fault
|
||||
when(io.cpu.req) {
|
||||
when(addr_err) {
|
||||
|
|
|
@ -57,11 +57,11 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
|
||||
val satp = io.csr.satp.asTypeOf(satpBundle)
|
||||
val mstatus = io.csr.mstatus.asTypeOf(new Mstatus)
|
||||
val mode = io.csr.mode
|
||||
val imode = io.csr.imode
|
||||
val dmode = io.csr.dmode
|
||||
// 当SUM=0时,S模式内存访问U模式可访问的页面(U=1)将出现故障。
|
||||
// 当SUM=1时,这些访问是允许的。当基于页面的虚拟内存不生效时,SUM无效。
|
||||
// 请注意,虽然SUM通常在不在S模式下执行时被忽略,但当MPRV=1和MPP=S时,SUM有效。
|
||||
val sum_valid = (mode === ModeS) || mstatus.mprv && mstatus.mpp === ModeS
|
||||
val sum = mstatus.sum
|
||||
// 当MXR=0时,只有标记为可读的页面(R=1)的加载才会成功。
|
||||
// 当MXR=1时,标记为可读或可执行的页面(R=1或X=1)的加载才会成功。
|
||||
|
@ -69,7 +69,8 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
val mxr = mstatus.mxr
|
||||
|
||||
// 只有当satp.mode为8且当前模式低于M模式时,才启用虚拟内存
|
||||
val vm_enabled = (satp.mode === 8.U) && (mode < ModeM)
|
||||
val ivm_enabled = (satp.mode === 8.U) && (imode < ModeM)
|
||||
val dvm_enabled = (satp.mode === 8.U) && (dmode < ModeM)
|
||||
|
||||
val itlb = RegInit(0.U.asTypeOf(tlbBundle))
|
||||
val dtlb = RegInit(0.U.asTypeOf(tlbBundle))
|
||||
|
@ -120,7 +121,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
val ar_sel_lock = RegInit(false.B)
|
||||
val ar_sel_val = RegInit(false.B)
|
||||
// 我们默认优先发送数据tlb的请求
|
||||
val ar_sel = Mux(ar_sel_lock, ar_sel_val, !req_ptw(0) && req_ptw(1))
|
||||
val ar_sel = Mux(ar_sel_lock, ar_sel_val, req_ptw(0) && !req_ptw(1))
|
||||
|
||||
when(io.dcache.ptw.vpn.valid) {
|
||||
when(io.dcache.ptw.vpn.ready) {
|
||||
|
@ -140,13 +141,13 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
|
||||
// 将ptw模块集成到dcache中,ptw通过dcache的axi进行内存访问
|
||||
io.dcache.ptw.vpn.valid := false.B
|
||||
io.dcache.ptw.access_type := Mux(ar_sel === 0.U, AccessType.fetch, io.dcache.access_type)
|
||||
io.dcache.ptw.vpn.bits := Mux(ar_sel === 0.U, ivpn, dvpn)
|
||||
io.dcache.ptw.access_type := Mux(ar_sel, AccessType.fetch, io.dcache.access_type)
|
||||
io.dcache.ptw.vpn.bits := Mux(ar_sel, ivpn, dvpn)
|
||||
io.dcache.ptw.pte.ready := true.B // 恒为true
|
||||
io.dcache.csr <> io.csr
|
||||
|
||||
def imodeCheck(): Unit = {
|
||||
switch(mode) {
|
||||
switch(imode) {
|
||||
is(ModeS) {
|
||||
when(itlb.flag.u && sum === 0.U) {
|
||||
ipage_fault := true.B
|
||||
|
@ -167,7 +168,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
}
|
||||
|
||||
def dmodeCheck(): Unit = {
|
||||
switch(mode) {
|
||||
switch(dmode) {
|
||||
is(ModeS) {
|
||||
when(dtlb.flag.u && sum === 0.U) {
|
||||
dpage_fault := true.B
|
||||
|
@ -196,7 +197,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
// 在icache实现访问tlb的pma和pmp权限检查
|
||||
ipage_fault := false.B
|
||||
iaccess_fault := false.B
|
||||
when(!vm_enabled) {
|
||||
when(!ivm_enabled) {
|
||||
io.icache.hit := true.B
|
||||
}.elsewhen(itlbl1_hit) {
|
||||
// 在这里进行取指需要的所有的权限检查
|
||||
|
@ -222,7 +223,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
itlb := tlbl2(PriorityEncoder(il2_hit_vec))
|
||||
}.otherwise {
|
||||
req_ptw(0) := true.B
|
||||
when(ar_sel === 0.U && io.dcache.ptw.vpn.ready) {
|
||||
when(ar_sel && io.dcache.ptw.vpn.ready) {
|
||||
io.dcache.ptw.vpn.valid := true.B
|
||||
immu_state := search_pte
|
||||
}
|
||||
|
@ -269,7 +270,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
// 在dcache实现访问tlb的pma和pmp权限检查
|
||||
dpage_fault := false.B
|
||||
daccess_fault := false.B
|
||||
when(!vm_enabled) {
|
||||
when(!dvm_enabled) {
|
||||
io.dcache.hit := true.B
|
||||
}.elsewhen(dtlbl1_hit) {
|
||||
// 在这里进行取指需要的所有的权限检查
|
||||
|
@ -316,8 +317,8 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
dmmu_state := search_l1
|
||||
dtlb := tlbl2(PriorityEncoder(il2_hit_vec))
|
||||
}.otherwise {
|
||||
req_ptw(0) := true.B
|
||||
when(ar_sel === 0.U && io.dcache.ptw.vpn.ready) {
|
||||
req_ptw(1) := true.B
|
||||
when(!ar_sel && io.dcache.ptw.vpn.ready) {
|
||||
io.dcache.ptw.vpn.valid := true.B
|
||||
dmmu_state := search_pte
|
||||
}
|
||||
|
@ -408,11 +409,11 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
|
|||
}
|
||||
|
||||
io.icache.uncached := AddressSpace.isMMIO(io.icache.addr)
|
||||
io.icache.ptag := Mux(vm_enabled, itlb.ppn, io.icache.addr(PADDR_WID - 1, pageOffsetLen))
|
||||
io.icache.ptag := Mux(ivm_enabled, itlb.ppn, io.icache.addr(PADDR_WID - 1, pageOffsetLen))
|
||||
io.icache.paddr := Cat(io.icache.ptag, io.icache.addr(pageOffsetLen - 1, 0))
|
||||
|
||||
io.dcache.uncached := AddressSpace.isMMIO(io.dcache.addr)
|
||||
io.dcache.ptag := Mux(vm_enabled, dtlb.ppn, io.dcache.addr(PADDR_WID - 1, pageOffsetLen))
|
||||
io.dcache.ptag := Mux(dvm_enabled, dtlb.ppn, io.dcache.addr(PADDR_WID - 1, pageOffsetLen))
|
||||
io.dcache.paddr := Cat(io.dcache.ptag, io.dcache.addr(pageOffsetLen - 1, 0))
|
||||
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ class Cache_DCache extends Bundle {
|
|||
|
||||
val rdata = Input(UInt(XLEN.W))
|
||||
val access_fault = Input(Bool())
|
||||
val page_fault = Input(Bool())
|
||||
val dcache_ready = Input(Bool())
|
||||
|
||||
val tlb = new Tlb_DCache()
|
||||
|
|
|
@ -50,7 +50,8 @@ class CsrDecodeUnit extends Bundle {
|
|||
class CsrTlb extends Bundle {
|
||||
val satp = Output(UInt(XLEN.W))
|
||||
val mstatus = Output(UInt(XLEN.W))
|
||||
val mode = Output(Priv())
|
||||
val imode = Output(Priv())
|
||||
val dmode = Output(Priv())
|
||||
}
|
||||
|
||||
class Csr(implicit val cpuConfig: CpuConfig) extends Module with HasCSRConst {
|
||||
|
@ -245,11 +246,13 @@ class Csr(implicit val cpuConfig: CpuConfig) extends Module with HasCSRConst {
|
|||
val mip_has_interrupt = WireInit(mip.asTypeOf(new Interrupt()))
|
||||
mip_has_interrupt.e.s := mip.asTypeOf(new Interrupt).e.s | seip
|
||||
|
||||
val mstatusBundle = mstatus.asTypeOf(new Mstatus())
|
||||
|
||||
val ideleg = (mideleg & mip_has_interrupt.asUInt)
|
||||
def priviledgedEnableDetect(x: Bool): Bool = Mux(
|
||||
x,
|
||||
((mode === ModeS) && mstatus.asTypeOf(new Mstatus()).ie.s) || (mode < ModeS),
|
||||
((mode === ModeM) && mstatus.asTypeOf(new Mstatus()).ie.m) || (mode < ModeM)
|
||||
((mode === ModeS) && mstatusBundle.ie.s) || (mode < ModeS),
|
||||
((mode === ModeM) && mstatusBundle.ie.m) || (mode < ModeM)
|
||||
)
|
||||
|
||||
val interrupt_enable = Wire(Vec(INT_WID, Bool()))
|
||||
|
@ -414,7 +417,8 @@ class Csr(implicit val cpuConfig: CpuConfig) extends Module with HasCSRConst {
|
|||
ret_target := sepc(VADDR_WID - 1, 0)
|
||||
}
|
||||
|
||||
io.tlb.mode := mode
|
||||
io.tlb.imode := mode
|
||||
io.tlb.dmode := Mux(mstatusBundle.mprv, mstatusBundle.mpp, mode)
|
||||
io.tlb.satp := satp
|
||||
io.tlb.mstatus := mstatus
|
||||
io.decodeUnit.mode := mode
|
||||
|
|
|
@ -9,7 +9,8 @@ import chisel3.util.experimental.BoringUtils
|
|||
|
||||
class Lsu_DataMemory extends Bundle {
|
||||
val in = Input(new Bundle {
|
||||
val acc_err = Bool()
|
||||
val access_fault = Bool()
|
||||
val page_fault = Bool()
|
||||
val ready = Bool()
|
||||
val rdata = UInt(XLEN.W)
|
||||
})
|
||||
|
@ -183,7 +184,9 @@ class Lsu(implicit val cpuConfig: CpuConfig) extends Module {
|
|||
lsExe.out.loadAddrMisaligned ||
|
||||
lsExe.out.storeAddrMisaligned ||
|
||||
lsExe.out.loadAccessFault ||
|
||||
lsExe.out.storeAccessFault
|
||||
lsExe.out.storeAccessFault ||
|
||||
lsExe.out.loadPageFault ||
|
||||
lsExe.out.storePageFault
|
||||
) {
|
||||
state := s_idle
|
||||
io.memoryUnit.out.ready := true.B
|
||||
|
@ -201,6 +204,8 @@ class Lsu(implicit val cpuConfig: CpuConfig) extends Module {
|
|||
io.memoryUnit.out.ex.exception(storeAddrMisaligned) := lsExe.out.storeAddrMisaligned
|
||||
io.memoryUnit.out.ex.exception(loadAccessFault) := lsExe.out.loadAccessFault
|
||||
io.memoryUnit.out.ex.exception(storeAccessFault) := lsExe.out.storeAccessFault
|
||||
io.memoryUnit.out.ex.exception(loadPageFault) := lsExe.out.loadPageFault
|
||||
io.memoryUnit.out.ex.exception(storePageFault) := lsExe.out.storePageFault
|
||||
|
||||
io.memoryUnit.out.ex.tval := io.dataMemory.out.addr
|
||||
io.memoryUnit.out.rdata := MuxCase(
|
||||
|
|
|
@ -20,6 +20,8 @@ class LsExecute extends Module {
|
|||
val storeAddrMisaligned = Bool()
|
||||
val loadAccessFault = Bool()
|
||||
val storeAccessFault = Bool()
|
||||
val loadPageFault = Bool()
|
||||
val storePageFault = Bool()
|
||||
val rdata = UInt(XLEN.W)
|
||||
val ready = Bool()
|
||||
})
|
||||
|
@ -84,7 +86,8 @@ class LsExecute extends Module {
|
|||
val reqWmask = if (XLEN == 32) genWmask32(addr, size) else genWmask(addr, size)
|
||||
|
||||
val rdata = io.dataMemory.in.rdata
|
||||
val acc_err = io.dataMemory.in.acc_err
|
||||
val access_fault = io.dataMemory.in.access_fault
|
||||
val page_fault = io.dataMemory.in.page_fault
|
||||
|
||||
val rdataSel64 = LookupTree(
|
||||
addr(2, 0),
|
||||
|
@ -141,7 +144,9 @@ class LsExecute extends Module {
|
|||
io.out.ready := io.dataMemory.in.ready && io.dataMemory.out.en
|
||||
io.out.rdata := Mux(partialLoad, rdataPartialLoad, rdataSel)
|
||||
io.out.loadAddrMisaligned := valid && !isStore && !is_amo && !addrAligned
|
||||
io.out.loadAccessFault := valid && !isStore && !is_amo && (acc_err || has_acc_err)
|
||||
io.out.loadAccessFault := valid && !isStore && !is_amo && (access_fault || has_acc_err)
|
||||
io.out.loadPageFault := valid && !isStore && !is_amo && page_fault
|
||||
io.out.storeAddrMisaligned := valid && (isStore || is_amo) && !addrAligned
|
||||
io.out.storeAccessFault := valid && (isStore || is_amo) && (acc_err || has_acc_err)
|
||||
io.out.storeAccessFault := valid && (isStore || is_amo) && (access_fault || has_acc_err)
|
||||
io.out.storePageFault := valid && (isStore || is_amo) && page_fault
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue