xref: /XiangShan/build.sc (revision 8795ffc00d922e6e6cde93b1027e9f79782b0564)
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
18import mill._
19import scalalib._
20import scalafmt._
21import $packages._
22import $file.`rocket-chip`.common
23import $file.`rocket-chip`.cde.common
24import $file.`rocket-chip`.hardfloat.common
25import $file.huancun.common
26import $file.coupledL2.common
27import $file.openLLC.common
28
29/* for publishVersion */
30import $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version::0.4.0`
31import de.tobiasroeser.mill.vcs.version.VcsVersion
32import java.io.{BufferedReader, InputStreamReader}
33import java.time.LocalDateTime
34import java.time.format.DateTimeFormatter
35import java.util.Locale
36import scala.util.matching.Regex
37
38val defaultScalaVersion = "2.13.15"
39val pwd = os.Path(sys.env("MILL_WORKSPACE_ROOT"))
40
41def defaultVersions = Map(
42  "chisel"        -> ivy"org.chipsalliance::chisel:6.6.0",
43  "chisel-plugin" -> ivy"org.chipsalliance:::chisel-plugin:6.6.0",
44  "chiseltest"    -> ivy"edu.berkeley.cs::chiseltest:6.0.0"
45)
46
47trait HasChisel extends SbtModule {
48  def chiselModule: Option[ScalaModule] = None
49
50  def chiselPluginJar: T[Option[PathRef]] = None
51
52  def chiselIvy: Option[Dep] = Some(defaultVersions("chisel"))
53
54  def chiselPluginIvy: Option[Dep] = Some(defaultVersions("chisel-plugin"))
55
56  override def scalaVersion = defaultScalaVersion
57
58  override def scalacOptions = super.scalacOptions() ++
59    Agg("-language:reflectiveCalls", "-Ymacro-annotations", "-Ytasty-reader")
60
61  override def ivyDeps = super.ivyDeps() ++ Agg(chiselIvy.get)
62
63  override def scalacPluginIvyDeps = super.scalacPluginIvyDeps() ++ Agg(chiselPluginIvy.get)
64}
65
66object rocketchip
67  extends $file.`rocket-chip`.common.RocketChipModule
68    with HasChisel {
69  def scalaVersion: T[String] = T(defaultScalaVersion)
70
71  override def millSourcePath = pwd / "rocket-chip"
72
73  def macrosModule = macros
74
75  def hardfloatModule = hardfloat
76
77  def cdeModule = cde
78
79  def mainargsIvy = ivy"com.lihaoyi::mainargs:0.7.0"
80
81  def json4sJacksonIvy = ivy"org.json4s::json4s-jackson:4.0.7"
82
83  object macros extends Macros
84
85  trait Macros
86    extends $file.`rocket-chip`.common.MacrosModule
87      with SbtModule {
88
89    def scalaVersion: T[String] = T(defaultScalaVersion)
90
91    def scalaReflectIvy = ivy"org.scala-lang:scala-reflect:${defaultScalaVersion}"
92  }
93
94  object hardfloat
95    extends $file.`rocket-chip`.hardfloat.common.HardfloatModule with HasChisel {
96
97    def scalaVersion: T[String] = T(defaultScalaVersion)
98
99    override def millSourcePath = pwd / "rocket-chip" / "hardfloat" / "hardfloat"
100
101  }
102
103  object cde
104    extends $file.`rocket-chip`.cde.common.CDEModule with ScalaModule {
105
106    def scalaVersion: T[String] = T(defaultScalaVersion)
107
108    override def millSourcePath = pwd / "rocket-chip" / "cde" / "cde"
109  }
110}
111
112object utility extends HasChisel {
113
114  override def millSourcePath = pwd / "utility"
115
116  override def moduleDeps = super.moduleDeps ++ Seq(
117    rocketchip
118  )
119
120  override def ivyDeps = super.ivyDeps() ++ Agg(
121    ivy"com.lihaoyi::sourcecode:0.4.2",
122  )
123
124  object test extends SbtTests with TestModule.ScalaTest {
125    override def ivyDeps = Agg(ivy"org.scalatest::scalatest:3.2.7")
126  }
127}
128
129object yunsuan extends HasChisel {
130
131  override def millSourcePath = pwd / "yunsuan"
132
133}
134
135object huancun extends $file.huancun.common.HuanCunModule with HasChisel {
136
137  override def millSourcePath = pwd / "huancun"
138
139  def rocketModule: ScalaModule = rocketchip
140
141  def utilityModule: ScalaModule = utility
142
143}
144
145object coupledL2 extends $file.coupledL2.common.CoupledL2Module with HasChisel {
146
147  override def millSourcePath = pwd / "coupledL2"
148
149  def rocketModule: ScalaModule = rocketchip
150
151  def utilityModule: ScalaModule = utility
152
153  def huancunModule: ScalaModule = huancun
154
155}
156
157object openNCB extends SbtModule with HasChisel {
158
159  override def millSourcePath = pwd / "openLLC" / "openNCB"
160
161  override def moduleDeps = super.moduleDeps ++ Seq(
162    rocketchip
163  )
164
165}
166
167object openLLC extends $file.openLLC.common.OpenLLCModule with HasChisel {
168
169  override def millSourcePath = pwd / "openLLC"
170
171  def coupledL2Module: ScalaModule = coupledL2
172
173  def rocketModule: ScalaModule = rocketchip
174
175  def utilityModule: ScalaModule = utility
176
177  def openNCBModule: ScalaModule = openNCB
178
179}
180
181object difftest extends HasChisel {
182
183  override def millSourcePath = pwd / "difftest"
184
185  object test extends SbtTests with TestModule.ScalaTest {
186    override def sources = T.sources {
187      super.sources() ++ Seq(PathRef(this.millSourcePath / "src" / "generator" / "chisel"))
188    }
189  }
190
191}
192
193object fudian extends HasChisel {
194
195  override def millSourcePath = pwd / "fudian"
196
197}
198
199object chiselAIA extends HasChisel {
200  override def millSourcePath = pwd / "ChiselAIA"
201
202  override def moduleDeps = super.moduleDeps ++ Seq(
203    rocketchip,
204    utility
205  )
206}
207
208object macros extends ScalaModule {
209
210  override def millSourcePath = pwd / "macros"
211
212  override def scalaVersion: T[String] = T(defaultScalaVersion)
213
214  override def ivyDeps = super.ivyDeps() ++ Agg(ivy"org.scala-lang:scala-reflect:${defaultScalaVersion}")
215
216  def scalaReflectIvy = ivy"org.scala-lang:scala-reflect:${defaultScalaVersion}"
217}
218
219// extends this trait to use XiangShan in other projects
220trait XiangShanModule extends ScalaModule {
221
222  def rocketModule: ScalaModule
223
224  def difftestModule: ScalaModule
225
226  def huancunModule: ScalaModule
227
228  def coupledL2Module: ScalaModule
229
230  def openLLCModule: ScalaModule
231
232  def fudianModule: ScalaModule
233
234  def utilityModule: ScalaModule
235
236  def yunsuanModule: ScalaModule
237
238  def chiselAIAModule: ScalaModule
239
240  def macrosModule: ScalaModule
241
242  override def moduleDeps = super.moduleDeps ++ Seq(
243    rocketModule,
244    difftestModule,
245    huancunModule,
246    coupledL2Module,
247    openLLCModule,
248    yunsuanModule,
249    fudianModule,
250    utilityModule,
251    chiselAIAModule,
252    macrosModule,
253  )
254
255  val resourcesPATH = pwd.toString() + "/src/main/resources"
256  val envPATH = sys.env("PATH") + ":" + resourcesPATH
257
258  override def forkEnv = Map("PATH" -> envPATH)
259}
260
261object xiangshan extends XiangShanModule with HasChisel with ScalafmtModule {
262
263  override def millSourcePath = pwd
264
265  def rocketModule = rocketchip
266
267  def difftestModule = difftest
268
269  def huancunModule = huancun
270
271  def coupledL2Module = coupledL2
272
273  def openLLCModule = openLLC
274
275  def fudianModule = fudian
276
277  def utilityModule = utility
278
279  def yunsuanModule = yunsuan
280
281  def chiselAIAModule = chiselAIA
282
283  def macrosModule = macros
284
285  // properties may be changed by user. Use `Task.Input` here.
286  def forkArgsTask = Task.Input {
287    Seq(s"-Xmx${sys.props.getOrElse("jvm-xmx", "40G")}", s"-Xss${sys.props.getOrElse("jvm-xss", "256m")}")
288  }
289
290  override def forkArgs = forkArgsTask()
291
292  override def ivyDeps = super.ivyDeps() ++ Agg(
293    defaultVersions("chiseltest"),
294    ivy"io.circe::circe-yaml:1.15.0",
295    ivy"io.circe::circe-generic-extras:0.14.4"
296  )
297
298  override def scalacOptions = super.scalacOptions() ++ Agg("-deprecation", "-feature")
299
300  def publishVersion: T[String] = VcsVersion.vcsState().format(
301    revHashDigits = 8,
302    dirtyHashDigits = 0,
303    commitCountPad = -1,
304    countSep = "",
305    tagModifier = (tag: String) => "[Rr]elease.*".r.findFirstMatchIn(tag) match {
306      case Some(_) => "Kunminghu-Release-" + LocalDateTime.now().format(
307                                 DateTimeFormatter.ofPattern("MMM-dd-yyyy").withLocale(new Locale("en")))
308      case None => "Kunminghu-dev"
309    },
310    /* add "username, buildhost, buildtime" for non-release version */
311    untaggedSuffix = " (%s@%s) # %s".format(
312      System.getProperty("user.name"),
313      java.net.InetAddress.getLocalHost().getHostName(),
314      LocalDateTime.now().format(DateTimeFormatter.ofPattern("MMM dd hh:mm:ss yyyy").withLocale(new Locale("en")))),
315  )
316
317  // gitStatus changes frequently and unpredictably. Use `Task.Input` here.
318  def gitStatus: T[String] = Task.Input {
319    val gitRevParseBuilder = new ProcessBuilder("git", "rev-parse", "HEAD")
320    val gitRevParseProcess = gitRevParseBuilder.start()
321    val shaReader = new BufferedReader(new InputStreamReader(gitRevParseProcess.getInputStream))
322    val sha = shaReader.readLine()
323
324    val gitStatusBuilder = new ProcessBuilder("git", "status", "-uno", "--porcelain")
325    val gitStatusProcess = gitStatusBuilder.start()
326    val gitStatusReader = new BufferedReader(new InputStreamReader(gitStatusProcess.getInputStream))
327    val status = gitStatusReader.readLine()
328    val gitDirty = if (status == null) 0 else 1
329
330    val str =
331      s"""|SHA=$sha
332          |dirty=$gitDirty
333          |""".stripMargin
334    str
335  }
336
337  def packDifftestResources(destDir: os.Path): Unit = {
338    // package difftest source as resources, only git tracked files were collected
339    val difftest_srcs = os.proc("git", "ls-files").call(cwd = pwd / "difftest").out
340                          .text().split("\n").filter(_.nonEmpty).toSeq
341                          .map(os.RelPath(_))
342    difftest_srcs.foreach { f =>
343      os.copy(pwd / "difftest" / f, destDir / "difftest-src" / f, createFolders = true)
344    }
345
346    // package ready-to-run binary as resources
347    val ready_to_run = Seq("riscv64-nemu-interpreter-dual-so",
348                           "riscv64-nemu-interpreter-so",
349                           "riscv64-spike-so")
350    ready_to_run.foreach { f =>
351      os.copy(pwd / "ready-to-run" / f, destDir / "ready-to-run" / f, createFolders = true)
352    }
353  }
354
355  override def resources = T.sources {
356    os.write(T.dest / "publishVersion", publishVersion())
357    os.write(T.dest / "gitStatus", gitStatus())
358    os.write(T.dest / "gitModules", os.proc("git", "submodule", "status").call().out.text())
359    packDifftestResources(T.dest)
360    super.resources() ++ Seq(PathRef(T.dest))
361  }
362
363  object test extends SbtTests with TestModule.ScalaTest {
364    override def moduleDeps = super.moduleDeps ++ Seq(
365      difftestModule.test
366    )
367
368    override def forkArgs = forkArgsTask()
369
370    override def scalacOptions = super.scalacOptions() ++ Agg("-deprecation", "-feature")
371
372    val resourcesPATH = pwd.toString() + "/src/main/resources"
373    val envPATH = sys.env("PATH") + ":" + resourcesPATH
374
375    override def forkEnv = Map("PATH" -> envPATH)
376  }
377}
378