diff --git a/build.sc b/build.sc new file mode 100644 index 0000000..85ba7cc --- /dev/null +++ b/build.sc @@ -0,0 +1,133 @@ +import mill._ +import mill.scalalib._ +import mill.define.{TaskModule, Command} +import mill.scalalib.publish._ +import mill.scalalib.scalafmt._ +import mill.scalalib.TestModule.Utest +import coursier.maven.MavenRepository +import $file.common + +object v { + val scala = "2.12.10" + val utest = ivy"com.lihaoyi::utest:latest.integration" + val mainargs = ivy"com.lihaoyi::mainargs:0.3.0" + // for arithmetic + val upickle = ivy"com.lihaoyi::upickle:latest.integration" + val osLib = ivy"com.lihaoyi::os-lib:latest.integration" + val bc = ivy"org.bouncycastle:bcprov-jdk15to18:latest.integration" + val spire = ivy"org.typelevel::spire:latest.integration" + val evilplot = ivy"io.github.cibotech::evilplot:latest.integration" + val chisel3 = ivy"edu.berkeley.cs::chisel3:3.5.5" + val chisel3plugin = ivy"edu.berkeley.cs:::chisel3-plugin:3.5.5" + val rocketchip = ivy"edu.berkeley.cs::rocketchip:1.5-SNAPSHOT" +} + +object rocketchipblocks extends common.RocketChipBlocksModule with ScalafmtModule { + m => + def millSourcePath = os.pwd + + def scalaVersion = v.scala + + override def scalacOptions = Seq( + "-language:reflectiveCalls", + "-deprecation", + "-feature", + "-Xcheckinit", + "-P:chiselplugin:genBundleElements" + ) + + override def scalacPluginIvyDeps = T { + Seq( + v.chisel3plugin + ) + } + override def ivyDeps = T { + Seq( + v.chisel3, + v.rocketchip + ) + } +} + +object tests extends Module { + object elaborate extends ScalaModule with ScalafmtModule { +// override def scalacPluginClasspath = T { +// Agg(chisel3.plugin.jar()) +// } +// +// override def scalacOptions = T { +// super.scalacOptions() ++ Some(chisel3.plugin.jar()).map(path => s"-Xplugin:${path.path}") ++ Seq("-Ymacro-annotations") +// } + + override def scalaVersion = v.scala + + override def moduleDeps = Seq(rocketchipblocks) + + override def ivyDeps = T { + Seq( + v.chisel3 + ) + } + + def elaborate = T { + // class path for `moduleDeps` is only a directory, not a jar, which breaks the cache. + // so we need to manually add the class files of `moduleDeps` here. + upstreamCompileOutput() + mill.modules.Jvm.runLocal( + finalMainClass(), + runClasspath().map(_.path), + Seq( + "--dir", T.dest.toString, + ), + ) + PathRef(T.dest) + } + + def chiselAnno = T { + os.walk(elaborate().path).collectFirst { case p if p.last.endsWith("anno.json") => p }.map(PathRef(_)).get + } + + def chirrtl = T { + os.walk(elaborate().path).collectFirst { case p if p.last.endsWith("fir") => p }.map(PathRef(_)).get + } + + def topName = T { + chirrtl().path.last.split('.').head + } + + } + + object mfccompile extends Module { + + def compile = T { + os.proc("firtool", + elaborate.chirrtl().path, + s"--annotation-file=${elaborate.chiselAnno().path}", + "-disable-infer-rw", + "-dedup", + "-O=debug", + "--split-verilog", + "--preserve-values=named", + "--output-annotation-file=mfc.anno.json", + s"-o=${T.dest}" + ).call(T.dest) + PathRef(T.dest) + } + + def rtls = T { + os.read(compile().path / "filelist.f").split("\n").map(str => + try { + os.Path(str) + } catch { + case e: IllegalArgumentException if e.getMessage.contains("is not an absolute path") => + compile().path / str.stripPrefix("./") + } + ).filter(p => p.ext == "v" || p.ext == "sv").map(PathRef(_)).toSeq + } + + def annotations = T { + os.walk(compile().path).filter(p => p.last.endsWith("mfc.anno.json")).map(PathRef(_)) + } + } + +} diff --git a/common.sc b/common.sc new file mode 100644 index 0000000..272b9ba --- /dev/null +++ b/common.sc @@ -0,0 +1,64 @@ +// hats off for sequencer's vector project. This is copied from there and modified +import mill._ +import mill.scalalib._ +import mill.scalalib.publish._ +import coursier.maven.MavenRepository + +import $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version::0.1.4` +import de.tobiasroeser.mill.vcs.version.VcsVersion + +trait RocketChipBlocksModule extends ScalaModule with PublishModule { + // SNAPSHOT of Chisel is published to the SONATYPE + override def repositoriesTask = T.task { super.repositoriesTask() ++ Seq( + MavenRepository("https://oss.sonatype.org/content/repositories/snapshots"), + MavenRepository("https://oss.sonatype.org/content/repositories/releases") + ) } + + + // override to build from source, see the usage of chipsalliance/playground + def chisel3Module: Option[PublishModule] = None + + // override to build from source, see the usage of chipsalliance/playground + def chisel3PluginJar: T[Option[PathRef]] = T { + None + } + + // override to build from source, see the usage of chipsalliance/playground + def chiseltestModule: Option[PublishModule] = None + + // Use SNAPSHOT chisel by default, downstream users should override this for their own project versions. + def chisel3IvyDep: T[Option[Dep]] = None + + def chisel3PluginIvyDep: T[Option[Dep]] = None + + def chiseltestIvyDep: T[Option[Dep]] = None + + override def moduleDeps = Seq() ++ chisel3Module ++ chiseltestModule + + override def scalacPluginClasspath = T { + super.scalacPluginClasspath() ++ chisel3PluginJar() + } + + override def scalacPluginIvyDeps = T { + Agg() ++ chisel3PluginIvyDep() + } + + override def scalacOptions = T { + super.scalacOptions() ++ chisel3PluginJar().map(path => s"-Xplugin:${path.path}") + } + + override def ivyDeps = T { + Agg() ++ chisel3IvyDep() + } + + def publishVersion = de.tobiasroeser.mill.vcs.version.VcsVersion.vcsState().format() + + def pomSettings = PomSettings( + description = artifactName(), + organization = "edu.berkeley.cs", + url = "https://github.com/chipsalliance/rocket-chip-blocks", + licenses = Seq(License.`Apache-2.0`), + versionControl = VersionControl.github("chipsalliance", "rocket-chip-blocks"), + developers = Seq() + ) +} diff --git a/sifiveblocks.sc b/sifiveblocks.sc deleted file mode 100644 index b6da764..0000000 --- a/sifiveblocks.sc +++ /dev/null @@ -1,9 +0,0 @@ -import mill._ -import mill.scalalib._ -import ammonite.ops._ - -import $file.^.`scala-wake`.common, common._ - -trait SifiveBlocksBase extends ScalaModule with WakeModule with CommonOptions { - def millSourcePath = os.pwd -} diff --git a/src/main/scala/devices/chiplink/SinkA.scala b/src/main/scala/devices/chiplink/SinkA.scala index 547bfe9..c1c1c47 100644 --- a/src/main/scala/devices/chiplink/SinkA.scala +++ b/src/main/scala/devices/chiplink/SinkA.scala @@ -13,8 +13,8 @@ class SinkA(info: ChipLinkInfo) extends Module // Map TileLink sources to ChipLink sources+domain val tl2cl = info.sourceMap - val source = info.mux(tl2cl.mapValues(_.source)) - val domain = info.mux(tl2cl.mapValues(_.domain)) + val source = info.mux(tl2cl.mapValues(_.source).toMap) + val domain = info.mux(tl2cl.mapValues(_.domain).toMap) // We need a Q because we stall the channel while serializing it's header val inject = Module(new PartialInjector(io.a.bits)) diff --git a/src/main/scala/devices/chiplink/SinkC.scala b/src/main/scala/devices/chiplink/SinkC.scala index 2438854..be7cbc2 100644 --- a/src/main/scala/devices/chiplink/SinkC.scala +++ b/src/main/scala/devices/chiplink/SinkC.scala @@ -13,8 +13,8 @@ class SinkC(info: ChipLinkInfo) extends Module // Map TileLink sources to ChipLink sources+domain val tl2cl = info.sourceMap - val source = info.mux(tl2cl.mapValues(_.source)) - val domain = info.mux(tl2cl.mapValues(_.domain)) + val source = info.mux(tl2cl.mapValues(_.source).toMap) + val domain = info.mux(tl2cl.mapValues(_.domain).toMap) // We need a Q because we stall the channel while serializing it's header val c = Queue(io.c, 1, flow=true) diff --git a/src/main/scala/devices/chiplink/StuckSnooper.scala b/src/main/scala/devices/chiplink/StuckSnooper.scala index 1e88e43..830111b 100644 --- a/src/main/scala/devices/chiplink/StuckSnooper.scala +++ b/src/main/scala/devices/chiplink/StuckSnooper.scala @@ -26,7 +26,8 @@ class StuckSnooper(uFn: Seq[TLClientPortParameters] => TLClientPortParameters)(i { val node = new StuckSnooperNode(uFn) - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { val io = IO(new Bundle { val bypass = Bool(INPUT) val pending = Bool(OUTPUT) @@ -111,7 +112,8 @@ class TLStuckSnooperTester(txns: Int)(implicit p: Parameters) extends LazyModule ram.node := TLFragmenter(4, 16) := mux.node // how to test probe + release? - lazy val module = new LazyModuleImp(this) with UnitTestModule { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) with UnitTestModule { io.finished := fuzz1.module.io.finished && fuzz2.module.io.finished mux.module.io.bypass := LFSR64(Bool(true))(0) } diff --git a/src/main/scala/devices/gpio/GPIO.scala b/src/main/scala/devices/gpio/GPIO.scala index c822e5d..547c7c5 100644 --- a/src/main/scala/devices/gpio/GPIO.scala +++ b/src/main/scala/devices/gpio/GPIO.scala @@ -66,7 +66,8 @@ abstract class GPIO(busWidthBytes: Int, c: GPIOParams)(implicit p: Parameters) "interrupt-controller" -> Nil, "#interrupt-cells" -> Seq(ResourceInt(2))) - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { //-------------------------------------------------- // CSR Declarations diff --git a/src/main/scala/devices/i2c/I2C.scala b/src/main/scala/devices/i2c/I2C.scala index 9282c8a..3e01e2d 100644 --- a/src/main/scala/devices/i2c/I2C.scala +++ b/src/main/scala/devices/i2c/I2C.scala @@ -83,7 +83,8 @@ abstract class I2C(busWidthBytes: Int, params: I2CParams)(implicit p: Parameters def nInterrupts = 1 - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { val I2C_CMD_NOP = UInt(0x00) val I2C_CMD_START = UInt(0x01) diff --git a/src/main/scala/devices/mockaon/MockAON.scala b/src/main/scala/devices/mockaon/MockAON.scala index 43b74e0..7448cf9 100644 --- a/src/main/scala/devices/mockaon/MockAON.scala +++ b/src/main/scala/devices/mockaon/MockAON.scala @@ -2,7 +2,7 @@ package sifive.blocks.devices.mockaon import Chisel.{defaultCompileOptions => _, _} import freechips.rocketchip.util.CompileOptions.NotStrictInferReset -import chisel3.MultiIOModule +import chisel3.Module import freechips.rocketchip.config.Parameters import freechips.rocketchip.regmapper._ import freechips.rocketchip.tilelink._ @@ -50,7 +50,7 @@ trait HasMockAONBundleContents extends Bundle { val resetCauses = new ResetCauses().asInput } -trait HasMockAONModuleContents extends MultiIOModule with HasRegMap { +trait HasMockAONModuleContents extends Module with HasRegMap { val io: HasMockAONBundleContents val params: MockAONParams val c = params diff --git a/src/main/scala/devices/mockaon/MockAONWrapper.scala b/src/main/scala/devices/mockaon/MockAONWrapper.scala index 198cbd5..2b3b3d3 100644 --- a/src/main/scala/devices/mockaon/MockAONWrapper.scala +++ b/src/main/scala/devices/mockaon/MockAONWrapper.scala @@ -49,7 +49,8 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L // crossing lives outside in Periphery val intnode = IntSyncCrossingSource(alreadyRegistered = true) := aon.intnode - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { val io = IO(new MockAONWrapperBundle { val rtc = Clock(OUTPUT) val ndreset = Bool(INPUT) diff --git a/src/main/scala/devices/mockaon/RTC.scala b/src/main/scala/devices/mockaon/RTC.scala index 20823a5..92e7b60 100644 --- a/src/main/scala/devices/mockaon/RTC.scala +++ b/src/main/scala/devices/mockaon/RTC.scala @@ -3,13 +3,13 @@ package sifive.blocks.devices.mockaon import Chisel.{defaultCompileOptions => _, _} import freechips.rocketchip.util.CompileOptions.NotStrictInferReset import Chisel.ImplicitConversions._ -import chisel3.MultiIOModule +import chisel3.Module import freechips.rocketchip.util.AsyncResetReg import freechips.rocketchip.regmapper.RegFieldDesc import sifive.blocks.util.{SlaveRegIF, GenericTimer, GenericTimerIO, DefaultGenericTimerCfgDescs} -class RTC extends MultiIOModule with GenericTimer { +class RTC extends Module with GenericTimer { protected def prefix = "rtc" protected def countWidth = 48 diff --git a/src/main/scala/devices/mockaon/WatchdogTimer.scala b/src/main/scala/devices/mockaon/WatchdogTimer.scala index 6b58462..4dbdb75 100644 --- a/src/main/scala/devices/mockaon/WatchdogTimer.scala +++ b/src/main/scala/devices/mockaon/WatchdogTimer.scala @@ -3,7 +3,7 @@ package sifive.blocks.devices.mockaon import Chisel.{defaultCompileOptions => _, _} import freechips.rocketchip.util.CompileOptions.NotStrictInferReset import Chisel.ImplicitConversions._ -import chisel3.MultiIOModule +import chisel3.Module import freechips.rocketchip.util.AsyncResetReg import freechips.rocketchip.regmapper.{RegFieldDesc} @@ -21,7 +21,7 @@ object WatchdogTimer { val key = 0x51F15E } -class WatchdogTimer extends MultiIOModule with GenericTimer { +class WatchdogTimer extends Module with GenericTimer { protected def prefix = "wdog" protected def countWidth = 31 protected def cmpWidth = 16 @@ -60,8 +60,7 @@ class WatchdogTimer extends MultiIOModule with GenericTimer { lazy val io = IO(new GenericTimerIO(regWidth, ncmp, maxcmp, scaleWidth, countWidth, cmpWidth) { val corerst = Bool(INPUT) val rst = Bool(OUTPUT) - } - ) + }) io.rst := AsyncResetReg(Bool(true), rsten && elapsed(0)) } diff --git a/src/main/scala/devices/pwm/PWM.scala b/src/main/scala/devices/pwm/PWM.scala index 5340a99..7eda789 100644 --- a/src/main/scala/devices/pwm/PWM.scala +++ b/src/main/scala/devices/pwm/PWM.scala @@ -3,7 +3,7 @@ package sifive.blocks.devices.pwm import Chisel.{defaultCompileOptions => _, _} import freechips.rocketchip.util.CompileOptions.NotStrictInferReset import Chisel.ImplicitConversions._ -import chisel3.MultiIOModule +import chisel3.Module import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.diplomacy._ @@ -21,7 +21,7 @@ import freechips.rocketchip.util._ import sifive.blocks.util._ // Core PWM Functionality & Register Interface -class PWMTimer(val ncmp: Int = 4, val cmpWidth: Int = 16, val prefix: String = "pwm") extends MultiIOModule with GenericTimer { +class PWMTimer(val ncmp: Int = 4, val cmpWidth: Int = 16, val prefix: String = "pwm") extends Module with GenericTimer { def orR(v: Vec[Bool]): Bool = v.foldLeft(Bool(false))( _||_ ) protected def countWidth = ((1 << scaleWidth) - 1) + cmpWidth diff --git a/src/main/scala/devices/stream/PseudoStream.scala b/src/main/scala/devices/stream/PseudoStream.scala index f2d4567..9437eda 100644 --- a/src/main/scala/devices/stream/PseudoStream.scala +++ b/src/main/scala/devices/stream/PseudoStream.scala @@ -38,7 +38,8 @@ abstract class PseudoStream(busWidthBytes: Int, val params: PseudoStreamParams)( size = 1 << log2Up(4096 * params.nChannels), beatBytes = busWidthBytes), new PseudoStreamPortIO(params)) { - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { val nbports = Wire(Vec(params.nChannels, new PseudoStreamChannelIO(params))) val bports = Wire(Vec(params.nChannels, new PseudoStreamChannelIO(params))) diff --git a/src/main/scala/devices/timer/Timer.scala b/src/main/scala/devices/timer/Timer.scala index e951951..fdfb2aa 100644 --- a/src/main/scala/devices/timer/Timer.scala +++ b/src/main/scala/devices/timer/Timer.scala @@ -41,7 +41,8 @@ class Timer(w: Int, c: TimerParams)(implicit p: Parameters) with HasInterruptSources with HasTLControlRegMap { def nInterrupts: Int = 1 - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { val timer = Module(new PWMTimer(1, c.cmpWidth, "timer")) interrupts := timer.io.ip val mapping = (GenericTimer.timerRegMap(timer, 0, c.regBytes)) diff --git a/src/main/scala/devices/uart/UART.scala b/src/main/scala/devices/uart/UART.scala index eb57423..7679dcf 100755 --- a/src/main/scala/devices/uart/UART.scala +++ b/src/main/scala/devices/uart/UART.scala @@ -73,7 +73,8 @@ class UART(busWidthBytes: Int, val c: UARTParams, divisorInit: Int = 0) require(divisorInit != 0, "UART divisor wasn't initialized during instantiation") require(divisorInit >> c.divisorBits == 0, s"UART divisor reg (width $c.divisorBits) not wide enough to hold $divisorInit") - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { val txm = Module(new UARTTx(c)) val txq = Module(new Queue(txm.io.in.bits, c.nTxEntries)) diff --git a/src/main/scala/devices/wdt/TLWDT.scala b/src/main/scala/devices/wdt/TLWDT.scala index d9f6cae..a052ace 100644 --- a/src/main/scala/devices/wdt/TLWDT.scala +++ b/src/main/scala/devices/wdt/TLWDT.scala @@ -3,7 +3,7 @@ package sifive.blocks.devices.wdt import Chisel.{defaultCompileOptions => _, _} import freechips.rocketchip.util.CompileOptions.NotStrictInferReset import Chisel.ImplicitConversions._ -import chisel3.MultiIOModule +import chisel3.Module import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.diplomacy._ @@ -44,7 +44,8 @@ abstract class WDT(busWidthBytes: Int, val params: WDTParams)(implicit p: Parame def nInterrupts: Int = 1 - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { val wdt = Module(new WatchdogTimer()) interrupts := wdt.io.ip port.rst := wdt.io.rst diff --git a/src/main/scala/util/Devices.scala b/src/main/scala/util/Devices.scala index b36a5ef..a6e41d5 100644 --- a/src/main/scala/util/Devices.scala +++ b/src/main/scala/util/Devices.scala @@ -50,7 +50,8 @@ class DevicesSubsystem( def devicesSubhierarchies = None - lazy val module = new LazyModuleImp(this) { + lazy val module = new Impl + class Impl extends LazyModuleImp(this) { override def desiredName: String = hierarchyName } } diff --git a/src/main/scala/util/Timer.scala b/src/main/scala/util/Timer.scala index d794ef9..efcf824 100644 --- a/src/main/scala/util/Timer.scala +++ b/src/main/scala/util/Timer.scala @@ -5,6 +5,7 @@ import freechips.rocketchip.util.CompileOptions.NotStrictInferReset import Chisel.ImplicitConversions._ import freechips.rocketchip.regmapper._ import freechips.rocketchip.util.WideCounter +import chisel3.Module import scala.math.{min, max} @@ -197,6 +198,7 @@ trait GenericTimer { protected def cfg_desc: GenericTimerCfgDescs = DefaultGenericTimerCfgDescs(prefix, ncmp) val io: GenericTimerIO + //val io protected val scale = RegEnable(io.regs.cfg.write.scale, io.regs.cfg.write_scale && unlocked) protected lazy val zerocmp = RegEnable(io.regs.cfg.write.zerocmp, io.regs.cfg.write_zerocmp && unlocked)