xref: /XiangShan/src/main/scala/device/AXI4RAM.scala (revision 2225d46ebbe2fd16b9b29963c27a7d0385a42709)
1package device
2
3import chipsalliance.rocketchip.config.Parameters
4import chisel3._
5import chisel3.util._
6import freechips.rocketchip.amba.axi4.{AXI4SlaveNode, AXI4EdgeParameters, AXI4MasterNode}
7import freechips.rocketchip.diplomacy.{AddressSet, InModuleBody, LazyModule, LazyModuleImp, RegionType}
8import top.HaveAXI4MemPort
9import xiangshan.HasXSParameter
10import utils.MaskExpand
11
12class RAMHelper(memByte: BigInt) extends BlackBox {
13  val DataBits = 64
14  val io = IO(new Bundle {
15    val clk   = Input(Clock())
16    val en    = Input(Bool())
17    val rIdx  = Input(UInt(DataBits.W))
18    val rdata = Output(UInt(DataBits.W))
19    val wIdx  = Input(UInt(DataBits.W))
20    val wdata = Input(UInt(DataBits.W))
21    val wmask = Input(UInt(DataBits.W))
22    val wen   = Input(Bool())
23  })
24}
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 split = beatBytes / 8
40    val bankByte = memByte / split
41    val offsetBits = log2Up(memByte)
42
43    require(address.length >= 1)
44    val baseAddress = address(0).base
45
46    def index(addr: UInt) = ((addr - baseAddress.U)(offsetBits - 1, 0) >> log2Ceil(beatBytes)).asUInt()
47
48    def inRange(idx: UInt) = idx < (memByte / beatBytes).U
49
50    val wIdx = index(waddr) + writeBeatCnt
51    val rIdx = index(raddr) + readBeatCnt
52    val wen = in.w.fire() && inRange(wIdx)
53    require(beatBytes >= 8)
54
55    val rdata = if (useBlackBox) {
56      val mems = (0 until split).map {_ => Module(new RAMHelper(bankByte))}
57      mems.zipWithIndex map { case (mem, i) =>
58        mem.io.clk   := clock
59        mem.io.en    := !reset.asBool() && ((state === s_rdata) || (state === s_wdata))
60        mem.io.rIdx  := (rIdx << log2Up(split)) + i.U
61        mem.io.wIdx  := (wIdx << log2Up(split)) + i.U
62        mem.io.wdata := in.w.bits.data((i + 1) * 64 - 1, i * 64)
63        mem.io.wmask := MaskExpand(in.w.bits.strb((i + 1) * 8 - 1, i * 8))
64        mem.io.wen   := wen
65      }
66      val rdata = mems.map {mem => mem.io.rdata}
67      Cat(rdata.reverse)
68    } else {
69      val mem = Mem(memByte / beatBytes, Vec(beatBytes, UInt(8.W)))
70
71      val wdata = VecInit.tabulate(beatBytes) { i => in.w.bits.data(8 * (i + 1) - 1, 8 * i) }
72      when(wen) {
73        mem.write(wIdx, wdata, in.w.bits.strb.asBools())
74      }
75
76      Cat(mem.read(rIdx).reverse)
77    }
78    in.r.bits.data := rdata
79  }
80}
81
82class AXI4RAMWrapper
83(snode: AXI4SlaveNode, memByte: Long, useBlackBox: Boolean = false)
84(implicit p: Parameters)
85  extends LazyModule {
86
87  val mnode = AXI4MasterNode(List(snode.in.head._2.master))
88
89  val portParam = snode.portParams.head
90  val slaveParam = portParam.slaves.head
91  val burstLen = portParam.maxTransfer / portParam.beatBytes
92  val ram = LazyModule(new AXI4RAM(
93    slaveParam.address, memByte, useBlackBox,
94    slaveParam.executable, portParam.beatBytes, burstLen
95  ))
96  ram.node := mnode
97
98  val io_axi4 = InModuleBody{ mnode.makeIOs() }
99  def connectToSoC(soc: HaveAXI4MemPort) = {
100    io_axi4 <> soc.memory
101  }
102
103  lazy val module = new LazyModuleImp(this){}
104}
105