171784e68SYinan Xu/*************************************************************************************** 271784e68SYinan Xu * Copyright (c) 2020-2022 Institute of Computing Technology, Chinese Academy of Sciences 371784e68SYinan Xu * 471784e68SYinan Xu * XiangShan is licensed under Mulan PSL v2. 571784e68SYinan Xu * You can use this software according to the terms and conditions of the Mulan PSL v2. 671784e68SYinan Xu * You may obtain a copy of Mulan PSL v2 at: 771784e68SYinan Xu * http://license.coscl.org.cn/MulanPSL2 871784e68SYinan Xu * 971784e68SYinan Xu * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 1071784e68SYinan Xu * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 1171784e68SYinan Xu * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 1271784e68SYinan Xu * 1371784e68SYinan Xu * See the Mulan PSL v2 for more details. 1471784e68SYinan Xu ***************************************************************************************/ 1571784e68SYinan Xu 1671784e68SYinan Xupackage device 1771784e68SYinan Xu 188891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 1971784e68SYinan Xuimport chisel3._ 209f659d72SKamimiaoimport chisel3.experimental.{ExtModule, prefix} 2171784e68SYinan Xuimport chisel3.util._ 229f659d72SKamimiaoimport difftest.common.DifftestMem 2371784e68SYinan Xuimport freechips.rocketchip.amba.axi4.{AXI4MasterNode, AXI4Parameters, AXI4SlaveNode} 2471784e68SYinan Xuimport freechips.rocketchip.diplomacy.{AddressSet, InModuleBody, LazyModule, LazyModuleImp} 25bb2f3f51STang Haojinimport utility._ 2671784e68SYinan Xu 2771784e68SYinan Xuclass MemoryRequestHelper(requestType: Int) 2871784e68SYinan Xu extends ExtModule(Map("REQUEST_TYPE" -> requestType)) 2971784e68SYinan Xu with HasExtModuleInline 3071784e68SYinan Xu{ 3171784e68SYinan Xu val clock = IO(Input(Clock())) 3271784e68SYinan Xu val reset = IO(Input(Reset())) 3371784e68SYinan Xu val io = IO(new Bundle { 3471784e68SYinan Xu val req = Flipped(ValidIO(new Bundle { 3571784e68SYinan Xu val addr = UInt(64.W) 3671784e68SYinan Xu val id = UInt(32.W) 3771784e68SYinan Xu })) 3871784e68SYinan Xu val response = Output(Bool()) 3971784e68SYinan Xu }) 4071784e68SYinan Xu 4171784e68SYinan Xu val verilogLines = Seq( 4271784e68SYinan Xu "import \"DPI-C\" function bit memory_request (", 4371784e68SYinan Xu " input longint address,", 4471784e68SYinan Xu " input int id,", 4571784e68SYinan Xu " input bit isWrite", 4671784e68SYinan Xu ");", 4771784e68SYinan Xu "", 4871784e68SYinan Xu "module MemoryRequestHelper #(", 4971784e68SYinan Xu " parameter REQUEST_TYPE", 5071784e68SYinan Xu ")(", 5171784e68SYinan Xu " input clock,", 5271784e68SYinan Xu " input reset,", 5371784e68SYinan Xu " input io_req_valid,", 5471784e68SYinan Xu " input [63:0] io_req_bits_addr,", 5571784e68SYinan Xu " input [31:0] io_req_bits_id,", 5671784e68SYinan Xu " output reg io_response", 5771784e68SYinan Xu ");", 5871784e68SYinan Xu "", 5971784e68SYinan Xu "always @(posedge clock or posedge reset) begin", 6071784e68SYinan Xu " if (reset) begin", 6171784e68SYinan Xu " io_response <= 1'b0;", 6271784e68SYinan Xu " end", 6371784e68SYinan Xu " else if (io_req_valid) begin", 6471784e68SYinan Xu " io_response <= memory_request(io_req_bits_addr, io_req_bits_id, REQUEST_TYPE);", 6571784e68SYinan Xu " end" + 6671784e68SYinan Xu " else begin", 6771784e68SYinan Xu " io_response <= 1'b0;", 6871784e68SYinan Xu " end", 6971784e68SYinan Xu "end", 7071784e68SYinan Xu "", 7171784e68SYinan Xu "endmodule" 7271784e68SYinan Xu ) 7371784e68SYinan Xu setInline(s"$desiredName.v", verilogLines.mkString("\n")) 7471784e68SYinan Xu} 7571784e68SYinan Xu 7671784e68SYinan Xuclass MemoryResponseHelper(requestType: Int) 7771784e68SYinan Xu extends ExtModule(Map("REQUEST_TYPE" -> requestType)) 7871784e68SYinan Xu with HasExtModuleInline 7971784e68SYinan Xu{ 8071784e68SYinan Xu val clock = IO(Input(Clock())) 8171784e68SYinan Xu val reset = IO(Input(Reset())) 8271784e68SYinan Xu val enable = IO(Input(Bool())) 8371784e68SYinan Xu val response = IO(Output(UInt(64.W))) 8471784e68SYinan Xu 8571784e68SYinan Xu val verilogLines = Seq( 8671784e68SYinan Xu "import \"DPI-C\" function longint memory_response (", 8771784e68SYinan Xu " input bit isWrite", 8871784e68SYinan Xu ");", 8971784e68SYinan Xu "", 9071784e68SYinan Xu "module MemoryResponseHelper #(", 9171784e68SYinan Xu " parameter REQUEST_TYPE", 9271784e68SYinan Xu ")(", 9371784e68SYinan Xu " input clock,", 9471784e68SYinan Xu " input reset,", 9571784e68SYinan Xu " input enable,", 9671784e68SYinan Xu " output reg [63:0] response", 9771784e68SYinan Xu ");", 9871784e68SYinan Xu "", 9971784e68SYinan Xu "always @(posedge clock or posedge reset) begin", 10071784e68SYinan Xu " if (reset) begin", 10171784e68SYinan Xu " response <= 64'b0;", 10271784e68SYinan Xu " end", 10371784e68SYinan Xu " else if (!reset && enable) begin", 10471784e68SYinan Xu " response <= memory_response(REQUEST_TYPE);", 10571784e68SYinan Xu " end", 10671784e68SYinan Xu " else begin", 10771784e68SYinan Xu " response <= 64'b0;", 10871784e68SYinan Xu " end", 10971784e68SYinan Xu "end", 11071784e68SYinan Xu "", 11171784e68SYinan Xu "endmodule" 11271784e68SYinan Xu ) 11371784e68SYinan Xu setInline(s"$desiredName.v", verilogLines.mkString("\n")) 11471784e68SYinan Xu} 11571784e68SYinan Xu 11671784e68SYinan Xutrait MemoryHelper { this: Module => 11771784e68SYinan Xu private def requestType(isWrite: Boolean): Int = if (isWrite) 1 else 0 11871784e68SYinan Xu private def request(valid: Bool, addr: UInt, id: UInt, isWrite: Boolean): Bool = { 11971784e68SYinan Xu val helper = Module(new MemoryRequestHelper(requestType(isWrite))) 12071784e68SYinan Xu helper.clock := clock 12171784e68SYinan Xu helper.reset := reset 12271784e68SYinan Xu helper.io.req.valid := valid 12371784e68SYinan Xu helper.io.req.bits.addr := addr 12471784e68SYinan Xu helper.io.req.bits.id := id 12571784e68SYinan Xu helper.io.response 12671784e68SYinan Xu } 12771784e68SYinan Xu protected def readRequest(valid: Bool, addr: UInt, id: UInt): Bool = 12871784e68SYinan Xu request(valid, addr, id, false) 12971784e68SYinan Xu protected def writeRequest(valid: Bool, addr: UInt, id: UInt): Bool = 13071784e68SYinan Xu request(valid, addr, id, true) 13171784e68SYinan Xu private def response(enable: Bool, isWrite: Boolean): (Bool, UInt) = { 13271784e68SYinan Xu val helper = Module(new MemoryResponseHelper(requestType(isWrite))) 13371784e68SYinan Xu helper.clock := clock 13471784e68SYinan Xu helper.reset := reset 13571784e68SYinan Xu helper.enable := enable 13671784e68SYinan Xu (helper.response(32), helper.response(31, 0)) 13771784e68SYinan Xu } 13871784e68SYinan Xu protected def readResponse(enable: Bool): (Bool, UInt) = 13971784e68SYinan Xu response(enable, false) 14071784e68SYinan Xu protected def writeResponse(enable: Bool): (Bool, UInt) = 14171784e68SYinan Xu response(enable, true) 14271784e68SYinan Xu} 14371784e68SYinan Xu 14471784e68SYinan Xuclass AXI4MemoryImp[T <: Data](outer: AXI4Memory) extends AXI4SlaveModuleImp(outer) with MemoryHelper { 14571784e68SYinan Xu val ramBaseAddr = outer.address.head.base 1469f659d72SKamimiao val (ramIndexBits, ramOffsetBits) = (log2Ceil(outer.beatBytes), log2Ceil(outer.memByte)) 1479f659d72SKamimiao def ramIndex(addr: UInt) = ((addr - ramBaseAddr.U)(ramOffsetBits - 1, 0) >> ramIndexBits).asUInt 1489f659d72SKamimiao val ramHelper = DifftestMem(outer.memByte, outer.beatBytes, 8, singlePort = false) 14971784e68SYinan Xu 15071784e68SYinan Xu val numOutstanding = 1 << in.ar.bits.id.getWidth 1519f659d72SKamimiao // Note: we are using in.ar.bits.addr.getWidth insead of ramOffsetBits here. 1529f659d72SKamimiao // Why: the CPU may access out-of-range addresses. Let the RAM helper deal with it. 1539f659d72SKamimiao val addressMem = Mem(numOutstanding, UInt((in.ar.bits.addr.getWidth - ramIndexBits).W)) 15471784e68SYinan Xu val arlenMem = Mem(numOutstanding, UInt(in.ar.bits.len.getWidth.W)) 15571784e68SYinan Xu 15671784e68SYinan Xu // accept a read request and send it to the external model 15771784e68SYinan Xu val pending_read_req_valid = RegInit(false.B) 15871784e68SYinan Xu val pending_read_req_bits = RegEnable(in.ar.bits, in.ar.fire) 15971784e68SYinan Xu val pending_read_req_ready = Wire(Bool()) 16071784e68SYinan Xu val pending_read_need_req = pending_read_req_valid && !pending_read_req_ready 16171784e68SYinan Xu val read_req_valid = pending_read_need_req || in.ar.valid 16271784e68SYinan Xu val read_req_bits = Mux(pending_read_need_req, pending_read_req_bits, in.ar.bits) 16371784e68SYinan Xu pending_read_req_ready := readRequest(read_req_valid, read_req_bits.addr, read_req_bits.id) 16471784e68SYinan Xu 16571784e68SYinan Xu when (in.ar.fire) { 16671784e68SYinan Xu pending_read_req_valid := true.B 16771784e68SYinan Xu addressMem.write(read_req_bits.id, ramIndex(read_req_bits.addr)) 16871784e68SYinan Xu arlenMem.write(read_req_bits.id, read_req_bits.len) 16971784e68SYinan Xu }.elsewhen (pending_read_req_ready) { 17071784e68SYinan Xu pending_read_req_valid := false.B 17171784e68SYinan Xu } 17271784e68SYinan Xu in.ar.ready := !pending_read_req_valid || pending_read_req_ready 17371784e68SYinan Xu 17471784e68SYinan Xu // accept a write request (including address and data) and send it to the external model 17571784e68SYinan Xu val pending_write_req_valid = RegInit(VecInit.fill(2)(false.B)) 17671784e68SYinan Xu val pending_write_req_bits = RegEnable(in.aw.bits, in.aw.fire) 17771784e68SYinan Xu val pending_write_req_data = RegEnable(in.w.bits, in.w.fire) 17871784e68SYinan Xu val pending_write_req_ready = Wire(Bool()) 17971784e68SYinan Xu val pending_write_need_req = pending_write_req_valid.last && !pending_write_req_ready 180*9e0994abScz4e val aw_and_w_last_arrive_at_same_time = in.aw.fire && in.w.fire && in.w.bits.last 181*9e0994abScz4e val w_last_arrive_before_aw = in.aw.fire && pending_write_need_req 182*9e0994abScz4e val aw_arrive_before_w_last = pending_write_req_valid.head && in.w.fire && in.w.bits.last 183*9e0994abScz4e val aw_arrive_before_w = pending_write_req_valid.head && pending_write_need_req 184*9e0994abScz4e val write_req_enq_pending = aw_arrive_before_w || aw_arrive_before_w_last 185*9e0994abScz4e val write_req_enq_no_pending = aw_and_w_last_arrive_at_same_time || w_last_arrive_before_aw 186*9e0994abScz4e val write_req_valid = write_req_enq_pending || write_req_enq_no_pending 187*9e0994abScz4e val write_req_enq_addr = Mux(write_req_enq_pending, pending_write_req_bits.addr, in.aw.bits.addr) 188*9e0994abScz4e val write_req_enq_id = Mux(write_req_enq_pending, pending_write_req_bits.id, in.aw.bits.id) 189*9e0994abScz4e pending_write_req_ready := writeRequest(write_req_valid, write_req_enq_addr, write_req_enq_id) 19071784e68SYinan Xu 191*9e0994abScz4e when (in.aw.fire && !write_req_enq_no_pending) { 19271784e68SYinan Xu pending_write_req_valid.head := true.B 19371784e68SYinan Xu }.elsewhen (pending_write_req_ready) { 19471784e68SYinan Xu pending_write_req_valid.head := false.B 19571784e68SYinan Xu } 19671784e68SYinan Xu val write_req_last = in.w.fire && in.w.bits.last 19771784e68SYinan Xu when (write_req_last) { 19871784e68SYinan Xu pending_write_req_valid.last := true.B 19971784e68SYinan Xu }.elsewhen (pending_write_req_ready) { 20071784e68SYinan Xu pending_write_req_valid.last := false.B 20171784e68SYinan Xu } 20271784e68SYinan Xu in.aw.ready := !pending_write_req_valid.head || pending_write_req_ready 20371784e68SYinan Xu in.w.ready := in.aw.ready || !pending_write_req_valid.last 20471784e68SYinan Xu 20571784e68SYinan Xu // ram is written when write data fire 20671784e68SYinan Xu val wdata_cnt = Counter(outer.burstLen) 20771784e68SYinan Xu val write_req_addr = Mux(in.aw.fire, in.aw.bits.addr, pending_write_req_bits.addr) 2089f659d72SKamimiao val write_req_index = ramIndex(write_req_addr) + wdata_cnt.value 2099f659d72SKamimiao when (in.w.fire) { 2109f659d72SKamimiao ramHelper.write( 2119f659d72SKamimiao addr = write_req_index, 2129f659d72SKamimiao data = in.w.bits.data.asTypeOf(Vec(outer.beatBytes, UInt(8.W))), 2139f659d72SKamimiao mask = in.w.bits.strb.asBools 2149f659d72SKamimiao ) 21571784e68SYinan Xu } 21671784e68SYinan Xu when (write_req_last) { 21771784e68SYinan Xu wdata_cnt.reset() 21871784e68SYinan Xu }.elsewhen (in.w.fire) { 21971784e68SYinan Xu wdata_cnt.inc() 22071784e68SYinan Xu } 22171784e68SYinan Xu 2229f659d72SKamimiao // read data response: resp from DRAMsim3; read data and response to in.r 2239f659d72SKamimiao // This is the output of the last pipeline before in.r. This is not the pipeline registers. 2249f659d72SKamimiao val r_resp = Wire(Decoupled(chiselTypeOf(in.r.bits))) 2259f659d72SKamimiao 22671784e68SYinan Xu val pending_read_resp_valid = RegInit(false.B) 2279f659d72SKamimiao val pending_read_resp_id = Reg(UInt(r_resp.bits.id.getWidth.W)) 22871784e68SYinan Xu val has_read_resp = Wire(Bool()) 2299f659d72SKamimiao val read_resp_last = r_resp.fire && r_resp.bits.last 230021511b6SKamimiao val read_request_cnt = RegInit(0.U(8.W)) 231021511b6SKamimiao val read_have_req_cnt = read_request_cnt =/= 0.U 232021511b6SKamimiao val (read_resp_valid, read_resp_id) = readResponse((!has_read_resp || read_resp_last) && read_have_req_cnt) 23371784e68SYinan Xu has_read_resp := (read_resp_valid && !read_resp_last) || pending_read_resp_valid 23471784e68SYinan Xu val rdata_cnt = Counter(outer.burstLen) 2359f659d72SKamimiao val read_resp_addr = addressMem(r_resp.bits.id) + rdata_cnt.value 2369f659d72SKamimiao val read_resp_len = arlenMem(r_resp.bits.id) 2379f659d72SKamimiao r_resp.valid := read_resp_valid || pending_read_resp_valid 2389f659d72SKamimiao r_resp.bits.id := Mux(pending_read_resp_valid, pending_read_resp_id, read_resp_id) 2399f659d72SKamimiao // We cannot get the read data this cycle because the RAM helper has one-cycle latency. 2409f659d72SKamimiao r_resp.bits.data := DontCare 2419f659d72SKamimiao r_resp.bits.resp := AXI4Parameters.RESP_OKAY 2429f659d72SKamimiao r_resp.bits.last := (rdata_cnt.value === read_resp_len) 24371784e68SYinan Xu 244021511b6SKamimiao // The return values of DPI-C are used to determine whether a request has been made or completed 245021511b6SKamimiao // pending_read_req_ready ---> readRequest() 246021511b6SKamimiao // read_resp_valid <--- readResponse() 247021511b6SKamimiao when (pending_read_req_ready && !read_resp_valid) { 248021511b6SKamimiao read_request_cnt := read_request_cnt + 1.U 249021511b6SKamimiao }.elsewhen (read_resp_valid && !pending_read_req_ready) { 250021511b6SKamimiao read_request_cnt := read_request_cnt - 1.U 251021511b6SKamimiao } 25271784e68SYinan Xu when (!pending_read_resp_valid && read_resp_valid && !read_resp_last) { 25371784e68SYinan Xu pending_read_resp_valid := true.B 25471784e68SYinan Xu pending_read_resp_id := read_resp_id 25571784e68SYinan Xu }.elsewhen (pending_read_resp_valid && !read_resp_valid && read_resp_last) { 25671784e68SYinan Xu pending_read_resp_valid := false.B 25771784e68SYinan Xu } 25871784e68SYinan Xu when (read_resp_last) { 25971784e68SYinan Xu rdata_cnt.reset() 2609f659d72SKamimiao }.elsewhen (r_resp.fire) { 26171784e68SYinan Xu rdata_cnt.inc() 26271784e68SYinan Xu } 26371784e68SYinan Xu 2649f659d72SKamimiao // `r_pipe`: the extra pipeline registers for the read response `in.r` 2659f659d72SKamimiao prefix("r_pipe") { 2669f659d72SKamimiao val valid = RegInit(false.B) 267bcdee821SJiuyue Ma when (in.r.fire) { valid := false.B } 268bcdee821SJiuyue Ma when (r_resp.fire) { valid := true.B } 2699f659d72SKamimiao in.r.valid := valid 270bcdee821SJiuyue Ma in.r.bits := RegEnable(r_resp.bits, r_resp.fire) 2719f659d72SKamimiao r_resp.ready := !valid || in.r.ready 2729f659d72SKamimiao 2739f659d72SKamimiao // the data should be auto-hold 2749f659d72SKamimiao in.r.bits.data := ramHelper.readAndHold(read_resp_addr, r_resp.fire).asUInt 2759f659d72SKamimiao } 2769f659d72SKamimiao 27771784e68SYinan Xu // write response 27871784e68SYinan Xu val pending_write_resp_valid = RegInit(false.B) 27971784e68SYinan Xu val pending_write_resp_id = Reg(UInt(in.b.bits.id.getWidth.W)) 28071784e68SYinan Xu val has_write_resp = Wire(Bool()) 281021511b6SKamimiao val write_request_cnt = RegInit(0.U(8.W)) 282021511b6SKamimiao val write_have_req_cnt = write_request_cnt =/= 0.U 283021511b6SKamimiao val (write_resp_valid, write_resp_id) = writeResponse((!has_write_resp || in.b.fire) && write_have_req_cnt) 28404ac809eSYinan Xu has_write_resp := write_resp_valid || pending_write_resp_valid 28571784e68SYinan Xu in.b.valid := write_resp_valid || pending_write_resp_valid 28671784e68SYinan Xu in.b.bits.id := Mux(pending_write_resp_valid, pending_write_resp_id, write_resp_id) 28771784e68SYinan Xu in.b.bits.resp := AXI4Parameters.RESP_OKAY 28871784e68SYinan Xu 289021511b6SKamimiao // The return values of DPI-C are used to determine whether a request has been made or completed 290021511b6SKamimiao // pending_write_req_ready ---> writeRequest() 291021511b6SKamimiao // write_resp_valid <--- writeResponse() 292021511b6SKamimiao when (pending_write_req_ready && !write_resp_valid) { 293021511b6SKamimiao write_request_cnt := write_request_cnt + 1.U 294021511b6SKamimiao }.elsewhen (write_resp_valid && !pending_write_req_ready) { 295021511b6SKamimiao write_request_cnt := write_request_cnt - 1.U 296021511b6SKamimiao } 29771784e68SYinan Xu when (!pending_write_resp_valid && write_resp_valid && !in.b.ready) { 29871784e68SYinan Xu pending_write_resp_valid := true.B 29904ac809eSYinan Xu pending_write_resp_id := write_resp_id 30071784e68SYinan Xu }.elsewhen (pending_write_resp_valid && !write_resp_valid && in.b.ready) { 30171784e68SYinan Xu pending_write_resp_valid := false.B 30271784e68SYinan Xu } 30371784e68SYinan Xu} 30471784e68SYinan Xu 30571784e68SYinan Xuclass AXI4Memory 30671784e68SYinan Xu( 30771784e68SYinan Xu val address: Seq[AddressSet], 30871784e68SYinan Xu val memByte: Long, 30971784e68SYinan Xu val useBlackBox: Boolean = false, 31071784e68SYinan Xu val executable: Boolean = true, 31171784e68SYinan Xu val beatBytes: Int, 31271784e68SYinan Xu val burstLen: Int, 31371784e68SYinan Xu)(implicit p: Parameters) 31471784e68SYinan Xu extends AXI4SlaveModule(address, executable, beatBytes, burstLen) 31571784e68SYinan Xu{ 31671784e68SYinan Xu override lazy val module = new AXI4MemoryImp(this) 31771784e68SYinan Xu} 31871784e68SYinan Xu 31971784e68SYinan Xuclass AXI4MemoryWrapper ( 32071784e68SYinan Xu slave: AXI4SlaveNode, 32171784e68SYinan Xu memByte: Long, 32271784e68SYinan Xu useBlackBox: Boolean = false 32371784e68SYinan Xu)(implicit p: Parameters) extends AXI4MemorySlave(slave, memByte, useBlackBox) { 32471784e68SYinan Xu val ram = LazyModule(new AXI4Memory( 32571784e68SYinan Xu slaveParam.address, 32671784e68SYinan Xu memByte, 32771784e68SYinan Xu useBlackBox, 32871784e68SYinan Xu slaveParam.executable, 32971784e68SYinan Xu portParam.beatBytes, 33071784e68SYinan Xu burstLen 33171784e68SYinan Xu )) 33271784e68SYinan Xu ram.node := master 33371784e68SYinan Xu} 33471784e68SYinan Xu 33571784e68SYinan Xuabstract class AXI4MemorySlave ( 33671784e68SYinan Xu slave: AXI4SlaveNode, 33771784e68SYinan Xu memByte: Long, 33871784e68SYinan Xu useBlackBox: Boolean = false 33971784e68SYinan Xu)(implicit p: Parameters) extends LazyModule { 34071784e68SYinan Xu val master = AXI4MasterNode(List(slave.in.head._2.master)) 34171784e68SYinan Xu 34271784e68SYinan Xu val portParam = slave.portParams.head 34371784e68SYinan Xu val slaveParam = portParam.slaves.head 34471784e68SYinan Xu val burstLen = portParam.maxTransfer / portParam.beatBytes 34571784e68SYinan Xu 34671784e68SYinan Xu val io_axi4 = InModuleBody{ master.makeIOs() } 34771784e68SYinan Xu 34871784e68SYinan Xu lazy val module = new LazyModuleImp(this) { } 34971784e68SYinan Xu} 35071784e68SYinan Xu 35171784e68SYinan Xuobject AXI4MemorySlave { 35271784e68SYinan Xu def apply( 35371784e68SYinan Xu slave: AXI4SlaveNode, 35471784e68SYinan Xu memByte: Long, 35571784e68SYinan Xu useBlackBox: Boolean = false, 35671784e68SYinan Xu dynamicLatency: Boolean = false 35771784e68SYinan Xu )(implicit p: Parameters): AXI4MemorySlave = { 35871784e68SYinan Xu val memory = if (dynamicLatency) { 35971784e68SYinan Xu LazyModule(new AXI4MemoryWrapper(slave, memByte, useBlackBox)) 36071784e68SYinan Xu } else { 36171784e68SYinan Xu LazyModule(new AXI4RAMWrapper(slave, memByte, useBlackBox)) 36271784e68SYinan Xu } 36371784e68SYinan Xu memory 36471784e68SYinan Xu } 36571784e68SYinan Xu} 366