19ff1c68fSsinceforYypackage xiangshan.backend.fu.NewCSR 29ff1c68fSsinceforYy 39ff1c68fSsinceforYyimport chisel3._ 49ff1c68fSsinceforYyimport chisel3.util._ 59ff1c68fSsinceforYyimport xiangshan._ 6*011d262cSZhaoyang Youimport freechips.rocketchip.rocket.CSRs 79ff1c68fSsinceforYyimport org.chipsalliance.cde.config.Parameters 89ff1c68fSsinceforYyimport xiangshan.HasPMParameters 99ff1c68fSsinceforYy 109ff1c68fSsinceforYytrait PMPConst extends HasPMParameters { 119ff1c68fSsinceforYy val PMPOffBits = 2 // minimal 4bytes 129ff1c68fSsinceforYy val CoarserGrain: Boolean = PlatformGrain > PMPOffBits 139ff1c68fSsinceforYy} 149ff1c68fSsinceforYy 159ff1c68fSsinceforYyabstract class PMPBundle(implicit val p: Parameters) extends Bundle with PMPConst 169ff1c68fSsinceforYyabstract class PMPModule(implicit val p: Parameters) extends Module with PMPConst 179ff1c68fSsinceforYy 189ff1c68fSsinceforYyclass PMPEntryHandleModule(implicit p: Parameters) extends PMPModule { 199ff1c68fSsinceforYy val io = IO(new PMPEntryHandleIOBundle) 209ff1c68fSsinceforYy 219ff1c68fSsinceforYy val pmpCfg = io.in.pmpCfg 229ff1c68fSsinceforYy val pmpAddr = io.in.pmpAddr 239ff1c68fSsinceforYy 249ff1c68fSsinceforYy val ren = io.in.ren 259ff1c68fSsinceforYy val wen = io.in.wen 269ff1c68fSsinceforYy val addr = io.in.addr 279ff1c68fSsinceforYy val wdata = io.in.wdata 289ff1c68fSsinceforYy 299ff1c68fSsinceforYy val pmpMask = RegInit(VecInit(Seq.fill(p(PMParameKey).NumPMP)(0.U(PMPAddrBits.W)))) 309ff1c68fSsinceforYy 319ff1c68fSsinceforYy val pmpEntry = Wire(Vec(p(PMParameKey).NumPMP, new PMPEntry)) 329ff1c68fSsinceforYy for (i <- pmpEntry.indices) { 3316214c85SsinceforYy pmpEntry(i).gen(pmpCfg(i), pmpAddr(i), pmpMask(i)) 349ff1c68fSsinceforYy } 359ff1c68fSsinceforYy 369ff1c68fSsinceforYy // write pmpCfg 379ff1c68fSsinceforYy val cfgVec = WireInit(VecInit(Seq.fill(8)(0.U.asTypeOf(new PMPCfgBundle)))) 389ff1c68fSsinceforYy for (i <- 0 until (p(PMParameKey).NumPMP/8+1) by 2) { 39*011d262cSZhaoyang You when (wen && (addr === (CSRs.pmpcfg0 + i).U)) { 409ff1c68fSsinceforYy for (j <- cfgVec.indices) { 419ff1c68fSsinceforYy val cfgOldTmp = pmpEntry(8*i/2+j).cfg 4216214c85SsinceforYy val cfgNewTmp = Wire(new PMPCfgBundle) 4316214c85SsinceforYy cfgNewTmp := wdata(8*(j+1)-1, 8*j) 449ff1c68fSsinceforYy cfgVec(j) := cfgOldTmp 459ff1c68fSsinceforYy when (!cfgOldTmp.L.asBool) { 469ff1c68fSsinceforYy cfgVec(j) := cfgNewTmp 479ff1c68fSsinceforYy cfgVec(j).W := cfgNewTmp.W.asBool && cfgNewTmp.R.asBool 489ff1c68fSsinceforYy if (CoarserGrain) { 499ff1c68fSsinceforYy cfgVec(j).A := Cat(cfgNewTmp.A.asUInt(1), cfgNewTmp.A.asUInt.orR) 509ff1c68fSsinceforYy } 519ff1c68fSsinceforYy when (PMPCfgAField.isNa4OrNapot(cfgVec(j))) { 529ff1c68fSsinceforYy pmpMask(8*i/2+j) := pmpEntry(8*i/2+j).matchMask(cfgVec(j), pmpEntry(8*i/2+j).addr.ADDRESS.asUInt) 539ff1c68fSsinceforYy } 549ff1c68fSsinceforYy } 559ff1c68fSsinceforYy } 569ff1c68fSsinceforYy } 579ff1c68fSsinceforYy } 589ff1c68fSsinceforYy 5916214c85SsinceforYy io.out.pmpCfgWData := Cat(cfgVec.map(_.asUInt).reverse) 609ff1c68fSsinceforYy 619ff1c68fSsinceforYy val pmpAddrW = Wire(Vec(p(PMParameKey).NumPMP, UInt(64.W))) 629ff1c68fSsinceforYy val pmpAddrR = Wire(Vec(p(PMParameKey).NumPMP, UInt(64.W))) 639ff1c68fSsinceforYy 649ff1c68fSsinceforYy for (i <- 0 until p(PMParameKey).NumPMP) { 659ff1c68fSsinceforYy pmpAddrW(i) := pmpEntry(i).addr.ADDRESS.asUInt 669ff1c68fSsinceforYy pmpAddrR(i) := pmpEntry(i).addr.ADDRESS.asUInt 679ff1c68fSsinceforYy // write pmpAddr 68*011d262cSZhaoyang You when (wen && (addr === (CSRs.pmpaddr0 + i).U)) { 699ff1c68fSsinceforYy if (i != (p(PMParameKey).NumPMP - 1)) { 709ff1c68fSsinceforYy val addrNextLocked: Bool = PMPCfgLField.addrLocked(pmpEntry(i).cfg, pmpEntry(i + 1).cfg) 719ff1c68fSsinceforYy pmpMask(i) := Mux(!addrNextLocked, pmpEntry(i).matchMask(wdata), pmpEntry(i).mask) 729ff1c68fSsinceforYy pmpAddrW(i) := Mux(!addrNextLocked, wdata, pmpEntry(i).addr.ADDRESS.asUInt) 739ff1c68fSsinceforYy } else { 749ff1c68fSsinceforYy val addrLocked: Bool = PMPCfgLField.addrLocked(pmpEntry(i).cfg) 759ff1c68fSsinceforYy pmpMask(i) := Mux(!addrLocked, pmpEntry(i).matchMask(wdata), pmpEntry(i).mask) 769ff1c68fSsinceforYy pmpAddrW(i) := Mux(!addrLocked, wdata, pmpEntry(i).addr.ADDRESS.asUInt) 779ff1c68fSsinceforYy } 789ff1c68fSsinceforYy } 799ff1c68fSsinceforYy // read pmpAddr 80*011d262cSZhaoyang You when(ren && (addr === (CSRs.pmpaddr0 + i).U)) { 819ff1c68fSsinceforYy pmpAddrR(i) := pmpEntry(i).readAddr(pmpEntry(i).cfg, pmpEntry(i).addr.ADDRESS.asUInt) 829ff1c68fSsinceforYy } 839ff1c68fSsinceforYy } 849ff1c68fSsinceforYy 859ff1c68fSsinceforYy io.out.pmpAddrWData := pmpAddrW 869ff1c68fSsinceforYy io.out.pmpAddrRData := pmpAddrR 879ff1c68fSsinceforYy 889ff1c68fSsinceforYy} 899ff1c68fSsinceforYy 909ff1c68fSsinceforYyclass PMPEntryHandleIOBundle(implicit p: Parameters) extends PMPBundle { 919ff1c68fSsinceforYy val in = Input(new Bundle { 929ff1c68fSsinceforYy val wen = Bool() 939ff1c68fSsinceforYy val ren = Bool() 949ff1c68fSsinceforYy val addr = UInt(12.W) 959ff1c68fSsinceforYy val wdata = UInt(64.W) 9616214c85SsinceforYy val pmpCfg = Vec(NumPMP, new PMPCfgBundle) 9716214c85SsinceforYy val pmpAddr = Vec(NumPMP, new PMPAddrBundle) 989ff1c68fSsinceforYy }) 999ff1c68fSsinceforYy 1009ff1c68fSsinceforYy val out = Output(new Bundle { 1019ff1c68fSsinceforYy val pmpCfgWData = UInt(PMXLEN.W) 1029ff1c68fSsinceforYy val pmpAddrRData = Vec(NumPMP, UInt(64.W)) 1039ff1c68fSsinceforYy val pmpAddrWData = Vec(NumPMP, UInt(64.W)) 1049ff1c68fSsinceforYy }) 1059ff1c68fSsinceforYy} 1069ff1c68fSsinceforYy 1079ff1c68fSsinceforYytrait PMPReadWrite extends PMPConst { 1089ff1c68fSsinceforYy def matchMask(cfg: PMPCfgBundle, paddr: UInt): UInt = { 1099ff1c68fSsinceforYy val matchMaskCAddr = Cat(paddr, cfg.A.asUInt(0)) | (((1 << PlatformGrain) - 1) >> PMPOffBits).U((paddr.getWidth + 1).W) 1109ff1c68fSsinceforYy Cat(matchMaskCAddr & (~(matchMaskCAddr + 1.U)).asUInt, ((1 << PMPOffBits) - 1).U(PMPOffBits.W)) 1119ff1c68fSsinceforYy } 1129ff1c68fSsinceforYy 1139ff1c68fSsinceforYy /** 1149ff1c68fSsinceforYy * In general, the PMP grain is 2**{G+2} bytes. when G >= 1, na4 is not selectable. 1159ff1c68fSsinceforYy * When G >= 2 and cfg.A(1) is set(then the mode is napot), the bits addr(G-2, 0) read as zeros. 1169ff1c68fSsinceforYy * When G >= 1 and cfg.A(1) is clear(the mode is off or tor), the addr(G-1, 0) read as zeros. 1179ff1c68fSsinceforYy * The low Offbits is dropped 1189ff1c68fSsinceforYy * @param cfg 1199ff1c68fSsinceforYy * @param addr 1209ff1c68fSsinceforYy * @return 1219ff1c68fSsinceforYy */ 1229ff1c68fSsinceforYy def readAddr(cfg: PMPCfgBundle, addr: UInt): UInt = { 1239ff1c68fSsinceforYy val G = PlatformGrain - PMPOffBits 1249ff1c68fSsinceforYy require(G >= 0) 1259ff1c68fSsinceforYy if (G == 0) { 1269ff1c68fSsinceforYy addr 1279ff1c68fSsinceforYy } else if (G >= 2) { 1289ff1c68fSsinceforYy Mux(PMPCfgAField.isNa4OrNapot(cfg), setLowBits(addr, G-1), clearLowBits(addr, G)) 1299ff1c68fSsinceforYy } else { // G is 1 1309ff1c68fSsinceforYy Mux(PMPCfgAField.isOffOrTor(cfg), clearLowBits(addr, G), addr) 1319ff1c68fSsinceforYy } 1329ff1c68fSsinceforYy } 1339ff1c68fSsinceforYy 1349ff1c68fSsinceforYy def setLowBits(data: UInt, num: Int): UInt = { 1359ff1c68fSsinceforYy require(num >= 0) 1369ff1c68fSsinceforYy data | ((1 << num)-1).U 1379ff1c68fSsinceforYy } 1389ff1c68fSsinceforYy 1399ff1c68fSsinceforYy /** 1409ff1c68fSsinceforYy * mask the data's low num bits (lsb) 1419ff1c68fSsinceforYy * @param data 1429ff1c68fSsinceforYy * @param num 1439ff1c68fSsinceforYy * @return 1449ff1c68fSsinceforYy */ 1459ff1c68fSsinceforYy def clearLowBits(data: UInt, num: Int): UInt = { 1469ff1c68fSsinceforYy require(num >= 0) 1479ff1c68fSsinceforYy // use Cat instead of & with mask to avoid "Signal Width" problem 1489ff1c68fSsinceforYy if (num == 0) { 1499ff1c68fSsinceforYy data 1509ff1c68fSsinceforYy } else { 1519ff1c68fSsinceforYy Cat(data(data.getWidth - 1, num), 0.U(num.W)) 1529ff1c68fSsinceforYy } 1539ff1c68fSsinceforYy } 1549ff1c68fSsinceforYy 1559ff1c68fSsinceforYy} 1569ff1c68fSsinceforYy 1579ff1c68fSsinceforYy/** 1589ff1c68fSsinceforYy * PMPEntry for outside pmp copies with one more elements mask to help napot match 1599ff1c68fSsinceforYy * TODO: make mask an element, not an method, for timing opt 1609ff1c68fSsinceforYy */ 1619ff1c68fSsinceforYyclass PMPEntry(implicit p: Parameters) extends PMPBundle with PMPReadWrite { 1629ff1c68fSsinceforYy val cfg = new PMPCfgBundle 1639ff1c68fSsinceforYy val addr = new PMPAddrBundle 1649ff1c68fSsinceforYy val mask = UInt(PMPAddrBits.W) // help to match in napot 1659ff1c68fSsinceforYy 1669ff1c68fSsinceforYy def gen(cfg: PMPCfgBundle, addr: PMPAddrBundle, mask: UInt) = { 1679ff1c68fSsinceforYy require(addr.ADDRESS.getWidth == this.addr.ADDRESS.getWidth) 1689ff1c68fSsinceforYy this.cfg := cfg 1699ff1c68fSsinceforYy this.addr.ADDRESS := addr.ADDRESS 1709ff1c68fSsinceforYy this.mask := mask 1719ff1c68fSsinceforYy } 1729ff1c68fSsinceforYy 1739ff1c68fSsinceforYy // generate match mask to help match in napot mode 1749ff1c68fSsinceforYy def matchMask(paddr: UInt): UInt = { 1759ff1c68fSsinceforYy matchMask(cfg, paddr) 1769ff1c68fSsinceforYy } 1779ff1c68fSsinceforYy}