完成除vma指令外的框架

This commit is contained in:
Liphen 2024-01-15 13:36:44 +08:00
parent 3a3680fb02
commit 2f3ff6e5dd
8 changed files with 180 additions and 77 deletions

View File

@ -71,7 +71,8 @@ class Core(implicit val cpuConfig: CpuConfig) extends Module {
instFifo.wen(i) := io.inst.inst_valid(i)
instFifo.write(i).pc := io.inst.addr(0) + (i * 4).U
instFifo.write(i).inst := io.inst.inst(i)
instFifo.write(i).acc_err := io.inst.acc_err
instFifo.write(i).access_fault := io.inst.access_fault
instFifo.write(i).page_fault := io.inst.page_fault
}
decodeUnit.instFifo.info.empty := instFifo.empty
@ -108,7 +109,7 @@ 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.acc_err
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

View File

@ -199,6 +199,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
io.cpu.tlb.addr := io.cpu.addr
io.cpu.tlb.access_type := Mux(io.cpu.en && io.cpu.wen.orR, AccessType.store, AccessType.load)
io.cpu.tlb.en := io.cpu.en
val bank_raddr = Mux(state === s_fence, dirty_index, Mux(use_next_addr, exe_index, replace_index))
val tag_raddr = Mux(state === s_fence, dirty_index, tag_rindex)
@ -259,12 +260,10 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
io.axi.b.ready := true.B
val acc_err = RegInit(false.B)
val access_fault = RegInit(false.B)
val addr_err = io.cpu.addr(XLEN - 1, VADDR_WID).orR
when(acc_err) {
acc_err := false.B
}
io.cpu.acc_err := acc_err
io.cpu.access_fault := access_fault
// write buffer
when(writeFifo_axi_busy) {
@ -295,9 +294,10 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
switch(state) {
is(s_idle) {
access_fault := false.B // 在idle时清除acc_err
when(io.cpu.en) {
when(addr_err) {
acc_err := true.B
access_fault := true.B
}.elsewhen(!io.cpu.tlb.hit) {
state := s_tlb_refill
}.elsewhen(io.cpu.tlb.uncached) {
@ -365,7 +365,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
when(io.axi.r.fire) {
rready := false.B
saved_rdata := io.axi.r.bits.data
acc_err := io.axi.r.bits.resp =/= RESP_OKEY.U
access_fault := io.axi.r.bits.resp =/= RESP_OKEY.U
state := s_wait
}
}
@ -507,7 +507,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
val sum = mstatus.sum
val mxr = mstatus.mxr
val vpn = io.cpu.tlb.ptw.vpn.bits.asTypeOf(vpnBundle)
val access_type = io.cpu.tlb.access_type
val access_type = io.cpu.tlb.ptw.access_type
val ppn = RegInit(0.U(ppnLen.W))
val vpn_index = RegInit(0.U(log2Up(level).W)) // 页表访问的层级
val pte = RegInit(0.U.asTypeOf(pteBundle)) // 页表项
@ -516,6 +516,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
io.cpu.tlb.ptw.pte.bits := DontCare
io.cpu.tlb.ptw.pte.bits.access_fault := false.B
io.cpu.tlb.ptw.pte.bits.page_fault := false.B
io.cpu.tlb.complete_single_request := io.cpu.complete_single_request
require(AXI_DATA_WID == XLEN) // 目前只考虑了AXI_DATA_WID == XLEN的情况
def raisePageFault(): Unit = {
@ -643,7 +644,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
io.cpu.tlb.ptw.pte.valid := true.B
io.cpu.tlb.ptw.pte.bits.addr := ar.addr
io.cpu.tlb.ptw.pte.bits.entry := pte
val ppn_set = WireInit(ppnBundle)
val ppn_set = Wire(ppnBundle)
when(vpn_index === 2.U) {
ppn_set.ppn2 := pte.ppn.asTypeOf(ppnBundle).ppn2
ppn_set.ppn1 := vpn.vpn1

View File

@ -187,7 +187,10 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
}
io.cpu.icache_stall := Mux(state === s_idle, (!cache_hit_available && io.cpu.req), state =/= s_wait)
io.cpu.tlb.addr := io.cpu.addr(0)
io.cpu.tlb.complete_single_request := io.cpu.complete_single_request
io.cpu.tlb.en := io.cpu.req
val ar = RegInit(0.U.asTypeOf(new AR()))
val arvalid = RegInit(false.B)
@ -199,19 +202,22 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
r <> io.axi.r.bits
rready <> io.axi.r.ready
val acc_err = RegInit(false.B)
val access_fault = RegInit(false.B)
val page_fault = RegInit(false.B)
val addr_err = io.cpu.addr(use_next_addr)(XLEN - 1, VADDR_WID).orR
when(acc_err) { acc_err := false.B }
io.cpu.acc_err := acc_err //TODO实现cached段中的访存错误
io.cpu.access_fault := access_fault //TODO实现cached段中的访存response错误
io.cpu.page_fault := page_fault
switch(state) {
is(s_idle) {
access_fault := false.B // 在idle时清除acc_err
page_fault := false.B // 在idle时清除page_fault
when(io.cpu.req) {
when(addr_err) {
acc_err := true.B
access_fault := true.B
state := s_wait
rdata_in_wait(0).inst := 0.U
rdata_in_wait(0).inst := Instructions.NOP
rdata_in_wait(0).valid := true.B
}.elsewhen(!io.cpu.tlb.hit) {
state := s_tlb_refill
@ -252,11 +258,11 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
}
}.elsewhen(io.axi.r.fire) {
// * uncached not support burst transport * //
state := s_wait
rdata_in_wait(0).inst := Mux(ar.addr(2), io.axi.r.bits.data(63, 32), io.axi.r.bits.data(31, 0))
rdata_in_wait(0).valid := true.B
rready := false.B
acc_err := io.axi.r.bits.resp =/= RESP_OKEY.U
access_fault := io.axi.r.bits.resp =/= RESP_OKEY.U
state := s_wait
}
}
is(s_replace) {
@ -294,7 +300,21 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
}
}
is(s_tlb_refill) {
// TODO:
when(io.cpu.tlb.access_fault) {
access_fault := true.B
state := s_wait
rdata_in_wait(0).inst := Instructions.NOP
rdata_in_wait(0).valid := true.B
}.elsewhen(io.cpu.tlb.page_fault) {
page_fault := true.B
state := s_wait
rdata_in_wait(0).inst := Instructions.NOP
rdata_in_wait(0).valid := true.B
}.otherwise {
when(io.cpu.tlb.hit) {
state := s_idle
}
}
}
}

View File

@ -27,6 +27,7 @@ class Tlb_Ptw extends Bundle with Sv39Const {
}
class Tlb_ICache extends Bundle with Sv39Const {
val en = Input(Bool())
val addr = Input(UInt(XLEN.W))
val complete_single_request = Input(Bool())
@ -39,8 +40,10 @@ class Tlb_ICache extends Bundle with Sv39Const {
}
class Tlb_DCache extends Tlb_ICache {
val ptw = new Tlb_Ptw()
val access_type = Input(AccessType())
// ptw 相关参数
val ptw = new Tlb_Ptw()
val csr = new CsrTlb()
}
@ -49,10 +52,10 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
val icache = new Tlb_ICache()
val dcache = new Tlb_DCache()
val csr = Flipped(new CsrTlb())
val fence_vma = Input(new Bundle {
val src1 = UInt(XLEN.W)
val src2 = UInt(XLEN.W)
})
// val fence_vma = Input(new Bundle {
// val src1 = UInt(XLEN.W)
// val src2 = UInt(XLEN.W)
// })
})
val satp = io.csr.satp.asTypeOf(satpBundle)
@ -103,6 +106,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
val search_l1 :: search_l2 :: search_pte :: search_fault :: Nil = Enum(4)
val immu_state = RegInit(search_l1)
val dmmu_state = RegInit(search_l1)
// 使用随机的方法替换TLB条目
val replace_index = new Counter(cpuConfig.tlbEntries)
@ -144,10 +148,13 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
io.dcache.ptw.pte.ready := true.B // 恒为true
io.dcache.csr <> io.csr
// 指令虚实地址转换
// ---------------------------------------------------
// ----------------- 指令虚实地址转换 -----------------
// ---------------------------------------------------
switch(immu_state) {
is(search_l1) {
// TODO在这里实现访问tlb的pma和pmp权限检查
when(io.icache.en) {
// 在icache实现访问tlb的pma和pmp权限检查
ipage_fault := false.B
iaccess_fault := false.B
when(!vm_enabled) {
@ -181,6 +188,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
immu_state := search_l2
}
}
}
is(search_l2) {
when(il2_hit_vec.asUInt.orR) {
immu_state := search_l1
@ -225,6 +233,75 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
}
}
// ---------------------------------------------------
// ----------------- 指令虚实地址转换 -----------------
// ---------------------------------------------------
switch(dmmu_state) {
is(search_l1) {
when(io.dcache.en) {
// 在dcache实现访问tlb的pma和pmp权限检查
dpage_fault := false.B
daccess_fault := false.B
when(!vm_enabled) {
io.dcache.hit := true.B
}.elsewhen(dtlbl1_hit) {
// 在这里进行取指需要的所有的权限检查
// 0. X位检查只有可执行的页面才能取指
// 1. M模式不可能到这里因为vm_enabled为false
// 2. S模式如果U位为1需要检查SUM
// 3. U模式必须保证U位为1
io.dcache.hit := false.B // 只有权限检查通过后可以置为true
// TODO:增加权限检查
}.otherwise {
dmmu_state := search_l2
}
}
}
is(search_l2) {
when(il2_hit_vec.asUInt.orR) {
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) {
io.dcache.ptw.vpn.valid := true.B
dmmu_state := search_pte
}
}
}
is(search_pte) {
io.dcache.ptw.vpn.valid := true.B
when(io.dcache.ptw.pte.valid) {
when(io.dcache.ptw.pte.bits.access_fault) {
daccess_fault := true.B
dmmu_state := search_fault
}.elsewhen(io.dcache.ptw.pte.bits.page_fault) {
dpage_fault := true.B
dmmu_state := search_fault
}.otherwise {
// 在内存中找寻到了页表将其写入TLB
val replace_entry = Wire(tlbBundle)
replace_entry.vpn := ivpn
replace_entry.asid := satp.asid
replace_entry.flag := io.dcache.ptw.pte.bits.entry.flag
replace_entry.ppn := io.dcache.ptw.pte.bits.entry.ppn
replace_entry.pteaddr := io.dcache.ptw.pte.bits.addr
tlbl2(replace_index.value) := replace_entry
dtlb := replace_entry
dmmu_state := search_l1
}
}
}
is(search_fault) {
when(io.dcache.complete_single_request) {
dpage_fault := false.B
daccess_fault := false.B
dmmu_state := search_l1
}
}
}
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.paddr := Cat(io.icache.ptag, io.icache.addr(pageOffsetLen - 1, 0))

View File

@ -109,15 +109,16 @@ class WriteBackCtrl extends Bundle {
class Cache_ICache(implicit val cpuConfig: CpuConfig) extends Bundle {
// read inst request from cpu
val req = Output(Bool())
val complete_single_request = Output(Bool()) // !cpu_stall
val complete_single_request = Output(Bool())
val addr = Output(Vec(cpuConfig.instFetchNum, UInt(XLEN.W))) // virtual address and next virtual address
val fence_i = Output(Bool())
val dcache_stall = Output(Bool()) // dcache_stall
val dcache_stall = Output(Bool())
// read inst result
val inst = Input(Vec(cpuConfig.instFetchNum, UInt(XLEN.W)))
val inst_valid = Input(Vec(cpuConfig.instFetchNum, Bool()))
val acc_err = Input(Bool())
val access_fault = Input(Bool())
val page_fault = Input(Bool())
val icache_stall = Input(Bool()) // icache_stall
// tlb
@ -137,7 +138,7 @@ class Cache_DCache extends Bundle {
val wstrb = Output(UInt(AXI_STRB_WID.W))
val rdata = Input(UInt(XLEN.W))
val acc_err = Input(Bool())
val access_fault = Input(Bool())
val dcache_ready = Input(Bool())
val tlb = new Tlb_DCache()

View File

@ -122,7 +122,8 @@ class DecodeUnit(implicit val cpuConfig: CpuConfig) extends Module with HasExcep
(0 until (INT_WID)).foreach(i => io.executeStage.inst0.ex.interrupt(i) := io.csr.interrupt(i))
io.executeStage.inst0.ex.exception.map(_ := false.B)
io.executeStage.inst0.ex.exception(illegalInstr) := !info(0).inst_legal
io.executeStage.inst0.ex.exception(instrAccessFault) := io.instFifo.inst(0).acc_err
io.executeStage.inst0.ex.exception(instrAccessFault) := io.instFifo.inst(0).access_fault
io.executeStage.inst0.ex.exception(instrPageFault) := io.instFifo.inst(0).page_fault
io.executeStage.inst0.ex.exception(instrAddrMisaligned) := pc(0)(log2Ceil(INST_WID / 8) - 1, 0).orR ||
io.fetchUnit.target(log2Ceil(INST_WID / 8) - 1, 0).orR && io.fetchUnit.branch
io.executeStage.inst0.ex.exception(breakPoint) := info(0).inst(31, 20) === privEbreak &&
@ -165,7 +166,8 @@ class DecodeUnit(implicit val cpuConfig: CpuConfig) extends Module with HasExcep
(0 until (INT_WID)).foreach(i => io.executeStage.inst1.ex.interrupt(i) := io.csr.interrupt(i))
io.executeStage.inst1.ex.exception.map(_ := false.B)
io.executeStage.inst1.ex.exception(illegalInstr) := !info(1).inst_legal
io.executeStage.inst1.ex.exception(instrAccessFault) := io.instFifo.inst(1).acc_err
io.executeStage.inst1.ex.exception(instrAccessFault) := io.instFifo.inst(1).access_fault
io.executeStage.inst1.ex.exception(instrPageFault) := io.instFifo.inst(1).page_fault
io.executeStage.inst1.ex.exception(instrAddrMisaligned) := pc(1)(log2Ceil(INST_WID / 8) - 1, 0).orR ||
io.fetchUnit.target(log2Ceil(INST_WID / 8) - 1, 0).orR && io.fetchUnit.branch
io.executeStage.inst1.ex.exception(breakPoint) := info(1).inst(31, 20) === privEbreak &&

View File

@ -9,7 +9,8 @@ class BufferUnit extends Bundle {
val bpuConfig = new BranchPredictorConfig()
val inst = UInt(XLEN.W)
val pht_index = UInt(bpuConfig.phtDepth.W)
val acc_err = Bool()
val access_fault = Bool()
val page_fault = Bool()
val pc = UInt(XLEN.W)
}

View File

@ -8,7 +8,7 @@ import icache.mmu.Tlb
object TestMain extends App {
implicit val cpuConfig = new CpuConfig()
implicit val dCacheConfig = CacheConfig(cacheType = "dcache")
def top = new Tlb
def top = new DCache(dCacheConfig)
val useMFC = false // use MLIR-based firrtl compiler
val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top))
if (useMFC) {