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