Skip to content
This repository has been archived by the owner on Jun 16, 2024. It is now read-only.

Commit

Permalink
cxxsim: user makes arbitrary CXXRTLPlatforms.
Browse files Browse the repository at this point in the history
  • Loading branch information
kivikakk committed May 26, 2024
1 parent e53c302 commit 23a0614
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 26 deletions.
33 changes: 31 additions & 2 deletions src/main/scala/ee/hrzn/chryse/ChryseApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ee.hrzn.chryse.platform.Platform
import ee.hrzn.chryse.platform.PlatformBoard
import ee.hrzn.chryse.platform.PlatformBoardResources
import ee.hrzn.chryse.platform.cxxrtl.CXXRTLOptions
import ee.hrzn.chryse.platform.cxxrtl.CXXRTLPlatform
import org.rogach.scallop._

import scala.collection.mutable
Expand Down Expand Up @@ -40,7 +41,7 @@ abstract class ChryseApp {
choice(
targetPlatforms.map(_.id),
argName = "board",
descr = s"Board to build for. ", // XXX (Scallop): It appends " Choices: …". Kinda ugly.
descr = s"Board to build for.", // XXX (Scallop): It appends " Choices: …". Kinda ugly.
required = true,
)
val program =
Expand All @@ -56,6 +57,24 @@ abstract class ChryseApp {

object cxxsim extends Subcommand("cxxsim") {
banner("Run the C++ simulator tests.")

val platformChoices: Seq[_ <: CXXRTLPlatform] = cxxrtlOptions
.map(_.platforms.map(_.getConstructor().newInstance()))
.getOrElse(Seq())

val platform =
if (platformChoices.length > 1)
Some(
choice(
platformChoices.map(_.id),
name = "platform",
argName = "platform",
descr = "CXXRTL platform to use.",
required = true,
),
)
else
None
val compileOnly =
opt[Boolean](
name = "compile",
Expand All @@ -80,7 +99,9 @@ abstract class ChryseApp {
required = false,
)
}
if (cxxrtlOptions.isDefined) addSubcommand(cxxsim)
if (cxxrtlOptions.isDefined) {
addSubcommand(cxxsim)
}

for { sc <- additionalSubcommands }
addSubcommand(sc)
Expand All @@ -102,8 +123,16 @@ abstract class ChryseApp {
)
case Some(Conf.cxxsim) =>
println(versionBanner)
val platform =
if (Conf.cxxsim.platformChoices.length > 1)
Conf.cxxsim.platformChoices
.find(_.id == Conf.cxxsim.platform.get())
.get
else
Conf.cxxsim.platformChoices(0)
tasks.CxxsimTask(
this,
platform,
cxxrtlOptions.get,
tasks.CxxsimTask.Options(
Conf.cxxsim.debug(),
Expand Down
8 changes: 5 additions & 3 deletions src/main/scala/ee/hrzn/chryse/ExampleApp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import chisel3._
import ee.hrzn.chryse.platform.Platform
import ee.hrzn.chryse.platform.cxxrtl.CXXRTLOptions
import ee.hrzn.chryse.platform.ice40.IceBreakerPlatform
import ee.hrzn.chryse.platform.cxxrtl.CXXRTLPlatform

object ExampleApp extends ChryseApp {
class Top(implicit platform: Platform) extends Module {}
Expand All @@ -12,8 +13,9 @@ object ExampleApp extends ChryseApp {
override def genTop()(implicit platform: Platform) = new Top
override val targetPlatforms = Seq(IceBreakerPlatform())
override val cxxrtlOptions = Some(
CXXRTLOptions(
clockHz = 3_000_000,
),
CXXRTLOptions(platforms = Seq(classOf[ExampleCXXRTLPlatform])),
)
}

class ExampleCXXRTLPlatform
extends CXXRTLPlatform(id = "ex", clockHz = 3_000_000)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@ import ee.hrzn.chryse.chisel.DirectionOf
import java.io.Writer

class BlackBoxGenerator(private val wr: Writer) {
// TODO: Can we just add attributes somehow and output Verilog instead?
// Can we just add attributes somehow and output Verilog instead?
//
// -- I looked into this and there's many levels of things missing:
// https://github.com/chipsalliance/chisel/pull/4023#issuecomment-2130283723
// Note that annotations on ports are also very required, and not even in
// firtool yet.
//
// It'd still be nice to do it even if hackily — I'd like to support bundles
// and normal stuff like that, which right now will require quite a bit more
// fun. TODO: bundles, proper descent, flipping etc.

def runOn(bb: Class[_ <: BlackBox]): Unit = {
wr.write("attribute \\cxxrtl_blackbox 1\n")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import chisel3.BlackBox
import scala.sys.process._

final case class CXXRTLOptions(
clockHz: Int,
platforms: Seq[Class[_ <: CXXRTLPlatform]],
blackboxes: Seq[Class[_ <: BlackBox]] = Seq(),
cxxFlags: Seq[String] = Seq(),
ldFlags: Seq[String] = Seq(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ package ee.hrzn.chryse.platform.cxxrtl
import chisel3._
import ee.hrzn.chryse.platform.ElaboratablePlatform

final case class CXXRTLPlatform(clockHz: Int) extends ElaboratablePlatform {
val id = "cxxrtl"

abstract case class CXXRTLPlatform(id: String, clockHz: Int)
extends ElaboratablePlatform {
override def apply[Top <: Module](genTop: => Top) =
genTop
}
2 changes: 1 addition & 1 deletion src/main/scala/ee/hrzn/chryse/tasks/BuildTask.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object BuildTask extends BaseTask {

// TODO (ECP5): refactor — different steps and build products are involved
// after synthesis.
def apply[Top <: Module](
def apply(
chryse: ChryseApp,
platform: PlatformBoard[_ <: PlatformBoardResources],
options: Options,
Expand Down
33 changes: 18 additions & 15 deletions src/main/scala/ee/hrzn/chryse/tasks/CxxsimTask.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,39 @@ object CxxsimTask extends BaseTask {
args: Seq[String],
)

def apply[Top <: Module](
def apply[P <: CXXRTLPlatform](
chryse: ChryseApp,
platform: P,
appOptions: CXXRTLOptions,
runOptions: Options,
): Unit = {
val platform = CXXRTLPlatform(appOptions.clockHz)
println(s"Building cxxsim ${platform.id} ...")

println(s"Building cxxsim ...")

Files.createDirectories(Paths.get(buildDir))
Files.createDirectories(Paths.get(buildDir, platform.id))

val name = chryse.name

val verilogPath = s"$buildDir/$name-${platform.id}.sv"
val verilogPath = s"$buildDir/${platform.id}/$name.sv"
val verilog =
ChiselStage.emitSystemVerilog(
platform(chryse.genTop()(platform)),
firtoolOpts = firtoolOpts,
)
writePath(verilogPath, verilog)

val blackboxIlPath = s"$buildDir/$name-${platform.id}-blackbox.il"
val blackboxIlPath = s"$buildDir/${platform.id}/$name-blackbox.il"
writePath(blackboxIlPath) { wr =>
for { (bb, bbIx) <- appOptions.blackboxes.zipWithIndex } {
if (bbIx > 0) wr.write("\n")
BlackBoxGenerator(wr, bb)
}
}

val yosysScriptPath = s"$buildDir/$name-${platform.id}.ys"
val ccPath = s"$buildDir/$name.cc"
// XXX: We don't call ccPath buildDir/name-platform.cc because that'd imply
// the user needs to include different .h files depending on the chosen plat
// too.
val yosysScriptPath = s"$buildDir/${platform.id}/$name.ys"
val ccPath = s"$buildDir/${platform.id}/$name.cc"
writePath(
yosysScriptPath,
s"""read_rtlil $blackboxIlPath
Expand All @@ -75,7 +77,7 @@ object CxxsimTask extends BaseTask {
"-q",
"-g",
"-l",
s"$buildDir/$name-${platform.id}.rpt",
s"$buildDir/${platform.id}/$name.rpt",
"-s",
yosysScriptPath,
),
Expand All @@ -96,17 +98,18 @@ object CxxsimTask extends BaseTask {
val yosysDatDir = Seq("yosys-config", "--datdir").!!.trim()
val cxxOpts = new mutable.ArrayBuffer[String]
cxxOpts.appendAll(baseCxxOpts)
cxxOpts.append(s"-DCLOCK_HZ=${appOptions.clockHz}")
cxxOpts.append(s"-DCLOCK_HZ=${platform.clockHz}")
if (runOptions.debug) cxxOpts.append("-g")
if (runOptions.optimize) cxxOpts.append("-O3")

def buildPathForCc(cc: String) =
cc.replace(s"$cxxsimDir/", s"$buildDir/")
cc.replace(s"$cxxsimDir/", s"$buildDir/${platform.id}/")
.replace(".cc", ".o")

def compileCmdForCc(cc: String, obj: String): Seq[String] = Seq(
"c++",
s"-I$buildDir",
s"-I$buildDir/${platform.id}",
s"-I$buildDir", // XXX: other artefacts the user might generate
s"-I$yosysDatDir/include/backends/cxxrtl/runtime",
"-c",
cc,
Expand All @@ -121,14 +124,14 @@ object CxxsimTask extends BaseTask {
cmd = compileCmdForCc(cc, obj)
} yield CompilationUnit(Some(cc), headers, obj, cmd)

val cwd = System.getProperty("user.dir")
// clangd won't look deeper than $buildDir, so just overwrite.
writePath(s"$buildDir/compile_commands.json") { wr =>
upickle.default.writeTo(cus.map(ClangdEntry(_)), wr)
}

runCus(CmdStepCompile, cus)

val binPath = s"$buildDir/$name"
val binPath = s"$buildDir/${platform.id}/$name"
val linkCu = CompilationUnit(
None,
cus.map(_.outPath),
Expand Down

0 comments on commit 23a0614

Please sign in to comment.