xref: /XiangShan/src/main/scala/device/AXI4Memory.scala (revision 71784e682e0e51f8ea068d2f28919c7a9e97f805)
1*71784e68SYinan Xu/***************************************************************************************
2*71784e68SYinan Xu  * Copyright (c) 2020-2022 Institute of Computing Technology, Chinese Academy of Sciences
3*71784e68SYinan Xu  *
4*71784e68SYinan Xu  * XiangShan is licensed under Mulan PSL v2.
5*71784e68SYinan Xu  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6*71784e68SYinan Xu  * You may obtain a copy of Mulan PSL v2 at:
7*71784e68SYinan Xu  *          http://license.coscl.org.cn/MulanPSL2
8*71784e68SYinan Xu  *
9*71784e68SYinan Xu  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10*71784e68SYinan Xu  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11*71784e68SYinan Xu  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12*71784e68SYinan Xu  *
13*71784e68SYinan Xu  * See the Mulan PSL v2 for more details.
14*71784e68SYinan Xu  ***************************************************************************************/
15*71784e68SYinan Xu
16*71784e68SYinan Xupackage device
17*71784e68SYinan Xu
18*71784e68SYinan Xuimport chipsalliance.rocketchip.config.Parameters
19*71784e68SYinan Xuimport chisel3._
20*71784e68SYinan Xuimport chisel3.experimental.ExtModule
21*71784e68SYinan Xuimport chisel3.util._
22*71784e68SYinan Xuimport freechips.rocketchip.amba.axi4.{AXI4MasterNode, AXI4Parameters, AXI4SlaveNode}
23*71784e68SYinan Xuimport freechips.rocketchip.diplomacy.{AddressSet, InModuleBody, LazyModule, LazyModuleImp}
24*71784e68SYinan Xuimport utils._
25*71784e68SYinan Xu
26*71784e68SYinan Xuclass MemoryRWHelper extends ExtModule with HasExtModuleInline {
27*71784e68SYinan Xu  val DataBits = 64
28*71784e68SYinan Xu
29*71784e68SYinan Xu  val clock = IO(Input(Clock()))
30*71784e68SYinan Xu  val reset = IO(Input(Reset()))
31*71784e68SYinan Xu  val ren   = IO(Input(Bool()))
32*71784e68SYinan Xu  val rIdx  = IO(Input(UInt(DataBits.W)))
33*71784e68SYinan Xu  val rdata = IO(Output(UInt(DataBits.W)))
34*71784e68SYinan Xu  val wen   = IO(Input(Bool()))
35*71784e68SYinan Xu  val wIdx  = IO(Input(UInt(DataBits.W)))
36*71784e68SYinan Xu  val wdata = IO(Input(UInt(DataBits.W)))
37*71784e68SYinan Xu  val wmask = IO(Input(UInt(DataBits.W)))
38*71784e68SYinan Xu
39*71784e68SYinan Xu  def read(enable: Bool, address: UInt): UInt = {
40*71784e68SYinan Xu    ren := enable
41*71784e68SYinan Xu    rIdx := address
42*71784e68SYinan Xu    rdata
43*71784e68SYinan Xu  }
44*71784e68SYinan Xu  def write(enable: Bool, address: UInt, data: UInt, mask: UInt): Unit = {
45*71784e68SYinan Xu    wen := enable
46*71784e68SYinan Xu    wIdx := address
47*71784e68SYinan Xu    wdata := data
48*71784e68SYinan Xu    wmask := mask
49*71784e68SYinan Xu  }
50*71784e68SYinan Xu
51*71784e68SYinan Xu  val verilogLines = Seq(
52*71784e68SYinan Xu    "module MemoryRWHelper(",
53*71784e68SYinan Xu    "  input         clock,",
54*71784e68SYinan Xu    "  input         reset,",
55*71784e68SYinan Xu    "  input         ren,",
56*71784e68SYinan Xu    "  input  [63:0] rIdx,",
57*71784e68SYinan Xu    "  output [63:0] rdata,",
58*71784e68SYinan Xu    "  input  [63:0] wIdx,",
59*71784e68SYinan Xu    "  input  [63:0] wdata,",
60*71784e68SYinan Xu    "  input  [63:0] wmask,",
61*71784e68SYinan Xu    "  input         wen",
62*71784e68SYinan Xu    ");",
63*71784e68SYinan Xu    "",
64*71784e68SYinan Xu    "  assign rdata = (!reset && ren) ? ram_read_helper(1, rIdx) : 64'b0;",
65*71784e68SYinan Xu    "",
66*71784e68SYinan Xu    "  always @(posedge clock) begin",
67*71784e68SYinan Xu    "    if (!reset && wen) begin",
68*71784e68SYinan Xu    "      ram_write_helper(wIdx, wdata, wmask, 1);",
69*71784e68SYinan Xu    "    end",
70*71784e68SYinan Xu    "  end",
71*71784e68SYinan Xu    "",
72*71784e68SYinan Xu    "endmodule"
73*71784e68SYinan Xu  )
74*71784e68SYinan Xu  setInline(s"$desiredName.v", verilogLines.mkString("\n"))
75*71784e68SYinan Xu}
76*71784e68SYinan Xu
77*71784e68SYinan Xuobject MemoryRWHelper {
78*71784e68SYinan Xu  def apply(clock: Clock, reset: Reset): MemoryRWHelper = {
79*71784e68SYinan Xu    val helper = Module(new MemoryRWHelper)
80*71784e68SYinan Xu    helper.clock := clock
81*71784e68SYinan Xu    helper.reset := reset
82*71784e68SYinan Xu    helper
83*71784e68SYinan Xu  }
84*71784e68SYinan Xu}
85*71784e68SYinan Xu
86*71784e68SYinan Xuclass MemoryRequestHelper(requestType: Int)
87*71784e68SYinan Xu  extends ExtModule(Map("REQUEST_TYPE" -> requestType))
88*71784e68SYinan Xu  with HasExtModuleInline
89*71784e68SYinan Xu{
90*71784e68SYinan Xu  val clock     = IO(Input(Clock()))
91*71784e68SYinan Xu  val reset     = IO(Input(Reset()))
92*71784e68SYinan Xu  val io = IO(new Bundle {
93*71784e68SYinan Xu    val req = Flipped(ValidIO(new Bundle {
94*71784e68SYinan Xu      val addr = UInt(64.W)
95*71784e68SYinan Xu      val id   = UInt(32.W)
96*71784e68SYinan Xu    }))
97*71784e68SYinan Xu    val response = Output(Bool())
98*71784e68SYinan Xu  })
99*71784e68SYinan Xu
100*71784e68SYinan Xu  val verilogLines = Seq(
101*71784e68SYinan Xu    "import \"DPI-C\" function bit memory_request (",
102*71784e68SYinan Xu    "  input longint address,",
103*71784e68SYinan Xu    "  input int id,",
104*71784e68SYinan Xu    "  input bit isWrite",
105*71784e68SYinan Xu    ");",
106*71784e68SYinan Xu    "",
107*71784e68SYinan Xu    "module MemoryRequestHelper #(",
108*71784e68SYinan Xu    "  parameter REQUEST_TYPE",
109*71784e68SYinan Xu    ")(",
110*71784e68SYinan Xu    "  input             clock,",
111*71784e68SYinan Xu    "  input             reset,",
112*71784e68SYinan Xu    "  input             io_req_valid,",
113*71784e68SYinan Xu    "  input      [63:0] io_req_bits_addr,",
114*71784e68SYinan Xu    "  input      [31:0] io_req_bits_id,",
115*71784e68SYinan Xu    "  output reg        io_response",
116*71784e68SYinan Xu    ");",
117*71784e68SYinan Xu    "",
118*71784e68SYinan Xu    "always @(posedge clock or posedge reset) begin",
119*71784e68SYinan Xu    "  if (reset) begin",
120*71784e68SYinan Xu    "    io_response <= 1'b0;",
121*71784e68SYinan Xu    "  end",
122*71784e68SYinan Xu    "  else if (io_req_valid) begin",
123*71784e68SYinan Xu    "    io_response <= memory_request(io_req_bits_addr, io_req_bits_id, REQUEST_TYPE);",
124*71784e68SYinan Xu    "  end" +
125*71784e68SYinan Xu    "  else begin",
126*71784e68SYinan Xu    "    io_response <= 1'b0;",
127*71784e68SYinan Xu    "  end",
128*71784e68SYinan Xu    "end",
129*71784e68SYinan Xu    "",
130*71784e68SYinan Xu    "endmodule"
131*71784e68SYinan Xu  )
132*71784e68SYinan Xu  setInline(s"$desiredName.v", verilogLines.mkString("\n"))
133*71784e68SYinan Xu}
134*71784e68SYinan Xu
135*71784e68SYinan Xuclass MemoryResponseHelper(requestType: Int)
136*71784e68SYinan Xu  extends ExtModule(Map("REQUEST_TYPE" -> requestType))
137*71784e68SYinan Xu  with HasExtModuleInline
138*71784e68SYinan Xu{
139*71784e68SYinan Xu  val clock    = IO(Input(Clock()))
140*71784e68SYinan Xu  val reset    = IO(Input(Reset()))
141*71784e68SYinan Xu  val enable   = IO(Input(Bool()))
142*71784e68SYinan Xu  val response = IO(Output(UInt(64.W)))
143*71784e68SYinan Xu
144*71784e68SYinan Xu  val verilogLines = Seq(
145*71784e68SYinan Xu    "import \"DPI-C\" function longint memory_response (",
146*71784e68SYinan Xu    "  input bit isWrite",
147*71784e68SYinan Xu    ");",
148*71784e68SYinan Xu    "",
149*71784e68SYinan Xu    "module MemoryResponseHelper #(",
150*71784e68SYinan Xu    "  parameter REQUEST_TYPE",
151*71784e68SYinan Xu    ")(",
152*71784e68SYinan Xu    "  input             clock,",
153*71784e68SYinan Xu    "  input             reset,",
154*71784e68SYinan Xu    "  input             enable,",
155*71784e68SYinan Xu    "  output reg [63:0] response",
156*71784e68SYinan Xu    ");",
157*71784e68SYinan Xu    "",
158*71784e68SYinan Xu    "always @(posedge clock or posedge reset) begin",
159*71784e68SYinan Xu    "  if (reset) begin",
160*71784e68SYinan Xu    "    response <= 64'b0;",
161*71784e68SYinan Xu    "  end",
162*71784e68SYinan Xu    "  else if (!reset && enable) begin",
163*71784e68SYinan Xu    "    response <= memory_response(REQUEST_TYPE);",
164*71784e68SYinan Xu    "  end",
165*71784e68SYinan Xu    " else begin",
166*71784e68SYinan Xu    "    response <= 64'b0;",
167*71784e68SYinan Xu    "  end",
168*71784e68SYinan Xu    "end",
169*71784e68SYinan Xu    "",
170*71784e68SYinan Xu    "endmodule"
171*71784e68SYinan Xu  )
172*71784e68SYinan Xu  setInline(s"$desiredName.v", verilogLines.mkString("\n"))
173*71784e68SYinan Xu}
174*71784e68SYinan Xu
175*71784e68SYinan Xutrait MemoryHelper { this: Module =>
176*71784e68SYinan Xu  private def requestType(isWrite: Boolean): Int = if (isWrite) 1 else 0
177*71784e68SYinan Xu  private def request(valid: Bool, addr: UInt, id: UInt, isWrite: Boolean): Bool = {
178*71784e68SYinan Xu    val helper = Module(new MemoryRequestHelper(requestType(isWrite)))
179*71784e68SYinan Xu    helper.clock := clock
180*71784e68SYinan Xu    helper.reset := reset
181*71784e68SYinan Xu    helper.io.req.valid := valid
182*71784e68SYinan Xu    helper.io.req.bits.addr := addr
183*71784e68SYinan Xu    helper.io.req.bits.id := id
184*71784e68SYinan Xu    helper.io.response
185*71784e68SYinan Xu  }
186*71784e68SYinan Xu  protected def readRequest(valid: Bool, addr: UInt, id: UInt): Bool =
187*71784e68SYinan Xu    request(valid, addr, id, false)
188*71784e68SYinan Xu  protected def writeRequest(valid: Bool, addr: UInt, id: UInt): Bool =
189*71784e68SYinan Xu    request(valid, addr, id, true)
190*71784e68SYinan Xu  private def response(enable: Bool, isWrite: Boolean): (Bool, UInt) = {
191*71784e68SYinan Xu    val helper = Module(new MemoryResponseHelper(requestType(isWrite)))
192*71784e68SYinan Xu    helper.clock := clock
193*71784e68SYinan Xu    helper.reset := reset
194*71784e68SYinan Xu    helper.enable := enable
195*71784e68SYinan Xu    (helper.response(32), helper.response(31, 0))
196*71784e68SYinan Xu  }
197*71784e68SYinan Xu  protected def readResponse(enable: Bool): (Bool, UInt) =
198*71784e68SYinan Xu    response(enable, false)
199*71784e68SYinan Xu  protected def writeResponse(enable: Bool): (Bool, UInt) =
200*71784e68SYinan Xu    response(enable, true)
201*71784e68SYinan Xu}
202*71784e68SYinan Xu
203*71784e68SYinan Xuclass AXI4MemoryImp[T <: Data](outer: AXI4Memory) extends AXI4SlaveModuleImp(outer) with MemoryHelper {
204*71784e68SYinan Xu  val ramWidth = 8
205*71784e68SYinan Xu  val ramSplit = outer.beatBytes / ramWidth
206*71784e68SYinan Xu  val ramBaseAddr = outer.address.head.base
207*71784e68SYinan Xu  val ramOffsetBits = log2Ceil(outer.memByte)
208*71784e68SYinan Xu  def ramIndex(addr: UInt) = ((addr - ramBaseAddr.U)(ramOffsetBits - 1, 0) >> log2Ceil(ramWidth)).asUInt
209*71784e68SYinan Xu  val ramHelper = Seq.fill(ramSplit)(MemoryRWHelper(clock, reset))
210*71784e68SYinan Xu
211*71784e68SYinan Xu  val numOutstanding = 1 << in.ar.bits.id.getWidth
212*71784e68SYinan Xu  val addressMem = Mem(numOutstanding, UInt((in.ar.bits.addr.getWidth - log2Ceil(ramWidth)).W))
213*71784e68SYinan Xu  val arlenMem = Mem(numOutstanding, UInt(in.ar.bits.len.getWidth.W))
214*71784e68SYinan Xu
215*71784e68SYinan Xu  // accept a read request and send it to the external model
216*71784e68SYinan Xu  val pending_read_req_valid = RegInit(false.B)
217*71784e68SYinan Xu  val pending_read_req_bits  = RegEnable(in.ar.bits, in.ar.fire)
218*71784e68SYinan Xu  val pending_read_req_ready = Wire(Bool())
219*71784e68SYinan Xu  val pending_read_need_req = pending_read_req_valid && !pending_read_req_ready
220*71784e68SYinan Xu  val read_req_valid = pending_read_need_req || in.ar.valid
221*71784e68SYinan Xu  val read_req_bits  = Mux(pending_read_need_req, pending_read_req_bits, in.ar.bits)
222*71784e68SYinan Xu  pending_read_req_ready := readRequest(read_req_valid, read_req_bits.addr, read_req_bits.id)
223*71784e68SYinan Xu
224*71784e68SYinan Xu  when (in.ar.fire) {
225*71784e68SYinan Xu    pending_read_req_valid := true.B
226*71784e68SYinan Xu    addressMem.write(read_req_bits.id, ramIndex(read_req_bits.addr))
227*71784e68SYinan Xu    arlenMem.write(read_req_bits.id, read_req_bits.len)
228*71784e68SYinan Xu  }.elsewhen (pending_read_req_ready) {
229*71784e68SYinan Xu    pending_read_req_valid := false.B
230*71784e68SYinan Xu  }
231*71784e68SYinan Xu  in.ar.ready := !pending_read_req_valid || pending_read_req_ready
232*71784e68SYinan Xu
233*71784e68SYinan Xu  // accept a write request (including address and data) and send it to the external model
234*71784e68SYinan Xu  val pending_write_req_valid = RegInit(VecInit.fill(2)(false.B))
235*71784e68SYinan Xu  val pending_write_req_bits  = RegEnable(in.aw.bits, in.aw.fire)
236*71784e68SYinan Xu  val pending_write_req_data  = RegEnable(in.w.bits, in.w.fire)
237*71784e68SYinan Xu  XSError(in.aw.fire && in.aw.bits.len === 0.U, "data must have more than one beat now")
238*71784e68SYinan Xu  val pending_write_req_ready = Wire(Bool())
239*71784e68SYinan Xu  val pending_write_need_req = pending_write_req_valid.last && !pending_write_req_ready
240*71784e68SYinan Xu  val write_req_valid = pending_write_req_valid.head && (pending_write_need_req || in.w.valid && in.w.bits.last)
241*71784e68SYinan Xu  pending_write_req_ready := writeRequest(write_req_valid, pending_write_req_bits.addr, pending_write_req_bits.id)
242*71784e68SYinan Xu
243*71784e68SYinan Xu  when (in.aw.fire) {
244*71784e68SYinan Xu    pending_write_req_valid.head := true.B
245*71784e68SYinan Xu  }.elsewhen (pending_write_req_ready) {
246*71784e68SYinan Xu    pending_write_req_valid.head := false.B
247*71784e68SYinan Xu  }
248*71784e68SYinan Xu  val write_req_last = in.w.fire && in.w.bits.last
249*71784e68SYinan Xu  when (write_req_last) {
250*71784e68SYinan Xu    pending_write_req_valid.last := true.B
251*71784e68SYinan Xu  }.elsewhen (pending_write_req_ready) {
252*71784e68SYinan Xu    pending_write_req_valid.last := false.B
253*71784e68SYinan Xu  }
254*71784e68SYinan Xu  in.aw.ready := !pending_write_req_valid.head || pending_write_req_ready
255*71784e68SYinan Xu  in.w.ready := in.aw.ready || !pending_write_req_valid.last
256*71784e68SYinan Xu
257*71784e68SYinan Xu  // ram is written when write data fire
258*71784e68SYinan Xu  val wdata_cnt = Counter(outer.burstLen)
259*71784e68SYinan Xu  val write_req_addr = Mux(in.aw.fire, in.aw.bits.addr, pending_write_req_bits.addr)
260*71784e68SYinan Xu  val write_req_index = ramIndex(write_req_addr) + Cat(wdata_cnt.value, 0.U(log2Ceil(ramSplit).W))
261*71784e68SYinan Xu  for ((ram, i) <- ramHelper.zipWithIndex) {
262*71784e68SYinan Xu    val enable = in.w.fire
263*71784e68SYinan Xu    val address = write_req_index + i.U
264*71784e68SYinan Xu    val data = in.w.bits.data(ramWidth * 8 * i + 63, ramWidth * 8 * i)
265*71784e68SYinan Xu    val mask = MaskExpand(in.w.bits.strb(i * 8 + 7, i * 8))
266*71784e68SYinan Xu    ram.write(enable, address, data, mask)
267*71784e68SYinan Xu  }
268*71784e68SYinan Xu  when (write_req_last) {
269*71784e68SYinan Xu    wdata_cnt.reset()
270*71784e68SYinan Xu  }.elsewhen (in.w.fire) {
271*71784e68SYinan Xu    wdata_cnt.inc()
272*71784e68SYinan Xu  }
273*71784e68SYinan Xu
274*71784e68SYinan Xu  // read data response
275*71784e68SYinan Xu  val pending_read_resp_valid = RegInit(false.B)
276*71784e68SYinan Xu  val pending_read_resp_id = Reg(UInt(in.r.bits.id.getWidth.W))
277*71784e68SYinan Xu  val has_read_resp = Wire(Bool())
278*71784e68SYinan Xu  val read_resp_last = in.r.fire && in.r.bits.last
279*71784e68SYinan Xu  val (read_resp_valid, read_resp_id) = readResponse(!has_read_resp || read_resp_last)
280*71784e68SYinan Xu  has_read_resp := (read_resp_valid && !read_resp_last) || pending_read_resp_valid
281*71784e68SYinan Xu  val rdata_cnt = Counter(outer.burstLen)
282*71784e68SYinan Xu  val read_resp_addr = addressMem(in.r.bits.id) + Cat(rdata_cnt.value, 0.U(log2Ceil(ramSplit).W))
283*71784e68SYinan Xu  val read_resp_len = arlenMem(in.r.bits.id)
284*71784e68SYinan Xu  in.r.valid := read_resp_valid || pending_read_resp_valid
285*71784e68SYinan Xu  in.r.bits.id := Mux(pending_read_resp_valid, pending_read_resp_id, read_resp_id)
286*71784e68SYinan Xu  val rdata = ramHelper.zipWithIndex.map{ case (ram, i) => ram.read(in.r.valid, read_resp_addr + i.U) }
287*71784e68SYinan Xu  in.r.bits.data := VecInit(rdata).asUInt
288*71784e68SYinan Xu  in.r.bits.resp := AXI4Parameters.RESP_OKAY
289*71784e68SYinan Xu  in.r.bits.last := (rdata_cnt.value === read_resp_len)
290*71784e68SYinan Xu
291*71784e68SYinan Xu  when (!pending_read_resp_valid && read_resp_valid && !read_resp_last) {
292*71784e68SYinan Xu    pending_read_resp_valid := true.B
293*71784e68SYinan Xu    pending_read_resp_id := read_resp_id
294*71784e68SYinan Xu  }.elsewhen (pending_read_resp_valid && !read_resp_valid && read_resp_last) {
295*71784e68SYinan Xu    pending_read_resp_valid := false.B
296*71784e68SYinan Xu  }
297*71784e68SYinan Xu  when (read_resp_last) {
298*71784e68SYinan Xu    rdata_cnt.reset()
299*71784e68SYinan Xu  }.elsewhen (in.r.fire) {
300*71784e68SYinan Xu    rdata_cnt.inc()
301*71784e68SYinan Xu  }
302*71784e68SYinan Xu
303*71784e68SYinan Xu  // write response
304*71784e68SYinan Xu  val pending_write_resp_valid = RegInit(false.B)
305*71784e68SYinan Xu  val pending_write_resp_id = Reg(UInt(in.b.bits.id.getWidth.W))
306*71784e68SYinan Xu  val has_write_resp = Wire(Bool())
307*71784e68SYinan Xu  val (write_resp_valid, write_resp_id) = writeResponse(!has_write_resp || in.b.fire)
308*71784e68SYinan Xu  has_write_resp := (write_resp_valid && !read_resp_last) || pending_write_resp_valid
309*71784e68SYinan Xu  in.b.valid := write_resp_valid || pending_write_resp_valid
310*71784e68SYinan Xu  in.b.bits.id := Mux(pending_write_resp_valid, pending_write_resp_id, write_resp_id)
311*71784e68SYinan Xu  in.b.bits.resp := AXI4Parameters.RESP_OKAY
312*71784e68SYinan Xu
313*71784e68SYinan Xu  when (!pending_write_resp_valid && write_resp_valid && !in.b.ready) {
314*71784e68SYinan Xu    pending_write_resp_valid := true.B
315*71784e68SYinan Xu    pending_write_resp_id := pending_write_resp_id
316*71784e68SYinan Xu  }.elsewhen (pending_write_resp_valid && !write_resp_valid && in.b.ready) {
317*71784e68SYinan Xu    pending_write_resp_valid := false.B
318*71784e68SYinan Xu  }
319*71784e68SYinan Xu}
320*71784e68SYinan Xu
321*71784e68SYinan Xuclass AXI4Memory
322*71784e68SYinan Xu(
323*71784e68SYinan Xu  val address: Seq[AddressSet],
324*71784e68SYinan Xu  val memByte: Long,
325*71784e68SYinan Xu  val useBlackBox: Boolean = false,
326*71784e68SYinan Xu  val executable: Boolean = true,
327*71784e68SYinan Xu  val beatBytes: Int,
328*71784e68SYinan Xu  val burstLen: Int,
329*71784e68SYinan Xu)(implicit p: Parameters)
330*71784e68SYinan Xu  extends AXI4SlaveModule(address, executable, beatBytes, burstLen)
331*71784e68SYinan Xu{
332*71784e68SYinan Xu  override lazy val module = new AXI4MemoryImp(this)
333*71784e68SYinan Xu}
334*71784e68SYinan Xu
335*71784e68SYinan Xuclass AXI4MemoryWrapper (
336*71784e68SYinan Xu  slave: AXI4SlaveNode,
337*71784e68SYinan Xu  memByte: Long,
338*71784e68SYinan Xu  useBlackBox: Boolean = false
339*71784e68SYinan Xu)(implicit p: Parameters) extends AXI4MemorySlave(slave, memByte, useBlackBox) {
340*71784e68SYinan Xu  val ram = LazyModule(new AXI4Memory(
341*71784e68SYinan Xu    slaveParam.address,
342*71784e68SYinan Xu    memByte,
343*71784e68SYinan Xu    useBlackBox,
344*71784e68SYinan Xu    slaveParam.executable,
345*71784e68SYinan Xu    portParam.beatBytes,
346*71784e68SYinan Xu    burstLen
347*71784e68SYinan Xu  ))
348*71784e68SYinan Xu  ram.node := master
349*71784e68SYinan Xu}
350*71784e68SYinan Xu
351*71784e68SYinan Xuabstract class AXI4MemorySlave (
352*71784e68SYinan Xu  slave: AXI4SlaveNode,
353*71784e68SYinan Xu  memByte: Long,
354*71784e68SYinan Xu  useBlackBox: Boolean = false
355*71784e68SYinan Xu)(implicit p: Parameters) extends LazyModule {
356*71784e68SYinan Xu  val master = AXI4MasterNode(List(slave.in.head._2.master))
357*71784e68SYinan Xu
358*71784e68SYinan Xu  val portParam = slave.portParams.head
359*71784e68SYinan Xu  val slaveParam = portParam.slaves.head
360*71784e68SYinan Xu  val burstLen = portParam.maxTransfer / portParam.beatBytes
361*71784e68SYinan Xu
362*71784e68SYinan Xu  val io_axi4 = InModuleBody{ master.makeIOs() }
363*71784e68SYinan Xu
364*71784e68SYinan Xu  lazy val module = new LazyModuleImp(this) { }
365*71784e68SYinan Xu}
366*71784e68SYinan Xu
367*71784e68SYinan Xuobject AXI4MemorySlave {
368*71784e68SYinan Xu  def apply(
369*71784e68SYinan Xu    slave: AXI4SlaveNode,
370*71784e68SYinan Xu    memByte: Long,
371*71784e68SYinan Xu    useBlackBox: Boolean = false,
372*71784e68SYinan Xu    dynamicLatency: Boolean = false
373*71784e68SYinan Xu  )(implicit p: Parameters): AXI4MemorySlave = {
374*71784e68SYinan Xu    val memory = if (dynamicLatency) {
375*71784e68SYinan Xu      LazyModule(new AXI4MemoryWrapper(slave, memByte, useBlackBox))
376*71784e68SYinan Xu    } else {
377*71784e68SYinan Xu      LazyModule(new AXI4RAMWrapper(slave, memByte, useBlackBox))
378*71784e68SYinan Xu    }
379*71784e68SYinan Xu    memory
380*71784e68SYinan Xu  }
381*71784e68SYinan Xu}
382