1package xiangshan.backend.fu.NewCSR 2 3import chisel3._ 4import chisel3.util._ 5import freechips.rocketchip.rocket.CSRs 6import org.chipsalliance.cde.config.Parameters 7import xiangshan.backend.fu.PMAConfigEntry 8import xiangshan.backend.fu.util.CSRConst 9import xiangshan.{HasPMParameters, PMParameKey} 10import CSRConfig._ 11 12trait PMAConst extends PMPConst 13 14abstract class PMABundle(implicit val p: Parameters) extends Bundle with PMAConst 15abstract class PMAModule(implicit val p: Parameters) extends Module with PMAConst 16 17class PMAEntryHandleModule(implicit p: Parameters) extends PMAModule with PMAInit with PMAReadWrite { 18 val io = IO(new PMAEntryHandleIOBundle) 19 20 val pmaCfg = io.in.pmaCfg 21 22 val ren = io.in.ren 23 val wen = io.in.wen 24 val addr = io.in.addr 25 val wdata = io.in.wdata 26 27 require(NumPMA >= 16, "The number of PMA should be greater than or equal to 16.") 28 29 val pmaAddrInit = VecInit(Seq.fill(p(PMParameKey).NumPMA)(0.U((PMPAddrWidth-PMPOffBits).W))) 30 val pmaMaskInit = VecInit(Seq.fill(p(PMParameKey).NumPMA)(0.U(PMPAddrWidth.W))) 31 32 pmaAddrInit.zip(pmaMaskInit).zip(pmaInit).foreach { case ((addr, mask), init) => 33 addr := genAddr(init).U((PMPAddrWidth-PMPOffBits).W) 34 mask := genMask(init.a, genAddr(init)) 35 } 36 37 val pmaAddr = RegInit(pmaAddrInit) 38 val pmaMask = RegInit(pmaMaskInit) 39 40 val pmaEntry = Wire(Vec(p(PMParameKey).NumPMA, new PMAEntry)) 41 42 for (i <- pmaEntry.indices) { 43 pmaEntry(i).gen(pmaCfg(i), pmaAddr(i), pmaMask(i)) 44 } 45 46 // write pmaCfg 47 val cfgVec = WireInit(VecInit(Seq.fill(8)(0.U.asTypeOf(new PMACfgBundle)))) 48 for (i <- 0 until (p(PMParameKey).NumPMA/8+1) by 2) { 49 when (wen && (addr === (CSRConst.PmacfgBase + i).U)) { 50 for (j <- cfgVec.indices) { 51 val cfgOldTmp = pmaEntry(8*i/2+j).cfg 52 val cfgNewTmp = Wire(new PMACfgBundle) 53 cfgNewTmp := wdata(8*(j+1)-1, 8*j) 54 cfgVec(j) := cfgOldTmp 55 when (!cfgOldTmp.L.asBool) { 56 cfgVec(j) := cfgNewTmp 57 cfgVec(j).W := cfgNewTmp.W.asBool && cfgNewTmp.R.asBool 58 if (CoarserGrain) { 59 cfgVec(j).A := Cat(cfgNewTmp.A.asUInt(1), cfgNewTmp.A.asUInt.orR) 60 } 61 when (PMPCfgAField.isNa4OrNapot(cfgVec(j))) { 62 pmaMask(8*i/2+j) := pmaEntry(8*i/2+j).matchMask(cfgVec(j), pmaEntry(8*i/2+j).addr) 63 } 64 } 65 } 66 } 67 } 68 69 io.out.pmaCfgWdata := Cat(cfgVec.map(_.asUInt).reverse) 70 71 72 val pmaAddrR = Wire(Vec(p(PMParameKey).NumPMA, UInt(64.W))) 73 74 for (i <- 0 until p(PMParameKey).NumPMA) { 75 pmaAddrR(i) := pmaEntry(i).addr 76 // write pmaAddr 77 when (wen && (addr === (CSRConst.PmaaddrBase + i).U)) { 78 if (i != (p(PMParameKey).NumPMA - 1)) { 79 val addrNextLocked: Bool = PMPCfgLField.addrLocked(pmaEntry(i).cfg, pmaEntry(i + 1).cfg) 80 pmaMask(i) := Mux(!addrNextLocked, pmaEntry(i).matchMask(wdata), pmaEntry(i).mask) 81 pmaAddr(i) := Mux(!addrNextLocked, wdata, pmaEntry(i).addr) 82 } else { 83 val addrLocked: Bool = PMPCfgLField.addrLocked(pmaEntry(i).cfg) 84 pmaMask(i) := Mux(!addrLocked, pmaEntry(i).matchMask(wdata), pmaEntry(i).mask) 85 pmaAddr(i) := Mux(!addrLocked, wdata, pmaEntry(i).addr) 86 } 87 } 88 // read pmaAddr 89 when (ren && (addr === (CSRConst.PmaaddrBase + i).U)) { 90 pmaAddrR(i) := pmaEntry(i).readAddr(pmaEntry(i).cfg, pmaEntry(i).addr) 91 } 92 } 93 94 io.out.pmaAddrRData := pmaAddrR 95 96} 97 98class PMAEntryHandleIOBundle(implicit p: Parameters) extends PMABundle { 99 val in = Input(new Bundle { 100 val wen = Bool() 101 val ren = Bool() 102 val addr = UInt(12.W) 103 val wdata = UInt(64.W) 104 val pmaCfg = Vec(NumPMA, new PMACfgBundle) 105 }) 106 107 val out = Output(new Bundle { 108 val pmaCfgWdata = UInt(PMXLEN.W) 109 val pmaAddrRData = Vec(NumPMA, UInt(64.W)) 110 }) 111} 112 113trait PMAReadWrite extends PMAConst with PMPReadWrite { 114 def shift_addr(addr: BigInt): BigInt = { 115 addr >> 2 116 } 117 118 def get_napot(base: BigInt, range: BigInt): BigInt = { 119 val PlatformGrainBytes = 1 << PlatformGrain 120 if ((base % PlatformGrainBytes) != 0) { 121 println("base: %x", base) 122 } 123 if ((range % PlatformGrainBytes) != 0) { 124 println("range: %x", range) 125 } 126 require((base % PlatformGrainBytes) == 0) 127 require((range % PlatformGrainBytes) == 0) 128 129 (base + (range/2 - 1)) >> PMPOffBits 130 } 131 132 def matchMask(cfgA0: Bool, paddr: UInt): UInt = { 133 val matchMaskCAddr = Cat(paddr, cfgA0) | (((1 << PlatformGrain) - 1) >> PMPOffBits).U((paddr.getWidth + 1).W) 134 Cat(matchMaskCAddr & (~(matchMaskCAddr + 1.U)).asUInt, ((1 << PMPOffBits) - 1).U(PMPOffBits.W)) 135 } 136 137 def readAddr(cfg: PMACfgBundle, addr: UInt): UInt = { 138 val G = PlatformGrain - PMPOffBits 139 require(G >= 0) 140 if (G == 0) { 141 addr 142 } else if (G >= 2) { 143 Mux(PMPCfgAField.isNa4OrNapot(cfg), setLowBits(addr, G-1), clearLowBits(addr, G)) 144 } else { 145 Mux(PMPCfgAField.isOffOrTor(cfg), clearLowBits(addr, G), addr) 146 } 147 } 148 149 def genAddr(init: PMAConfigEntry): BigInt = { 150 if (init.a < 2) { 151 shift_addr(init.base_addr) 152 } else { 153 get_napot(init.base_addr, init.range) 154 } 155 } 156 157 def genMask(a: BigInt, initAddr: BigInt) = { 158 val matchMaskAddr = (initAddr << 1) | (a & 0x1) | (((1 << PlatformGrain) - 1) >> PMPOffBits) 159 val mask = ((matchMaskAddr & ~(matchMaskAddr + 1)) << PMPOffBits) | ((1 << PMPOffBits) - 1) 160 mask.U(PMPAddrWidth.W) 161 } 162} 163 164class PMAEntry(implicit p: Parameters) extends PMABundle with PMAReadWrite { 165 val cfg = new PMACfgBundle 166 val addr = UInt((PMPAddrWidth-PMPOffBits).W) 167 val mask = UInt(PMPAddrBits.W) 168 169 def gen(cfg: PMACfgBundle, addr: UInt, mask: UInt) = { 170 this.cfg := cfg 171 this.addr := addr 172 this.mask := mask 173 } 174 175 def matchMask(paddr: UInt): UInt = { 176 matchMask(cfg.A.asUInt(0), paddr) 177 } 178} 179