xref: /XiangShan/src/main/scala/top/ArgParser.scala (revision 8cfc24b28454f1915c339ce79485711f8e438f59)
1/***************************************************************************************
2* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC)
3* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences
4* Copyright (c) 2020-2021 Peng Cheng Laboratory
5*
6* XiangShan is licensed under Mulan PSL v2.
7* You can use this software according to the terms and conditions of the Mulan PSL v2.
8* You may obtain a copy of Mulan PSL v2 at:
9*          http://license.coscl.org.cn/MulanPSL2
10*
11* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14*
15* See the Mulan PSL v2 for more details.
16***************************************************************************************/
17
18package top
19
20import org.chipsalliance.cde.config.{Config, Parameters}
21import system.SoCParamsKey
22import xiangshan.{DebugOptionsKey, XSTileKey}
23import freechips.rocketchip.tile.MaxHartIdBits
24import difftest.DifftestModule
25
26import scala.annotation.tailrec
27import scala.sys.exit
28import chisel3.util.log2Up
29import utility._
30import device.IMSICBusType
31
32object ArgParser {
33  // TODO: add more explainations
34  val usage =
35    """
36      |XiangShan Options
37      |--xs-help                  print this help message
38      |--version                  print version info
39      |--config <ConfigClassName>
40      |--num-cores <Int>
41      |--hartidbits <Int>
42      |--with-dramsim3
43      |--fpga-platform
44      |--reset-gen
45      |--enable-difftest
46      |--enable-log
47      |--with-chiseldb
48      |--with-rollingdb
49      |--disable-perf
50      |--disable-alwaysdb
51      |--enable-dfx
52      |""".stripMargin
53
54  def getConfigByName(confString: String): Parameters = {
55    var prefix = "top." // default package is 'top'
56    if(confString.contains('.')){ // already a full name
57      prefix = ""
58    }
59    val c = Class.forName(prefix + confString).getConstructor(Integer.TYPE)
60    c.newInstance(1.asInstanceOf[Object]).asInstanceOf[Parameters]
61  }
62  def parse(args: Array[String]): (Parameters, Array[String], Array[String]) = {
63    val default = new DefaultConfig(1)
64    var firrtlOpts = Array[String]()
65    var firtoolOpts = Array[String]()
66    @tailrec
67    def nextOption(config: Parameters, list: List[String]): Parameters = {
68      list match {
69        case Nil => config
70        case "--xs-help" :: tail =>
71          println(usage)
72          if(tail == Nil) exit(0)
73          nextOption(config, tail)
74        case "--version" :: tail =>
75          println(os.read(os.resource / "publishVersion"))
76          if(tail == Nil) exit(0)
77          nextOption(config, tail)
78        case "--config" :: confString :: tail =>
79          nextOption(getConfigByName(confString), tail)
80        case "--issue" :: issueString :: tail =>
81          nextOption(config.alter((site, here, up) => {
82            case coupledL2.tl2chi.CHIIssue => issueString
83          }), tail)
84        case "--num-cores" :: value :: tail =>
85          nextOption(config.alter((site, here, up) => {
86            case XSTileKey => (0 until value.toInt) map { i =>
87              up(XSTileKey).head.copy(HartId = i)
88            }
89            case MaxHartIdBits =>
90              log2Up(value.toInt) max up(MaxHartIdBits)
91          }), tail)
92        case "--hartidbits" :: hartidbits :: tail =>
93          nextOption(config.alter((site, here, up) => {
94            case MaxHartIdBits => hartidbits.toInt
95          }), tail)
96        case "--with-dramsim3" :: tail =>
97          nextOption(config.alter((site, here, up) => {
98            case DebugOptionsKey => up(DebugOptionsKey).copy(UseDRAMSim = true)
99          }), tail)
100        case "--with-chiseldb" :: tail =>
101          nextOption(config.alter((site, here, up) => {
102            case DebugOptionsKey => up(DebugOptionsKey).copy(EnableChiselDB = true)
103          }), tail)
104        case "--with-rollingdb" :: tail =>
105          nextOption(config.alter((site, here, up) => {
106            case DebugOptionsKey => up(DebugOptionsKey).copy(EnableRollingDB = true)
107          }), tail)
108        case "--with-constantin" :: tail =>
109          nextOption(config.alter((site, here, up) => {
110            case DebugOptionsKey => up(DebugOptionsKey).copy(EnableConstantin = true)
111          }), tail)
112        case "--fpga-platform" :: tail =>
113          nextOption(config.alter((site, here, up) => {
114            case DebugOptionsKey => up(DebugOptionsKey).copy(FPGAPlatform = true)
115          }), tail)
116        case "--reset-gen" :: tail =>
117          nextOption(config.alter((site, here, up) => {
118            case DebugOptionsKey => up(DebugOptionsKey).copy(ResetGen = true)
119          }), tail)
120        case "--enable-difftest" :: tail =>
121          nextOption(config.alter((site, here, up) => {
122            case DebugOptionsKey => up(DebugOptionsKey).copy(EnableDifftest = true)
123          }), tail)
124        case "--disable-always-basic-diff" :: tail =>
125          nextOption(config.alter((site, here, up) => {
126            case DebugOptionsKey => up(DebugOptionsKey).copy(AlwaysBasicDiff = false)
127          }), tail)
128        case "--enable-log" :: tail =>
129          nextOption(config.alter((site, here, up) => {
130            case DebugOptionsKey => up(DebugOptionsKey).copy(EnableDebug = true)
131          }), tail)
132        case "--disable-perf" :: tail =>
133          nextOption(config.alter((site, here, up) => {
134            case DebugOptionsKey => up(DebugOptionsKey).copy(EnablePerfDebug = false)
135          }), tail)
136        case "--perf-level" :: value :: tail =>
137          nextOption(config.alter((site, here, up) => {
138            case DebugOptionsKey => up(DebugOptionsKey).copy(PerfLevel = value)
139          }), tail)
140        case "--disable-alwaysdb" :: tail =>
141          nextOption(config.alter((site, here, up) => {
142            case DebugOptionsKey => up(DebugOptionsKey).copy(AlwaysBasicDB = false)
143          }), tail)
144        case "--xstop-prefix" :: value :: tail =>
145          nextOption(config.alter((site, here, up) => {
146            case SoCParamsKey => up(SoCParamsKey).copy(XSTopPrefix = Some(value))
147          }), tail)
148        case "--imsic-bus-type" :: value :: tail =>
149          nextOption(config.alter((site, here, up) => {
150            case SoCParamsKey => up(SoCParamsKey).copy(IMSICBusType = device.IMSICBusType.withName(value))
151          }), tail)
152        case "--enable-ns" :: tail =>
153          nextOption(config.alter((site, here, up) => {
154            case coupledL2.tl2chi.NonSecureKey => true
155          }), tail)
156        case "--firtool-opt" :: option :: tail =>
157          firtoolOpts ++= option.split(" ").filter(_.nonEmpty)
158          nextOption(config, tail)
159        case "--l2-cache-size" :: value :: tail =>
160          nextOption(config.alter((site, here, up) => {
161            case XSTileKey =>
162              val tileParams = up(XSTileKey)
163              val banks = tileParams.map(_.L2NBanks)
164              val ways = tileParams.map(_.L2CacheParamsOpt.map(_.ways))
165              val l2sets = banks zip ways map { case (banks, ways) =>
166                ways.map(value.toInt * 1024 / banks / _ / 64)
167              }
168              val newL2Params = tileParams zip l2sets map { case (tileParam, l2sets) =>
169                tileParam.L2CacheParamsOpt.map(_.copy(
170                  sets = l2sets.get
171                ))
172              }
173              tileParams zip newL2Params map { case (tileParam, newL2Param) =>
174                tileParam.copy(L2CacheParamsOpt = newL2Param)
175              }
176          }), tail)
177        case "--l3-cache-size" :: value :: tail =>
178          nextOption(config.alter((site, here, up) => {
179            case SoCParamsKey =>
180              val socParam = up(SoCParamsKey)
181              val banks = socParam.L3NBanks
182              val l3Ways = socParam.L3CacheParamsOpt.map(_.ways)
183              val l3Sets = l3Ways.map(value.toInt * 1024 / banks / _ / 64)
184              val openLLCWays = socParam.OpenLLCParamsOpt.map(_.ways)
185              val openLLCSets = openLLCWays.map(value.toInt * 1024 / banks / _ / 64)
186              val newL3Param = socParam.L3CacheParamsOpt.map(_.copy(
187                sets = l3Sets.get
188              ))
189              val openLLCParam = socParam.OpenLLCParamsOpt.map(_.copy(
190                sets = openLLCSets.get
191              ))
192              socParam.copy(
193                L3CacheParamsOpt = newL3Param,
194                OpenLLCParamsOpt = openLLCParam
195              )
196          }), tail)
197        case "--dfx" :: value :: tail =>
198          nextOption(config.alter((site, here, up) => {
199            case XSTileKey => up(XSTileKey).map(_.copy(hasMbist = value.toBoolean))
200          }), tail)
201        case "--sram-with-ctl" :: tail =>
202          nextOption(config.alter((site, here, up) => {
203            case XSTileKey => up(XSTileKey).map(_.copy(hasSramCtl = true))
204          }), tail)
205        case "--seperate-tl-bus" :: tail =>
206          nextOption(config.alter((site, here, up) => {
207            case SoCParamsKey => up(SoCParamsKey).copy(SeperateTLBus = true)
208          }), tail)
209        case "--seperate-dm" :: tail =>
210          nextOption(config.alter((site, here, up) => {
211            case SoCParamsKey => up(SoCParamsKey).copy(SeperateDM = true)
212          }), tail)
213        case "--wfi-resume" :: value :: tail =>
214          nextOption(config.alter((site, here, up) => {
215            case XSTileKey => up(XSTileKey).map(_.copy(wfiResume = value.toBoolean))
216          }), tail)
217        case "--yaml-config" :: yamlFile :: tail =>
218          nextOption(YamlParser.parseYaml(config, yamlFile), tail)
219        case option :: tail =>
220          // unknown option, maybe a firrtl option, skip
221          firrtlOpts :+= option
222          nextOption(config, tail)
223      }
224    }
225    val newArgs = DifftestModule.parseArgs(args)
226    val config = nextOption(default, newArgs.toList).alter((site, here, up) => {
227      case LogUtilsOptionsKey => LogUtilsOptions(
228        here(DebugOptionsKey).EnableDebug,
229        here(DebugOptionsKey).EnablePerfDebug,
230        here(DebugOptionsKey).FPGAPlatform
231      )
232      case PerfCounterOptionsKey => PerfCounterOptions(
233        here(DebugOptionsKey).EnablePerfDebug && !here(DebugOptionsKey).FPGAPlatform,
234        here(DebugOptionsKey).EnableRollingDB && !here(DebugOptionsKey).FPGAPlatform,
235        XSPerfLevel.withName(here(DebugOptionsKey).PerfLevel),
236        0
237      )
238    })
239    (config, firrtlOpts, firtoolOpts)
240  }
241}
242