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