xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/Uncache.scala (revision 4f94c0c6a6566aaa01312dd72d05c29ac896b8ab)
11f0e2dc7SJiawei Lin/***************************************************************************************
21f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
31f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Peng Cheng Laboratory
41f0e2dc7SJiawei Lin*
51f0e2dc7SJiawei Lin* XiangShan is licensed under Mulan PSL v2.
61f0e2dc7SJiawei Lin* You can use this software according to the terms and conditions of the Mulan PSL v2.
71f0e2dc7SJiawei Lin* You may obtain a copy of Mulan PSL v2 at:
81f0e2dc7SJiawei Lin*          http://license.coscl.org.cn/MulanPSL2
91f0e2dc7SJiawei Lin*
101f0e2dc7SJiawei Lin* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
111f0e2dc7SJiawei Lin* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
121f0e2dc7SJiawei Lin* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
131f0e2dc7SJiawei Lin*
141f0e2dc7SJiawei Lin* See the Mulan PSL v2 for more details.
151f0e2dc7SJiawei Lin***************************************************************************************/
161f0e2dc7SJiawei Lin
171f0e2dc7SJiawei Linpackage xiangshan.cache
181f0e2dc7SJiawei Lin
191f0e2dc7SJiawei Linimport chisel3._
201f0e2dc7SJiawei Linimport chisel3.util._
211f0e2dc7SJiawei Linimport utils.{HasTLDump, PriorityMuxWithFlag, XSDebug}
221f0e2dc7SJiawei Linimport chipsalliance.rocketchip.config.Parameters
231f0e2dc7SJiawei Linimport freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes}
241f0e2dc7SJiawei Linimport freechips.rocketchip.tilelink.{TLArbiter, TLBundleA, TLBundleD, TLClientNode, TLEdgeOut, TLMasterParameters, TLMasterPortParameters}
251f0e2dc7SJiawei Linimport xiangshan.{MicroOp, Redirect}
261f0e2dc7SJiawei Lin
271f0e2dc7SJiawei Lin// One miss entry deals with one mmio request
281f0e2dc7SJiawei Linclass MMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule
291f0e2dc7SJiawei Lin{
301f0e2dc7SJiawei Lin  val io = IO(new Bundle {
311f0e2dc7SJiawei Lin    // MSHR ID
321f0e2dc7SJiawei Lin    val id = Input(UInt())
331f0e2dc7SJiawei Lin
341f0e2dc7SJiawei Lin    // client requests
351f0e2dc7SJiawei Lin    val req = Flipped(DecoupledIO(new DCacheWordReq ))
361f0e2dc7SJiawei Lin    val resp = DecoupledIO(new DCacheWordResp)
371f0e2dc7SJiawei Lin
381f0e2dc7SJiawei Lin    val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle))
391f0e2dc7SJiawei Lin    val mem_grant   = Flipped(DecoupledIO(new TLBundleD(edge.bundle)))
401f0e2dc7SJiawei Lin  })
411f0e2dc7SJiawei Lin
421f0e2dc7SJiawei Lin
431f0e2dc7SJiawei Lin  val s_invalid :: s_refill_req :: s_refill_resp :: s_send_resp :: Nil = Enum(4)
441f0e2dc7SJiawei Lin
451f0e2dc7SJiawei Lin  val state = RegInit(s_invalid)
461f0e2dc7SJiawei Lin
471f0e2dc7SJiawei Lin  val req       = Reg(new DCacheWordReq )
481f0e2dc7SJiawei Lin  val resp_data = Reg(UInt(DataBits.W))
491f0e2dc7SJiawei Lin
501f0e2dc7SJiawei Lin
511f0e2dc7SJiawei Lin  // assign default values to output signals
521f0e2dc7SJiawei Lin  io.req.ready           := false.B
531f0e2dc7SJiawei Lin  io.resp.valid          := false.B
541f0e2dc7SJiawei Lin  io.resp.bits           := DontCare
551f0e2dc7SJiawei Lin
561f0e2dc7SJiawei Lin  io.mem_acquire.valid   := false.B
571f0e2dc7SJiawei Lin  io.mem_acquire.bits    := DontCare
581f0e2dc7SJiawei Lin
591f0e2dc7SJiawei Lin  io.mem_grant.ready     := false.B
601f0e2dc7SJiawei Lin
611f0e2dc7SJiawei Lin
621f0e2dc7SJiawei Lin  XSDebug("entry: %d state: %d\n", io.id, state)
631f0e2dc7SJiawei Lin  // --------------------------------------------
641f0e2dc7SJiawei Lin  // s_invalid: receive requests
651f0e2dc7SJiawei Lin  when (state === s_invalid) {
661f0e2dc7SJiawei Lin    io.req.ready := true.B
671f0e2dc7SJiawei Lin
681f0e2dc7SJiawei Lin    when (io.req.fire()) {
691f0e2dc7SJiawei Lin      req   := io.req.bits
701f0e2dc7SJiawei Lin      req.addr := io.req.bits.addr
711f0e2dc7SJiawei Lin      state := s_refill_req
721f0e2dc7SJiawei Lin    }
731f0e2dc7SJiawei Lin  }
741f0e2dc7SJiawei Lin
751f0e2dc7SJiawei Lin  // --------------------------------------------
761f0e2dc7SJiawei Lin  // refill
771f0e2dc7SJiawei Lin  // TODO: determine 'lgSize' in memend
781f0e2dc7SJiawei Lin  val size = PopCount(req.mask)
791f0e2dc7SJiawei Lin  val (lgSize, legal) = PriorityMuxWithFlag(Seq(
801f0e2dc7SJiawei Lin    1.U -> 0.U,
811f0e2dc7SJiawei Lin    2.U -> 1.U,
821f0e2dc7SJiawei Lin    4.U -> 2.U,
831f0e2dc7SJiawei Lin    8.U -> 3.U
841f0e2dc7SJiawei Lin  ).map(m => (size===m._1) -> m._2))
851f0e2dc7SJiawei Lin  assert(!(io.mem_acquire.valid && !legal))
861f0e2dc7SJiawei Lin
871f0e2dc7SJiawei Lin  val load = edge.Get(
881f0e2dc7SJiawei Lin    fromSource      = io.id,
891f0e2dc7SJiawei Lin    toAddress       = req.addr,
901f0e2dc7SJiawei Lin    lgSize          = lgSize
911f0e2dc7SJiawei Lin  )._2
921f0e2dc7SJiawei Lin
931f0e2dc7SJiawei Lin  val store = edge.Put(
941f0e2dc7SJiawei Lin    fromSource      = io.id,
951f0e2dc7SJiawei Lin    toAddress = req.addr,
961f0e2dc7SJiawei Lin    lgSize  = lgSize,
971f0e2dc7SJiawei Lin    data  = req.data,
981f0e2dc7SJiawei Lin    mask = req.mask
991f0e2dc7SJiawei Lin  )._2
1001f0e2dc7SJiawei Lin
1011f0e2dc7SJiawei Lin  when (state === s_refill_req) {
1021f0e2dc7SJiawei Lin    io.mem_acquire.valid := true.B
1031f0e2dc7SJiawei Lin    io.mem_acquire.bits  := Mux(req.cmd === MemoryOpConstants.M_XWR, store, load)
1041f0e2dc7SJiawei Lin
1051f0e2dc7SJiawei Lin    when (io.mem_acquire.fire()) {
1061f0e2dc7SJiawei Lin      state := s_refill_resp
1071f0e2dc7SJiawei Lin    }
1081f0e2dc7SJiawei Lin  }
1091f0e2dc7SJiawei Lin
1101f0e2dc7SJiawei Lin  val (_, _, refill_done, _) = edge.addr_inc(io.mem_grant)
1111f0e2dc7SJiawei Lin
1121f0e2dc7SJiawei Lin  when (state === s_refill_resp) {
1131f0e2dc7SJiawei Lin    io.mem_grant.ready := true.B
1141f0e2dc7SJiawei Lin
1151f0e2dc7SJiawei Lin    when (io.mem_grant.fire()) {
1161f0e2dc7SJiawei Lin      resp_data := io.mem_grant.bits.data
1171f0e2dc7SJiawei Lin      assert(refill_done, "MMIO response should be one beat only!")
1181f0e2dc7SJiawei Lin      state := s_send_resp
1191f0e2dc7SJiawei Lin    }
1201f0e2dc7SJiawei Lin  }
1211f0e2dc7SJiawei Lin
1221f0e2dc7SJiawei Lin  // --------------------------------------------
1231f0e2dc7SJiawei Lin  when (state === s_send_resp) {
1241f0e2dc7SJiawei Lin    io.resp.valid := true.B
1251f0e2dc7SJiawei Lin    io.resp.bits.data   := resp_data
1261f0e2dc7SJiawei Lin    // meta data should go with the response
1271f0e2dc7SJiawei Lin    io.resp.bits.id     := req.id
1281f0e2dc7SJiawei Lin    io.resp.bits.miss   := false.B
1291f0e2dc7SJiawei Lin    io.resp.bits.replay := false.B
1301f0e2dc7SJiawei Lin
1311f0e2dc7SJiawei Lin    when (io.resp.fire()) {
1321f0e2dc7SJiawei Lin      state := s_invalid
1331f0e2dc7SJiawei Lin    }
1341f0e2dc7SJiawei Lin  }
1351f0e2dc7SJiawei Lin}
1361f0e2dc7SJiawei Lin
1371f0e2dc7SJiawei Linclass UncacheIO(implicit p: Parameters) extends DCacheBundle {
1381f0e2dc7SJiawei Lin  val lsq = Flipped(new DCacheWordIO)
1391f0e2dc7SJiawei Lin}
1401f0e2dc7SJiawei Lin
1411f0e2dc7SJiawei Lin// convert DCacheIO to TileLink
1421f0e2dc7SJiawei Lin// for Now, we only deal with TL-UL
1431f0e2dc7SJiawei Lin
144*4f94c0c6SJiawei Linclass Uncache()(implicit p: Parameters) extends LazyModule {
1451f0e2dc7SJiawei Lin
1461f0e2dc7SJiawei Lin  val clientParameters = TLMasterPortParameters.v1(
1471f0e2dc7SJiawei Lin    clients = Seq(TLMasterParameters.v1(
1481f0e2dc7SJiawei Lin      "uncache",
149*4f94c0c6SJiawei Lin      sourceId = IdRange(0, 1)
1501f0e2dc7SJiawei Lin    ))
1511f0e2dc7SJiawei Lin  )
1521f0e2dc7SJiawei Lin  val clientNode = TLClientNode(Seq(clientParameters))
1531f0e2dc7SJiawei Lin
1541f0e2dc7SJiawei Lin  lazy val module = new UncacheImp(this)
1551f0e2dc7SJiawei Lin
1561f0e2dc7SJiawei Lin}
1571f0e2dc7SJiawei Lin
1581f0e2dc7SJiawei Linclass UncacheImp(outer: Uncache)
1591f0e2dc7SJiawei Lin  extends LazyModuleImp(outer)
1601f0e2dc7SJiawei Lin    with HasTLDump
1611f0e2dc7SJiawei Lin{
1621f0e2dc7SJiawei Lin  val io = IO(new UncacheIO)
1631f0e2dc7SJiawei Lin
1641f0e2dc7SJiawei Lin  val (bus, edge) = outer.clientNode.out.head
1651f0e2dc7SJiawei Lin
166*4f94c0c6SJiawei Lin  val resp_arb = Module(new Arbiter(new DCacheWordResp, 1))
1671f0e2dc7SJiawei Lin
1681f0e2dc7SJiawei Lin  val req  = io.lsq.req
1691f0e2dc7SJiawei Lin  val resp = io.lsq.resp
1701f0e2dc7SJiawei Lin  val mem_acquire = bus.a
1711f0e2dc7SJiawei Lin  val mem_grant   = bus.d
1721f0e2dc7SJiawei Lin
1731f0e2dc7SJiawei Lin  val entry_alloc_idx = Wire(UInt())
1741f0e2dc7SJiawei Lin  val req_ready = WireInit(false.B)
1751f0e2dc7SJiawei Lin
1761f0e2dc7SJiawei Lin  // assign default values to output signals
1771f0e2dc7SJiawei Lin  bus.b.ready := false.B
1781f0e2dc7SJiawei Lin  bus.c.valid := false.B
1791f0e2dc7SJiawei Lin  bus.c.bits  := DontCare
1801f0e2dc7SJiawei Lin  bus.d.ready := false.B
1811f0e2dc7SJiawei Lin  bus.e.valid := false.B
1821f0e2dc7SJiawei Lin  bus.e.bits  := DontCare
1831f0e2dc7SJiawei Lin
184*4f94c0c6SJiawei Lin  //TODO: rewrite following code since we only have 1 entry
185*4f94c0c6SJiawei Lin  val entries = (0 until 1) map { i =>
1861f0e2dc7SJiawei Lin    val entry = Module(new MMIOEntry(edge))
1871f0e2dc7SJiawei Lin
188*4f94c0c6SJiawei Lin    entry.io.id := i.U(1.W)
1891f0e2dc7SJiawei Lin
1901f0e2dc7SJiawei Lin    // entry req
1911f0e2dc7SJiawei Lin    entry.io.req.valid := (i.U === entry_alloc_idx) && req.valid
1921f0e2dc7SJiawei Lin    entry.io.req.bits  := req.bits
1931f0e2dc7SJiawei Lin    when (i.U === entry_alloc_idx) {
1941f0e2dc7SJiawei Lin      req_ready := entry.io.req.ready
1951f0e2dc7SJiawei Lin    }
1961f0e2dc7SJiawei Lin
1971f0e2dc7SJiawei Lin    // entry resp
1981f0e2dc7SJiawei Lin    resp_arb.io.in(i) <> entry.io.resp
1991f0e2dc7SJiawei Lin
2001f0e2dc7SJiawei Lin    entry.io.mem_grant.valid := false.B
2011f0e2dc7SJiawei Lin    entry.io.mem_grant.bits  := DontCare
2021f0e2dc7SJiawei Lin    when (mem_grant.bits.source === i.U) {
2031f0e2dc7SJiawei Lin      entry.io.mem_grant <> mem_grant
2041f0e2dc7SJiawei Lin    }
2051f0e2dc7SJiawei Lin    entry
2061f0e2dc7SJiawei Lin  }
2071f0e2dc7SJiawei Lin
2081f0e2dc7SJiawei Lin  entry_alloc_idx    := PriorityEncoder(entries.map(m=>m.io.req.ready))
2091f0e2dc7SJiawei Lin
2101f0e2dc7SJiawei Lin  req.ready  := req_ready
2111f0e2dc7SJiawei Lin  resp          <> resp_arb.io.out
2121f0e2dc7SJiawei Lin  TLArbiter.lowestFromSeq(edge, mem_acquire, entries.map(_.io.mem_acquire))
2131f0e2dc7SJiawei Lin
2141f0e2dc7SJiawei Lin
2151f0e2dc7SJiawei Lin  // print all input/output requests for debug purpose
2161f0e2dc7SJiawei Lin
2171f0e2dc7SJiawei Lin  // print req/resp
2181f0e2dc7SJiawei Lin  XSDebug(req.fire(), "req cmd: %x addr: %x data: %x mask: %x\n",
2191f0e2dc7SJiawei Lin    req.bits.cmd, req.bits.addr, req.bits.data, req.bits.mask)
2201f0e2dc7SJiawei Lin  XSDebug(resp.fire(), "data: %x\n", req.bits.data)
2211f0e2dc7SJiawei Lin
2221f0e2dc7SJiawei Lin  // print tilelink messages
2231f0e2dc7SJiawei Lin  when(mem_acquire.valid){
2241f0e2dc7SJiawei Lin    XSDebug("mem_acquire valid, ready=%d ", mem_acquire.ready)
2251f0e2dc7SJiawei Lin    mem_acquire.bits.dump
2261f0e2dc7SJiawei Lin  }
2271f0e2dc7SJiawei Lin  when (mem_grant.fire()) {
2281f0e2dc7SJiawei Lin    XSDebug("mem_grant fire ")
2291f0e2dc7SJiawei Lin    mem_grant.bits.dump
2301f0e2dc7SJiawei Lin  }
2311f0e2dc7SJiawei Lin}
232