11d8f4dcbSJay/*************************************************************************************** 26c106319Sxu_zh* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 36c106319Sxu_zh* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 41d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 51d8f4dcbSJay* 61d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 71d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 81d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 91d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 101d8f4dcbSJay* 111d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 121d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 131d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 141d8f4dcbSJay* 151d8f4dcbSJay* See the Mulan PSL v2 for more details. 161d8f4dcbSJay***************************************************************************************/ 171d8f4dcbSJay 181d8f4dcbSJaypackage xiangshan.frontend.icache 191d8f4dcbSJay 201d8f4dcbSJayimport chisel3._ 211d8f4dcbSJayimport chisel3.util._ 22cf7d6b7aSMuziimport freechips.rocketchip.diplomacy.IdRange 23cf7d6b7aSMuziimport freechips.rocketchip.diplomacy.LazyModule 24cf7d6b7aSMuziimport freechips.rocketchip.diplomacy.LazyModuleImp 25cf7d6b7aSMuziimport freechips.rocketchip.tilelink.TLArbiter 26cf7d6b7aSMuziimport freechips.rocketchip.tilelink.TLBundleA 27cf7d6b7aSMuziimport freechips.rocketchip.tilelink.TLBundleD 28cf7d6b7aSMuziimport freechips.rocketchip.tilelink.TLClientNode 29cf7d6b7aSMuziimport freechips.rocketchip.tilelink.TLEdgeOut 30cf7d6b7aSMuziimport freechips.rocketchip.tilelink.TLMasterParameters 31cf7d6b7aSMuziimport freechips.rocketchip.tilelink.TLMasterPortParameters 328891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 33cf7d6b7aSMuziimport utils._ 341d8f4dcbSJayimport xiangshan.frontend._ 351d8f4dcbSJay 36cf7d6b7aSMuziclass InsUncacheReq(implicit p: Parameters) extends ICacheBundle { 37415fcbe2Sxu_zh val addr: UInt = UInt(PAddrBits.W) 381d8f4dcbSJay} 391d8f4dcbSJay 40cf7d6b7aSMuziclass InsUncacheResp(implicit p: Parameters) extends ICacheBundle { 41415fcbe2Sxu_zh val data: UInt = UInt(maxInstrLen.W) 42*dfb03ba2Sxu_zh val corrupt: Bool = Bool() 43415fcbe2Sxu_zh} 44415fcbe2Sxu_zh 45415fcbe2Sxu_zhclass InstrMMIOEntryIO(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { 46415fcbe2Sxu_zh val id: UInt = Input(UInt(log2Up(cacheParams.nMMIOs).W)) 47415fcbe2Sxu_zh // client requests 48415fcbe2Sxu_zh val req: DecoupledIO[InsUncacheReq] = Flipped(DecoupledIO(new InsUncacheReq)) 49415fcbe2Sxu_zh val resp: DecoupledIO[InsUncacheResp] = DecoupledIO(new InsUncacheResp) 50415fcbe2Sxu_zh 51415fcbe2Sxu_zh val mmio_acquire: DecoupledIO[TLBundleA] = DecoupledIO(new TLBundleA(edge.bundle)) 52415fcbe2Sxu_zh val mmio_grant: DecoupledIO[TLBundleD] = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 53415fcbe2Sxu_zh 54415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 551d8f4dcbSJay} 561d8f4dcbSJay 571d8f4dcbSJay// One miss entry deals with one mmio request 58415fcbe2Sxu_zhclass InstrMMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModule with HasIFUConst { 59415fcbe2Sxu_zh val io: InstrMMIOEntryIO = IO(new InstrMMIOEntryIO(edge)) 601d8f4dcbSJay 61415fcbe2Sxu_zh private val s_invalid :: s_refill_req :: s_refill_resp :: s_send_resp :: Nil = Enum(4) 621d8f4dcbSJay 63415fcbe2Sxu_zh private val state = RegInit(s_invalid) 641d8f4dcbSJay 65415fcbe2Sxu_zh private val req = Reg(new InsUncacheReq) 66*dfb03ba2Sxu_zh private val respDataReg = RegInit(0.U(mmioBusWidth.W)) 67*dfb03ba2Sxu_zh private val respCorruptReg = RegInit(false.B) 681d8f4dcbSJay 691d8f4dcbSJay // assign default values to output signals 701d8f4dcbSJay io.req.ready := false.B 711d8f4dcbSJay io.resp.valid := false.B 721d8f4dcbSJay io.resp.bits := DontCare 731d8f4dcbSJay 741d8f4dcbSJay io.mmio_acquire.valid := false.B 751d8f4dcbSJay io.mmio_acquire.bits := DontCare 761d8f4dcbSJay 771d8f4dcbSJay io.mmio_grant.ready := false.B 781d8f4dcbSJay 79415fcbe2Sxu_zh private val needFlush = RegInit(false.B) 801d8f4dcbSJay 81cf7d6b7aSMuzi when(io.flush && (state =/= s_invalid) && (state =/= s_send_resp))(needFlush := true.B) 82cf7d6b7aSMuzi .elsewhen((state === s_send_resp) && needFlush)(needFlush := false.B) 831d8f4dcbSJay 841d8f4dcbSJay // -------------------------------------------- 851d8f4dcbSJay // s_invalid: receive requests 861d8f4dcbSJay when(state === s_invalid) { 871d8f4dcbSJay io.req.ready := true.B 881d8f4dcbSJay 89935edac4STang Haojin when(io.req.fire) { 901d8f4dcbSJay req := io.req.bits 911d8f4dcbSJay state := s_refill_req 921d8f4dcbSJay } 931d8f4dcbSJay } 941d8f4dcbSJay 951d8f4dcbSJay when(state === s_refill_req) { 961d8f4dcbSJay val address_aligned = req.addr(req.addr.getWidth - 1, log2Ceil(mmioBusBytes)) 971d8f4dcbSJay io.mmio_acquire.valid := true.B 981d8f4dcbSJay io.mmio_acquire.bits := edge.Get( 991d8f4dcbSJay fromSource = io.id, 1001d8f4dcbSJay toAddress = Cat(address_aligned, 0.U(log2Ceil(mmioBusBytes).W)), 1011d8f4dcbSJay lgSize = log2Ceil(mmioBusBytes).U 1021d8f4dcbSJay )._2 1031d8f4dcbSJay 104935edac4STang Haojin when(io.mmio_acquire.fire) { 1051d8f4dcbSJay state := s_refill_resp 1061d8f4dcbSJay } 1071d8f4dcbSJay } 1081d8f4dcbSJay 1091d8f4dcbSJay val (_, _, refill_done, _) = edge.addr_inc(io.mmio_grant) 1101d8f4dcbSJay 1111d8f4dcbSJay when(state === s_refill_resp) { 1121d8f4dcbSJay io.mmio_grant.ready := true.B 1131d8f4dcbSJay 114935edac4STang Haojin when(io.mmio_grant.fire) { 1151d8f4dcbSJay respDataReg := io.mmio_grant.bits.data 116*dfb03ba2Sxu_zh respCorruptReg := io.mmio_grant.bits.corrupt // this includes bits.denied, as tilelink spec defines 1171d8f4dcbSJay state := s_send_resp 1181d8f4dcbSJay } 1191d8f4dcbSJay } 1201d8f4dcbSJay 121415fcbe2Sxu_zh private def getDataFromBus(pc: UInt): UInt = { 1221d8f4dcbSJay val respData = Wire(UInt(maxInstrLen.W)) 123cf7d6b7aSMuzi respData := Mux( 124cf7d6b7aSMuzi pc(2, 1) === "b00".U, 125cf7d6b7aSMuzi respDataReg(31, 0), 126cf7d6b7aSMuzi Mux( 127cf7d6b7aSMuzi pc(2, 1) === "b01".U, 128cf7d6b7aSMuzi respDataReg(47, 16), 129cf7d6b7aSMuzi Mux(pc(2, 1) === "b10".U, respDataReg(63, 32), Cat(0.U, respDataReg(63, 48))) 1301d8f4dcbSJay ) 1311d8f4dcbSJay ) 1321d8f4dcbSJay respData 1331d8f4dcbSJay } 1341d8f4dcbSJay 1351d8f4dcbSJay when(state === s_send_resp) { 1361d8f4dcbSJay io.resp.valid := !needFlush 1371d8f4dcbSJay io.resp.bits.data := getDataFromBus(req.addr) 138*dfb03ba2Sxu_zh io.resp.bits.corrupt := respCorruptReg 1391d8f4dcbSJay // metadata should go with the response 140935edac4STang Haojin when(io.resp.fire || needFlush) { 1411d8f4dcbSJay state := s_invalid 1421d8f4dcbSJay } 1431d8f4dcbSJay } 1441d8f4dcbSJay} 1451d8f4dcbSJay 1461d8f4dcbSJayclass InstrUncacheIO(implicit p: Parameters) extends ICacheBundle { 147415fcbe2Sxu_zh val req: DecoupledIO[InsUncacheReq] = Flipped(DecoupledIO(new InsUncacheReq)) 148415fcbe2Sxu_zh val resp: DecoupledIO[InsUncacheResp] = DecoupledIO(new InsUncacheResp) 149415fcbe2Sxu_zh val flush: Bool = Input(Bool()) 1501d8f4dcbSJay} 1511d8f4dcbSJay 1521d8f4dcbSJayclass InstrUncache()(implicit p: Parameters) extends LazyModule with HasICacheParameters { 15395e60e55STang Haojin override def shouldBeInlined: Boolean = false 1541d8f4dcbSJay 155415fcbe2Sxu_zh val clientParameters: TLMasterPortParameters = TLMasterPortParameters.v1( 1561d8f4dcbSJay clients = Seq(TLMasterParameters.v1( 1571d8f4dcbSJay "InstrUncache", 1581d8f4dcbSJay sourceId = IdRange(0, cacheParams.nMMIOs) 1591d8f4dcbSJay )) 1601d8f4dcbSJay ) 161415fcbe2Sxu_zh val clientNode: TLClientNode = TLClientNode(Seq(clientParameters)) 1621d8f4dcbSJay 163415fcbe2Sxu_zh lazy val module: InstrUncacheImp = new InstrUncacheImp(this) 1641d8f4dcbSJay} 1651d8f4dcbSJay 1661d8f4dcbSJayclass InstrUncacheImp(outer: InstrUncache) 1671d8f4dcbSJay extends LazyModuleImp(outer) 1681d8f4dcbSJay with HasICacheParameters 169cf7d6b7aSMuzi with HasTLDump { 170415fcbe2Sxu_zh val io: InstrUncacheIO = IO(new InstrUncacheIO) 1711d8f4dcbSJay 172415fcbe2Sxu_zh private val (bus, edge) = outer.clientNode.out.head 1731d8f4dcbSJay 174415fcbe2Sxu_zh private val resp_arb = Module(new Arbiter(new InsUncacheResp, cacheParams.nMMIOs)) 1751d8f4dcbSJay 176415fcbe2Sxu_zh private val req = io.req 177415fcbe2Sxu_zh private val resp = io.resp 178415fcbe2Sxu_zh private val mmio_acquire = bus.a 179415fcbe2Sxu_zh private val mmio_grant = bus.d 1801d8f4dcbSJay 181415fcbe2Sxu_zh private val entry_alloc_idx = Wire(UInt()) 182415fcbe2Sxu_zh private val req_ready = WireInit(false.B) 1831d8f4dcbSJay 1841d8f4dcbSJay // assign default values to output signals 1851d8f4dcbSJay bus.b.ready := false.B 1861d8f4dcbSJay bus.c.valid := false.B 1871d8f4dcbSJay bus.c.bits := DontCare 1881d8f4dcbSJay bus.d.ready := false.B 1891d8f4dcbSJay bus.e.valid := false.B 1901d8f4dcbSJay bus.e.bits := DontCare 1911d8f4dcbSJay 192415fcbe2Sxu_zh private val entries = (0 until cacheParams.nMMIOs).map { i => 1931d8f4dcbSJay val entry = Module(new InstrMMIOEntry(edge)) 1941d8f4dcbSJay 1951d8f4dcbSJay entry.io.id := i.U(log2Up(cacheParams.nMMIOs).W) 1961d8f4dcbSJay entry.io.flush := io.flush 1971d8f4dcbSJay 1981d8f4dcbSJay // entry req 1991d8f4dcbSJay entry.io.req.valid := (i.U === entry_alloc_idx) && req.valid 2001d8f4dcbSJay entry.io.req.bits := req.bits 2011d8f4dcbSJay when(i.U === entry_alloc_idx) { 2021d8f4dcbSJay req_ready := entry.io.req.ready 2031d8f4dcbSJay } 2041d8f4dcbSJay 2051d8f4dcbSJay // entry resp 2061d8f4dcbSJay resp_arb.io.in(i) <> entry.io.resp 2071d8f4dcbSJay 2081d8f4dcbSJay entry.io.mmio_grant.valid := false.B 2091d8f4dcbSJay entry.io.mmio_grant.bits := DontCare 2101d8f4dcbSJay when(mmio_grant.bits.source === i.U) { 2111d8f4dcbSJay entry.io.mmio_grant <> mmio_grant 2121d8f4dcbSJay } 2131d8f4dcbSJay entry 2141d8f4dcbSJay } 2151d8f4dcbSJay 216*dfb03ba2Sxu_zh // override mmio_grant.ready to prevent x-propagation 217*dfb03ba2Sxu_zh mmio_grant.ready := true.B 218*dfb03ba2Sxu_zh 2191d8f4dcbSJay entry_alloc_idx := PriorityEncoder(entries.map(m => m.io.req.ready)) 2201d8f4dcbSJay 2211d8f4dcbSJay req.ready := req_ready 2221d8f4dcbSJay resp <> resp_arb.io.out 2231d8f4dcbSJay TLArbiter.lowestFromSeq(edge, mmio_acquire, entries.map(_.io.mmio_acquire)) 2241d8f4dcbSJay} 225