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, 1) 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 tlnode 131 } 132 133 tlnodes 134 } 135 136 val tl_m = tl.map(x => InModuleBody(x(0).makeIOs())) 137 val tl_s = tl.map(x => InModuleBody(x(1).makeIOs())) 138 139 val axiMasterNode = Option.when(!useTL) { 140 val node = AXI4MasterNode(Seq(AXI4MasterPortParameters( 141 Seq(AXI4MasterParameters( 142 name = "s_axi_", 143 id = IdRange(0, 1 << AXI_ID_WIDTH) 144 )) 145 ))) 146 val xbar = AXI4Xbar(TLArbiter.lowestIndexFirst) 147 axi4nodes.foreach { _ := xbar } 148 xbar := node 149 node 150 } 151 152 class imsic_bus_top_imp(wrapper: imsic_bus_top) extends LazyModuleImp(wrapper) { 153 // imsic csr top io 154 val o_msi_info = IO(Output(UInt(MSI_INFO_WIDTH.W))) 155 val o_msi_info_vld = IO(Output(Bool())) 156 157 // axi4lite io 158 val axi4lite = Option.when(!useTL)(IO(Flipped(new VerilogAXI4LiteRecord(AXI_ADDR_WIDTH, 32, AXI_ID_WIDTH)))) 159 160 // imsic axi top 161 val u_imsic_axi_top = Module(new imsic_axi_top) 162 163 // connection: crg 164 u_imsic_axi_top.io.axi_clk := clock 165 u_imsic_axi_top.io.axi_rstn := (~reset.asBool).asAsyncReset 166 u_imsic_axi_top.io.fifo_rstn := (~reset.asBool).asAsyncReset // TODO: axi_rstn & sw_rstn 167 168 // connection: imsic csr top 169 o_msi_info := u_imsic_axi_top.io.o_msi_info 170 o_msi_info_vld := u_imsic_axi_top.io.o_msi_info_vld 171 172 // connection: axi4lite 173 axi4lite.foreach { 174 _.viewAs[AXI4LiteBundle].connectToAXI4(wrapper.axiMasterNode.get.out.head._1) 175 } 176 177 // connection: axi4 178 wrapper.axi4nodes.map(_.in.head._1) zip 179 Seq(u_imsic_axi_top.io.m_s, u_imsic_axi_top.io.s_s) foreach { 180 case (axi4, axi4lite) => axi4lite.viewAs[AXI4LiteBundle].connectFromAXI4(axi4) 181 } 182 } 183 184 lazy val module = new imsic_bus_top_imp(this) 185} 186