增加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 csr.ext_int := io.ext_int
memoryUnit.dataMemory.in.rdata := io.data.rdata 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.ready := io.data.dcache_ready memoryUnit.dataMemory.in.page_fault := io.data.page_fault
io.data.en := memoryUnit.dataMemory.out.en memoryUnit.dataMemory.in.ready := io.data.dcache_ready
io.data.rlen := memoryUnit.dataMemory.out.rlen io.data.en := memoryUnit.dataMemory.out.en
io.data.wen := memoryUnit.dataMemory.out.wen io.data.rlen := memoryUnit.dataMemory.out.rlen
io.data.wdata := memoryUnit.dataMemory.out.wdata io.data.wen := memoryUnit.dataMemory.out.wen
io.data.addr := memoryUnit.dataMemory.out.addr io.data.wdata := memoryUnit.dataMemory.out.wdata
io.data.wstrb := memoryUnit.dataMemory.out.wstrb io.data.addr := memoryUnit.dataMemory.out.addr
io.data.exe_addr := executeUnit.dataMemory.addr io.data.wstrb := memoryUnit.dataMemory.out.wstrb
io.data.exe_addr := executeUnit.dataMemory.addr
writeBackStage.memoryUnit <> memoryUnit.writeBackStage writeBackStage.memoryUnit <> memoryUnit.writeBackStage
writeBackStage.ctrl.allow_to_go := ctrl.writeBackUnit.allow_to_go 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 io.axi.b.ready := true.B
val access_fault = RegInit(false.B) val access_fault = RegInit(false.B)
val page_fault = RegInit(false.B)
val addr_err = io.cpu.addr(XLEN - 1, VADDR_WID).orR val addr_err = io.cpu.addr(XLEN - 1, VADDR_WID).orR
io.cpu.access_fault := access_fault io.cpu.access_fault := access_fault
io.cpu.page_fault := page_fault
// write buffer // write buffer
when(writeFifo_axi_busy) { when(writeFifo_axi_busy) {
@ -294,7 +296,8 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
switch(state) { switch(state) {
is(s_idle) { 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(io.cpu.en) {
when(addr_err) { when(addr_err) {
access_fault := true.B access_fault := true.B
@ -496,6 +499,17 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
} }
is(s_tlb_refill) { is(s_tlb_refill) {
io.cpu.tlb.ptw.vpn.ready := ptw_state === s_handshake 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 // 实现页表访问回填tlb
val satp = io.cpu.tlb.csr.satp.asTypeOf(satpBundle) val satp = io.cpu.tlb.csr.satp.asTypeOf(satpBundle)
val mstatus = io.cpu.tlb.csr.mstatus.asTypeOf(new Mstatus) 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 sum = mstatus.sum
val mxr = mstatus.mxr val mxr = mstatus.mxr
val vpn = io.cpu.tlb.ptw.vpn.bits.asTypeOf(vpnBundle) 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) { switch(state) {
is(s_idle) { is(s_idle) {
access_fault := false.B // 在idle时清除acc_err access_fault := false.B // 在idle时清除access_fault
page_fault := false.B // 在idle时清除page_fault page_fault := false.B // 在idle时清除page_fault
when(io.cpu.req) { when(io.cpu.req) {
when(addr_err) { 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 satp = io.csr.satp.asTypeOf(satpBundle)
val mstatus = io.csr.mstatus.asTypeOf(new Mstatus) 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=0S模式内存访问U模式可访问的页面U=1将出现故障
// 当SUM=1这些访问是允许的当基于页面的虚拟内存不生效时SUM无效 // 当SUM=1这些访问是允许的当基于页面的虚拟内存不生效时SUM无效
// 请注意虽然SUM通常在不在S模式下执行时被忽略但当MPRV=1和MPP=S时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=0只有标记为可读的页面R=1的加载才会成功
// 当MXR=1标记为可读或可执行的页面R=1或X=1的加载才会成功 // 当MXR=1标记为可读或可执行的页面R=1或X=1的加载才会成功
// 当基于页面的虚拟内存无效时MXR无效 // 当基于页面的虚拟内存无效时MXR无效
val mxr = mstatus.mxr val mxr = mstatus.mxr
// 只有当satp.mode为8且当前模式低于M模式时才启用虚拟内存 // 只有当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 itlb = RegInit(0.U.asTypeOf(tlbBundle))
val dtlb = 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_lock = RegInit(false.B)
val ar_sel_val = RegInit(false.B) val ar_sel_val = RegInit(false.B)
// 我们默认优先发送数据tlb的请求 // 我们默认优先发送数据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.valid) {
when(io.dcache.ptw.vpn.ready) { when(io.dcache.ptw.vpn.ready) {
@ -140,13 +141,13 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
// 将ptw模块集成到dcache中ptw通过dcache的axi进行内存访问 // 将ptw模块集成到dcache中ptw通过dcache的axi进行内存访问
io.dcache.ptw.vpn.valid := false.B 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.access_type := Mux(ar_sel, AccessType.fetch, io.dcache.access_type)
io.dcache.ptw.vpn.bits := Mux(ar_sel === 0.U, ivpn, dvpn) io.dcache.ptw.vpn.bits := Mux(ar_sel, ivpn, dvpn)
io.dcache.ptw.pte.ready := true.B // 恒为true io.dcache.ptw.pte.ready := true.B // 恒为true
io.dcache.csr <> io.csr io.dcache.csr <> io.csr
def imodeCheck(): Unit = { def imodeCheck(): Unit = {
switch(mode) { switch(imode) {
is(ModeS) { is(ModeS) {
when(itlb.flag.u && sum === 0.U) { when(itlb.flag.u && sum === 0.U) {
ipage_fault := true.B ipage_fault := true.B
@ -167,7 +168,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
} }
def dmodeCheck(): Unit = { def dmodeCheck(): Unit = {
switch(mode) { switch(dmode) {
is(ModeS) { is(ModeS) {
when(dtlb.flag.u && sum === 0.U) { when(dtlb.flag.u && sum === 0.U) {
dpage_fault := true.B dpage_fault := true.B
@ -196,7 +197,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
// 在icache实现访问tlb的pma和pmp权限检查 // 在icache实现访问tlb的pma和pmp权限检查
ipage_fault := false.B ipage_fault := false.B
iaccess_fault := false.B iaccess_fault := false.B
when(!vm_enabled) { when(!ivm_enabled) {
io.icache.hit := true.B io.icache.hit := true.B
}.elsewhen(itlbl1_hit) { }.elsewhen(itlbl1_hit) {
// 在这里进行取指需要的所有的权限检查 // 在这里进行取指需要的所有的权限检查
@ -222,7 +223,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
itlb := tlbl2(PriorityEncoder(il2_hit_vec)) itlb := tlbl2(PriorityEncoder(il2_hit_vec))
}.otherwise { }.otherwise {
req_ptw(0) := true.B 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 io.dcache.ptw.vpn.valid := true.B
immu_state := search_pte immu_state := search_pte
} }
@ -269,7 +270,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
// 在dcache实现访问tlb的pma和pmp权限检查 // 在dcache实现访问tlb的pma和pmp权限检查
dpage_fault := false.B dpage_fault := false.B
daccess_fault := false.B daccess_fault := false.B
when(!vm_enabled) { when(!dvm_enabled) {
io.dcache.hit := true.B io.dcache.hit := true.B
}.elsewhen(dtlbl1_hit) { }.elsewhen(dtlbl1_hit) {
// 在这里进行取指需要的所有的权限检查 // 在这里进行取指需要的所有的权限检查
@ -316,8 +317,8 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
dmmu_state := search_l1 dmmu_state := search_l1
dtlb := tlbl2(PriorityEncoder(il2_hit_vec)) dtlb := tlbl2(PriorityEncoder(il2_hit_vec))
}.otherwise { }.otherwise {
req_ptw(0) := true.B req_ptw(1) := 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 io.dcache.ptw.vpn.valid := true.B
dmmu_state := search_pte 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.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.icache.paddr := Cat(io.icache.ptag, io.icache.addr(pageOffsetLen - 1, 0))
io.dcache.uncached := AddressSpace.isMMIO(io.dcache.addr) 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)) 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 rdata = Input(UInt(XLEN.W))
val access_fault = Input(Bool()) val access_fault = Input(Bool())
val page_fault = Input(Bool())
val dcache_ready = Input(Bool()) val dcache_ready = Input(Bool())
val tlb = new Tlb_DCache() val tlb = new Tlb_DCache()

View File

@ -50,7 +50,8 @@ class CsrDecodeUnit extends Bundle {
class CsrTlb extends Bundle { class CsrTlb extends Bundle {
val satp = Output(UInt(XLEN.W)) val satp = Output(UInt(XLEN.W))
val mstatus = 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 { 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())) val mip_has_interrupt = WireInit(mip.asTypeOf(new Interrupt()))
mip_has_interrupt.e.s := mip.asTypeOf(new Interrupt).e.s | seip 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) val ideleg = (mideleg & mip_has_interrupt.asUInt)
def priviledgedEnableDetect(x: Bool): Bool = Mux( def priviledgedEnableDetect(x: Bool): Bool = Mux(
x, x,
((mode === ModeS) && mstatus.asTypeOf(new Mstatus()).ie.s) || (mode < ModeS), ((mode === ModeS) && mstatusBundle.ie.s) || (mode < ModeS),
((mode === ModeM) && mstatus.asTypeOf(new Mstatus()).ie.m) || (mode < ModeM) ((mode === ModeM) && mstatusBundle.ie.m) || (mode < ModeM)
) )
val interrupt_enable = Wire(Vec(INT_WID, Bool())) 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) 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.satp := satp
io.tlb.mstatus := mstatus io.tlb.mstatus := mstatus
io.decodeUnit.mode := mode io.decodeUnit.mode := mode

View File

@ -9,9 +9,10 @@ import chisel3.util.experimental.BoringUtils
class Lsu_DataMemory extends Bundle { class Lsu_DataMemory extends Bundle {
val in = Input(new Bundle { val in = Input(new Bundle {
val acc_err = Bool() val access_fault = Bool()
val ready = Bool() val page_fault = Bool()
val rdata = UInt(XLEN.W) val ready = Bool()
val rdata = UInt(XLEN.W)
}) })
val out = Output(new Bundle { val out = Output(new Bundle {
val en = Bool() val en = Bool()
@ -183,7 +184,9 @@ class Lsu(implicit val cpuConfig: CpuConfig) extends Module {
lsExe.out.loadAddrMisaligned || lsExe.out.loadAddrMisaligned ||
lsExe.out.storeAddrMisaligned || lsExe.out.storeAddrMisaligned ||
lsExe.out.loadAccessFault || lsExe.out.loadAccessFault ||
lsExe.out.storeAccessFault lsExe.out.storeAccessFault ||
lsExe.out.loadPageFault ||
lsExe.out.storePageFault
) { ) {
state := s_idle state := s_idle
io.memoryUnit.out.ready := true.B 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(storeAddrMisaligned) := lsExe.out.storeAddrMisaligned
io.memoryUnit.out.ex.exception(loadAccessFault) := lsExe.out.loadAccessFault io.memoryUnit.out.ex.exception(loadAccessFault) := lsExe.out.loadAccessFault
io.memoryUnit.out.ex.exception(storeAccessFault) := lsExe.out.storeAccessFault 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.ex.tval := io.dataMemory.out.addr
io.memoryUnit.out.rdata := MuxCase( io.memoryUnit.out.rdata := MuxCase(

View File

@ -20,6 +20,8 @@ class LsExecute extends Module {
val storeAddrMisaligned = Bool() val storeAddrMisaligned = Bool()
val loadAccessFault = Bool() val loadAccessFault = Bool()
val storeAccessFault = Bool() val storeAccessFault = Bool()
val loadPageFault = Bool()
val storePageFault = Bool()
val rdata = UInt(XLEN.W) val rdata = UInt(XLEN.W)
val ready = Bool() 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 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 reqWmask = if (XLEN == 32) genWmask32(addr, size) else genWmask(addr, size)
val rdata = io.dataMemory.in.rdata 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( val rdataSel64 = LookupTree(
addr(2, 0), addr(2, 0),
@ -141,7 +144,9 @@ class LsExecute extends Module {
io.out.ready := io.dataMemory.in.ready && io.dataMemory.out.en io.out.ready := io.dataMemory.in.ready && io.dataMemory.out.en
io.out.rdata := Mux(partialLoad, rdataPartialLoad, rdataSel) io.out.rdata := Mux(partialLoad, rdataPartialLoad, rdataSel)
io.out.loadAddrMisaligned := valid && !isStore && !is_amo && !addrAligned 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.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
} }