tlb支持巨页

This commit is contained in:
Liphen 2024-01-18 16:10:59 +08:00
parent f182d9b1b1
commit a99cf13f87
6 changed files with 96 additions and 108 deletions

View File

@ -2,7 +2,7 @@ package cpu
import chisel3.util._
import cpu.defines.Const._
import cpu.defines.Sv39Const
import cpu.defines.HasTlbConst
case class CpuConfig(
val build: Boolean = false, // 是否为build模式
@ -32,7 +32,7 @@ case class BranchPredictorConfig(
case class CacheConfig(
cacheType: String = "icache" // icache, dcache
) extends Sv39Const {
) extends HasTlbConst {
// ==========================================================
// | tag | index | offset |
// | | | bank index | bank offset |

View File

@ -42,30 +42,30 @@ class CacheAXIInterface extends Module {
// mux ar {
// we need to lock ar to avoid signals change during handshake
val ar_sel_lock = RegInit(false.B)
val ar_sel_val = RegInit(false.B)
val ar_sel = Mux(ar_sel_lock, ar_sel_val, !io.icache.ar.valid && io.dcache.ar.valid)
val ar_sel_lock = RegInit(false.B)
val ar_sel_val = RegInit(false.B)
val choose_dcache = Mux(ar_sel_lock, ar_sel_val, !io.icache.ar.valid && io.dcache.ar.valid)
when(io.axi.ar.valid) {
when(io.axi.ar.ready) {
ar_sel_lock := false.B
}.otherwise {
ar_sel_lock := true.B
ar_sel_val := ar_sel
ar_sel_val := choose_dcache
}
}
io.axi.ar.bits.id := Cat(0.U(3.W), ar_sel)
io.axi.ar.bits.addr := Mux(ar_sel, io.dcache.ar.bits.addr, io.icache.ar.bits.addr)
io.axi.ar.bits.len := Mux(ar_sel, io.dcache.ar.bits.len, io.icache.ar.bits.len)
io.axi.ar.bits.size := Mux(ar_sel, io.dcache.ar.bits.size, io.icache.ar.bits.size)
io.axi.ar.valid := Mux(ar_sel, io.dcache.ar.valid, io.icache.ar.valid)
io.axi.ar.bits.id := Cat(0.U(3.W), choose_dcache)
io.axi.ar.bits.addr := Mux(choose_dcache, io.dcache.ar.bits.addr, io.icache.ar.bits.addr)
io.axi.ar.bits.len := Mux(choose_dcache, io.dcache.ar.bits.len, io.icache.ar.bits.len)
io.axi.ar.bits.size := Mux(choose_dcache, io.dcache.ar.bits.size, io.icache.ar.bits.size)
io.axi.ar.valid := Mux(choose_dcache, io.dcache.ar.valid, io.icache.ar.valid)
io.axi.ar.bits.burst := 1.U
io.axi.ar.bits.prot := 0.U
io.axi.ar.bits.cache := 0.U
io.axi.ar.bits.lock := 0.U
io.icache.ar.ready := !ar_sel && io.axi.ar.ready
io.dcache.ar.ready := ar_sel && io.axi.ar.ready
io.icache.ar.ready := !choose_dcache && io.axi.ar.ready
io.dcache.ar.ready := choose_dcache && io.axi.ar.ready
// mux ar }
// mux r based on rid {

View File

@ -51,7 +51,7 @@ class WriteBufferUnit extends Bundle {
val size = UInt(AXI_SIZE_WID.W)
}
class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Module with Sv39Const with HasCSRConst {
class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Module with HasTlbConst with HasCSRConst {
val nway = cacheConfig.nway
val nindex = cacheConfig.nindex
val nbank = cacheConfig.nbank
@ -69,6 +69,17 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
// TODO:目前的实现只保证了AXI_DATA_WID为XLEN的情况下的正确性
require(AXI_DATA_WID == XLEN, "AXI_DATA_WID should be greater than XLEN")
def pAddr = new Bundle {
val tag = UInt(ppnLen.W)
val index = UInt(indexWidth.W)
val offset = UInt(offsetWidth.W)
}
def bankAddr = new Bundle {
val index = UInt(bankIndexWidth.W)
val offset = UInt(bankOffsetWidth.W)
}
val io = IO(new Bundle {
val cpu = Flipped(new Cache_DCache())
val axi = new DCache_AXIInterface()
@ -85,7 +96,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
// 临时寄存器
val ptw_working = ptw_state =/= ptw_handshake && ptw_state =/= ptw_set
val ptw_scratch = RegInit(0.U.asTypeOf(new Bundle {
val paddr = cacheAddr
val paddr = pAddr
val replace = Bool()
val dcache_wait = Bool()
}))
@ -99,17 +110,6 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
// | | | bank index | bank offset |
// ==========================================================
def cacheAddr = new Bundle {
val tag = UInt(tagWidth.W)
val index = UInt(indexWidth.W)
val offset = UInt(offsetWidth.W)
}
def bankAddr = new Bundle {
val index = UInt(bankIndexWidth.W)
val offset = UInt(bankOffsetWidth.W)
}
// exe级的index用于访问第i行的数据
val exe_index = io.cpu.exe_addr(indexWidth + offsetWidth - 1, offsetWidth)
// mem级的bank的index用于访问第i个bank的数据
@ -219,7 +219,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
io.cpu.rdata := Mux(state === s_wait, saved_rdata, data(bank_index)(select_way))
io.cpu.tlb.addr := io.cpu.addr
io.cpu.tlb.vaddr := 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
@ -357,7 +357,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
burst.wstrb(replace_way) := 1.U // 先写入第一块bank
when(replace_dirty) {
// cache行的脏位为真时需要写回备份一下cache行便于处理读写时序问题
(0 until nbank).map(i => bank_replication(i) := data(i)(select_way))
(0 until nbank).map(i => bank_replication(i) := data(i)(replace_way))
}
}.otherwise {
when(io.cpu.dcache_ready) {
@ -624,7 +624,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
(vpn_index === 2.U) -> vpn.vpn2
)
)
val ptw_addr = paddrApply(ppn, vpnn).asTypeOf(cacheAddr)
val ptw_addr = paddrApply(ppn, vpnn).asTypeOf(pAddr)
val uncached = AddressSpace.isMMIO(ptw_addr.asUInt)
when(uncached) {
arvalid := true.B
@ -679,12 +679,12 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
burst.wstrb(replace_way) := 1.U // 先写入第一块bank
when(replace_dirty) {
// cache行的脏位为真时需要写回备份一下cache行便于处理读写时序问题
(0 until nbank).map(i => bank_replication(i) := data(i)(select_way))
(0 until nbank).map(i => bank_replication(i) := data(i)(replace_way))
}
}
}
}
is(ptw_uncached) {
is(ptw_uncached) { // 3
when(io.axi.ar.fire) {
arvalid := false.B
}
@ -711,7 +711,7 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
}
}
}
is(ptw_check) {
is(ptw_check) { // 4
// 检查权限
switch(access_type) {
is(AccessType.load) {
@ -745,30 +745,33 @@ class DCache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
}
}
}
is(ptw_set) {
is(ptw_set) { // 5
when(
vpn_index > 0.U && (
vpn_index === 1.U && pte.ppn(0) ||
vpn_index === 2.U && pte.ppn(1, 0).orR
vpn_index === 1.U && pte.ppn.asTypeOf(ppnBundle).ppn0.orR ||
vpn_index === 2.U && (pte.ppn.asTypeOf(ppnBundle).ppn1.orR || pte.ppn.asTypeOf(ppnBundle).ppn0.orR)
)
) {
raisePageFault()
}.elsewhen(!pte.flag.a || access_type === AccessType.store && !pte.flag.d) {
raisePageFault() // 使用软件的方式设置脏位以及访问位
}.otherwise {
}.otherwise {
// 翻译成功
val rmask = WireInit(~0.U(maskLen.W))
io.cpu.tlb.ptw.pte.valid := true.B
io.cpu.tlb.ptw.pte.bits.addr := ar.addr
io.cpu.tlb.ptw.pte.bits.rmask := rmask
io.cpu.tlb.ptw.pte.bits.entry := pte
val ppn_set = Wire(ppnBundle)
when(vpn_index === 2.U) {
ppn_set.ppn2 := pte.ppn.asTypeOf(ppnBundle).ppn2
ppn_set.ppn1 := vpn.vpn1
ppn_set.ppn0 := vpn.vpn0
rmask := 0.U
}.elsewhen(vpn_index === 1.U) {
ppn_set.ppn2 := pte.ppn.asTypeOf(ppnBundle).ppn2
ppn_set.ppn1 := pte.ppn.asTypeOf(ppnBundle).ppn1
ppn_set.ppn0 := vpn.vpn0
rmask := Cat(Fill(ppn1Len, true.B), 0.U(ppn0Len.W))
}.otherwise {
ppn_set := pte.ppn.asTypeOf(ppnBundle)
}

View File

@ -45,7 +45,7 @@ import cpu.defines.Const._
=====================================
*/
class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Module {
class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Module with HasTlbConst {
val nway = cacheConfig.nway
val nindex = cacheConfig.nindex
val nbank = cacheConfig.nbank
@ -57,6 +57,18 @@ class ICache(cacheConfig: CacheConfig)(implicit cpuConfig: CpuConfig) extends Mo
val indexWidth = cacheConfig.indexWidth
val offsetWidth = cacheConfig.offsetWidth
val bitsPerBank = cacheConfig.bitsPerBank
def pAddr = new Bundle {
val tag = UInt(ppnLen.W)
val index = UInt(indexWidth.W)
val offset = UInt(offsetWidth.W)
}
def bankAddr = new Bundle {
val index = UInt(bankIndexWidth.W)
val offset = UInt(bankOffsetWidth.W)
}
val io = IO(new Bundle {
val cpu = Flipped(new Cache_ICache())
val axi = new ICache_AXIInterface()
@ -188,7 +200,7 @@ 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.vaddr := io.cpu.addr(0)
io.cpu.tlb.complete_single_request := io.cpu.complete_single_request
io.cpu.tlb.en := io.cpu.req && (state === s_idle || state === s_tlb_refill)

View File

@ -15,20 +15,20 @@ object AccessType {
def store = "b10".U
}
class Tlb_Ptw extends Bundle with Sv39Const {
class Tlb_Ptw extends Bundle with HasTlbConst {
val vpn = Decoupled(UInt(vpnLen.W))
val access_type = Output(AccessType())
val pte = Flipped(Decoupled(new Bundle {
val access_fault = Bool()
val page_fault = Bool()
val entry = pteBundle
val addr = UInt(PADDR_WID.W)
val rmask = UInt(maskLen.W)
}))
}
class Tlb_ICache extends Bundle with Sv39Const {
class Tlb_ICache extends Bundle with HasTlbConst {
val en = Input(Bool())
val addr = Input(UInt(XLEN.W))
val vaddr = Input(UInt(XLEN.W))
val complete_single_request = Input(Bool())
val uncached = Output(Bool())
@ -76,27 +76,27 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
val dtlb = RegInit(0.U.asTypeOf(tlbBundle))
val tlbl2 = RegInit(VecInit(Seq.fill(cpuConfig.tlbEntries)(0.U.asTypeOf(tlbBundle))))
val ivpn = io.icache.addr(VADDR_WID - 1, pageOffsetLen)
val dvpn = io.dcache.addr(VADDR_WID - 1, pageOffsetLen)
val ivpn = io.icache.vaddr(VADDR_WID - 1, pageOffsetLen)
val dvpn = io.dcache.vaddr(VADDR_WID - 1, pageOffsetLen)
// (VPN一致)(ASID一致或PTE.G为1时)(PTE.V为1)TLB命中
val itlbl1_hit = itlb.vpn === ivpn &&
val itlbl1_hit = vpnEq(itlb.rmask, ivpn, itlb.vpn) &&
(itlb.asid === satp.asid || itlb.flag.g) &&
itlb.flag.v
val dtlbl1_hit = dtlb.vpn === dvpn &&
val dtlbl1_hit = vpnEq(dtlb.rmask, dvpn, dtlb.vpn) &&
(dtlb.asid === satp.asid || dtlb.flag.g) &&
dtlb.flag.v
val il2_hit_vec = VecInit(
tlbl2.map(tlb =>
tlb.vpn === ivpn &&
vpnEq(tlb.rmask, ivpn, tlb.vpn) &&
(tlb.asid === satp.asid || tlb.flag.g) &&
tlb.flag.v
)
)
val dl2_hit_vec = VecInit(
tlbl2.map(tlb =>
tlb.vpn === dvpn &&
vpnEq(tlb.rmask, dvpn, tlb.vpn) &&
(tlb.asid === satp.asid || tlb.flag.g) &&
tlb.flag.v
)
@ -243,7 +243,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
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
replace_entry.rmask := io.dcache.ptw.pte.bits.rmask
tlbl2(replace_index.value) := replace_entry
itlb := replace_entry
replace_index.inc()
@ -343,7 +343,7 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
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
replace_entry.rmask := io.dcache.ptw.pte.bits.rmask
tlbl2(replace_index.value) := replace_entry
dtlb := replace_entry
replace_index.inc()
@ -360,8 +360,8 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
}
}
val src1 = io.sfence_vma.src_info.src1_data
val src2 = io.sfence_vma.src_info.src2_data
val src1 = io.sfence_vma.src_info.src1_data(vpnLen - 1, 0)
val src2 = io.sfence_vma.src_info.src2_data(asidLen - 1, 0)
when(io.sfence_vma.valid) {
when(!src1.orR && !src2.orR) {
// 将所有tlb的有效位置为0
@ -385,39 +385,42 @@ class Tlb extends Module with HasTlbConst with HasCSRConst {
}
}.elsewhen(src1.orR && !src2.orR) {
// 将vpn一致的tlb的有效位置为0
when(itlb.vpn === src1) {
when(vpnEq(itlb.rmask, src1, itlb.vpn)) {
itlb.flag.v := false.B
}
when(dtlb.vpn === src1) {
when(vpnEq(dtlb.rmask, src1, dtlb.vpn)) {
dtlb.flag.v := false.B
}
for (i <- 0 until cpuConfig.tlbEntries) {
when(tlbl2(i).vpn === src1) {
when(vpnEq(tlbl2(i).rmask, src1, tlbl2(i).vpn)) {
tlbl2(i).flag.v := false.B
}
}
}.elsewhen(src1.orR && src2.orR) {
// 将asid一致的且vpn一致的tlb的有效位置为0g为1的除外
when(itlb.asid === src2 && itlb.vpn === src1 && !itlb.flag.g) {
when(itlb.asid === src2 && vpnEq(itlb.rmask, src1, itlb.vpn) && !itlb.flag.g) {
itlb.flag.v := false.B
}
when(dtlb.asid === src2 && dtlb.vpn === src1 && !dtlb.flag.g) {
when(dtlb.asid === src2 && vpnEq(dtlb.rmask, src1, dtlb.vpn) && !dtlb.flag.g) {
dtlb.flag.v := false.B
}
for (i <- 0 until cpuConfig.tlbEntries) {
when(tlbl2(i).asid === src2 && tlbl2(i).vpn === src1 && !tlbl2(i).flag.g) {
when(tlbl2(i).asid === src2 && vpnEq(tlbl2(i).rmask, src1, tlbl2(i).vpn) && !tlbl2(i).flag.g) {
tlbl2(i).flag.v := false.B
}
}
}
}
io.icache.uncached := AddressSpace.isMMIO(io.icache.addr)
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))
val imasktag = maskTag(itlb.rmask, itlb.ppn, ivpn)
val dmasktag = maskTag(dtlb.rmask, dtlb.ppn, dvpn)
io.dcache.uncached := AddressSpace.isMMIO(io.dcache.addr)
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.icache.uncached := AddressSpace.isMMIO(io.icache.vaddr)
io.icache.ptag := Mux(ivm_enabled, imasktag, ivpn)
io.icache.paddr := Cat(io.icache.ptag, io.icache.vaddr(pageOffsetLen - 1, 0))
io.dcache.uncached := AddressSpace.isMMIO(io.dcache.vaddr)
io.dcache.ptag := Mux(dvm_enabled, dmasktag, dvpn)
io.dcache.paddr := Cat(io.dcache.ptag, io.dcache.vaddr(pageOffsetLen - 1, 0))
}

View File

@ -6,7 +6,7 @@ import cpu.defines.Const._
import cpu.CacheConfig
import cpu.CpuConfig
trait Sv39Const extends CoreParameter {
trait HasTlbConst extends CoreParameter {
val PAddrBits = PADDR_WID // 32
val level = 3
val pageOffsetLen = 12 // 页面大小为4KB对应的偏移量长度为12位
@ -18,6 +18,7 @@ trait Sv39Const extends CoreParameter {
val vpn1Len = 9
val vpn0Len = 9
val vpnLen = vpn2Len + vpn1Len + vpn0Len // 27
val maskLen = ppn1Len + ppn0Len // 18
val satpLen = XLEN
val satpModeLen = 4
@ -31,21 +32,14 @@ trait Sv39Const extends CoreParameter {
val cacheTagLen = PADDR_WID - pageOffsetLen // 32 - 12 = 20
require(ppnLen == cacheTagLen)
def vaBundle = new Bundle {
val vpn2 = UInt(vpn2Len.W)
val vpn1 = UInt(vpn1Len.W)
val vpn0 = UInt(vpn0Len.W)
val offset = UInt(pageOffsetLen.W)
def vpnEq(mask: UInt, vpn: UInt, tlbvpn: UInt) = {
val fullmask = Cat(Fill(vpn2Len, true.B), mask)
(vpn & fullmask) === (tlbvpn & fullmask)
}
def vaBundle2 = new Bundle {
val vpn = UInt(vpnLen.W)
val offset = UInt(pageOffsetLen.W)
}
def vaBundle3 = new Bundle {
val vpn = UInt(vpnLen.W)
val offset = UInt(pageOffsetLen.W)
def maskTag(mask: UInt, ppn: UInt, vpn: UInt) = {
val fullmask = Cat(Fill(ppn2Len, true.B), mask)
(ppn & fullmask) | (vpn & ~fullmask)
}
def vpnBundle = new Bundle {
@ -54,18 +48,6 @@ trait Sv39Const extends CoreParameter {
val vpn0 = UInt(vpn0Len.W)
}
def paBundle = new Bundle {
val ppn2 = UInt(ppn2Len.W)
val ppn1 = UInt(ppn1Len.W)
val ppn0 = UInt(ppn0Len.W)
val offset = UInt(pageOffsetLen.W)
}
def paBundle2 = new Bundle {
val ppn = UInt(ppnLen.W)
val offset = UInt(pageOffsetLen.W)
}
def ppnBundle = new Bundle {
val ppn2 = UInt(ppn2Len.W)
val ppn1 = UInt(ppn1Len.W)
@ -110,23 +92,11 @@ trait Sv39Const extends CoreParameter {
val v = Bool()
}
def maskPaddr(ppn: UInt, vaddr: UInt, mask: UInt) = {
MaskData(vaddr, Cat(ppn, 0.U(pageOffsetLen.W)), Cat(Fill(ppn2Len, 1.U(1.W)), mask, 0.U(pageOffsetLen.W)))
}
def MaskEQ(mask: UInt, pattern: UInt, vpn: UInt) = {
(Cat("h1ff".U(vpn2Len.W), mask) & pattern) === (Cat("h1ff".U(vpn2Len.W), mask) & vpn)
}
}
trait HasTlbConst extends Sv39Const {
def tlbBundle = new Bundle {
val vpn = UInt(vpnLen.W)
val asid = UInt(asidLen.W)
val flag = flagBundle
val ppn = UInt(ppnLen.W)
val pteaddr = UInt(PAddrBits.W)
val vpn = UInt(vpnLen.W)
val asid = UInt(asidLen.W)
val flag = flagBundle
val ppn = UInt(ppnLen.W)
val rmask = UInt(maskLen.W)
}
}