xref: /XiangShan/src/main/scala/device/AXI4Memory.scala (revision 9e0994ab89a743c3ab1680cfe89ef51d7657ac83)
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