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 chipsalliance.rocketchip.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import chisel3.experimental.ExtModule 23import freechips.rocketchip.amba.axi4.{AXI4EdgeParameters, AXI4MasterNode, AXI4SlaveNode} 24import freechips.rocketchip.diplomacy.{AddressSet, InModuleBody, LazyModule, LazyModuleImp, RegionType} 25import top.HaveAXI4MemPort 26import xiangshan.HasXSParameter 27import utils.MaskExpand 28 29class RAMHelper(memByte: BigInt) extends ExtModule { 30 val DataBits = 64 31 32 val clk = IO(Input(Clock())) 33 val en = IO(Input(Bool())) 34 val rIdx = IO(Input(UInt(DataBits.W))) 35 val rdata = IO(Output(UInt(DataBits.W))) 36 val wIdx = IO(Input(UInt(DataBits.W))) 37 val wdata = IO(Input(UInt(DataBits.W))) 38 val wmask = IO(Input(UInt(DataBits.W))) 39 val wen = IO(Input(Bool())) 40} 41 42class AXI4RAM 43( 44 address: Seq[AddressSet], 45 memByte: Long, 46 useBlackBox: Boolean = false, 47 executable: Boolean = true, 48 beatBytes: Int = 8, 49 burstLen: Int = 16, 50)(implicit p: Parameters) 51 extends AXI4SlaveModule(address, executable, beatBytes, burstLen) 52{ 53 override lazy val module = new AXI4SlaveModuleImp(this){ 54 55 val split = beatBytes / 8 56 val bankByte = memByte / split 57 val offsetBits = log2Up(memByte) 58 59 require(address.length >= 1) 60 val baseAddress = address(0).base 61 62 def index(addr: UInt) = ((addr - baseAddress.U)(offsetBits - 1, 0) >> log2Ceil(beatBytes)).asUInt() 63 64 def inRange(idx: UInt) = idx < (memByte / beatBytes).U 65 66 val wIdx = index(waddr) + writeBeatCnt 67 val rIdx = index(raddr) + readBeatCnt 68 val wen = in.w.fire() && inRange(wIdx) 69 require(beatBytes >= 8) 70 71 val rdata = if (useBlackBox) { 72 val mems = (0 until split).map {_ => Module(new RAMHelper(bankByte))} 73 mems.zipWithIndex map { case (mem, i) => 74 mem.clk := clock 75 mem.en := !reset.asBool() && ((state === s_rdata) || (state === s_wdata)) 76 mem.rIdx := (rIdx << log2Up(split)) + i.U 77 mem.wIdx := (wIdx << log2Up(split)) + i.U 78 mem.wdata := in.w.bits.data((i + 1) * 64 - 1, i * 64) 79 mem.wmask := MaskExpand(in.w.bits.strb((i + 1) * 8 - 1, i * 8)) 80 mem.wen := wen 81 } 82 val rdata = mems.map {mem => mem.rdata} 83 Cat(rdata.reverse) 84 } else { 85 val mem = Mem(memByte / beatBytes, Vec(beatBytes, UInt(8.W))) 86 87 val wdata = VecInit.tabulate(beatBytes) { i => in.w.bits.data(8 * (i + 1) - 1, 8 * i) } 88 when(wen) { 89 mem.write(wIdx, wdata, in.w.bits.strb.asBools()) 90 } 91 92 Cat(mem.read(rIdx).reverse) 93 } 94 in.r.bits.data := rdata 95 } 96} 97 98class AXI4RAMWrapper 99(snode: AXI4SlaveNode, memByte: Long, useBlackBox: Boolean = false) 100(implicit p: Parameters) 101 extends LazyModule { 102 103 val mnode = AXI4MasterNode(List(snode.in.head._2.master)) 104 105 val portParam = snode.portParams.head 106 val slaveParam = portParam.slaves.head 107 val burstLen = portParam.maxTransfer / portParam.beatBytes 108 val ram = LazyModule(new AXI4RAM( 109 slaveParam.address, memByte, useBlackBox, 110 slaveParam.executable, portParam.beatBytes, burstLen 111 )) 112 ram.node := mnode 113 114 val io_axi4 = InModuleBody{ mnode.makeIOs() } 115 def connectToSoC(soc: HaveAXI4MemPort) = { 116 io_axi4 <> soc.memory 117 } 118 119 lazy val module = new LazyModuleImp(this){} 120} 121