11d8f4dcbSJay/*************************************************************************************** 21d8f4dcbSJay* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 31d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 41d8f4dcbSJay* 51d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 61d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 71d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 81d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 91d8f4dcbSJay* 101d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 111d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 121d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 131d8f4dcbSJay* 141d8f4dcbSJay* See the Mulan PSL v2 for more details. 151d8f4dcbSJay***************************************************************************************/ 161d8f4dcbSJay 171d8f4dcbSJaypackage xiangshan.frontend.icache 181d8f4dcbSJay 191d8f4dcbSJayimport chisel3._ 201d8f4dcbSJayimport chisel3.util._ 211d8f4dcbSJayimport utils._ 223c02ee8fSwakafaimport utility._ 231d8f4dcbSJayimport chipsalliance.rocketchip.config.Parameters 241d8f4dcbSJayimport freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes} 251d8f4dcbSJayimport freechips.rocketchip.tilelink.{TLArbiter, TLBundleA, TLBundleD, TLClientNode, TLEdgeOut, TLMasterParameters, TLMasterPortParameters} 261d8f4dcbSJayimport xiangshan._ 271d8f4dcbSJayimport xiangshan.frontend._ 281d8f4dcbSJay 291d8f4dcbSJayclass InsUncacheReq(implicit p: Parameters) extends ICacheBundle 301d8f4dcbSJay{ 311d8f4dcbSJay val addr = UInt(PAddrBits.W) 321d8f4dcbSJay} 331d8f4dcbSJay 341d8f4dcbSJayclass InsUncacheResp(implicit p: Parameters) extends ICacheBundle 351d8f4dcbSJay{ 361d8f4dcbSJay val data = UInt(maxInstrLen.W) 371d8f4dcbSJay} 381d8f4dcbSJay 391d8f4dcbSJay// One miss entry deals with one mmio request 401d8f4dcbSJayclass InstrMMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends XSModule with HasICacheParameters with HasIFUConst 411d8f4dcbSJay{ 421d8f4dcbSJay val io = IO(new Bundle { 431d8f4dcbSJay val id = Input(UInt(log2Up(cacheParams.nMMIOs).W)) 441d8f4dcbSJay // client requests 451d8f4dcbSJay val req = Flipped(DecoupledIO(new InsUncacheReq)) 461d8f4dcbSJay val resp = DecoupledIO(new InsUncacheResp) 471d8f4dcbSJay 481d8f4dcbSJay val mmio_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 491d8f4dcbSJay val mmio_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 501d8f4dcbSJay 511d8f4dcbSJay val flush = Input(Bool()) 521d8f4dcbSJay }) 531d8f4dcbSJay 541d8f4dcbSJay 551d8f4dcbSJay val s_invalid :: s_refill_req :: s_refill_resp :: s_send_resp :: Nil = Enum(4) 561d8f4dcbSJay 571d8f4dcbSJay val state = RegInit(s_invalid) 581d8f4dcbSJay 591d8f4dcbSJay val req = Reg(new InsUncacheReq ) 601d8f4dcbSJay val respDataReg = Reg(UInt(mmioBusWidth.W)) 611d8f4dcbSJay 621d8f4dcbSJay // assign default values to output signals 631d8f4dcbSJay io.req.ready := false.B 641d8f4dcbSJay io.resp.valid := false.B 651d8f4dcbSJay io.resp.bits := DontCare 661d8f4dcbSJay 671d8f4dcbSJay io.mmio_acquire.valid := false.B 681d8f4dcbSJay io.mmio_acquire.bits := DontCare 691d8f4dcbSJay 701d8f4dcbSJay io.mmio_grant.ready := false.B 711d8f4dcbSJay 721d8f4dcbSJay val needFlush = RegInit(false.B) 731d8f4dcbSJay 741d8f4dcbSJay when(io.flush && (state =/= s_invalid) && (state =/= s_send_resp)){ needFlush := true.B } 751d8f4dcbSJay .elsewhen((state=== s_send_resp) && needFlush){ needFlush := false.B } 761d8f4dcbSJay 771d8f4dcbSJay // -------------------------------------------- 781d8f4dcbSJay // s_invalid: receive requests 791d8f4dcbSJay when (state === s_invalid) { 801d8f4dcbSJay io.req.ready := true.B 811d8f4dcbSJay 821d8f4dcbSJay when (io.req.fire()) { 831d8f4dcbSJay req := io.req.bits 841d8f4dcbSJay state := s_refill_req 851d8f4dcbSJay } 861d8f4dcbSJay } 871d8f4dcbSJay 881d8f4dcbSJay 891d8f4dcbSJay when (state === s_refill_req) { 901d8f4dcbSJay val address_aligned = req.addr(req.addr.getWidth - 1, log2Ceil(mmioBusBytes)) 911d8f4dcbSJay io.mmio_acquire.valid := true.B 921d8f4dcbSJay io.mmio_acquire.bits := edge.Get( 931d8f4dcbSJay fromSource = io.id, 941d8f4dcbSJay toAddress = Cat(address_aligned, 0.U(log2Ceil(mmioBusBytes).W)), 951d8f4dcbSJay lgSize = log2Ceil(mmioBusBytes).U 961d8f4dcbSJay )._2 971d8f4dcbSJay 981d8f4dcbSJay when (io.mmio_acquire.fire()) { 991d8f4dcbSJay state := s_refill_resp 1001d8f4dcbSJay } 1011d8f4dcbSJay } 1021d8f4dcbSJay 1031d8f4dcbSJay val (_, _, refill_done, _) = edge.addr_inc(io.mmio_grant) 1041d8f4dcbSJay 1051d8f4dcbSJay when (state === s_refill_resp) { 1061d8f4dcbSJay io.mmio_grant.ready := true.B 1071d8f4dcbSJay 1081d8f4dcbSJay when (io.mmio_grant.fire()) { 1091d8f4dcbSJay respDataReg := io.mmio_grant.bits.data 1101d8f4dcbSJay state := s_send_resp 1111d8f4dcbSJay } 1121d8f4dcbSJay } 1131d8f4dcbSJay 1141d8f4dcbSJay def getDataFromBus(pc: UInt) = { 1151d8f4dcbSJay val respData = Wire(UInt(maxInstrLen.W)) 1161d8f4dcbSJay respData := Mux(pc(2,1) === "b00".U, respDataReg(31,0), 1171d8f4dcbSJay Mux(pc(2,1) === "b01".U, respDataReg(47,16), 1181d8f4dcbSJay Mux(pc(2,1) === "b10".U, respDataReg(63,32), 1191d8f4dcbSJay Cat(0.U, respDataReg(63,48)) 1201d8f4dcbSJay ) 1211d8f4dcbSJay ) 1221d8f4dcbSJay ) 1231d8f4dcbSJay respData 1241d8f4dcbSJay } 1251d8f4dcbSJay 1261d8f4dcbSJay when (state === s_send_resp) { 1271d8f4dcbSJay io.resp.valid := !needFlush 1281d8f4dcbSJay io.resp.bits.data := getDataFromBus(req.addr) 1291d8f4dcbSJay // meta data should go with the response 1301d8f4dcbSJay when (io.resp.fire() || needFlush) { 1311d8f4dcbSJay state := s_invalid 1321d8f4dcbSJay } 1331d8f4dcbSJay } 1341d8f4dcbSJay} 1351d8f4dcbSJay 1361d8f4dcbSJayclass InstrUncacheIO(implicit p: Parameters) extends ICacheBundle { 1371d8f4dcbSJay val req = Flipped(DecoupledIO(new InsUncacheReq )) 1381d8f4dcbSJay val resp = DecoupledIO(new InsUncacheResp) 1391d8f4dcbSJay val flush = Input(Bool()) 1401d8f4dcbSJay} 1411d8f4dcbSJay 1421d8f4dcbSJayclass InstrUncache()(implicit p: Parameters) extends LazyModule with HasICacheParameters { 143*95e60e55STang Haojin override def shouldBeInlined: Boolean = false 1441d8f4dcbSJay 1451d8f4dcbSJay val clientParameters = TLMasterPortParameters.v1( 1461d8f4dcbSJay clients = Seq(TLMasterParameters.v1( 1471d8f4dcbSJay "InstrUncache", 1481d8f4dcbSJay sourceId = IdRange(0, cacheParams.nMMIOs) 1491d8f4dcbSJay )) 1501d8f4dcbSJay ) 1511d8f4dcbSJay val clientNode = TLClientNode(Seq(clientParameters)) 1521d8f4dcbSJay 1531d8f4dcbSJay lazy val module = new InstrUncacheImp(this) 1541d8f4dcbSJay 1551d8f4dcbSJay} 1561d8f4dcbSJay 1571d8f4dcbSJayclass InstrUncacheImp(outer: InstrUncache) 1581d8f4dcbSJay extends LazyModuleImp(outer) 1591d8f4dcbSJay with HasICacheParameters 1601d8f4dcbSJay with HasTLDump 1611d8f4dcbSJay{ 1621d8f4dcbSJay val io = IO(new InstrUncacheIO) 1631d8f4dcbSJay 1641d8f4dcbSJay val (bus, edge) = outer.clientNode.out.head 1651d8f4dcbSJay 1661d8f4dcbSJay val resp_arb = Module(new Arbiter(new InsUncacheResp, cacheParams.nMMIOs)) 1671d8f4dcbSJay 1681d8f4dcbSJay val req = io.req 1691d8f4dcbSJay val resp = io.resp 1701d8f4dcbSJay val mmio_acquire = bus.a 1711d8f4dcbSJay val mmio_grant = bus.d 1721d8f4dcbSJay 1731d8f4dcbSJay val entry_alloc_idx = Wire(UInt()) 1741d8f4dcbSJay val req_ready = WireInit(false.B) 1751d8f4dcbSJay 1761d8f4dcbSJay // assign default values to output signals 1771d8f4dcbSJay bus.b.ready := false.B 1781d8f4dcbSJay bus.c.valid := false.B 1791d8f4dcbSJay bus.c.bits := DontCare 1801d8f4dcbSJay bus.d.ready := false.B 1811d8f4dcbSJay bus.e.valid := false.B 1821d8f4dcbSJay bus.e.bits := DontCare 1831d8f4dcbSJay 1841d8f4dcbSJay val entries = (0 until cacheParams.nMMIOs) map { i => 1851d8f4dcbSJay val entry = Module(new InstrMMIOEntry(edge)) 1861d8f4dcbSJay 1871d8f4dcbSJay entry.io.id := i.U(log2Up(cacheParams.nMMIOs).W) 1881d8f4dcbSJay entry.io.flush := io.flush 1891d8f4dcbSJay 1901d8f4dcbSJay // entry req 1911d8f4dcbSJay entry.io.req.valid := (i.U === entry_alloc_idx) && req.valid 1921d8f4dcbSJay entry.io.req.bits := req.bits 1931d8f4dcbSJay when (i.U === entry_alloc_idx) { 1941d8f4dcbSJay req_ready := entry.io.req.ready 1951d8f4dcbSJay } 1961d8f4dcbSJay 1971d8f4dcbSJay // entry resp 1981d8f4dcbSJay resp_arb.io.in(i) <> entry.io.resp 1991d8f4dcbSJay 2001d8f4dcbSJay entry.io.mmio_grant.valid := false.B 2011d8f4dcbSJay entry.io.mmio_grant.bits := DontCare 2021d8f4dcbSJay when (mmio_grant.bits.source === i.U) { 2031d8f4dcbSJay entry.io.mmio_grant <> mmio_grant 2041d8f4dcbSJay } 2051d8f4dcbSJay entry 2061d8f4dcbSJay } 2071d8f4dcbSJay 2081d8f4dcbSJay entry_alloc_idx := PriorityEncoder(entries.map(m=>m.io.req.ready)) 2091d8f4dcbSJay 2101d8f4dcbSJay req.ready := req_ready 2111d8f4dcbSJay resp <> resp_arb.io.out 2121d8f4dcbSJay TLArbiter.lowestFromSeq(edge, mmio_acquire, entries.map(_.io.mmio_acquire)) 2131d8f4dcbSJay 2141d8f4dcbSJay} 215