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