xref: /XiangShan/src/main/scala/device/imsic_axi_top.scala (revision 1bc48dd1fa0af361fd194c65bad3b86349ec2903)
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 := 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