增加lsu的例外处理

This commit is contained in:
Liphen 2024-01-15 16:01:22 +08:00
parent 7a3a3417c7
commit b16eff1ba7
8 changed files with 72 additions and 41 deletions

View File

@ -109,16 +109,17 @@ 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.ready := io.data.dcache_ready
io.data.en := memoryUnit.dataMemory.out.en
io.data.rlen := memoryUnit.dataMemory.out.rlen
io.data.wen := memoryUnit.dataMemory.out.wen
io.data.wdata := memoryUnit.dataMemory.out.wdata
io.data.addr := memoryUnit.dataMemory.out.addr
io.data.wstrb := memoryUnit.dataMemory.out.wstrb
io.data.exe_addr := executeUnit.dataMemory.addr
memoryUnit.dataMemory.in.rdata := io.data.rdata
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
io.data.wen := memoryUnit.dataMemory.out.wen
io.data.wdata := memoryUnit.dataMemory.out.wdata
io.data.addr := memoryUnit.dataMemory.out.addr
io.data.wstrb := memoryUnit.dataMemory.out.wstrb
io.data.exe_addr := executeUnit.dataMemory.addr
writeBackStage.memoryUnit <> memoryUnit.writeBackStage
writeBackStage.ctrl.allow_to_go := ctrl.writeBackUnit.allow_to_go

View File

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

View File

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

View File

@ -57,19 +57,20 @@ 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=0S模式内存访问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
val sum = mstatus.sum
// 当MXR=0只有标记为可读的页面R=1的加载才会成功
// 当MXR=1标记为可读或可执行的页面R=1或X=1的加载才会成功
// 当基于页面的虚拟内存无效时MXR无效
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))
}

View File

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

View File

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

View File

@ -9,9 +9,10 @@ import chisel3.util.experimental.BoringUtils
class Lsu_DataMemory extends Bundle {
val in = Input(new Bundle {
val acc_err = Bool()
val ready = Bool()
val rdata = UInt(XLEN.W)
val access_fault = Bool()
val page_fault = Bool()
val ready = Bool()
val rdata = UInt(XLEN.W)
})
val out = Output(new Bundle {
val en = Bool()
@ -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(

View File

@ -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()
})
@ -83,8 +85,9 @@ class LsExecute extends Module {
val reqWdata = if (XLEN == 32) genWdata32(io.in.wdata, size) else genWdata(io.in.wdata, size)
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 rdata = io.dataMemory.in.rdata
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
}