1ca2f90a6SLemover/*************************************************************************************** 2ca2f90a6SLemover * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3ca2f90a6SLemover * Copyright (c) 2020-2021 Peng Cheng Laboratory 4ca2f90a6SLemover * 5ca2f90a6SLemover * XiangShan is licensed under Mulan PSL v2. 6ca2f90a6SLemover * You can use this software according to the terms and conditions of the Mulan PSL v2. 7ca2f90a6SLemover * You may obtain a copy of Mulan PSL v2 at: 8ca2f90a6SLemover * http://license.coscl.org.cn/MulanPSL2 9ca2f90a6SLemover * 10ca2f90a6SLemover * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11ca2f90a6SLemover * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12ca2f90a6SLemover * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13ca2f90a6SLemover * 14ca2f90a6SLemover * See the Mulan PSL v2 for more details. 15ca2f90a6SLemover ***************************************************************************************/ 16ca2f90a6SLemover 17ca2f90a6SLemoverpackage xiangshan.backend.fu 18ca2f90a6SLemover 19ca2f90a6SLemoverimport chipsalliance.rocketchip.config.Parameters 20ca2f90a6SLemoverimport chisel3._ 21ca2f90a6SLemoverimport chisel3.internal.naming.chiselName 22ca2f90a6SLemoverimport chisel3.util._ 23ca2f90a6SLemoverimport xiangshan.{HasXSParameter, XSModule} 24ca2f90a6SLemoverimport xiangshan.backend.fu.util.HasCSRConst 25ca2f90a6SLemoverimport xiangshan.cache.mmu.TlbCmd 26ca2f90a6SLemover 27ca2f90a6SLemovertrait PMAMethod extends HasXSParameter with PMPConst { this: XSModule => 28ca2f90a6SLemover /** 29ca2f90a6SLemover def SimpleMemMapList = List( 30ca2f90a6SLemover // Base address Top address Width Description Mode (RWXIDSAC) 31ca2f90a6SLemover MemMap("h00_0000_0000", "h00_0FFF_FFFF", "h0", "Reserved", "RW"), 32ca2f90a6SLemover MemMap("h00_1000_0000", "h00_1FFF_FFFF", "h0", "QSPI_Flash", "RWX"), 33ca2f90a6SLemover MemMap("h00_2000_0000", "h00_2FFF_FFFF", "h0", "Reserved", "RW"), 34ca2f90a6SLemover MemMap("h00_3000_0000", "h00_3000_FFFF", "h0", "DMA", "RW"), 35ca2f90a6SLemover MemMap("h00_3001_0000", "h00_3004_FFFF", "h0", "GPU", "RWC"), 36ca2f90a6SLemover MemMap("h00_3005_0000", "h00_3006_FFFF", "h0", "USB/SDMMC", "RW"), 37ca2f90a6SLemover MemMap("h00_3007_0000", "h00_30FF_FFFF", "h0", "Reserved", "RW"), 38ca2f90a6SLemover MemMap("h00_3100_0000", "h00_3111_FFFF", "h0", "MMIO", "RW"), 39ca2f90a6SLemover MemMap("h00_3112_0000", "h00_37FF_FFFF", "h0", "Reserved", "RW"), 40ca2f90a6SLemover MemMap("h00_3800_0000", "h00_3800_FFFF", "h0", "CLINT", "RW"), 41ca2f90a6SLemover MemMap("h00_3801_0000", "h00_3801_FFFF", "h0", "BEU", "RW"), 42ca2f90a6SLemover MemMap("h00_3802_0000", "h00_3802_0FFF", "h0", "DebugModule", "RWX"), 43ca2f90a6SLemover MemMap("h00_3802_1000", "h00_3BFF_FFFF", "h0", "Reserved", ""), 44ca2f90a6SLemover MemMap("h00_3C00_0000", "h00_3FFF_FFFF", "h0", "PLIC", "RW"), 45ca2f90a6SLemover MemMap("h00_4000_0000", "h00_7FFF_FFFF", "h0", "PCIe", "RW"), 46*2f30d658SYinan Xu MemMap("h00_8000_0000", "h0F_FFFF_FFFF", "h0", "DDR", "RWXIDSA"), 47ca2f90a6SLemover ) 48ca2f90a6SLemover */ 49ca2f90a6SLemover 50ca2f90a6SLemover def pma_init() : (Vec[UInt], Vec[UInt], Vec[UInt]) = { 51ca2f90a6SLemover // the init value is zero 52ca2f90a6SLemover // from 0 to num(default 16) - 1, lower priority 53ca2f90a6SLemover // according to simple map, 9 entries is needed, pick 6-14, leave 0-5 & 15 unusedcfgMerged.map(_ := 0.U) 54ca2f90a6SLemover 55ca2f90a6SLemover val num = NumPMA 56ca2f90a6SLemover require(num >= 16) 57ca2f90a6SLemover val cfg = WireInit(0.U.asTypeOf(Vec(num, new PMPConfig()))) 58ca2f90a6SLemover 59ca2f90a6SLemover val addr = Wire(Vec(num, UInt((PAddrBits-PMPOffBits).W))) 60ca2f90a6SLemover val mask = Wire(Vec(NumPMP, UInt(PAddrBits.W))) 61ca2f90a6SLemover addr := DontCare 62ca2f90a6SLemover mask := DontCare 63ca2f90a6SLemover 64*2f30d658SYinan Xu addr(15) := 0x3FFFFFFFEL.U 65*2f30d658SYinan Xu cfg(15).a := 1.U; cfg(15).r := true.B; cfg(15).w := true.B; cfg(15).x := true.B; cfg(15).c := true.B; cfg(14).atomic := true.B 66*2f30d658SYinan Xu 67ca2f90a6SLemover // use tor instead of napot, for napot may be confusing and hard to understand 68*2f30d658SYinan Xu addr(14) := shift_addr(0xFFFFFFFFFL) 69ca2f90a6SLemover cfg(14).a := 1.U; cfg(14).r := true.B; cfg(14).w := true.B; cfg(14).x := true.B; cfg(14).c := true.B; cfg(14).atomic := true.B 70ca2f90a6SLemover 71ca2f90a6SLemover addr(13) := shift_addr(0x80000000L) 72ca2f90a6SLemover cfg(13).a := 1.U; cfg(13).r := true.B; cfg(13).w := true.B 73ca2f90a6SLemover 74ca2f90a6SLemover addr(12) := shift_addr(0x3C000000) 75ca2f90a6SLemover cfg(12).a := 1.U 76ca2f90a6SLemover 77ca2f90a6SLemover addr(11) := shift_addr(0x38021000) 78ca2f90a6SLemover cfg(11).a := 1.U; cfg(11).r := true.B; cfg(11).w := true.B; cfg(11).x := true.B 79ca2f90a6SLemover 80ca2f90a6SLemover addr(10) := shift_addr(0x38020000) 81ca2f90a6SLemover cfg(10).a := 1.U; cfg(10).r := true.B; cfg(10).w := true.B 82ca2f90a6SLemover 83ca2f90a6SLemover addr(9) := shift_addr( 0x30050000) 84ca2f90a6SLemover cfg(9).a := 1.U; cfg(9).r := true.B; cfg(9).w := true.B; cfg(8).c := true.B 85ca2f90a6SLemover 86ca2f90a6SLemover addr(8) := shift_addr( 0x30010000) 87ca2f90a6SLemover cfg(8).a := 1.U; cfg(8).r := true.B; cfg(8).w := true.B 88ca2f90a6SLemover 89ca2f90a6SLemover addr(7) := shift_addr( 0x20000000) 90ca2f90a6SLemover cfg(7).a := 1.U; cfg(7).r := true.B; cfg(7).w := true.B; cfg(7).x := true.B 91ca2f90a6SLemover 92ca2f90a6SLemover addr(6) := shift_addr( 0x10000000) 93ca2f90a6SLemover cfg(6).a := 1.U; cfg(6).r := true.B; cfg(6).w := true.B 94ca2f90a6SLemover 95ca2f90a6SLemover addr(5) := shift_addr(0) 96ca2f90a6SLemover 97ca2f90a6SLemover val cfgInitMerge = cfg.asTypeOf(Vec(num/8, UInt(XLEN.W))) 98ca2f90a6SLemover (cfgInitMerge, addr, mask) 99ca2f90a6SLemover } 100ca2f90a6SLemover 101ca2f90a6SLemover def shift_addr(addr: BigInt) = { 102ca2f90a6SLemover (addr >> 2).U 103ca2f90a6SLemover } 104ca2f90a6SLemover} 105ca2f90a6SLemover 106ca2f90a6SLemovertrait PMACheckMethod extends HasXSParameter with HasCSRConst { this: PMPChecker => 107ca2f90a6SLemover def pma_check(cmd: UInt, cfg: PMPConfig) = { 108ca2f90a6SLemover val resp = Wire(new PMPRespBundle) 109ca2f90a6SLemover resp.ld := TlbCmd.isRead(cmd) && !TlbCmd.isAtom(cmd) && !cfg.r 110ca2f90a6SLemover resp.st := (TlbCmd.isWrite(cmd) || TlbCmd.isAtom(cmd) && cfg.atomic) && !cfg.w 111ca2f90a6SLemover resp.instr := TlbCmd.isExec(cmd) && !cfg.x 112ca2f90a6SLemover resp.mmio := !cfg.c 113ca2f90a6SLemover resp 114ca2f90a6SLemover } 115ca2f90a6SLemover 116ca2f90a6SLemover def pma_match_res(addr: UInt, size: UInt, pmaEntries: Vec[PMPEntry], mode: UInt, lgMaxSize: Int) = { 117ca2f90a6SLemover val num = pmaEntries.size 118ca2f90a6SLemover require(num == NumPMA) 119ca2f90a6SLemover // pma should always be checked, could not be ignored 120ca2f90a6SLemover // like amo and cached, it is the attribute not protection 121ca2f90a6SLemover // so it must have initialization. 122ca2f90a6SLemover require(!pmaEntries.isEmpty) 123ca2f90a6SLemover val default = if (pmaEntries.isEmpty) true.B else (mode > ModeS) 124ca2f90a6SLemover val pmpMinuxOne = WireInit(0.U.asTypeOf(new PMPEntry())) 125ca2f90a6SLemover 126ca2f90a6SLemover val res = pmaEntries.zip(pmpMinuxOne +: pmaEntries.take(num-1)).zipWithIndex 127ca2f90a6SLemover .reverse.foldLeft(pmpMinuxOne) { case (prev, ((pma, last_pma), i)) => 128ca2f90a6SLemover val is_match = pma.is_match(addr, size, lgMaxSize, last_pma) 129ca2f90a6SLemover val aligned = pma.aligned(addr, size, lgMaxSize, last_pma) 130ca2f90a6SLemover 131ca2f90a6SLemover val cur = WireInit(pma) 132ca2f90a6SLemover cur.cfg.r := aligned && pma.cfg.r 133ca2f90a6SLemover cur.cfg.w := aligned && pma.cfg.w 134ca2f90a6SLemover cur.cfg.x := aligned && pma.cfg.x 135ca2f90a6SLemover cur.cfg.atomic := aligned && pma.cfg.atomic 136ca2f90a6SLemover cur.cfg.c := aligned && pma.cfg.c 137ca2f90a6SLemover 138ca2f90a6SLemover Mux(is_match, cur, prev) 139ca2f90a6SLemover } 140ca2f90a6SLemover res 141ca2f90a6SLemover } 142ca2f90a6SLemover}