xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/PMAEntryModule.scala (revision 011d262c490b7fd9c718724a21daceb78ad6689a)
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