未验证 提交 a057a757 编写于 作者: Y Yinan Xu 提交者: GitHub

Merge pull request #447 from RISCVERS/tlb-sp

Tlb: divide normal 4k page and super page in tlb and l2tlb
......@@ -89,7 +89,9 @@ case class XSCoreParameters
StoreBufferSize: Int = 16,
RefillSize: Int = 512,
TlbEntrySize: Int = 32,
TlbSPEntrySize: Int = 4,
TlbL2EntrySize: Int = 256, // or 512
TlbL2SPEntrySize: Int = 16,
PtwL1EntrySize: Int = 16,
PtwL2EntrySize: Int = 256,
NumPerfCounters: Int = 16,
......@@ -165,7 +167,9 @@ trait HasXSParameter {
val RefillSize = core.RefillSize
val DTLBWidth = core.LoadPipelineWidth + core.StorePipelineWidth
val TlbEntrySize = core.TlbEntrySize
val TlbSPEntrySize = core.TlbSPEntrySize
val TlbL2EntrySize = core.TlbL2EntrySize
val TlbL2SPEntrySize = core.TlbL2SPEntrySize
val PtwL1EntrySize = core.PtwL1EntrySize
val PtwL2EntrySize = core.PtwL2EntrySize
val NumPerfCounters = core.NumPerfCounters
......
......@@ -166,7 +166,7 @@ class CSR extends FunctionUnit with HasCSRConst
if (HasFPU) { extList = extList ++ List('f', 'd') }
val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U
val misa = RegInit(UInt(XLEN.W), misaInitVal)
// MXL = 2 | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
// (XLEN-1, XLEN-2) | |(25, 0) ZY XWVU TSRQ PONM LKJI HGFE DCBA
......@@ -176,7 +176,7 @@ class CSR extends FunctionUnit with HasCSRConst
val mhartNo = hartId()
val mhartid = RegInit(UInt(XLEN.W), mhartNo.asUInt) // the hardware thread running the code
val mstatus = RegInit(UInt(XLEN.W), "h00001800".U) // another option: "h8000c0100".U
// mstatus Value Table
// | sd |
// | pad1 |
......@@ -196,7 +196,7 @@ class CSR extends FunctionUnit with HasCSRConst
// | spp | 0 |
// | pie | 0000 | pie.h is used as UBE
// | ie | 0000 | uie hardlinked to 0, as N ext is not implemented
val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
......@@ -318,11 +318,11 @@ class CSR extends FunctionUnit with HasCSRConst
// Emu perfcnt
val hasEmuPerfCnt = !env.FPGAPlatform
val nrEmuPerfCnts = if (hasEmuPerfCnt) 0x80 else 0x3
val emuPerfCnts = List.fill(nrEmuPerfCnts)(RegInit(0.U(XLEN.W)))
val emuPerfCntCond = List.fill(nrEmuPerfCnts)(WireInit(false.B))
(emuPerfCnts zip emuPerfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
val emuPerfCntsLoMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1000 + i, emuPerfCnts(i)))
val emuPerfCntsHiMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1080 + i, emuPerfCnts(i)(63, 32)))
println(s"CSR: hasEmuPerfCnt:${hasEmuPerfCnt}")
......@@ -336,7 +336,7 @@ class CSR extends FunctionUnit with HasCSRConst
mcycle := mcycle + 1.U
val minstret = RegInit(0.U(XLEN.W))
minstret := minstret + RegNext(csrio.perf.retiredInstr)
// CSR reg map
val basicPrivMapping = Map(
......@@ -424,11 +424,11 @@ class CSR extends FunctionUnit with HasCSRConst
val mapping = basicPrivMapping ++
perfCntMapping ++
pmpMapping ++
emuPerfCntsLoMapping ++
pmpMapping ++
emuPerfCntsLoMapping ++
(if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++
(if (HasFPU) fcsrMapping else Nil)
val addr = src2(11, 0)
val csri = src2(16, 12)
val rdata = Wire(UInt(XLEN.W))
......@@ -750,7 +750,7 @@ class CSR extends FunctionUnit with HasCSRConst
// "ExitLoop3" -> (0x102e, "CntExitLoop3")
// "L2cacheHit" -> (0x1023, "perfCntCondL2cacheHit")
) ++ (
(0 until dcacheParameters.nMissEntries).map(i =>
(0 until dcacheParameters.nMissEntries).map(i =>
("DCacheMissQueuePenalty" + Integer.toString(i, 10), (0x102a + i, "perfCntDCacheMissQueuePenaltyEntry" + Integer.toString(i, 10)))
).toMap
) ++ (
......
......@@ -156,6 +156,94 @@ class PtwEntries(num: Int, tagLen: Int) extends PtwBundle {
}
}
class L2TlbEntry extends TlbBundle {
val tag = UInt(vpnLen.W) // tag is vpn
val level = UInt(log2Up(Level).W) // 2 for 4KB, 1 for 2MB, 0 for 1GB
val ppn = UInt(ppnLen.W)
val perm = new PtePermBundle
def hit(vpn: UInt):Bool = {
val fullMask = VecInit((Seq.fill(vpnLen)(true.B))).asUInt
val maskLevel = VecInit((Level-1 to 0 by -1).map{i => // NOTE: level 2 for 4KB, 1 for 2MB, 0 for 1GB
Reverse(VecInit(Seq.fill(vpnLen-i*vpnnLen)(true.B) ++ Seq.fill(i*vpnnLen)(false.B)).asUInt)})
val mask = maskLevel(level)
(mask&this.tag) === (mask&vpn)
}
def apply(pte: UInt, level: UInt, vpn: UInt) = {
this.tag := vpn
this.level := level
this.ppn := pte.asTypeOf(pteBundle).ppn
this.perm := pte.asTypeOf(pteBundle).perm
this
}
override def toPrintable: Printable = {
p"vpn:0x${Hexadecimal(tag)} level:${level} ppn:${Hexadecimal(ppn)} perm:${perm}"
}
}
class L2TlbEntires(num: Int, tagLen: Int) extends TlbBundle {
require(log2Up(num)==log2Down(num))
/* vpn can be divide into three part */
// vpn: tagPart(17bit) + addrPart(8bit) + cutLenPart(2bit)
val cutLen = log2Up(num)
val tag = UInt(tagLen.W) // NOTE: high part of vpn
val ppns = Vec(num, UInt(ppnLen.W))
val perms = Vec(num, new PtePermBundle)
val vs = Vec(num, Bool())
def tagClip(vpn: UInt) = { // full vpn => tagLen
vpn(vpn.getWidth-1, vpn.getWidth-tagLen)
}
// NOTE: get insize idx
def idxClip(vpn: UInt) = {
vpn(cutLen-1, 0)
}
def hit(vpn: UInt) = {
(tag === tagClip(vpn)) && vs(idxClip(vpn))
}
def genEntries(data: UInt, level: UInt, vpn: UInt): L2TlbEntires = {
require((data.getWidth / XLEN) == num,
"input data length must be multiple of pte length")
assert(level===2.U, "tlb entries only support 4K pages")
val ts = Wire(new L2TlbEntires(num, tagLen))
ts.tag := tagClip(vpn)
for (i <- 0 until num) {
val pte = data((i+1)*XLEN-1, i*XLEN).asTypeOf(new PteBundle)
ts.ppns(i) := pte.ppn
ts.perms(i):= pte.perm // this.perms has no v
ts.vs(i) := !pte.isPf(level) && pte.isLeaf() // legal and leaf, store to l2Tlb
}
ts
}
def get(vpn: UInt): L2TlbEntry = {
val t = Wire(new L2TlbEntry)
val idx = idxClip(vpn)
t.tag := vpn // Note: Use input vpn, not vpn in TlbL2
t.level := 2.U // L2TlbEntries only support 4k page
t.ppn := ppns(idx)
t.perm := perms(idx)
t
}
override def cloneType: this.type = (new L2TlbEntires(num, tagLen)).asInstanceOf[this.type]
override def toPrintable: Printable = {
require(num == 4, "if num is not 4, please comment this toPrintable")
// NOTE: if num is not 4, please comment this toPrintable
p"tag:${Hexadecimal(tag)} ppn(0):${Hexadecimal(ppns(0))} ppn(1):${Hexadecimal(ppns(1))}" +
p"ppn(2):${Hexadecimal(ppns(2))} ppn(3):${Hexadecimal(ppns(3))} " +
p"perms(0):${perms(0)} perms(1):${perms(1)} perms(2):${perms(2)} perms(3):${perms(3)} vs:${Binary(vs.asUInt)}"
}
}
class PtwReq extends PtwBundle {
val vpn = UInt(vpnLen.W)
......@@ -165,8 +253,8 @@ class PtwReq extends PtwBundle {
}
class PtwResp extends PtwBundle {
val entry = new TlbEntry
val pf = Bool() // simple pf no matter cmd
val entry = new L2TlbEntry
val pf = Bool()
override def toPrintable: Printable = {
p"entry:${entry} pf:${pf}"
......@@ -237,11 +325,16 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
// pde/pte-cache is cache of page-table, speeding up ptw
val tlbl2 = Module(new SRAMWrapper(
"L2TLB",
new TlbEntires(num = TlbL2LineSize, tagLen = TlbL2TagLen),
new L2TlbEntires(num = TlbL2LineSize, tagLen = TlbL2TagLen),
set = TlbL2LineNum
)) // (total 256, one line is 4 => 64 lines)
val tlbv = RegInit(0.U(TlbL2LineNum.W)) // valid
val tlbg = Reg(UInt(TlbL2LineNum.W)) // global
val sp = Reg(Vec(TlbL2SPEntrySize, new L2TlbEntry)) // (total 16, one is 4M or 1G)
val spv = RegInit(0.U(TlbL2SPEntrySize.W))
val spg = Reg(UInt(TlbL2SPEntrySize.W))
val ptwl1 = Reg(Vec(PtwL1EntrySize, new PtwEntry(tagLen = PtwL1TagLen)))
val l1v = RegInit(0.U(PtwL1EntrySize.W)) // valid
val l1g = Reg(UInt(PtwL1EntrySize.W))
......@@ -287,7 +380,18 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
XSDebug(tlbl2.io.r.req.valid, p"tlbl2 Read rIdx:${Hexadecimal(ridx)}\n")
XSDebug(RegNext(tlbl2.io.r.req.valid), p"tlbl2 RamData:${ramData}\n")
XSDebug(RegNext(tlbl2.io.r.req.valid), p"tlbl2 v:${vidx} hit:${ramData.hit(req.vpn)} tlbPte:${ramData.get(req.vpn)}\n")
(ramData.hit(req.vpn) && vidx, ramData.get(req.vpn))
val spHitVec = sp.zipWithIndex.map{ case (a,i) =>
RegNext(a.hit(req.vpn) && spv(i), validOneCycle)
}
val spHitData = ParallelMux(spHitVec zip sp)
val spHit = Cat(spHitVec).orR
XSDebug(RegNext(validOneCycle), p"tlbl2 sp: spHit:${spHit} spPte:${spHitData}\n")
assert(RegNext(!(ramData.hit(req.vpn) && spHit)), "pages should not be normal page and super page as well")
(ramData.hit(req.vpn) && vidx || spHit, Mux(spHit, spHitData, ramData.get(req.vpn)))
}
/*
......@@ -369,7 +473,7 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
state := state_idle
}.otherwise {
state := state_wait_ready
latch.entry := new TlbEntry().genTlbEntry(memRdata, level, req.vpn)
latch.entry := Wire(new L2TlbEntry()).apply(memRdata, level, req.vpn)
latch.pf := memPte.isPf(level)
}
}.otherwise {
......@@ -426,7 +530,7 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
for(i <- 0 until PtwWidth) {
resp(i).valid := valid && arbChosen===i.U && ptwFinish // TODO: add resp valid logic
resp(i).bits.entry := Mux(tlbHit, tlbHitData,
Mux(state===state_wait_ready, latch.entry, new TlbEntry().genTlbEntry(memSelData, Mux(level===3.U, 2.U, level), req.vpn)))
Mux(state===state_wait_ready, latch.entry, Wire(new L2TlbEntry()).apply(memSelData, Mux(level===3.U, 2.U, level), req.vpn)))
resp(i).bits.pf := Mux(level===3.U || notFound, true.B, Mux(tlbHit, false.B, Mux(state===state_wait_ready, latch.pf, memPte.isPf(level))))
// TODO: the pf must not be correct, check it
}
......@@ -442,13 +546,15 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
when (memRespFire && !memPte.isPf(level) && !sfenceLatch) {
when (level===0.U && !memPte.isLeaf) {
val refillIdx = LFSR64()(log2Up(PtwL1EntrySize)-1,0) // TODO: may be LRU
val rfOH = UIntToOH(refillIdx)
ptwl1(refillIdx).refill(l1addr, memSelData)
l1v := l1v | UIntToOH(refillIdx)
l1g := (l1g & ~UIntToOH(refillIdx)) | Mux(memPte.perm.g, UIntToOH(refillIdx), 0.U)
l1v := l1v | rfOH
l1g := (l1g & ~rfOH) | Mux(memPte.perm.g, rfOH, 0.U)
}
when (level===1.U && !memPte.isLeaf) {
val l2addrStore = RegEnable(l2addr, memReqFire && state===state_req && level===1.U)
val refillIdx = genPtwL2Idx(l2addrStore) //getVpnn(req.vpn, 1)(log2Up(PtwL2EntrySize)-1, 0)
val rfOH = UIntToOH(refillIdx)
//TODO: check why the old refillIdx is right
assert(ptwl2.io.w.req.ready)
......@@ -459,26 +565,34 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
data = ps,
waymask = -1.S.asUInt
)
l2v := l2v | UIntToOH(refillIdx)
l2g := (l2g & ~UIntToOH(refillIdx)) | Mux(Cat(memPtes.map(_.perm.g)).andR, UIntToOH(refillIdx), 0.U)
l2v := l2v | rfOH
l2g := (l2g & ~rfOH) | Mux(Cat(memPtes.map(_.perm.g)).andR, rfOH, 0.U)
XSDebug(p"ptwl2 RefillIdx:${Hexadecimal(refillIdx)} ps:${ps}\n")
}
when (memPte.isLeaf() && (level===2.U)) {
val refillIdx = genTlbL2Idx(req.vpn)//getVpnn(req.vpn, 0)(log2Up(TlbL2EntrySize)-1, 0)
val rfOH = UIntToOH(refillIdx)
//TODO: check why the old refillIdx is right
assert(tlbl2.io.w.req.ready)
val ts = new TlbEntires(num = TlbL2LineSize, tagLen = TlbL2TagLen).genEntries(memRdata, level, req.vpn)
val ts = new L2TlbEntires(num = TlbL2LineSize, tagLen = TlbL2TagLen).genEntries(memRdata, level, req.vpn)
tlbl2.io.w.apply(
valid = true.B,
setIdx = refillIdx,
data = ts,
waymask = -1.S.asUInt
)
tlbv := tlbv | UIntToOH(refillIdx)
tlbg := (tlbg & ~UIntToOH(refillIdx)) | Mux(Cat(memPtes.map(_.perm.g)).andR, UIntToOH(refillIdx), 0.U)
tlbv := tlbv | rfOH
tlbg := (tlbg & ~rfOH) | Mux(Cat(memPtes.map(_.perm.g)).andR, rfOH, 0.U)
XSDebug(p"tlbl2 refillIdx:${Hexadecimal(refillIdx)} ts:${ts}\n")
}
when (memPte.isLeaf() && (level===1.U || level===0.U)) {
val refillIdx = LFSR64()(log2Up(TlbL2SPEntrySize)-1,0) // TODO: may be LRU
val rfOH = UIntToOH(refillIdx)
sp(refillIdx) := Wire(new L2TlbEntry()).apply(memSelData, Mux(level===3.U, 2.U, level), req.vpn)
spv := spv | rfOH
spg := (spg & ~rfOH) | Mux(memPte.perm.g, rfOH, 0.U)
}
}
/* sfence
......@@ -496,25 +610,29 @@ class PTWImp(outer: PTW) extends PtwModule(outer){
when (sfence.bits.rs2) {
// all va && all asid
tlbv := 0.U
tlbg := 0.U
spv := 0.U
// tlbg := 0.U
l1v := 0.U
l2v := 0.U
l2g := 0.U
// l2g := 0.U
} .otherwise {
// all va && specific asid except global
tlbv := tlbv & tlbg
spv := spv & spg
l1v := l1v & l1g
l2v := l2v & l2g
}
} .otherwise {
val sfenceTlbL2IdxOH = UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
when (sfence.bits.rs2) {
// specific leaf of addr && all asid
tlbv := tlbv & ~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
tlbg := tlbg & ~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))
tlbv := tlbv & ~sfenceTlbL2IdxOH
tlbg := tlbg & ~sfenceTlbL2IdxOH
} .otherwise {
// specific leaf of addr && specific asid
tlbv := tlbv & (~UIntToOH(genTlbL2Idx(sfence.bits.addr(sfence.bits.addr.getWidth-1, offLen)))| tlbg)
tlbv := tlbv & (~sfenceTlbL2IdxOH| tlbg)
}
spv := 0.U
}
}
......
......@@ -4,6 +4,7 @@
#include "ram.h"
#include "compress.h"
// #define TLB_UNITTEST
#ifdef WITH_DRAMSIM3
#include "cosimulation.h"
......@@ -84,8 +85,8 @@ void addpageSv39() {
//pdde[2] = ((0x80000000&0xc0000000) >> 2) | 0xf;
for(int i = 0; i < PTENUM ;i++) {
pde[i] = ((PTEADDR(i)&0xfffff000)>>2) | 0x1;
//pde[i] = (((0x8000000+i*2*1024*1024)&0xffe00000)>>2) | 0xf;
// pde[i] = ((PTEADDR(i)&0xfffff000)>>2) | 0x1;
pde[i] = (((0x80000000+i*2*1024*1024)&0xffe00000)>>2) | 0xf;
}
for(int outidx = 0; outidx < PTENUM; outidx++ ) {
......@@ -94,6 +95,7 @@ void addpageSv39() {
}
}
printf("try to add identical tlb page to ram\n");
memcpy((char *)ram+(TOPSIZE-PAGESIZE*(PTENUM+PDDENUM+PDENUM+PDEMMIONUM+PTEMMIONUM+PDEDEVNUM+PTEDEVNUM)),ptedev,PAGESIZE*PTEDEVNUM);
memcpy((char *)ram+(TOPSIZE-PAGESIZE*(PTENUM+PDDENUM+PDENUM+PDEMMIONUM+PTEMMIONUM+PDEDEVNUM)),pdedev,PAGESIZE*PDEDEVNUM);
memcpy((char *)ram+(TOPSIZE-PAGESIZE*(PTENUM+PDDENUM+PDENUM+PDEMMIONUM+PTEMMIONUM)),ptemmio, PAGESIZE*PTEMMIONUM);
......@@ -117,6 +119,12 @@ void init_ram(const char *img) {
assert(0);
}
#ifdef TLB_UNITTEST
//new add
addpageSv39();
//new end
#endif
int ret;
if (isGzFile(img)) {
printf("Gzip file detected and loading image from extracted gz file\n");
......@@ -143,12 +151,6 @@ void init_ram(const char *img) {
fclose(fp);
}
#ifdef TLB_UNITTEST
//new add
addpageSv39();
//new end
#endif
#ifdef WITH_DRAMSIM3
#if !defined(DRAMSIM3_CONFIG) || !defined(DRAMSIM3_OUTDIR)
#error DRAMSIM3_CONFIG or DRAMSIM3_OUTDIR is not defined
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册