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