1*1d8f4dcbSJay/*************************************************************************************** 2*1d8f4dcbSJay* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*1d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*1d8f4dcbSJay* 5*1d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 6*1d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*1d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 8*1d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 9*1d8f4dcbSJay* 10*1d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*1d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*1d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*1d8f4dcbSJay* 14*1d8f4dcbSJay* See the Mulan PSL v2 for more details. 15*1d8f4dcbSJay***************************************************************************************/ 16*1d8f4dcbSJay 17*1d8f4dcbSJaypackage xiangshan.frontend.icache 18*1d8f4dcbSJay 19*1d8f4dcbSJayimport chisel3._ 20*1d8f4dcbSJayimport chisel3.util._ 21*1d8f4dcbSJayimport utils._ 22*1d8f4dcbSJayimport chipsalliance.rocketchip.config.Parameters 23*1d8f4dcbSJayimport freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes} 24*1d8f4dcbSJayimport freechips.rocketchip.tilelink.{TLArbiter, TLBundleA, TLBundleD, TLClientNode, TLEdgeOut, TLMasterParameters, TLMasterPortParameters} 25*1d8f4dcbSJayimport xiangshan._ 26*1d8f4dcbSJayimport xiangshan.frontend._ 27*1d8f4dcbSJay 28*1d8f4dcbSJayclass InsUncacheReq(implicit p: Parameters) extends ICacheBundle 29*1d8f4dcbSJay{ 30*1d8f4dcbSJay val addr = UInt(PAddrBits.W) 31*1d8f4dcbSJay} 32*1d8f4dcbSJay 33*1d8f4dcbSJayclass InsUncacheResp(implicit p: Parameters) extends ICacheBundle 34*1d8f4dcbSJay{ 35*1d8f4dcbSJay val data = UInt(maxInstrLen.W) 36*1d8f4dcbSJay} 37*1d8f4dcbSJay 38*1d8f4dcbSJay// One miss entry deals with one mmio request 39*1d8f4dcbSJayclass InstrMMIOEntry(edge: TLEdgeOut)(implicit p: Parameters) extends XSModule with HasICacheParameters with HasIFUConst 40*1d8f4dcbSJay{ 41*1d8f4dcbSJay val io = IO(new Bundle { 42*1d8f4dcbSJay val id = Input(UInt(log2Up(cacheParams.nMMIOs).W)) 43*1d8f4dcbSJay // client requests 44*1d8f4dcbSJay val req = Flipped(DecoupledIO(new InsUncacheReq)) 45*1d8f4dcbSJay val resp = DecoupledIO(new InsUncacheResp) 46*1d8f4dcbSJay 47*1d8f4dcbSJay val mmio_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 48*1d8f4dcbSJay val mmio_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 49*1d8f4dcbSJay 50*1d8f4dcbSJay val flush = Input(Bool()) 51*1d8f4dcbSJay }) 52*1d8f4dcbSJay 53*1d8f4dcbSJay 54*1d8f4dcbSJay val s_invalid :: s_refill_req :: s_refill_resp :: s_send_resp :: Nil = Enum(4) 55*1d8f4dcbSJay 56*1d8f4dcbSJay val state = RegInit(s_invalid) 57*1d8f4dcbSJay 58*1d8f4dcbSJay val req = Reg(new InsUncacheReq ) 59*1d8f4dcbSJay val respDataReg = Reg(UInt(mmioBusWidth.W)) 60*1d8f4dcbSJay 61*1d8f4dcbSJay // assign default values to output signals 62*1d8f4dcbSJay io.req.ready := false.B 63*1d8f4dcbSJay io.resp.valid := false.B 64*1d8f4dcbSJay io.resp.bits := DontCare 65*1d8f4dcbSJay 66*1d8f4dcbSJay io.mmio_acquire.valid := false.B 67*1d8f4dcbSJay io.mmio_acquire.bits := DontCare 68*1d8f4dcbSJay 69*1d8f4dcbSJay io.mmio_grant.ready := false.B 70*1d8f4dcbSJay 71*1d8f4dcbSJay val needFlush = RegInit(false.B) 72*1d8f4dcbSJay 73*1d8f4dcbSJay when(io.flush && (state =/= s_invalid) && (state =/= s_send_resp)){ needFlush := true.B } 74*1d8f4dcbSJay .elsewhen((state=== s_send_resp) && needFlush){ needFlush := false.B } 75*1d8f4dcbSJay 76*1d8f4dcbSJay // -------------------------------------------- 77*1d8f4dcbSJay // s_invalid: receive requests 78*1d8f4dcbSJay when (state === s_invalid) { 79*1d8f4dcbSJay io.req.ready := true.B 80*1d8f4dcbSJay 81*1d8f4dcbSJay when (io.req.fire()) { 82*1d8f4dcbSJay req := io.req.bits 83*1d8f4dcbSJay state := s_refill_req 84*1d8f4dcbSJay } 85*1d8f4dcbSJay } 86*1d8f4dcbSJay 87*1d8f4dcbSJay 88*1d8f4dcbSJay when (state === s_refill_req) { 89*1d8f4dcbSJay val address_aligned = req.addr(req.addr.getWidth - 1, log2Ceil(mmioBusBytes)) 90*1d8f4dcbSJay io.mmio_acquire.valid := true.B 91*1d8f4dcbSJay io.mmio_acquire.bits := edge.Get( 92*1d8f4dcbSJay fromSource = io.id, 93*1d8f4dcbSJay toAddress = Cat(address_aligned, 0.U(log2Ceil(mmioBusBytes).W)), 94*1d8f4dcbSJay lgSize = log2Ceil(mmioBusBytes).U 95*1d8f4dcbSJay )._2 96*1d8f4dcbSJay 97*1d8f4dcbSJay when (io.mmio_acquire.fire()) { 98*1d8f4dcbSJay state := s_refill_resp 99*1d8f4dcbSJay } 100*1d8f4dcbSJay } 101*1d8f4dcbSJay 102*1d8f4dcbSJay val (_, _, refill_done, _) = edge.addr_inc(io.mmio_grant) 103*1d8f4dcbSJay 104*1d8f4dcbSJay when (state === s_refill_resp) { 105*1d8f4dcbSJay io.mmio_grant.ready := true.B 106*1d8f4dcbSJay 107*1d8f4dcbSJay when (io.mmio_grant.fire()) { 108*1d8f4dcbSJay respDataReg := io.mmio_grant.bits.data 109*1d8f4dcbSJay state := s_send_resp 110*1d8f4dcbSJay } 111*1d8f4dcbSJay } 112*1d8f4dcbSJay 113*1d8f4dcbSJay def getDataFromBus(pc: UInt) = { 114*1d8f4dcbSJay val respData = Wire(UInt(maxInstrLen.W)) 115*1d8f4dcbSJay respData := Mux(pc(2,1) === "b00".U, respDataReg(31,0), 116*1d8f4dcbSJay Mux(pc(2,1) === "b01".U, respDataReg(47,16), 117*1d8f4dcbSJay Mux(pc(2,1) === "b10".U, respDataReg(63,32), 118*1d8f4dcbSJay Cat(0.U, respDataReg(63,48)) 119*1d8f4dcbSJay ) 120*1d8f4dcbSJay ) 121*1d8f4dcbSJay ) 122*1d8f4dcbSJay respData 123*1d8f4dcbSJay } 124*1d8f4dcbSJay 125*1d8f4dcbSJay when (state === s_send_resp) { 126*1d8f4dcbSJay io.resp.valid := !needFlush 127*1d8f4dcbSJay io.resp.bits.data := getDataFromBus(req.addr) 128*1d8f4dcbSJay // meta data should go with the response 129*1d8f4dcbSJay when (io.resp.fire() || needFlush) { 130*1d8f4dcbSJay state := s_invalid 131*1d8f4dcbSJay } 132*1d8f4dcbSJay } 133*1d8f4dcbSJay} 134*1d8f4dcbSJay 135*1d8f4dcbSJayclass InstrUncacheIO(implicit p: Parameters) extends ICacheBundle { 136*1d8f4dcbSJay val req = Flipped(DecoupledIO(new InsUncacheReq )) 137*1d8f4dcbSJay val resp = DecoupledIO(new InsUncacheResp) 138*1d8f4dcbSJay val flush = Input(Bool()) 139*1d8f4dcbSJay} 140*1d8f4dcbSJay 141*1d8f4dcbSJayclass InstrUncache()(implicit p: Parameters) extends LazyModule with HasICacheParameters { 142*1d8f4dcbSJay 143*1d8f4dcbSJay val clientParameters = TLMasterPortParameters.v1( 144*1d8f4dcbSJay clients = Seq(TLMasterParameters.v1( 145*1d8f4dcbSJay "InstrUncache", 146*1d8f4dcbSJay sourceId = IdRange(0, cacheParams.nMMIOs) 147*1d8f4dcbSJay )) 148*1d8f4dcbSJay ) 149*1d8f4dcbSJay val clientNode = TLClientNode(Seq(clientParameters)) 150*1d8f4dcbSJay 151*1d8f4dcbSJay lazy val module = new InstrUncacheImp(this) 152*1d8f4dcbSJay 153*1d8f4dcbSJay} 154*1d8f4dcbSJay 155*1d8f4dcbSJayclass InstrUncacheImp(outer: InstrUncache) 156*1d8f4dcbSJay extends LazyModuleImp(outer) 157*1d8f4dcbSJay with HasICacheParameters 158*1d8f4dcbSJay with HasTLDump 159*1d8f4dcbSJay{ 160*1d8f4dcbSJay val io = IO(new InstrUncacheIO) 161*1d8f4dcbSJay 162*1d8f4dcbSJay val (bus, edge) = outer.clientNode.out.head 163*1d8f4dcbSJay 164*1d8f4dcbSJay val resp_arb = Module(new Arbiter(new InsUncacheResp, cacheParams.nMMIOs)) 165*1d8f4dcbSJay 166*1d8f4dcbSJay val req = io.req 167*1d8f4dcbSJay val resp = io.resp 168*1d8f4dcbSJay val mmio_acquire = bus.a 169*1d8f4dcbSJay val mmio_grant = bus.d 170*1d8f4dcbSJay 171*1d8f4dcbSJay val entry_alloc_idx = Wire(UInt()) 172*1d8f4dcbSJay val req_ready = WireInit(false.B) 173*1d8f4dcbSJay 174*1d8f4dcbSJay // assign default values to output signals 175*1d8f4dcbSJay bus.b.ready := false.B 176*1d8f4dcbSJay bus.c.valid := false.B 177*1d8f4dcbSJay bus.c.bits := DontCare 178*1d8f4dcbSJay bus.d.ready := false.B 179*1d8f4dcbSJay bus.e.valid := false.B 180*1d8f4dcbSJay bus.e.bits := DontCare 181*1d8f4dcbSJay 182*1d8f4dcbSJay val entries = (0 until cacheParams.nMMIOs) map { i => 183*1d8f4dcbSJay val entry = Module(new InstrMMIOEntry(edge)) 184*1d8f4dcbSJay 185*1d8f4dcbSJay entry.io.id := i.U(log2Up(cacheParams.nMMIOs).W) 186*1d8f4dcbSJay entry.io.flush := io.flush 187*1d8f4dcbSJay 188*1d8f4dcbSJay // entry req 189*1d8f4dcbSJay entry.io.req.valid := (i.U === entry_alloc_idx) && req.valid 190*1d8f4dcbSJay entry.io.req.bits := req.bits 191*1d8f4dcbSJay when (i.U === entry_alloc_idx) { 192*1d8f4dcbSJay req_ready := entry.io.req.ready 193*1d8f4dcbSJay } 194*1d8f4dcbSJay 195*1d8f4dcbSJay // entry resp 196*1d8f4dcbSJay resp_arb.io.in(i) <> entry.io.resp 197*1d8f4dcbSJay 198*1d8f4dcbSJay entry.io.mmio_grant.valid := false.B 199*1d8f4dcbSJay entry.io.mmio_grant.bits := DontCare 200*1d8f4dcbSJay when (mmio_grant.bits.source === i.U) { 201*1d8f4dcbSJay entry.io.mmio_grant <> mmio_grant 202*1d8f4dcbSJay } 203*1d8f4dcbSJay entry 204*1d8f4dcbSJay } 205*1d8f4dcbSJay 206*1d8f4dcbSJay entry_alloc_idx := PriorityEncoder(entries.map(m=>m.io.req.ready)) 207*1d8f4dcbSJay 208*1d8f4dcbSJay req.ready := req_ready 209*1d8f4dcbSJay resp <> resp_arb.io.out 210*1d8f4dcbSJay TLArbiter.lowestFromSeq(edge, mmio_acquire, entries.map(_.io.mmio_acquire)) 211*1d8f4dcbSJay 212*1d8f4dcbSJay} 213