提交 00f35d98 编写于 作者: J jinyue110

Merge branch 'dev-pma' into icache-uncache

package xiangshan
import chisel3._
import chisel3.util._
import utils._
import Chisel.experimental.chiselName
import xiangshan.cache.{DCache, HasDCacheParameters, DCacheParameters, ICache, ICacheParameters, L1plusCache, L1plusCacheParameters, PTW, Uncache}
object MemMap {
def apply (base: String, top: String, width: String, description: String, mode: String): ((String, String), Map[String, String]) = {
((base, top) -> Map(
"width" -> width, // 0 means no limitation
"description" -> description,
"mode" -> mode,
))
}
}
object AddressSpace {
def MemMapList = List(
// Base address Top address Width Description Mode (RWXIDSAC)
MemMap("h00_0000_0000", "h00_0FFF_FFFF", "h0", "Reserved", ""),
MemMap("h00_1000_0000", "h00_1FFF_FFFF", "h0", "QSPI_Flash", "RX"),
MemMap("h00_2000_0000", "h00_2FFF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3000_0000", "h00_3000_FFFF", "h0", "DMA", "RW"),
MemMap("h00_3001_0000", "h00_3004_FFFF", "h0", "GPU", "RWC"),
MemMap("h00_3005_0000", "h00_3005_FFFF", "h0", "USB", "RW"),
MemMap("h00_3006_0000", "h00_3006_FFFF", "h0", "SDMMC", "RW"),
MemMap("h00_3007_0000", "h00_30FF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3100_0000", "h00_3100_FFFF", "h0", "QSPI", "RW"),
MemMap("h00_3101_0000", "h00_3101_FFFF", "h0", "GMAC", "RW"),
MemMap("h00_3102_0000", "h00_3102_FFFF", "h0", "HDMI", "RW"),
MemMap("h00_3103_0000", "h00_3103_FFFF", "h0", "HDMI_PHY", "RW"),
MemMap("h00_3104_0000", "h00_3105_FFFF", "h0", "DP", "RW"),
MemMap("h00_3106_0000", "h00_3106_FFFF", "h0", "DDR0", "RW"),
MemMap("h00_3107_0000", "h00_3107_FFFF", "h0", "DDR0_PHY", "RW"),
MemMap("h00_3108_0000", "h00_3108_FFFF", "h0", "DDR1", "RW"),
MemMap("h00_3109_0000", "h00_3109_FFFF", "h0", "DDR1_PHY", "RW"),
MemMap("h00_310A_0000", "h00_310A_FFFF", "h0", "IIS", "RW"),
MemMap("h00_310B_0000", "h00_310B_FFFF", "h0", "UART0", "RW"),
MemMap("h00_310C_0000", "h00_310C_FFFF", "h0", "UART1", "RW"),
MemMap("h00_310D_0000", "h00_310D_FFFF", "h0", "IIC0", "RW"),
MemMap("h00_310E_0000", "h00_310E_FFFF", "h0", "IIC1", "RW"),
MemMap("h00_310F_0000", "h00_310F_FFFF", "h0", "IIC2", "RW"),
MemMap("h00_3110_0000", "h00_3110_FFFF", "h0", "GPIO", "RW"),
MemMap("h00_3111_0000", "h00_3111_FFFF", "h0", "CRU", "RW"),
MemMap("h00_3112_0000", "h00_37FF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3800_0000", "h00_3800_FFFF", "h0", "CLINT", "RW"),
MemMap("h00_3801_0000", "h00_3BFF_FFFF", "h0", "Reserved", ""),
MemMap("h00_3C00_0000", "h00_3FFF_FFFF", "h0", "PLIC", "RW"),
MemMap("h00_4000_0000", "h00_4FFF_FFFF", "h0", "PCIe0", "RW"),
MemMap("h00_5000_0000", "h00_5FFF_FFFF", "h0", "PCIe1", "RW"),
MemMap("h00_6000_0000", "h00_6FFF_FFFF", "h0", "PCIe2", "RW"),
MemMap("h00_7000_0000", "h00_7FFF_FFFF", "h0", "PCIe3", "RW"),
MemMap("h00_8000_0000", "h1F_FFFF_FFFF", "h0", "DDR", "RWXIDSA"),
)
def printMemmap(){
println("-------------------- memory map --------------------")
for(i <- MemMapList){
println(i._1._1 + "->" + i._1._2 + " width " + (if(i._2.get("width").get == "0") "unlimited" else i._2.get("width").get) + " " + i._2.get("description").get + " [" + i._2.get("mode").get + "]")
}
println("----------------------------------------------------")
}
def genMemmapMatchVec(addr: UInt): UInt = {
VecInit(MemMapList.map(i => {
i._1._1.U <= addr && addr < i._1._2.U
}).toSeq).asUInt
}
def queryMode(matchVec: UInt): UInt = {
Mux1H(matchVec, VecInit(MemMapList.map(i => {
PMAMode.strToMode(i._2.get("mode").get)
}).toSeq))
}
def queryWidth(matchVec: UInt): UInt = {
Mux1H(matchVec, VecInit(MemMapList.map(i => {
i._2.get("width").get.U
}).toSeq))
}
def memmapAddrMatch(addr: UInt): (UInt, UInt) = {
val matchVec = genMemmapMatchVec(addr)
(queryMode(matchVec), queryWidth(matchVec))
}
def isDMMIO(addr: UInt): Bool = !PMAMode.dcache(memmapAddrMatch(addr)._1)
def isIMMIO(addr: UInt): Bool = !PMAMode.icache(memmapAddrMatch(addr)._1)
def isConfigableAddr(addr: UInt): Bool = {
VecInit(MemMapList.map(i => {
i._1._1.U <= addr && addr < i._1._2.U && (i._2.get("mode").get.toUpperCase.indexOf("C") >= 0).B
}).toSeq).asUInt.orR
}
}
class PMAChecker extends XSModule with HasDCacheParameters
{
val io = IO(new Bundle() {
val paddr = Input(UInt(VAddrBits.W))
val mode = Output(PMAMode())
val widthLimit = Output(UInt(8.W)) // TODO: fixme
val updateCConfig = Input(Valid(Bool()))
})
val enableConfigableCacheZone = RegInit(false.B)
val updateCConfig = RegNext(RegNext(RegNext(io.updateCConfig)))
when(updateCConfig.valid) {
enableConfigableCacheZone := updateCConfig.bits
}
val (mode, widthLimit) = AddressSpace.memmapAddrMatch(io.paddr)
io.mode := Mux(AddressSpace.isConfigableAddr(io.paddr) && enableConfigableCacheZone, mode | PMAMode.D, mode)
io.widthLimit := widthLimit
}
\ No newline at end of file
......@@ -274,20 +274,20 @@ case class EnviromentParameters
EnableDebug: Boolean = false
)
object AddressSpace extends HasXSParameter {
// (start, size)
// address out of MMIO will be considered as DRAM
def mmio = List(
(0x00000000L, 0x40000000L), // internal devices, such as CLINT and PLIC
(0x40000000L, 0x40000000L) // external devices
)
// object AddressSpace extends HasXSParameter {
// // (start, size)
// // address out of MMIO will be considered as DRAM
// def mmio = List(
// (0x00000000L, 0x40000000L), // internal devices, such as CLINT and PLIC
// (0x40000000L, 0x40000000L) // external devices
// )
def isMMIO(addr: UInt): Bool = mmio.map(range => {
require(isPow2(range._2))
val bits = log2Up(range._2)
(addr ^ range._1.U)(PAddrBits-1, bits) === 0.U
}).reduce(_ || _)
}
// def isMMIO(addr: UInt): Bool = mmio.map(range => {
// require(isPow2(range._2))
// val bits = log2Up(range._2)
// (addr ^ range._1.U)(PAddrBits-1, bits) === 0.U
// }).reduce(_ || _)
// }
......@@ -333,6 +333,7 @@ class XSCoreImp(outer: XSCore) extends LazyModuleImp(outer)
})
println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}")
AddressSpace.printMemmap()
// to fast wake up fp, mem rs
val intBlockFastWakeUpFp = intExuConfigs.filter(fpFastFilter)
......
......@@ -609,6 +609,9 @@ class CSR extends FunctionUnit with HasCSRConst
val hasStorePageFault = csrio.exception.bits.cf.exceptionVec(storePageFault) && raiseException
val hasStoreAddrMisaligned = csrio.exception.bits.cf.exceptionVec(storeAddrMisaligned) && raiseException
val hasLoadAddrMisaligned = csrio.exception.bits.cf.exceptionVec(loadAddrMisaligned) && raiseException
val hasInstrAccessFault = csrio.exception.bits.cf.exceptionVec(instrAccessFault) && raiseException
val hasLoadAccessFault = csrio.exception.bits.cf.exceptionVec(loadAccessFault) && raiseException
val hasStoreAccessFault = csrio.exception.bits.cf.exceptionVec(storeAccessFault) && raiseException
val csrExceptionVec = Wire(Vec(16, Bool()))
csrExceptionVec.map(_ := false.B)
......@@ -622,6 +625,8 @@ class CSR extends FunctionUnit with HasCSRConst
csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
csrExceptionVec(loadPageFault) := hasLoadPageFault
csrExceptionVec(storePageFault) := hasStorePageFault
csrExceptionVec(loadAccessFault) := hasLoadAccessFault
csrExceptionVec(storeAccessFault) := hasStoreAccessFault
val iduExceptionVec = cfIn.exceptionVec
val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
......
......@@ -185,10 +185,15 @@ object TlbCmd {
def write = "b01".U
def exec = "b10".U
def apply() = UInt(2.W)
def isRead(a: UInt) = a===read
def isWrite(a: UInt) = a===write
def isExec(a: UInt) = a===exec
def atom_read = "b100".U // lr
def atom_write = "b101".U // sc / amo
def apply() = UInt(3.W)
def isRead(a: UInt) = a(1,0)===read
def isWrite(a: UInt) = a(1,0)===write
def isExec(a: UInt) = a(1,0)===exec
def isAtom(a: UInt) = a(2)
}
class TlbReq extends TlbBundle {
......@@ -207,12 +212,18 @@ class TlbReq extends TlbBundle {
class TlbResp extends TlbBundle {
val paddr = UInt(PAddrBits.W)
val miss = Bool()
val mmio = Bool()
val excp = new Bundle {
val pf = new Bundle {
val ld = Bool()
val st = Bool()
val instr = Bool()
}
val af = new Bundle {
val ld = Bool()
val st = Bool()
val instr = Bool()
}
}
override def toPrintable: Printable = {
p"paddr:0x${Hexadecimal(paddr)} miss:${miss} excp.pf: ld:${excp.pf.ld} st:${excp.pf.st} instr:${excp.pf.instr}"
......@@ -341,6 +352,12 @@ class TLB(Width: Int, isDtlb: Boolean) extends TlbModule with HasCSRConst{
resp(i).bits.excp.pf.st := stPf || update
resp(i).bits.excp.pf.instr := instrPf || update
val (pmaMode, accessWidth) = AddressSpace.memmapAddrMatch(resp(i).bits.paddr)
resp(i).bits.mmio := Mux(TlbCmd.isExec(cmdReg), !PMAMode.icache(pmaMode), !PMAMode.dcache(pmaMode))
resp(i).bits.excp.af.ld := Mux(TlbCmd.isAtom(cmdReg), !PMAMode.atomic(pmaMode), !PMAMode.read(pmaMode)) && TlbCmd.isRead(cmdReg)
resp(i).bits.excp.af.st := Mux(TlbCmd.isAtom(cmdReg), !PMAMode.atomic(pmaMode), !PMAMode.write(pmaMode)) && TlbCmd.isWrite(cmdReg)
resp(i).bits.excp.af.instr := Mux(TlbCmd.isAtom(cmdReg), false.B, !PMAMode.execute(pmaMode))
(hit, miss, pfHitVec, multiHit)
}
......
......@@ -28,6 +28,7 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
val atom_override_xtval = RegInit(false.B)
// paddr after translation
val paddr = Reg(UInt())
val is_mmio = Reg(Bool())
// dcache response data
val resp_data = Reg(UInt())
val is_lrsc_valid = Reg(Bool())
......@@ -68,7 +69,6 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
io.tlbFeedback.bits.hit := true.B
io.tlbFeedback.bits.roqIdx := in.uop.roqIdx
// tlb translation, manipulating signals && deal with exception
when (state === s_tlb) {
// send req to dtlb
......@@ -78,7 +78,7 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
io.dtlb.req.bits.roqIdx := in.uop.roqIdx
io.dtlb.resp.ready := true.B
val is_lr = in.uop.ctrl.fuOpType === LSUOpType.lr_w || in.uop.ctrl.fuOpType === LSUOpType.lr_d
io.dtlb.req.bits.cmd := Mux(is_lr, TlbCmd.read, TlbCmd.write)
io.dtlb.req.bits.cmd := Mux(is_lr, TlbCmd.atom_read, TlbCmd.atom_write)
io.dtlb.req.bits.debug.pc := in.uop.cf.pc
when(io.dtlb.resp.fire && !io.dtlb.resp.bits.miss){
......@@ -92,7 +92,14 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
in.uop.cf.exceptionVec(storeAddrMisaligned) := !addrAligned
in.uop.cf.exceptionVec(storePageFault) := io.dtlb.resp.bits.excp.pf.st
in.uop.cf.exceptionVec(loadPageFault) := io.dtlb.resp.bits.excp.pf.ld
val exception = !addrAligned || io.dtlb.resp.bits.excp.pf.st || io.dtlb.resp.bits.excp.pf.ld
in.uop.cf.exceptionVec(storeAccessFault) := io.dtlb.resp.bits.excp.af.st
in.uop.cf.exceptionVec(loadAccessFault) := io.dtlb.resp.bits.excp.af.ld
val exception = !addrAligned ||
io.dtlb.resp.bits.excp.pf.st ||
io.dtlb.resp.bits.excp.pf.ld ||
io.dtlb.resp.bits.excp.af.st ||
io.dtlb.resp.bits.excp.af.ld
is_mmio := io.dtlb.resp.bits.mmio
when (exception) {
// check for exceptions
// if there are exceptions, no need to execute it
......@@ -213,7 +220,7 @@ class AtomicsUnit extends XSModule with MemoryOpConstants{
io.out.bits.redirectValid := false.B
io.out.bits.redirect := DontCare
io.out.bits.brUpdate := DontCare
io.out.bits.debug.isMMIO := AddressSpace.isMMIO(paddr)
io.out.bits.debug.isMMIO := is_mmio
when (io.out.fire()) {
XSDebug("atomics writeback: pc %x data %x\n", io.out.bits.uop.cf.pc, io.dcache.resp.bits.data)
state := s_invalid
......
......@@ -93,7 +93,7 @@ class LoadUnit_S1 extends XSModule {
val s1_paddr = io.dtlbResp.bits.paddr
val s1_exception = io.out.bits.uop.cf.exceptionVec.asUInt.orR
val s1_tlb_miss = io.dtlbResp.bits.miss
val s1_mmio = !s1_tlb_miss && AddressSpace.isMMIO(s1_paddr)
val s1_mmio = !s1_tlb_miss && io.dtlbResp.bits.mmio
val s1_mask = io.in.bits.mask
io.out.bits := io.in.bits // forwardXX field will be updated in s1
......@@ -124,6 +124,7 @@ class LoadUnit_S1 extends XSModule {
io.out.bits.mmio := s1_mmio && !s1_exception
io.out.bits.tlbMiss := s1_tlb_miss
io.out.bits.uop.cf.exceptionVec(loadPageFault) := io.dtlbResp.bits.excp.pf.ld
io.out.bits.uop.cf.exceptionVec(loadAccessFault) := io.dtlbResp.bits.excp.af.ld
io.in.ready := !io.in.valid || io.out.ready
......
......@@ -85,8 +85,9 @@ class StoreUnit_S1 extends XSModule {
io.lsq.bits := io.in.bits
io.lsq.bits.paddr := s1_paddr
io.lsq.bits.miss := false.B
io.lsq.bits.mmio := AddressSpace.isMMIO(s1_paddr)
io.lsq.bits.mmio := io.dtlbResp.bits.mmio
io.lsq.bits.uop.cf.exceptionVec(storePageFault) := io.dtlbResp.bits.excp.pf.st
io.lsq.bits.uop.cf.exceptionVec(storeAccessFault) := io.dtlbResp.bits.excp.af.st
// mmio inst with exception will be writebacked immediately
val hasException = io.out.bits.uop.cf.exceptionVec.asUInt.orR
......
......@@ -108,4 +108,40 @@ package object xiangshan {
def flushItself(level: UInt) = level(0)
def isException(level: UInt) = level(1) && level(0)
}
object PMAMode {
def R = "b1".U << 0 //readable
def W = "b1".U << 1 //writeable
def X = "b1".U << 2 //executable
def I = "b1".U << 3 //cacheable: icache
def D = "b1".U << 4 //cacheable: dcache
def S = "b1".U << 5 //enable speculative access
def A = "b1".U << 6 //enable atomic operation, A imply R & W
def C = "b1".U << 7 //if it is cacheable is configable
def Reserved = "b0".U
def apply() = UInt(7.W)
def read(mode: UInt) = mode(0)
def write(mode: UInt) = mode(1)
def execute(mode: UInt) = mode(2)
def icache(mode: UInt) = mode(3)
def dcache(mode: UInt) = mode(4)
def speculate(mode: UInt) = mode(5)
def atomic(mode: UInt) = mode(6)
def configable_cache(mode: UInt) = mode(7)
def strToMode(s: String) = {
var result = 0.U << 8
if (s.toUpperCase.indexOf("R") >= 0) result = result + R
if (s.toUpperCase.indexOf("W") >= 0) result = result + W
if (s.toUpperCase.indexOf("X") >= 0) result = result + X
if (s.toUpperCase.indexOf("I") >= 0) result = result + I
if (s.toUpperCase.indexOf("D") >= 0) result = result + D
if (s.toUpperCase.indexOf("S") >= 0) result = result + S
if (s.toUpperCase.indexOf("A") >= 0) result = result + A
if (s.toUpperCase.indexOf("C") >= 0) result = result + C
result
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册