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 1871784e68SYinan Xuimport chipsalliance.rocketchip.config.Parameters 1971784e68SYinan Xuimport chisel3._ 2071784e68SYinan Xuimport chisel3.experimental.ExtModule 2171784e68SYinan Xuimport chisel3.util._ 2271784e68SYinan Xuimport freechips.rocketchip.amba.axi4.{AXI4MasterNode, AXI4Parameters, AXI4SlaveNode} 2371784e68SYinan Xuimport freechips.rocketchip.diplomacy.{AddressSet, InModuleBody, LazyModule, LazyModuleImp} 2471784e68SYinan Xuimport utils._ 25*3c02ee8fSwakafaimport utility._ 2671784e68SYinan Xu 2771784e68SYinan Xuclass MemoryRWHelper extends ExtModule with HasExtModuleInline { 2871784e68SYinan Xu val DataBits = 64 2971784e68SYinan Xu 3071784e68SYinan Xu val clock = IO(Input(Clock())) 3171784e68SYinan Xu val reset = IO(Input(Reset())) 3271784e68SYinan Xu val ren = IO(Input(Bool())) 3371784e68SYinan Xu val rIdx = IO(Input(UInt(DataBits.W))) 3471784e68SYinan Xu val rdata = IO(Output(UInt(DataBits.W))) 3571784e68SYinan Xu val wen = IO(Input(Bool())) 3671784e68SYinan Xu val wIdx = IO(Input(UInt(DataBits.W))) 3771784e68SYinan Xu val wdata = IO(Input(UInt(DataBits.W))) 3871784e68SYinan Xu val wmask = IO(Input(UInt(DataBits.W))) 3971784e68SYinan Xu 4071784e68SYinan Xu def read(enable: Bool, address: UInt): UInt = { 4171784e68SYinan Xu ren := enable 4271784e68SYinan Xu rIdx := address 4371784e68SYinan Xu rdata 4471784e68SYinan Xu } 4571784e68SYinan Xu def write(enable: Bool, address: UInt, data: UInt, mask: UInt): Unit = { 4671784e68SYinan Xu wen := enable 4771784e68SYinan Xu wIdx := address 4871784e68SYinan Xu wdata := data 4971784e68SYinan Xu wmask := mask 5071784e68SYinan Xu } 5171784e68SYinan Xu 5271784e68SYinan Xu val verilogLines = Seq( 5371784e68SYinan Xu "module MemoryRWHelper(", 5471784e68SYinan Xu " input clock,", 5571784e68SYinan Xu " input reset,", 5671784e68SYinan Xu " input ren,", 5771784e68SYinan Xu " input [63:0] rIdx,", 5871784e68SYinan Xu " output [63:0] rdata,", 5971784e68SYinan Xu " input [63:0] wIdx,", 6071784e68SYinan Xu " input [63:0] wdata,", 6171784e68SYinan Xu " input [63:0] wmask,", 6271784e68SYinan Xu " input wen", 6371784e68SYinan Xu ");", 6471784e68SYinan Xu "", 6571784e68SYinan Xu " assign rdata = (!reset && ren) ? ram_read_helper(1, rIdx) : 64'b0;", 6671784e68SYinan Xu "", 6771784e68SYinan Xu " always @(posedge clock) begin", 6871784e68SYinan Xu " if (!reset && wen) begin", 6971784e68SYinan Xu " ram_write_helper(wIdx, wdata, wmask, 1);", 7071784e68SYinan Xu " end", 7171784e68SYinan Xu " end", 7271784e68SYinan Xu "", 7371784e68SYinan Xu "endmodule" 7471784e68SYinan Xu ) 7571784e68SYinan Xu setInline(s"$desiredName.v", verilogLines.mkString("\n")) 7671784e68SYinan Xu} 7771784e68SYinan Xu 7871784e68SYinan Xuobject MemoryRWHelper { 7971784e68SYinan Xu def apply(clock: Clock, reset: Reset): MemoryRWHelper = { 8071784e68SYinan Xu val helper = Module(new MemoryRWHelper) 8171784e68SYinan Xu helper.clock := clock 8271784e68SYinan Xu helper.reset := reset 8371784e68SYinan Xu helper 8471784e68SYinan Xu } 8571784e68SYinan Xu} 8671784e68SYinan Xu 8771784e68SYinan Xuclass MemoryRequestHelper(requestType: Int) 8871784e68SYinan Xu extends ExtModule(Map("REQUEST_TYPE" -> requestType)) 8971784e68SYinan Xu with HasExtModuleInline 9071784e68SYinan Xu{ 9171784e68SYinan Xu val clock = IO(Input(Clock())) 9271784e68SYinan Xu val reset = IO(Input(Reset())) 9371784e68SYinan Xu val io = IO(new Bundle { 9471784e68SYinan Xu val req = Flipped(ValidIO(new Bundle { 9571784e68SYinan Xu val addr = UInt(64.W) 9671784e68SYinan Xu val id = UInt(32.W) 9771784e68SYinan Xu })) 9871784e68SYinan Xu val response = Output(Bool()) 9971784e68SYinan Xu }) 10071784e68SYinan Xu 10171784e68SYinan Xu val verilogLines = Seq( 10271784e68SYinan Xu "import \"DPI-C\" function bit memory_request (", 10371784e68SYinan Xu " input longint address,", 10471784e68SYinan Xu " input int id,", 10571784e68SYinan Xu " input bit isWrite", 10671784e68SYinan Xu ");", 10771784e68SYinan Xu "", 10871784e68SYinan Xu "module MemoryRequestHelper #(", 10971784e68SYinan Xu " parameter REQUEST_TYPE", 11071784e68SYinan Xu ")(", 11171784e68SYinan Xu " input clock,", 11271784e68SYinan Xu " input reset,", 11371784e68SYinan Xu " input io_req_valid,", 11471784e68SYinan Xu " input [63:0] io_req_bits_addr,", 11571784e68SYinan Xu " input [31:0] io_req_bits_id,", 11671784e68SYinan Xu " output reg io_response", 11771784e68SYinan Xu ");", 11871784e68SYinan Xu "", 11971784e68SYinan Xu "always @(posedge clock or posedge reset) begin", 12071784e68SYinan Xu " if (reset) begin", 12171784e68SYinan Xu " io_response <= 1'b0;", 12271784e68SYinan Xu " end", 12371784e68SYinan Xu " else if (io_req_valid) begin", 12471784e68SYinan Xu " io_response <= memory_request(io_req_bits_addr, io_req_bits_id, REQUEST_TYPE);", 12571784e68SYinan Xu " end" + 12671784e68SYinan Xu " else begin", 12771784e68SYinan Xu " io_response <= 1'b0;", 12871784e68SYinan Xu " end", 12971784e68SYinan Xu "end", 13071784e68SYinan Xu "", 13171784e68SYinan Xu "endmodule" 13271784e68SYinan Xu ) 13371784e68SYinan Xu setInline(s"$desiredName.v", verilogLines.mkString("\n")) 13471784e68SYinan Xu} 13571784e68SYinan Xu 13671784e68SYinan Xuclass MemoryResponseHelper(requestType: Int) 13771784e68SYinan Xu extends ExtModule(Map("REQUEST_TYPE" -> requestType)) 13871784e68SYinan Xu with HasExtModuleInline 13971784e68SYinan Xu{ 14071784e68SYinan Xu val clock = IO(Input(Clock())) 14171784e68SYinan Xu val reset = IO(Input(Reset())) 14271784e68SYinan Xu val enable = IO(Input(Bool())) 14371784e68SYinan Xu val response = IO(Output(UInt(64.W))) 14471784e68SYinan Xu 14571784e68SYinan Xu val verilogLines = Seq( 14671784e68SYinan Xu "import \"DPI-C\" function longint memory_response (", 14771784e68SYinan Xu " input bit isWrite", 14871784e68SYinan Xu ");", 14971784e68SYinan Xu "", 15071784e68SYinan Xu "module MemoryResponseHelper #(", 15171784e68SYinan Xu " parameter REQUEST_TYPE", 15271784e68SYinan Xu ")(", 15371784e68SYinan Xu " input clock,", 15471784e68SYinan Xu " input reset,", 15571784e68SYinan Xu " input enable,", 15671784e68SYinan Xu " output reg [63:0] response", 15771784e68SYinan Xu ");", 15871784e68SYinan Xu "", 15971784e68SYinan Xu "always @(posedge clock or posedge reset) begin", 16071784e68SYinan Xu " if (reset) begin", 16171784e68SYinan Xu " response <= 64'b0;", 16271784e68SYinan Xu " end", 16371784e68SYinan Xu " else if (!reset && enable) begin", 16471784e68SYinan Xu " response <= memory_response(REQUEST_TYPE);", 16571784e68SYinan Xu " end", 16671784e68SYinan Xu " else begin", 16771784e68SYinan Xu " response <= 64'b0;", 16871784e68SYinan Xu " end", 16971784e68SYinan Xu "end", 17071784e68SYinan Xu "", 17171784e68SYinan Xu "endmodule" 17271784e68SYinan Xu ) 17371784e68SYinan Xu setInline(s"$desiredName.v", verilogLines.mkString("\n")) 17471784e68SYinan Xu} 17571784e68SYinan Xu 17671784e68SYinan Xutrait MemoryHelper { this: Module => 17771784e68SYinan Xu private def requestType(isWrite: Boolean): Int = if (isWrite) 1 else 0 17871784e68SYinan Xu private def request(valid: Bool, addr: UInt, id: UInt, isWrite: Boolean): Bool = { 17971784e68SYinan Xu val helper = Module(new MemoryRequestHelper(requestType(isWrite))) 18071784e68SYinan Xu helper.clock := clock 18171784e68SYinan Xu helper.reset := reset 18271784e68SYinan Xu helper.io.req.valid := valid 18371784e68SYinan Xu helper.io.req.bits.addr := addr 18471784e68SYinan Xu helper.io.req.bits.id := id 18571784e68SYinan Xu helper.io.response 18671784e68SYinan Xu } 18771784e68SYinan Xu protected def readRequest(valid: Bool, addr: UInt, id: UInt): Bool = 18871784e68SYinan Xu request(valid, addr, id, false) 18971784e68SYinan Xu protected def writeRequest(valid: Bool, addr: UInt, id: UInt): Bool = 19071784e68SYinan Xu request(valid, addr, id, true) 19171784e68SYinan Xu private def response(enable: Bool, isWrite: Boolean): (Bool, UInt) = { 19271784e68SYinan Xu val helper = Module(new MemoryResponseHelper(requestType(isWrite))) 19371784e68SYinan Xu helper.clock := clock 19471784e68SYinan Xu helper.reset := reset 19571784e68SYinan Xu helper.enable := enable 19671784e68SYinan Xu (helper.response(32), helper.response(31, 0)) 19771784e68SYinan Xu } 19871784e68SYinan Xu protected def readResponse(enable: Bool): (Bool, UInt) = 19971784e68SYinan Xu response(enable, false) 20071784e68SYinan Xu protected def writeResponse(enable: Bool): (Bool, UInt) = 20171784e68SYinan Xu response(enable, true) 20271784e68SYinan Xu} 20371784e68SYinan Xu 20471784e68SYinan Xuclass AXI4MemoryImp[T <: Data](outer: AXI4Memory) extends AXI4SlaveModuleImp(outer) with MemoryHelper { 20571784e68SYinan Xu val ramWidth = 8 20671784e68SYinan Xu val ramSplit = outer.beatBytes / ramWidth 20771784e68SYinan Xu val ramBaseAddr = outer.address.head.base 20871784e68SYinan Xu val ramOffsetBits = log2Ceil(outer.memByte) 20971784e68SYinan Xu def ramIndex(addr: UInt) = ((addr - ramBaseAddr.U)(ramOffsetBits - 1, 0) >> log2Ceil(ramWidth)).asUInt 21071784e68SYinan Xu val ramHelper = Seq.fill(ramSplit)(MemoryRWHelper(clock, reset)) 21171784e68SYinan Xu 21271784e68SYinan Xu val numOutstanding = 1 << in.ar.bits.id.getWidth 21371784e68SYinan Xu val addressMem = Mem(numOutstanding, UInt((in.ar.bits.addr.getWidth - log2Ceil(ramWidth)).W)) 21471784e68SYinan Xu val arlenMem = Mem(numOutstanding, UInt(in.ar.bits.len.getWidth.W)) 21571784e68SYinan Xu 21671784e68SYinan Xu // accept a read request and send it to the external model 21771784e68SYinan Xu val pending_read_req_valid = RegInit(false.B) 21871784e68SYinan Xu val pending_read_req_bits = RegEnable(in.ar.bits, in.ar.fire) 21971784e68SYinan Xu val pending_read_req_ready = Wire(Bool()) 22071784e68SYinan Xu val pending_read_need_req = pending_read_req_valid && !pending_read_req_ready 22171784e68SYinan Xu val read_req_valid = pending_read_need_req || in.ar.valid 22271784e68SYinan Xu val read_req_bits = Mux(pending_read_need_req, pending_read_req_bits, in.ar.bits) 22371784e68SYinan Xu pending_read_req_ready := readRequest(read_req_valid, read_req_bits.addr, read_req_bits.id) 22471784e68SYinan Xu 22571784e68SYinan Xu when (in.ar.fire) { 22671784e68SYinan Xu pending_read_req_valid := true.B 22771784e68SYinan Xu addressMem.write(read_req_bits.id, ramIndex(read_req_bits.addr)) 22871784e68SYinan Xu arlenMem.write(read_req_bits.id, read_req_bits.len) 22971784e68SYinan Xu }.elsewhen (pending_read_req_ready) { 23071784e68SYinan Xu pending_read_req_valid := false.B 23171784e68SYinan Xu } 23271784e68SYinan Xu in.ar.ready := !pending_read_req_valid || pending_read_req_ready 23371784e68SYinan Xu 23471784e68SYinan Xu // accept a write request (including address and data) and send it to the external model 23571784e68SYinan Xu val pending_write_req_valid = RegInit(VecInit.fill(2)(false.B)) 23671784e68SYinan Xu val pending_write_req_bits = RegEnable(in.aw.bits, in.aw.fire) 23771784e68SYinan Xu val pending_write_req_data = RegEnable(in.w.bits, in.w.fire) 23871784e68SYinan Xu XSError(in.aw.fire && in.aw.bits.len === 0.U, "data must have more than one beat now") 23971784e68SYinan Xu val pending_write_req_ready = Wire(Bool()) 24071784e68SYinan Xu val pending_write_need_req = pending_write_req_valid.last && !pending_write_req_ready 24171784e68SYinan Xu val write_req_valid = pending_write_req_valid.head && (pending_write_need_req || in.w.valid && in.w.bits.last) 24271784e68SYinan Xu pending_write_req_ready := writeRequest(write_req_valid, pending_write_req_bits.addr, pending_write_req_bits.id) 24371784e68SYinan Xu 24471784e68SYinan Xu when (in.aw.fire) { 24571784e68SYinan Xu pending_write_req_valid.head := true.B 24671784e68SYinan Xu }.elsewhen (pending_write_req_ready) { 24771784e68SYinan Xu pending_write_req_valid.head := false.B 24871784e68SYinan Xu } 24971784e68SYinan Xu val write_req_last = in.w.fire && in.w.bits.last 25071784e68SYinan Xu when (write_req_last) { 25171784e68SYinan Xu pending_write_req_valid.last := true.B 25271784e68SYinan Xu }.elsewhen (pending_write_req_ready) { 25371784e68SYinan Xu pending_write_req_valid.last := false.B 25471784e68SYinan Xu } 25571784e68SYinan Xu in.aw.ready := !pending_write_req_valid.head || pending_write_req_ready 25671784e68SYinan Xu in.w.ready := in.aw.ready || !pending_write_req_valid.last 25771784e68SYinan Xu 25871784e68SYinan Xu // ram is written when write data fire 25971784e68SYinan Xu val wdata_cnt = Counter(outer.burstLen) 26071784e68SYinan Xu val write_req_addr = Mux(in.aw.fire, in.aw.bits.addr, pending_write_req_bits.addr) 26171784e68SYinan Xu val write_req_index = ramIndex(write_req_addr) + Cat(wdata_cnt.value, 0.U(log2Ceil(ramSplit).W)) 26271784e68SYinan Xu for ((ram, i) <- ramHelper.zipWithIndex) { 26371784e68SYinan Xu val enable = in.w.fire 26471784e68SYinan Xu val address = write_req_index + i.U 26571784e68SYinan Xu val data = in.w.bits.data(ramWidth * 8 * i + 63, ramWidth * 8 * i) 26671784e68SYinan Xu val mask = MaskExpand(in.w.bits.strb(i * 8 + 7, i * 8)) 26771784e68SYinan Xu ram.write(enable, address, data, mask) 26871784e68SYinan Xu } 26971784e68SYinan Xu when (write_req_last) { 27071784e68SYinan Xu wdata_cnt.reset() 27171784e68SYinan Xu }.elsewhen (in.w.fire) { 27271784e68SYinan Xu wdata_cnt.inc() 27371784e68SYinan Xu } 27471784e68SYinan Xu 27571784e68SYinan Xu // read data response 27671784e68SYinan Xu val pending_read_resp_valid = RegInit(false.B) 27771784e68SYinan Xu val pending_read_resp_id = Reg(UInt(in.r.bits.id.getWidth.W)) 27871784e68SYinan Xu val has_read_resp = Wire(Bool()) 27971784e68SYinan Xu val read_resp_last = in.r.fire && in.r.bits.last 28071784e68SYinan Xu val (read_resp_valid, read_resp_id) = readResponse(!has_read_resp || read_resp_last) 28171784e68SYinan Xu has_read_resp := (read_resp_valid && !read_resp_last) || pending_read_resp_valid 28271784e68SYinan Xu val rdata_cnt = Counter(outer.burstLen) 28371784e68SYinan Xu val read_resp_addr = addressMem(in.r.bits.id) + Cat(rdata_cnt.value, 0.U(log2Ceil(ramSplit).W)) 28471784e68SYinan Xu val read_resp_len = arlenMem(in.r.bits.id) 28571784e68SYinan Xu in.r.valid := read_resp_valid || pending_read_resp_valid 28671784e68SYinan Xu in.r.bits.id := Mux(pending_read_resp_valid, pending_read_resp_id, read_resp_id) 28771784e68SYinan Xu val rdata = ramHelper.zipWithIndex.map{ case (ram, i) => ram.read(in.r.valid, read_resp_addr + i.U) } 28871784e68SYinan Xu in.r.bits.data := VecInit(rdata).asUInt 28971784e68SYinan Xu in.r.bits.resp := AXI4Parameters.RESP_OKAY 29071784e68SYinan Xu in.r.bits.last := (rdata_cnt.value === read_resp_len) 29171784e68SYinan Xu 29271784e68SYinan Xu when (!pending_read_resp_valid && read_resp_valid && !read_resp_last) { 29371784e68SYinan Xu pending_read_resp_valid := true.B 29471784e68SYinan Xu pending_read_resp_id := read_resp_id 29571784e68SYinan Xu }.elsewhen (pending_read_resp_valid && !read_resp_valid && read_resp_last) { 29671784e68SYinan Xu pending_read_resp_valid := false.B 29771784e68SYinan Xu } 29871784e68SYinan Xu when (read_resp_last) { 29971784e68SYinan Xu rdata_cnt.reset() 30071784e68SYinan Xu }.elsewhen (in.r.fire) { 30171784e68SYinan Xu rdata_cnt.inc() 30271784e68SYinan Xu } 30371784e68SYinan Xu 30471784e68SYinan Xu // write response 30571784e68SYinan Xu val pending_write_resp_valid = RegInit(false.B) 30671784e68SYinan Xu val pending_write_resp_id = Reg(UInt(in.b.bits.id.getWidth.W)) 30771784e68SYinan Xu val has_write_resp = Wire(Bool()) 30871784e68SYinan Xu val (write_resp_valid, write_resp_id) = writeResponse(!has_write_resp || in.b.fire) 30904ac809eSYinan Xu has_write_resp := write_resp_valid || pending_write_resp_valid 31071784e68SYinan Xu in.b.valid := write_resp_valid || pending_write_resp_valid 31171784e68SYinan Xu in.b.bits.id := Mux(pending_write_resp_valid, pending_write_resp_id, write_resp_id) 31271784e68SYinan Xu in.b.bits.resp := AXI4Parameters.RESP_OKAY 31371784e68SYinan Xu 31471784e68SYinan Xu when (!pending_write_resp_valid && write_resp_valid && !in.b.ready) { 31571784e68SYinan Xu pending_write_resp_valid := true.B 31604ac809eSYinan Xu pending_write_resp_id := write_resp_id 31771784e68SYinan Xu }.elsewhen (pending_write_resp_valid && !write_resp_valid && in.b.ready) { 31871784e68SYinan Xu pending_write_resp_valid := false.B 31971784e68SYinan Xu } 32071784e68SYinan Xu} 32171784e68SYinan Xu 32271784e68SYinan Xuclass AXI4Memory 32371784e68SYinan Xu( 32471784e68SYinan Xu val address: Seq[AddressSet], 32571784e68SYinan Xu val memByte: Long, 32671784e68SYinan Xu val useBlackBox: Boolean = false, 32771784e68SYinan Xu val executable: Boolean = true, 32871784e68SYinan Xu val beatBytes: Int, 32971784e68SYinan Xu val burstLen: Int, 33071784e68SYinan Xu)(implicit p: Parameters) 33171784e68SYinan Xu extends AXI4SlaveModule(address, executable, beatBytes, burstLen) 33271784e68SYinan Xu{ 33371784e68SYinan Xu override lazy val module = new AXI4MemoryImp(this) 33471784e68SYinan Xu} 33571784e68SYinan Xu 33671784e68SYinan Xuclass AXI4MemoryWrapper ( 33771784e68SYinan Xu slave: AXI4SlaveNode, 33871784e68SYinan Xu memByte: Long, 33971784e68SYinan Xu useBlackBox: Boolean = false 34071784e68SYinan Xu)(implicit p: Parameters) extends AXI4MemorySlave(slave, memByte, useBlackBox) { 34171784e68SYinan Xu val ram = LazyModule(new AXI4Memory( 34271784e68SYinan Xu slaveParam.address, 34371784e68SYinan Xu memByte, 34471784e68SYinan Xu useBlackBox, 34571784e68SYinan Xu slaveParam.executable, 34671784e68SYinan Xu portParam.beatBytes, 34771784e68SYinan Xu burstLen 34871784e68SYinan Xu )) 34971784e68SYinan Xu ram.node := master 35071784e68SYinan Xu} 35171784e68SYinan Xu 35271784e68SYinan Xuabstract class AXI4MemorySlave ( 35371784e68SYinan Xu slave: AXI4SlaveNode, 35471784e68SYinan Xu memByte: Long, 35571784e68SYinan Xu useBlackBox: Boolean = false 35671784e68SYinan Xu)(implicit p: Parameters) extends LazyModule { 35771784e68SYinan Xu val master = AXI4MasterNode(List(slave.in.head._2.master)) 35871784e68SYinan Xu 35971784e68SYinan Xu val portParam = slave.portParams.head 36071784e68SYinan Xu val slaveParam = portParam.slaves.head 36171784e68SYinan Xu val burstLen = portParam.maxTransfer / portParam.beatBytes 36271784e68SYinan Xu 36371784e68SYinan Xu val io_axi4 = InModuleBody{ master.makeIOs() } 36471784e68SYinan Xu 36571784e68SYinan Xu lazy val module = new LazyModuleImp(this) { } 36671784e68SYinan Xu} 36771784e68SYinan Xu 36871784e68SYinan Xuobject AXI4MemorySlave { 36971784e68SYinan Xu def apply( 37071784e68SYinan Xu slave: AXI4SlaveNode, 37171784e68SYinan Xu memByte: Long, 37271784e68SYinan Xu useBlackBox: Boolean = false, 37371784e68SYinan Xu dynamicLatency: Boolean = false 37471784e68SYinan Xu )(implicit p: Parameters): AXI4MemorySlave = { 37571784e68SYinan Xu val memory = if (dynamicLatency) { 37671784e68SYinan Xu LazyModule(new AXI4MemoryWrapper(slave, memByte, useBlackBox)) 37771784e68SYinan Xu } else { 37871784e68SYinan Xu LazyModule(new AXI4RAMWrapper(slave, memByte, useBlackBox)) 37971784e68SYinan Xu } 38071784e68SYinan Xu memory 38171784e68SYinan Xu } 38271784e68SYinan Xu} 383