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