xref: /XiangShan/src/main/scala/device/AXI4RAM.scala (revision fc00d2822dcc80161e6da645d80c2385d229e73b)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package device
18
19import chisel3._
20import chisel3.util._
21import difftest.common.DifftestMem
22import freechips.rocketchip.amba.axi4.AXI4SlaveNode
23import freechips.rocketchip.diplomacy.{AddressSet, LazyModule}
24import org.chipsalliance.cde.config.Parameters
25
26class AXI4RAM
27(
28  address: Seq[AddressSet],
29  memByte: Long,
30  useBlackBox: Boolean = false,
31  executable: Boolean = true,
32  beatBytes: Int = 8,
33  burstLen: Int = 16,
34)(implicit p: Parameters)
35  extends AXI4SlaveModule(address, executable, beatBytes, burstLen)
36{
37  override lazy val module = new AXI4SlaveModuleImp(this){
38
39    val offsetBits = log2Up(memByte)
40
41    require(address.length >= 1)
42    val baseAddress = address(0).base
43
44    def index(addr: UInt) = ((addr - baseAddress.U)(offsetBits - 1, 0) >> log2Ceil(beatBytes)).asUInt
45
46    def inRange(idx: UInt) = idx < (memByte / beatBytes).U
47
48    val wIdx = index(waddr) + writeBeatCnt
49    val rIdx = index(raddr) + readBeatCnt
50    val wen = in.w.fire && inRange(wIdx)
51    require(beatBytes >= 8)
52
53    val rdata = if (useBlackBox) {
54      val mem = DifftestMem(memByte, beatBytes)
55      when (wen) {
56        mem.write(
57          addr = wIdx,
58          data = in.w.bits.data.asTypeOf(Vec(beatBytes, UInt(8.W))),
59          mask = in.w.bits.strb.asBools
60        )
61      }
62      val raddr = Mux(in.r.fire && !rLast, rIdx + 1.U, rIdx)
63      mem.readAndHold(raddr, in.ar.fire || in.r.fire).asUInt
64    } else {
65      val mem = Mem(memByte / beatBytes, Vec(beatBytes, UInt(8.W)))
66
67      val wdata = VecInit.tabulate(beatBytes) { i => in.w.bits.data(8 * (i + 1) - 1, 8 * i) }
68      when(wen) {
69        mem.write(wIdx, wdata, in.w.bits.strb.asBools)
70      }
71
72      Cat(mem.read(rIdx).reverse)
73    }
74    in.r.bits.data := rdata
75  }
76}
77
78class AXI4RAMWrapper (
79  slave: AXI4SlaveNode,
80  memByte: Long,
81  useBlackBox: Boolean = false
82 )(implicit p: Parameters) extends AXI4MemorySlave(slave, memByte, useBlackBox) {
83  val ram = LazyModule(new AXI4RAM(
84    slaveParam.address, memByte, useBlackBox,
85    slaveParam.executable, portParam.beatBytes, burstLen
86  ))
87  ram.node := master
88}
89