1/*************************************************************************************** 2* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3* Copyright (c) 2024 Institute of Computing Technology, Chinese Academy of Sciences 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 chisel3.experimental.dataview._ 22import org.chipsalliance.cde.config.Parameters 23import freechips.rocketchip.diplomacy._ 24import freechips.rocketchip.amba.axi4._ 25import freechips.rocketchip.tilelink._ 26import utils.{AXI4LiteBundle, VerilogAXI4LiteRecord} 27 28class imsic_axi_top( 29 AXI_ID_WIDTH: Int = 5, 30 AXI_ADDR_WIDTH: Int = 32, 31 NR_INTP_FILES: Int = 7, 32 NR_HARTS: Int = 1, 33 NR_SRC: Int = 256, 34 SETIP_KEEP_CYCLES: Int = 8 35) extends BlackBox(Map( 36 "AXI_ID_WIDTH" -> AXI_ID_WIDTH, 37 "AXI_ADDR_WIDTH" -> AXI_ADDR_WIDTH, 38 "NR_INTP_FILES" -> NR_INTP_FILES, 39 "NR_HARTS" -> NR_HARTS, 40 "NR_SRC" -> NR_SRC, 41 "SETIP_KEEP_CYCLES" -> SETIP_KEEP_CYCLES 42)) with HasBlackBoxResource { 43 private val NR_SRC_WIDTH = log2Ceil(NR_SRC) 44 private val NR_HARTS_WIDTH = if (NR_HARTS == 1) 1 else log2Ceil(NR_HARTS) 45 private val INTP_FILE_WIDTH = log2Ceil(NR_INTP_FILES) 46 private val MSI_INFO_WIDTH = NR_HARTS_WIDTH + INTP_FILE_WIDTH + NR_SRC_WIDTH 47 val io = IO(new Bundle { 48 // crg 49 val axi_clk = Input(Clock()) 50 val axi_rstn = Input(AsyncReset()) 51 val fifo_rstn = Input(AsyncReset()) 52 // bus to access the m interrupt file 53 val m_s = Flipped(new VerilogAXI4LiteRecord(AXI_ADDR_WIDTH, 32, AXI_ID_WIDTH)) 54 // bus to access the s interrupt file 55 val s_s = Flipped(new VerilogAXI4LiteRecord(AXI_ADDR_WIDTH, 32, AXI_ID_WIDTH)) 56 // imsic_csr_top 57 val o_msi_info = Output(UInt(MSI_INFO_WIDTH.W)) 58 val o_msi_info_vld = Output(Bool()) 59 }) 60 addResource("/aia/src/rtl/imsic/imsic_axi_top.sv") 61 addResource("/aia/src/rtl/imsic/imsic_axi2reg.sv") 62 addResource("/aia/src/rtl/imsic/imsic_regmap.sv") 63 addResource("/aia/src/rtl/imsic/common/generic_fifo_dc_gray.sv") 64 addResource("/aia/src/rtl/imsic/common/generic_dpram.sv") 65} 66 67class imsic_bus_top( 68 useTL: Boolean = false, 69 baseAddress: (BigInt, BigInt), /* (M-mode, S/VS-mode) */ 70 maxHarts: Int = 512, 71 AXI_ID_WIDTH: Int = 5, 72 AXI_ADDR_WIDTH: Int = 32, 73 NR_INTP_FILES: Int = 7, 74 NR_HARTS: Int = 1, 75 NR_SRC: Int = 256, 76 SETIP_KEEP_CYCLES: Int = 8 77)(implicit p: Parameters) extends LazyModule { 78 private val NR_SRC_WIDTH = log2Ceil(NR_SRC) 79 private val NR_HARTS_WIDTH = if (NR_HARTS == 1) 1 else log2Ceil(NR_HARTS) 80 private val INTP_FILE_WIDTH = log2Ceil(NR_INTP_FILES) 81 private val MSI_INFO_WIDTH = NR_HARTS_WIDTH + INTP_FILE_WIDTH + NR_SRC_WIDTH 82 83 private val m_base = baseAddress._1; 84 private val m_size = maxHarts * 0x1000; 85 private val s_base = baseAddress._2; 86 private val s_size = maxHarts * 0x8000; 87 88 println(f"IMSIC: address-mapping for ${maxHarts} HARTs") 89 println(f"IMSIC: M-mode: [0x${m_base}%08X, 0x${m_base + m_size - 1}%08X]") 90 println(f"IMSIC: S/VS-mode: [0x${s_base}%08X, 0x${s_base + s_size - 1}%08X]") 91 92 private val axi4nodes = Seq( 93 AXI4SlaveNode(Seq(AXI4SlavePortParameters( 94 Seq(AXI4SlaveParameters( 95 Seq(AddressSet(m_base, m_size - 1)), 96 regionType = RegionType.UNCACHED, 97 supportsWrite = TransferSizes(1, 4), 98 supportsRead = TransferSizes(1, 4), 99 interleavedId = Some(0) 100 )), 101 beatBytes = 4 102 ))), 103 AXI4SlaveNode(Seq(AXI4SlavePortParameters( 104 Seq(AXI4SlaveParameters( 105 Seq(AddressSet(s_base, s_size - 1)), 106 regionType = RegionType.UNCACHED, 107 supportsWrite = TransferSizes(1, 4), 108 supportsRead = TransferSizes(1, 4), 109 interleavedId = Some(0) 110 )), 111 beatBytes = 4 112 )))) 113 114 val tl = Option.when(useTL) { 115 val tlnodes = Seq.fill(2)(TLClientNode(Seq(TLMasterPortParameters.v1( 116 clients = Seq(TLMasterParameters.v1( 117 "tl", 118 sourceId = IdRange(0, 16) 119 )) 120 )))) 121 axi4nodes zip tlnodes foreach { case (axi4node, tlnode) => 122 axi4node := 123 AXI4IdIndexer(AXI_ID_WIDTH) := 124 AXI4Buffer() := 125 AXI4Buffer() := 126 AXI4UserYanker(Some(1)) := 127 TLToAXI4() := 128 TLWidthWidget(4) := 129 TLFIFOFixer() := 130 TLBuffer() := 131 tlnode 132 } 133 134 tlnodes 135 } 136 137 val tl_m = tl.map(x => InModuleBody(x(0).makeIOs())) 138 val tl_s = tl.map(x => InModuleBody(x(1).makeIOs())) 139 140 val axiMasterNode = Option.when(!useTL) { 141 val node = AXI4MasterNode(Seq(AXI4MasterPortParameters( 142 Seq(AXI4MasterParameters( 143 name = "s_axi_", 144 id = IdRange(0, 1 << AXI_ID_WIDTH) 145 )) 146 ))) 147 val xbar = AXI4Xbar(TLArbiter.lowestIndexFirst) 148 axi4nodes.foreach { _ := xbar } 149 xbar := AXI4Buffer() := node 150 node 151 } 152 153 class imsic_bus_top_imp(wrapper: imsic_bus_top) extends LazyModuleImp(wrapper) { 154 // imsic csr top io 155 val o_msi_info = IO(Output(UInt(MSI_INFO_WIDTH.W))) 156 val o_msi_info_vld = IO(Output(Bool())) 157 158 // axi4lite io 159 val axi4lite = Option.when(!useTL)(IO(Flipped(new VerilogAXI4LiteRecord(AXI_ADDR_WIDTH, 32, AXI_ID_WIDTH)))) 160 161 // imsic axi top 162 val u_imsic_axi_top = Module(new imsic_axi_top) 163 164 // connection: crg 165 u_imsic_axi_top.io.axi_clk := clock 166 u_imsic_axi_top.io.axi_rstn := (~reset.asBool).asAsyncReset 167 u_imsic_axi_top.io.fifo_rstn := (~reset.asBool).asAsyncReset // TODO: axi_rstn & sw_rstn 168 169 // connection: imsic csr top 170 o_msi_info := u_imsic_axi_top.io.o_msi_info 171 o_msi_info_vld := u_imsic_axi_top.io.o_msi_info_vld 172 173 // connection: axi4lite 174 axi4lite.foreach { 175 _.viewAs[AXI4LiteBundle].connectToAXI4(wrapper.axiMasterNode.get.out.head._1) 176 } 177 178 // connection: axi4 179 wrapper.axi4nodes.map(_.in.head._1) zip 180 Seq(u_imsic_axi_top.io.m_s, u_imsic_axi_top.io.s_s) foreach { 181 case (axi4, axi4lite) => axi4lite.viewAs[AXI4LiteBundle].connectFromAXI4(axi4) 182 } 183 } 184 185 lazy val module = new imsic_bus_top_imp(this) 186} 187