xref: /XiangShan/src/main/scala/device/standalone/StandAloneDevice.scala (revision 4adf8eb8a0d5935fb96f0a75edb6aafef5159178)
1720dd621STang Haojin/***************************************************************************************
2720dd621STang Haojin* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3720dd621STang Haojin* Copyright (c) 2020-2021 Peng Cheng Laboratory
4720dd621STang Haojin*
5720dd621STang Haojin* XiangShan is licensed under Mulan PSL v2.
6720dd621STang Haojin* You can use this software according to the terms and conditions of the Mulan PSL v2.
7720dd621STang Haojin* You may obtain a copy of Mulan PSL v2 at:
8720dd621STang Haojin*          http://license.coscl.org.cn/MulanPSL2
9720dd621STang Haojin*
10720dd621STang Haojin* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11720dd621STang Haojin* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12720dd621STang Haojin* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13720dd621STang Haojin*
14720dd621STang Haojin* See the Mulan PSL v2 for more details.
15720dd621STang Haojin***************************************************************************************/
16720dd621STang Haojin
17720dd621STang Haojinpackage device.standalone
18720dd621STang Haojin
19720dd621STang Haojinimport chisel3._
20720dd621STang Haojinimport chisel3.util._
21b64156d0Ssinsanctionimport chisel3.experimental.{annotate, ChiselAnnotation}
224391123aSTang Haojinimport chisel3.experimental.dataview._
23720dd621STang Haojinimport freechips.rocketchip.diplomacy._
24720dd621STang Haojinimport org.chipsalliance.cde.config.Parameters
25aef22314STang Haojinimport freechips.rocketchip.devices.debug.DebugModuleKey
26720dd621STang Haojinimport freechips.rocketchip.devices.tilelink._
27720dd621STang Haojinimport freechips.rocketchip.amba.axi4._
28720dd621STang Haojinimport freechips.rocketchip.tilelink._
29720dd621STang Haojinimport top.Generator
30720dd621STang Haojinimport system.SoCParamsKey
31720dd621STang Haojinimport sifive.enterprise.firrtl.NestedPrefixModulesAnnotation
32720dd621STang Haojinimport scala.annotation.tailrec
33720dd621STang Haojinimport xiangshan.XSTileKey
344391123aSTang Haojinimport utils.VerilogAXI4Record
35720dd621STang Haojin
36720dd621STang Haojintrait HasMasterInterface { this: StandAloneDevice =>
37720dd621STang Haojin
38*4adf8eb8STang Haojin  def masterAddrWidth: Int
39*4adf8eb8STang Haojin
40720dd621STang Haojin  protected val masternode = TLIdentityNode()
41720dd621STang Haojin  // tilelink master io
42720dd621STang Haojin  private val tlmaster = Option.when(useTL)(TLManagerNode(Seq(
43720dd621STang Haojin    TLSlavePortParameters.v1(
44720dd621STang Haojin      managers = Seq(
45720dd621STang Haojin        TLSlaveParameters.v1(
46*4adf8eb8STang Haojin          address = Seq(AddressSet(0, (BigInt(1) << masterAddrWidth) - 1)),
47720dd621STang Haojin          regionType = RegionType.UNCACHED,
48720dd621STang Haojin          supportsGet = TransferSizes(1, p(SoCParamsKey).L3BlockSize),
49720dd621STang Haojin          supportsPutPartial = TransferSizes(1, p(SoCParamsKey).L3BlockSize),
50720dd621STang Haojin          supportsPutFull = TransferSizes(1, p(SoCParamsKey).L3BlockSize),
51720dd621STang Haojin          fifoId = Some(0)
52720dd621STang Haojin        )
53720dd621STang Haojin      ),
54720dd621STang Haojin      beatBytes = p(SoCParamsKey).L3OuterBusWidth / 8
55720dd621STang Haojin    )
56720dd621STang Haojin  )))
57720dd621STang Haojin  tlmaster.foreach(_ := masternode)
58720dd621STang Haojin  val tlmasternode = tlmaster.map(tlmaster => InModuleBody(tlmaster.makeIOs()))
59720dd621STang Haojin
60720dd621STang Haojin  // axi4 master io
61720dd621STang Haojin  private val axi4master = Option.when(!useTL)(AXI4SlaveNode(Seq(
62720dd621STang Haojin    AXI4SlavePortParameters(
63720dd621STang Haojin      slaves = Seq(
64720dd621STang Haojin        AXI4SlaveParameters(
65*4adf8eb8STang Haojin          address = Seq(AddressSet(0, (BigInt(1) << masterAddrWidth) - 1)),
66720dd621STang Haojin          regionType = RegionType.UNCACHED,
67720dd621STang Haojin          supportsRead = TransferSizes(1, p(SoCParamsKey).L3BlockSize),
68720dd621STang Haojin          supportsWrite = TransferSizes(1, p(SoCParamsKey).L3BlockSize),
69720dd621STang Haojin          interleavedId = Some(0)
70720dd621STang Haojin        )
71720dd621STang Haojin      ),
72720dd621STang Haojin      beatBytes = p(SoCParamsKey).L3OuterBusWidth / 8
73720dd621STang Haojin    )
74720dd621STang Haojin  )))
75720dd621STang Haojin  axi4master.foreach(
76720dd621STang Haojin    _ :=
77720dd621STang Haojin      AXI4Buffer() :=
78720dd621STang Haojin      AXI4Buffer() :=
79720dd621STang Haojin      AXI4Buffer() :=
80720dd621STang Haojin      AXI4IdIndexer(1) :=
81720dd621STang Haojin      AXI4UserYanker() :=
82720dd621STang Haojin      AXI4Deinterleaver(p(SoCParamsKey).L3BlockSize) :=
83720dd621STang Haojin      TLToAXI4() :=
84720dd621STang Haojin      TLSourceShrinker(64) :=
85720dd621STang Haojin      TLWidthWidget(p(SoCParamsKey).L3OuterBusWidth / 8) :=
86720dd621STang Haojin      TLBuffer.chainNode(2) :=
87720dd621STang Haojin      masternode
88720dd621STang Haojin  )
894391123aSTang Haojin  val axi4masternode = axi4master.map(axi4master => InModuleBody {
90bb2f3f51STang Haojin    val axi4masternode = chisel3.IO(new VerilogAXI4Record(axi4master.in.head._1.params))
914391123aSTang Haojin    axi4masternode.viewAs[AXI4Bundle] <> axi4master.in.head._1
924391123aSTang Haojin    axi4masternode
934391123aSTang Haojin  })
94720dd621STang Haojin}
95720dd621STang Haojin
96720dd621STang Haojinabstract class StandAloneDevice (
97720dd621STang Haojin  val useTL: Boolean = false,
98720dd621STang Haojin  val baseAddress: BigInt,
99720dd621STang Haojin  val addrWidth: Int,
100720dd621STang Haojin  val dataWidth: Int,
101720dd621STang Haojin  val hartNum: Int
102720dd621STang Haojin)(implicit p: Parameters) extends LazyModule {
103720dd621STang Haojin
104720dd621STang Haojin  def addressSet: AddressSet
105720dd621STang Haojin
106720dd621STang Haojin  private val dummy = LazyModule(new TLError(
107720dd621STang Haojin    params = DevNullParams(
108720dd621STang Haojin      address = AddressSet(0, (BigInt(1) << addrWidth) - 1).subtract(addressSet),
109720dd621STang Haojin      maxAtomic = 8,
110720dd621STang Haojin      maxTransfer = 64
111720dd621STang Haojin    ),
112720dd621STang Haojin    beatBytes = dataWidth / 8
113720dd621STang Haojin  ))
114720dd621STang Haojin  protected val xbar = TLXbar()
115720dd621STang Haojin  dummy.node := xbar
116720dd621STang Haojin
117720dd621STang Haojin  // tilelink io
118720dd621STang Haojin  private val tl = Option.when(useTL)(TLClientNode(Seq(TLMasterPortParameters.v1(
119720dd621STang Haojin    Seq(TLMasterParameters.v1("tl", IdRange(0, 1)))
120720dd621STang Haojin  ))))
121720dd621STang Haojin  tl.foreach(xbar := _)
122720dd621STang Haojin  val tlnode = tl.map(tl => InModuleBody(tl.makeIOs()))
123720dd621STang Haojin
124720dd621STang Haojin  // axi4 io
125720dd621STang Haojin  private val axi4 = Option.when(!useTL)(AXI4MasterNode(Seq(AXI4MasterPortParameters(
126720dd621STang Haojin    Seq(AXI4MasterParameters("axi4", IdRange(0, 1)))
127720dd621STang Haojin  ))))
128720dd621STang Haojin  axi4.foreach(
129720dd621STang Haojin    xbar :=
130720dd621STang Haojin      TLFIFOFixer() :=
131720dd621STang Haojin      AXI4ToTL() :=
132720dd621STang Haojin      AXI4UserYanker(Some(1)) :=
133720dd621STang Haojin      AXI4Fragmenter() :=
134720dd621STang Haojin      AXI4Buffer() :=
135720dd621STang Haojin      AXI4Buffer() :=
136720dd621STang Haojin      AXI4IdIndexer(1) :=
137720dd621STang Haojin      _
138720dd621STang Haojin  )
1394391123aSTang Haojin  val axi4node = axi4.map(axi4 => InModuleBody {
140bb2f3f51STang Haojin    val axi4node = chisel3.IO(Flipped(new VerilogAXI4Record(axi4.out.head._1.params)))
1414391123aSTang Haojin    axi4node.viewAs[AXI4Bundle] <> axi4.out.head._1
1424391123aSTang Haojin    axi4node
1434391123aSTang Haojin  })
144720dd621STang Haojin
145b6ace320STang Haojin  lazy val module: LazyModuleImpLike = new StandAloneDeviceImp(this)
146720dd621STang Haojin
147720dd621STang Haojin}
148720dd621STang Haojin
14930e7906fSHaojin Tangclass StandAloneDeviceImp(outer: StandAloneDevice)(implicit p: Parameters) extends LazyModuleImp(outer) with RequireAsyncReset {
150720dd621STang Haojin  p(SoCParamsKey).XSTopPrefix.foreach { prefix =>
151720dd621STang Haojin    val mod = this.toNamed
152720dd621STang Haojin    annotate(new ChiselAnnotation {
153720dd621STang Haojin      def toFirrtl = NestedPrefixModulesAnnotation(mod, prefix, true)
154720dd621STang Haojin    })
155720dd621STang Haojin  }
156720dd621STang Haojin}
157720dd621STang Haojin
158b6ace320STang Haojinclass StandAloneDeviceRawImp(outer: StandAloneDevice)(implicit p: Parameters) extends LazyRawModuleImp(outer) {
159b6ace320STang Haojin  p(SoCParamsKey).XSTopPrefix.foreach { prefix =>
160b6ace320STang Haojin    val mod = this.toNamed
161b6ace320STang Haojin    annotate(new ChiselAnnotation {
162b6ace320STang Haojin      def toFirrtl = NestedPrefixModulesAnnotation(mod, prefix, true)
163b6ace320STang Haojin    })
164b6ace320STang Haojin  }
165b6ace320STang Haojin}
166b6ace320STang Haojin
167720dd621STang Haojinobject ArgParser {
168720dd621STang Haojin  def parse(args: Array[String], p: Parameters): (StandAloneDevice, Array[String]) = {
169720dd621STang Haojin    var firrtlOpts = Array[String]()
170720dd621STang Haojin    var module: String = ""
171720dd621STang Haojin    var useTL: Boolean = false
172720dd621STang Haojin    var baseAddress: BigInt = -1
173720dd621STang Haojin    var addrWidth: Int = -1
174720dd621STang Haojin    var dataWidth: Int = 64
175720dd621STang Haojin    @tailrec
176720dd621STang Haojin    def nextOption(list: List[String]): Unit = {
177720dd621STang Haojin      list match {
178720dd621STang Haojin        case Nil =>
179720dd621STang Haojin        case "--standalone-device" :: value :: tail =>
180720dd621STang Haojin          module = value
181720dd621STang Haojin          nextOption(tail)
182720dd621STang Haojin        case "--use-tl" :: tail =>
183720dd621STang Haojin          useTL = true
184720dd621STang Haojin          nextOption(tail)
185720dd621STang Haojin        case "--use-axi4" :: tail =>
186720dd621STang Haojin          useTL = false
187720dd621STang Haojin          nextOption(tail)
188720dd621STang Haojin        case "--device-base-addr" :: value :: tail =>
189720dd621STang Haojin          baseAddress = value match {
190720dd621STang Haojin            case s"0x$hex" => BigInt(hex, 16)
191720dd621STang Haojin            case s"0X$hex" => BigInt(hex, 16)
192720dd621STang Haojin            case _: String => BigInt(value)
193720dd621STang Haojin          }
194720dd621STang Haojin          nextOption(tail)
195720dd621STang Haojin        case "--device-addr-width" :: value :: tail =>
196720dd621STang Haojin          addrWidth = value.toInt
197720dd621STang Haojin          nextOption(tail)
198720dd621STang Haojin        case "--device-data-width" :: value :: tail =>
199720dd621STang Haojin          dataWidth = value.toInt
200720dd621STang Haojin          nextOption(tail)
201720dd621STang Haojin        case option :: tail =>
202720dd621STang Haojin          // unknown option, maybe a firrtl option, skip
203720dd621STang Haojin          firrtlOpts :+= option
204720dd621STang Haojin          nextOption(tail)
205720dd621STang Haojin      }
206720dd621STang Haojin    }
207720dd621STang Haojin    nextOption(args.toList)
208720dd621STang Haojin    require(baseAddress >= 0, "baseAddress not specified correctly")
209720dd621STang Haojin    require(addrWidth >= 0, "addrWidth not specified correctly")
210720dd621STang Haojin    require(dataWidth >= 0, "dataWidth not specified correctly")
211720dd621STang Haojin    val device: StandAloneDevice = module match {
212720dd621STang Haojin      case "StandAloneCLINT" =>
213720dd621STang Haojin        DisableMonitors(p => LazyModule(new StandAloneCLINT(
214720dd621STang Haojin          useTL, baseAddress, addrWidth, dataWidth, p(XSTileKey).size
215720dd621STang Haojin        )(p)))(p)
216720dd621STang Haojin      case "StandAlonePLIC" =>
217720dd621STang Haojin        DisableMonitors(p => LazyModule(new StandAlonePLIC(
218720dd621STang Haojin          useTL, baseAddress, addrWidth, dataWidth, p(XSTileKey).size
219720dd621STang Haojin        )(p)))(p)
220720dd621STang Haojin      case "StandAloneDebugModule" =>
221720dd621STang Haojin        DisableMonitors(p => LazyModule(new StandAloneDebugModule(
222720dd621STang Haojin          useTL, baseAddress, addrWidth, dataWidth, p(XSTileKey).size
223aef22314STang Haojin        )(p)))(p.alter((site, here, up) => {
224aef22314STang Haojin          case DebugModuleKey => up(DebugModuleKey).map(_.copy(baseAddress = baseAddress))
225aef22314STang Haojin        }))
226720dd621STang Haojin      case _: String => throw new IllegalArgumentException(s"$module not found")
227720dd621STang Haojin    }
228720dd621STang Haojin    (device, firrtlOpts)
229720dd621STang Haojin  }
230720dd621STang Haojin}
231720dd621STang Haojin
232720dd621STang Haojinobject Main extends App {
233720dd621STang Haojin  val (config, secondaryOpts, firtoolOpts) = top.ArgParser.parse(args)
234720dd621STang Haojin  val (device, firrtlOpts) = ArgParser.parse(secondaryOpts, config)
235720dd621STang Haojin
236720dd621STang Haojin  Generator.execute(firrtlOpts, device.module, firtoolOpts)
237720dd621STang Haojin}
238