From 9927231bc42f2405151f67e26396f686f2bfaa46 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sat, 17 Oct 2020 22:47:50 -0700 Subject: [PATCH 01/29] Support lazy-iobinders --- .../chipyard/src/main/scala/ChipTop.scala | 15 +- .../src/main/scala/HarnessBinders.scala | 79 ++--- .../chipyard/src/main/scala/IOBinders.scala | 282 ++++++++++-------- .../chipyard/src/main/scala/TestHarness.scala | 7 +- .../src/main/scala/BridgeBinders.scala | 16 +- .../firechip/src/main/scala/FireSim.scala | 4 +- 6 files changed, 214 insertions(+), 189 deletions(-) diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala index 1cef2180..e7456d80 100644 --- a/generators/chipyard/src/main/scala/ChipTop.scala +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -23,12 +23,10 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) * drive clock and reset generation */ -class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions { - // A publicly accessible list of IO cells (useful for a floorplanning tool, for example) - val iocells = ArrayBuffer.empty[IOCell] - +class ChipTop(implicit p: Parameters) extends LazyModule + with HasTestHarnessFunctions with HasIOBinders { // The system module specified by BuildSystem - val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") + lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system") // The implicitClockSinkNode provides the implicit clock and reset for the System val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock")))) @@ -45,13 +43,6 @@ class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunc val implicit_clock = implicitClockSinkNode.in.head._1.clock val implicit_reset = implicitClockSinkNode.in.head._1.reset - - // Note: IOBinders cannot rely on the implicit clock/reset, as this is a LazyRawModuleImp - val (_ports, _iocells, _portMap) = ApplyIOBinders(lazySystem, p(IOBinders)) - // We ignore _ports for now... - iocells ++= _iocells - portMap ++= _portMap - // Connect the implicit clock/reset, if present lazySystem.module match { case l: LazyModuleImp => { l.clock := implicit_clock diff --git a/generators/chipyard/src/main/scala/HarnessBinders.scala b/generators/chipyard/src/main/scala/HarnessBinders.scala index e5cfacfb..c5b95f75 100644 --- a/generators/chipyard/src/main/scala/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/HarnessBinders.scala @@ -1,7 +1,7 @@ package chipyard.harness import chisel3._ -import chisel3.experimental.{Analog} +import chisel3.experimental.{Analog, BaseModule} import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} @@ -31,42 +31,42 @@ case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalRefer Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => Nil) ) - object ApplyHarnessBinders { - def apply(th: HasHarnessSignalReferences, sys: LazyModule, map: Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]], portMap: Map[String, Seq[Data]]) = { + def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters) = { val pm = portMap.withDefaultValue(Nil) - map.map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) } + p(HarnessBinders).map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) } } } -class OverrideHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => { +class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Seq[Any]) => (T, S, Seq[U]) => Seq[Any])(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) extends Config((site, here, up) => { case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString -> ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { - val pts = ports.collect({case p: S => p}) + val pts = ports.collect({case p: U => p}) require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}") - t match { - case system: T => fn(system, th, pts) + val upfn = up(HarnessBinders, site)(tag.runtimeClass.toString) + th match { + case th: S => + t match { + case system: T => composer(upfn)(system, th, pts) + case _ => Nil + } case _ => Nil } }) ) }) -class ComposeHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => { - case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString -> - ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { - val pts = ports.collect({case p: S => p}) - require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}") - t match { - case system: T => up(HarnessBinders, site)(tag.runtimeClass.toString)(system, th, pts) ++ fn(system, th, pts) - case _ => Nil - } - }) - ) -}) +class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any]) + (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) + extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => fn) + +class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any]) + (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) + extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => (t, th, p) => upfn(t, th, p) ++ fn(t, th, p)) + class WithGPIOTiedOff extends OverrideHarnessBinder({ - (system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => { + (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Analog]) => { ports.foreach { _ <> AnalogConst(0) } Nil } @@ -74,7 +74,7 @@ class WithGPIOTiedOff extends OverrideHarnessBinder({ // DOC include start: WithUARTAdapter class WithUARTAdapter extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { + (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { UARTAdapter.connect(ports)(system.p) Nil } @@ -82,14 +82,14 @@ class WithUARTAdapter extends OverrideHarnessBinder({ // DOC include end: WithUARTAdapter class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({ - (system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { + (system: HasPeripherySPIFlashModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p) Nil } }) class WithSimBlockDevice extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) } Nil @@ -97,7 +97,7 @@ class WithSimBlockDevice extends OverrideHarnessBinder({ }) class WithBlockDeviceModel extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } } Nil @@ -105,7 +105,7 @@ class WithBlockDeviceModel extends OverrideHarnessBinder({ }) class WithLoopbackNIC extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { n => withClockAndReset(n.clock, th.harnessReset) { @@ -117,7 +117,7 @@ class WithLoopbackNIC extends OverrideHarnessBinder({ }) class WithSimNetwork extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) } Nil @@ -125,7 +125,7 @@ class WithSimNetwork extends OverrideHarnessBinder({ }) class WithSimAXIMem extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p)) @@ -139,7 +139,7 @@ class WithSimAXIMem extends OverrideHarnessBinder({ }) class WithBlackBoxSimMem extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => val memSize = p(ExtMem).get.master.size @@ -154,7 +154,7 @@ class WithBlackBoxSimMem extends OverrideHarnessBinder({ }) class WithSimAXIMMIO extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MMIOPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MMIOPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { val p: Parameters = chipyard.iobinders.GetSystemParameters(system) (ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) => val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p)) @@ -168,26 +168,27 @@ class WithSimAXIMMIO extends OverrideHarnessBinder({ }) class WithTieOffInterrupts extends OverrideHarnessBinder({ - (system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => { + (system: HasExtInterruptsModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UInt]) => { ports.foreach { _ := 0.U } Nil } }) class WithTieOffL2FBusAXI extends OverrideHarnessBinder({ - (system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveSlaveAXI4Port, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { ports.foreach({ p => p := DontCare; p.bits.tieoff() }) Nil } }) class WithSimDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => { + (system: HasPeripheryDebug, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { + implicit val p: Parameters = GetSystemParameters(system) ports.map { case d: ClockedDMIIO => val dtm_success = WireInit(false.B) when (dtm_success) { th.success := true.B } - val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success) + val dtm = Module(new SimDTM).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success) case j: JTAGIO => val dtm_success = WireInit(false.B) when (dtm_success) { th.success := true.B } @@ -198,7 +199,7 @@ class WithSimDebug extends OverrideHarnessBinder({ }) class WithTiedOffDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => { + (system: HasPeripheryDebug, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { ports.map { case j: JTAGIO => j.TCK := true.B.asClock @@ -224,7 +225,7 @@ class WithTiedOffDebug extends OverrideHarnessBinder({ class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { implicit val p = chipyard.iobinders.GetSystemParameters(system) ports.map({ port => val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -234,7 +235,7 @@ class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ }) class WithSimSerial extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { implicit val p = chipyard.iobinders.GetSystemParameters(system) ports.map({ port => val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -245,14 +246,14 @@ class WithSimSerial extends OverrideHarnessBinder({ }) class WithTraceGenSuccess extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => { + (system: TraceGenSystemModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Bool]) => { ports.map { p => when (p) { th.success := true.B } } Nil } }) class WithSimDromajoBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { + (system: CanHaveTraceIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) } Nil } diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 4a31e2c0..b083b5c0 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -1,17 +1,17 @@ package chipyard.iobinders import chisel3._ -import chisel3.util.experimental.{BoringUtils} import chisel3.experimental.{Analog, IO, DataMirror} import freechips.rocketchip.config._ -import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} +import freechips.rocketchip.diplomacy._ import freechips.rocketchip.devices.debug._ import freechips.rocketchip.jtag.{JTAGIO} import freechips.rocketchip.subsystem._ import freechips.rocketchip.system.{SimAXIMem} import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} import freechips.rocketchip.util._ +import freechips.rocketchip.prci.{ClockSinkNode, ClockSinkParameters} import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem} import sifive.blocks.devices.gpio._ @@ -28,6 +28,12 @@ import chipyard.GlobalResetSchemeKey import scala.reflect.{ClassTag} +object IOBinderTypes { + type IOBinderTuple = (Seq[Data], Seq[IOCell]) + type IOBinderFunction = (Boolean, =>Any) => ModuleValue[IOBinderTuple] +} +import IOBinderTypes._ + // System for instantiating binders based // on the scala type of the Target (_not_ its IO). This avoids needing to // duplicate harnesses (essentially test harnesses) for each target. @@ -40,21 +46,30 @@ import scala.reflect.{ClassTag} // You can add your own binder by adding a new (key, fn) pair, typically by using // the OverrideIOBinder or ComposeIOBinder macros -case object IOBinders extends Field[Map[String, (Any) => (Seq[Data], Seq[IOCell])]]( - Map[String, (Any) => (Seq[Data], Seq[IOCell])]().withDefaultValue((Any) => (Nil, Nil)) +case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]]( + Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil) ) -object ApplyIOBinders { - def apply(sys: LazyModule, map: Map[String, (Any) => (Seq[Data], Seq[IOCell])]): - (Iterable[Data], Iterable[IOCell], Map[String, Seq[Data]]) = { - val lzy = map.map({ case (s,f) => s -> f(sys) }) - val imp = map.map({ case (s,f) => s -> f(sys.module) }) - val unzipped = (lzy.values ++ imp.values).unzip - val ports: Iterable[Data] = unzipped._1.flatten - val cells: Iterable[IOCell] = unzipped._2.flatten - val portMap: Map[String, Seq[Data]] = map.keys.map(k => k -> (lzy(k)._1 ++ imp(k)._1)).toMap - (ports, cells, portMap) - } +abstract trait HasIOBinders { this: LazyModule => + val lazySystem: LazyModule + private val iobinders = p(IOBinders) + // Note: IOBinders cannot rely on the implicit clock/reset, as they may be called from the + // context of a LazyRawModuleImp + private val lzy = iobinders.map({ case (s,fns) => s -> fns.map(f => f(true, lazySystem)) }) + private val imp = iobinders.map({ case (s,fns) => s -> fns.map(f => f(false, lazySystem.module)) }) + + private lazy val lzyFlattened: Map[String, IOBinderTuple] = lzy.map({ + case (s,ms) => s -> (ms.map(_._1).flatten, ms.map(_._2).flatten) + }) + private lazy val impFlattened: Map[String, IOBinderTuple] = imp.map({ + case (s,ms) => s -> (ms.map(_._1).flatten, ms.map(_._2).flatten) + }) + + // A publicly accessible list of IO cells (useful for a floorplanning tool, for example) + lazy val iocells = (lzyFlattened.values ++ impFlattened.values).unzip._2.flatten.toBuffer + + // A mapping between stringified DigitalSystem traits and their corresponding ChipTop ports + lazy val portMap = iobinders.keys.map(k => k -> (lzyFlattened(k)._1 ++ impFlattened(k)._1)).toMap } // Note: The parameters instance is accessible only through LazyModule @@ -72,52 +87,46 @@ object GetSystemParameters { } } -class IOBinder(f: (View, View, View) => PartialFunction[Any, Any]) extends Config(f) - -// This macro overrides previous matches on some Top mixin. This is useful for -// binders which drive IO, since those typically cannot be composed -class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => { - case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((t: Any) => { - t match { - case system: T => - val (ports, cells) = fn(system) - (ports, cells) - case _ => (Nil, Nil) - } - }) - ) +class IOBinder[T](composer: Seq[IOBinderFunction] => Seq[IOBinderFunction])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { + case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> composer(up(IOBinders, site)(tag.runtimeClass.toString))) }) -// This macro composes with previous matches on some Top mixin. This is useful for -// annotation-like binders, since those can typically be composed -class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => { - case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((t: Any) => { - t match { - case system: T => - val r = up(IOBinders, site)(tag.runtimeClass.toString)(system) - val h = fn(system) - val ports = r._1 ++ h._1 - val cells = r._2 ++ h._2 - (ports, cells) - case _ => (Nil, Nil) - } - }) - ) -}) +class ConcreteIOBinder[T](composes: Boolean, fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends IOBinder[T]( + up => (if (composes) up else Nil) ++ Seq(((_, t) => { InModuleBody { + t match { + case system: T => fn(system) + case _ => (Nil, Nil) + } + }}): IOBinderFunction) +) -object BoreHelper { - def apply(name: String, source: Clock): Clock = { - val clock_io = IO(Output(Clock())).suggestName(name) - val clock_wire = Wire(Clock()).suggestName(s"chiptop_${name}") - dontTouch(clock_wire) - clock_wire := false.B.asClock // necessary for BoringUtils to work properly - BoringUtils.bore(source, Seq(clock_wire)) - clock_io := clock_wire - clock_io - } -} + +class LazyIOBinder[T](composes: Boolean, fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends IOBinder[T]( + up => (if (composes) up else Nil) ++ Seq(((isLazy, t) => { + val empty = new ModuleValue[IOBinderTuple] { + def getWrappedValue: IOBinderTuple = (Nil, Nil) + } + if (isLazy) { + t match { + case system: T => fn(system) + case _ => empty + } + } else { + empty + } + }): IOBinderFunction) +) + +// The "Override" binders override any previous IOBinders (lazy or concrete) defined on the same trait. +// The "Compose" binders do not override previously defined IOBinders on the same trait +// The default IOBinders evaluate only in the concrete "ModuleImp" phase of elaboration +// The "Lazy" IOBinders evaluate in the LazyModule phase, but can also generate hardware through InModuleBody + +class OverrideIOBinder[T](fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends ConcreteIOBinder[T](false, fn) +class ComposeIOBinder[T](fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends ConcreteIOBinder[T](true, fn) + +class OverrideLazyIOBinder[T](fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends LazyIOBinder[T](false, fn) +class ComposeLazyIOBinder[T](fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends LazyIOBinder[T](true, fn) case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams()) @@ -194,55 +203,55 @@ class WithExtInterruptIOCells extends OverrideIOBinder({ }) -class WithDebugIOCells extends OverrideIOBinder({ - (system: HasPeripheryDebugModuleImp) => { - system.debug.map({ debug => - val p = system.p - val tlbus = system.outer.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere) - val debug_clock = Wire(Clock()).suggestName("debug_clock") - val debug_reset = Wire(Reset()).suggestName("debug_reset") - debug_clock := false.B.asClock // must provide default assignment to avoid firrtl unassigned error - debug_reset := false.B // must provide default assignment to avoid firrtl unassigned error - BoringUtils.bore(tlbus.module.clock, Seq(debug_clock)) - BoringUtils.bore(tlbus.module.reset, Seq(debug_reset)) +class WithDebugIOCells extends OverrideLazyIOBinder({ + (system: HasPeripheryDebug) => { + implicit val p = GetSystemParameters(system) + val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere) + val clockSinkNode = system.debugOpt.map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) + clockSinkNode.map(_ := tlbus.fixedClockNode) + def clockBundle = clockSinkNode.get.in.head._1 - // We never use the PSDIO, so tie it off on-chip - system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) } - system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := debug_reset.asBool } } - system.debug.map { d => - // Tie off extTrigger - d.extTrigger.foreach { t => - t.in.req := false.B - t.out.ack := t.out.req + + InModuleBody { system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripheryDebugModuleImp => { + system.debug.map({ debug => + // We never use the PSDIO, so tie it off on-chip + system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) } + system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := clockBundle.reset.asBool } } + system.debug.map { d => + // Tie off extTrigger + d.extTrigger.foreach { t => + t.in.req := false.B + t.out.ack := t.out.req + } + // Tie off disableDebug + d.disableDebug.foreach { d => d := false.B } + // Drive JTAG on-chip IOs + d.systemjtag.map { j => + j.reset := clockBundle.reset + j.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W) + j.part_number := p(JtagDTMKey).idcodePartNum.U(16.W) + j.version := p(JtagDTMKey).idcodeVersion.U(4.W) + } } - // Tie off disableDebug - d.disableDebug.foreach { d => d := false.B } - // Drive JTAG on-chip IOs - d.systemjtag.map { j => - j.reset := debug_reset - j.mfr_id := system.p(JtagDTMKey).idcodeManufId.U(11.W) - j.part_number := system.p(JtagDTMKey).idcodePartNum.U(16.W) - j.version := system.p(JtagDTMKey).idcodeVersion.U(4.W) + Debug.connectDebugClockAndReset(Some(debug), clockBundle.clock) + + // Add IOCells for the DMI/JTAG/APB ports + val dmiTuple = debug.clockeddmi.map { d => + IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) } - } - Debug.connectDebugClockAndReset(Some(debug), debug_clock)(system.p) - // Add IOCells for the DMI/JTAG/APB ports - val dmiTuple = debug.clockeddmi.map { d => - IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) - } + val jtagTuple = debug.systemjtag.map { j => + IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) + } - val jtagTuple = debug.systemjtag.map { j => - IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) - } + val apbTuple = debug.apb.map { a => + IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) + } - val apbTuple = debug.apb.map { a => - IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) - } - - val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq - (allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq) - }).getOrElse((Nil, Nil)) + val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq + (allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq) + }).getOrElse((Nil, Nil)) + }}} } }) @@ -255,39 +264,60 @@ class WithSerialTLIOCells extends OverrideIOBinder({ }) -class WithAXI4MemPunchthrough extends OverrideIOBinder({ +class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({ (system: CanHaveMasterAXI4MemPort) => { - val ports: Seq[ClockedIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) => - val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}") - p.bits <> m - p.clock := BoreHelper("axi4_mem_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock) - p - }) - (ports, Nil) + implicit val p: Parameters = GetSystemParameters(system) + val clockSinkNode = p(ExtMem).map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) + clockSinkNode.map(_ := system.asInstanceOf[BaseSubsystem].mbus.fixedClockNode) + def clockBundle = clockSinkNode.get.in.head._1 + + InModuleBody { + val ports: Seq[ClockedIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) => + val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}") + p.bits <> m + p.clock := clockBundle.clock + p + }) + (ports, Nil) + } } }) -class WithAXI4MMIOPunchthrough extends OverrideIOBinder({ +class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({ (system: CanHaveMasterAXI4MMIOPort) => { - val ports: Seq[ClockedIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) => - val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}") - p.bits <> m - p.clock := BoreHelper("axi4_mmio_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock) - p - }) - (ports, Nil) + implicit val p: Parameters = GetSystemParameters(system) + val clockSinkNode = p(ExtBus).map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) + clockSinkNode.map(_ := system.asInstanceOf[BaseSubsystem].mbus.fixedClockNode) + def clockBundle = clockSinkNode.get.in.head._1 + + InModuleBody { + val ports: Seq[ClockedIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) => + val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}") + p.bits <> m + p.clock := clockBundle.clock + p + }) + (ports, Nil) + } } }) -class WithL2FBusAXI4Punchthrough extends OverrideIOBinder({ - (system: CanHaveSlaveAXI4Port) => { - val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) => - val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}") - m <> p.bits - p.clock := BoreHelper("axi4_fbus_clock", system.asInstanceOf[BaseSubsystem].fbus.module.clock) - p - }) - (ports, Nil) +class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({ + (system: CanHaveSlaveAXI4Port) => { + implicit val p: Parameters = GetSystemParameters(system) + val clockSinkNode = p(ExtIn).map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) + clockSinkNode.map(_ := system.asInstanceOf[BaseSubsystem].fbus.fixedClockNode) + def clockBundle = clockSinkNode.get.in.head._1 + + InModuleBody { + val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) => + val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}") + m <> p.bits + p.clock := clockBundle.clock + p + }) + (ports, Nil) + } } }) diff --git a/generators/chipyard/src/main/scala/TestHarness.scala b/generators/chipyard/src/main/scala/TestHarness.scala index 2faff565..9c5c9d2c 100644 --- a/generators/chipyard/src/main/scala/TestHarness.scala +++ b/generators/chipyard/src/main/scala/TestHarness.scala @@ -6,6 +6,7 @@ import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.config.{Field, Parameters} import chipyard.harness.{ApplyHarnessBinders, HarnessBinders} +import chipyard.iobinders.HasIOBinders // ------------------------------- // Chipyard Test Harness @@ -14,9 +15,7 @@ import chipyard.harness.{ApplyHarnessBinders, HarnessBinders} case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p)) trait HasTestHarnessFunctions { - val lazySystem: LazyModule val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]] - val portMap = scala.collection.mutable.Map[String, Seq[Data]]() } trait HasHarnessSignalReferences { @@ -44,7 +43,9 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign lazyDut match { case d: HasTestHarnessFunctions => d.harnessFunctions.foreach(_(this)) - ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap) + } + lazyDut match { case d: HasIOBinders => + ApplyHarnessBinders(this, d.lazySystem, d.portMap) } } diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index 444c7b33..2fa49fc3 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -66,7 +66,7 @@ class WithFireSimIOCellModels extends Config((site, here, up) => { }) class WithSerialBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => { ports.map { port => implicit val p = GetSystemParameters(system) val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -77,7 +77,7 @@ class WithSerialBridge extends OverrideHarnessBinder({ }) class WithNICBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => { val p: Parameters = GetSystemParameters(system) ports.map { n => NICBridge(n.clock, n.bits)(p) } Nil @@ -85,12 +85,12 @@ class WithNICBridge extends OverrideHarnessBinder({ }) class WithUARTBridge extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => + (system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) => ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil }) class WithBlockDeviceBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) } Nil @@ -98,7 +98,7 @@ class WithBlockDeviceBridge extends OverrideHarnessBinder({ }) class WithFASEDBridge extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveMasterAXI4MemPort, th: FireSim, ports: Seq[ClockedIO[AXI4Bundle]]) => { implicit val p: Parameters = GetSystemParameters(system) (ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) => val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth, @@ -118,20 +118,20 @@ class WithFASEDBridge extends OverrideHarnessBinder({ }) class WithTracerVBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { + (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => { ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) } Nil } }) class WithDromajoBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => + (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => ports.map { p => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil }) class WithTraceGenBridge extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => + (system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) => ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil }) diff --git a/generators/firechip/src/main/scala/FireSim.scala b/generators/firechip/src/main/scala/FireSim.scala index 90fd473a..70116456 100644 --- a/generators/firechip/src/main/scala/FireSim.scala +++ b/generators/firechip/src/main/scala/FireSim.scala @@ -160,7 +160,9 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSigna lazyModule match { case d: HasTestHarnessFunctions => require(d.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset") d.harnessFunctions.foreach(_(this)) - ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap) + } + lazyModule match { case d: HasIOBinders => + ApplyHarnessBinders(this, d.lazySystem, d.portMap) } NodeIdx.increment() } From 035e2e43158d7cb7aa79600cd1a7450b576dd105 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sat, 17 Oct 2020 22:55:07 -0700 Subject: [PATCH 02/29] Add test for make TOP=DigitalTop --- .circleci/defaults.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh index 1b41e395..e628de7b 100755 --- a/.circleci/defaults.sh +++ b/.circleci/defaults.sh @@ -47,7 +47,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim # key value store to get the build groups declare -A grouping -grouping["group-cores"]="chipyard-ariane chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor" +grouping["group-cores"]="chipyard-ariane chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop" grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif" grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough" grouping["group-tracegen"]="tracegen tracegen-boom" @@ -59,6 +59,7 @@ mapping["chipyard-rocket"]="" mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig" mapping["chipyard-lbwif"]=" CONFIG=LBWIFRocketConfig" mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig" +mapping["chipyard-digitaltop"]=" TOP=DigitalTop" mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig" mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig" mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig" From f3d666d2b7675eebbe890b530a9de2a25cdd8588 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Mon, 19 Oct 2020 10:16:44 -0700 Subject: [PATCH 03/29] Clarify HarnessBinders ClassTag naming --- generators/chipyard/src/main/scala/HarnessBinders.scala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/generators/chipyard/src/main/scala/HarnessBinders.scala b/generators/chipyard/src/main/scala/HarnessBinders.scala index c5b95f75..3cf70f3e 100644 --- a/generators/chipyard/src/main/scala/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/HarnessBinders.scala @@ -38,12 +38,13 @@ object ApplyHarnessBinders { } } -class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Seq[Any]) => (T, S, Seq[U]) => Seq[Any])(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) extends Config((site, here, up) => { - case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString -> +// The ClassTags here are necessary to overcome issues arising from type erasure +class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Seq[Any]) => (T, S, Seq[U]) => Seq[Any])(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => { + case HarnessBinders => up(HarnessBinders, site) + (systemTag.runtimeClass.toString -> ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { val pts = ports.collect({case p: U => p}) - require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}") - val upfn = up(HarnessBinders, site)(tag.runtimeClass.toString) + require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}") + val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString) th match { case th: S => t match { From 7a55c55aa3e640e83b710c7bc9e73882af8959d2 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Mon, 19 Oct 2020 16:17:46 -0700 Subject: [PATCH 04/29] Fix no-MBUS configs --- docs/Customization/IOBinders.rst | 4 ++-- generators/chipyard/src/main/scala/IOBinders.scala | 6 ++---- .../src/main/scala/config/SodorConfigs.scala | 12 ++++++------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/docs/Customization/IOBinders.rst b/docs/Customization/IOBinders.rst index ff180bcd..1ae95512 100644 --- a/docs/Customization/IOBinders.rst +++ b/docs/Customization/IOBinders.rst @@ -4,7 +4,7 @@ IOBinders and HarnessBinders In Chipyard we use special ``Parameters`` keys, ``IOBinders`` and ``HarnessBinders`` to bridge the gap between digital system IOs and TestHarness collateral. IOBinders -========= +--------- The ``IOBinder`` functions are responsible for instantiating IO cells and IOPorts in the ``ChipTop`` layer. @@ -19,7 +19,7 @@ For example, the ``WithUARTIOCells`` IOBinder will, for any ``System`` that migh :end-before: DOC include end: WithUARTIOCells HarnessBinders -============== +-------------- The ``HarnessBinder`` functions determine what modules to bind to the IOs of a ``ChipTop`` in the ``TestHarness``. The ``HarnessBinder`` interface is designed to be reused across various simulation/implementation modes, enabling decoupling of the target design from simulation and testing concerns. diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 6bf8a6df..46bed169 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -267,8 +267,7 @@ class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({ (system: CanHaveMasterAXI4MemPort) => { implicit val p: Parameters = GetSystemParameters(system) val clockSinkNode = p(ExtMem).map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) - val mbus = system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS) - clockSinkNode.map(_ := mbus.fixedClockNode) + clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode) def clockBundle = clockSinkNode.get.in.head._1 InModuleBody { @@ -288,8 +287,7 @@ class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({ (system: CanHaveMasterAXI4MMIOPort) => { implicit val p: Parameters = GetSystemParameters(system) val clockSinkNode = p(ExtBus).map(_ => ClockSinkNode(Seq(ClockSinkParameters()))) - val mbus = system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS) - clockSinkNode.map(_ := mbus.fixedClockNode) + clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode) def clockBundle = clockSinkNode.get.in.head._1 InModuleBody { diff --git a/generators/chipyard/src/main/scala/config/SodorConfigs.scala b/generators/chipyard/src/main/scala/config/SodorConfigs.scala index ea245fbc..998ccff9 100644 --- a/generators/chipyard/src/main/scala/config/SodorConfigs.scala +++ b/generators/chipyard/src/main/scala/config/SodorConfigs.scala @@ -9,7 +9,7 @@ class Sodor1StageConfig extends Config( new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++ new testchipip.WithSerialPBusMem ++ new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad - new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory + new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory new freechips.rocketchip.subsystem.WithNBanks(0) ++ new chipyard.config.AbstractConfig) @@ -18,7 +18,7 @@ class Sodor2StageConfig extends Config( new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++ new testchipip.WithSerialPBusMem ++ new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad - new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory + new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory new freechips.rocketchip.subsystem.WithNBanks(0) ++ new chipyard.config.AbstractConfig) @@ -27,7 +27,7 @@ class Sodor3StageConfig extends Config( new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++ new testchipip.WithSerialPBusMem ++ new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad - new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory + new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory new freechips.rocketchip.subsystem.WithNBanks(0) ++ new chipyard.config.AbstractConfig) @@ -36,7 +36,7 @@ class Sodor3StageSinglePortConfig extends Config( new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++ new testchipip.WithSerialPBusMem ++ new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad - new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory + new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory new freechips.rocketchip.subsystem.WithNBanks(0) ++ new chipyard.config.AbstractConfig) @@ -45,7 +45,7 @@ class Sodor5StageConfig extends Config( new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++ new testchipip.WithSerialPBusMem ++ new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad - new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory + new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory new freechips.rocketchip.subsystem.WithNBanks(0) ++ new chipyard.config.AbstractConfig) @@ -54,6 +54,6 @@ class SodorUCodeConfig extends Config( new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++ new testchipip.WithSerialPBusMem ++ new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad - new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory + new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory new freechips.rocketchip.subsystem.WithNBanks(0) ++ new chipyard.config.AbstractConfig) From 93e57ef23096528a6edd36c52e0ae69b6e629d06 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Mon, 26 Oct 2020 15:18:34 -0700 Subject: [PATCH 05/29] Make the ChipTop reset pin async always --- .../chipyard/src/main/scala/Clocks.scala | 52 +++---------------- .../chipyard/src/main/scala/IOBinders.scala | 18 +++---- .../chipyard/src/main/scala/TestHarness.scala | 3 +- 3 files changed, 15 insertions(+), 58 deletions(-) diff --git a/generators/chipyard/src/main/scala/Clocks.scala b/generators/chipyard/src/main/scala/Clocks.scala index 70fe38e7..3c9e70cd 100644 --- a/generators/chipyard/src/main/scala/Clocks.scala +++ b/generators/chipyard/src/main/scala/Clocks.scala @@ -15,40 +15,6 @@ import testchipip.{TLTileResetCtrl} import chipyard.clocking._ -/** - * Chipyard provides three baseline, top-level reset schemes, set using the - * [[GlobalResetSchemeKey]] in a Parameters instance. These are: - * - * 1) Synchronous: The input coming to the chip is synchronous to the provided - * clocks and will be used without modification as a synchronous reset. - * This is safe only for use in FireSim and SW simulation. - * - * 2) Asynchronous: The input reset is asynchronous to the input clock, but it - * is caught and synchronized to that clock before it is dissemenated. - * Thus, downsteam modules will be emitted with synchronously reset state - * elements. - * - * 3) Asynchronous Full: The input reset is asynchronous to the input clock, - * and is used globally as an async reset. Downstream modules will be emitted - * with asynchronously reset state elements. - * - */ -sealed trait GlobalResetScheme { - def pinIsAsync: Boolean -} -sealed trait HasAsyncInput { self: GlobalResetScheme => - def pinIsAsync = true -} - -sealed trait HasSyncInput { self: GlobalResetScheme => - def pinIsAsync = false -} - -case object GlobalResetSynchronous extends GlobalResetScheme with HasSyncInput -case object GlobalResetAsynchronous extends GlobalResetScheme with HasAsyncInput -case object GlobalResetAsynchronousFull extends GlobalResetScheme with HasAsyncInput -case object GlobalResetSchemeKey extends Field[GlobalResetScheme](GlobalResetSynchronous) - /** * A simple reset implementation that punches out reset ports * for standard Module classes. Three basic reset schemes @@ -58,18 +24,12 @@ object GenerateReset { def apply(chiptop: ChipTop, clock: Clock): Reset = { implicit val p = chiptop.p // this needs directionality so generateIOFromSignal works - val reset_wire = Wire(Input(Reset())) - val (reset_io, resetIOCell) = p(GlobalResetSchemeKey) match { - case GlobalResetSynchronous => - IOCell.generateIOFromSignal(reset_wire, "reset") - case GlobalResetAsynchronousFull => - IOCell.generateIOFromSignal(reset_wire, "reset", abstractResetAsAsync = true) - case GlobalResetAsynchronous => { - val async_reset_wire = Wire(Input(AsyncReset())) - reset_wire := ResetCatchAndSync(clock, async_reset_wire.asBool()) - IOCell.generateIOFromSignal(async_reset_wire, "reset", abstractResetAsAsync = true) - } - } + val async_reset_wire = Wire(Input(AsyncReset())) + val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(async_reset_wire, "reset", + abstractResetAsAsync = true) + + val reset_wire = ResetCatchAndSync(clock, async_reset_wire.asBool()) + chiptop.iocells ++= resetIOCell chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => { reset_io := th.dutReset diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 87480bfc..246d9c3d 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -24,8 +24,6 @@ import barstools.iocell.chisel._ import testchipip._ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} -import chipyard.GlobalResetSchemeKey - import scala.reflect.{ClassTag} // System for instantiating binders based @@ -157,7 +155,7 @@ class WithGPIOCells extends OverrideIOBinder({ class WithUARTIOCells extends OverrideIOBinder({ (system: HasPeripheryUARTModuleImp) => { val (ports: Seq[UARTPortIO], cells2d) = system.uart.zipWithIndex.map({ case (u, i) => - val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey)) + val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey), abstractResetAsAsync = true) (port, ios) }).unzip (ports, cells2d.flatten) @@ -173,8 +171,8 @@ class WithSPIIOCells extends OverrideIOBinder({ val iocellBase = s"iocell_${name}" // SCK and CS are unidirectional outputs - val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck"), system.p(IOCellKey)) - val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs"), system.p(IOCellKey)) + val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck"), system.p(IOCellKey), IOCell.toAsyncReset) + val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs"), system.p(IOCellKey), IOCell.toAsyncReset) // DQ are bidirectional, so then need special treatment val dqIOs = s.dq.zip(port.dq).zipWithIndex.map { case ((pin, ana), j) => @@ -196,7 +194,7 @@ class WithSPIIOCells extends OverrideIOBinder({ class WithExtInterruptIOCells extends OverrideIOBinder({ (system: HasExtInterruptsModuleImp) => { if (system.outer.nExtInterrupts > 0) { - val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey)) + val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey), abstractResetAsAsync = true) (Seq(port), cells) } else { (Nil, Nil) @@ -240,15 +238,15 @@ class WithDebugIOCells extends OverrideIOBinder({ // Add IOCells for the DMI/JTAG/APB ports val dmiTuple = debug.clockeddmi.map { d => - IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) + IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true) } val jtagTuple = debug.systemjtag.map { j => - IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) + IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = true) } val apbTuple = debug.apb.map { a => - IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync) + IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = true) } val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq @@ -260,7 +258,7 @@ class WithDebugIOCells extends OverrideIOBinder({ class WithSerialTLIOCells extends OverrideIOBinder({ (system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s => val sys = system.asInstanceOf[BaseSubsystem] - val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey)) + val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey), abstractResetAsAsync = true) (Seq(port), cells) }).getOrElse((Nil, Nil)) }) diff --git a/generators/chipyard/src/main/scala/TestHarness.scala b/generators/chipyard/src/main/scala/TestHarness.scala index 2faff565..0b49d03c 100644 --- a/generators/chipyard/src/main/scala/TestHarness.scala +++ b/generators/chipyard/src/main/scala/TestHarness.scala @@ -39,8 +39,7 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign val harnessReset = WireInit(reset) val success = io.success - // dutReset assignment can be overridden via a harnessFunction, but by default it is just reset - val dutReset = WireDefault(if (p(GlobalResetSchemeKey).pinIsAsync) reset.asAsyncReset else reset) + val dutReset = reset.asAsyncReset lazyDut match { case d: HasTestHarnessFunctions => d.harnessFunctions.foreach(_(this)) From f4d70128c007807ba7617f5c4fd47ebaf59c49c4 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 28 Oct 2020 15:34:14 -0700 Subject: [PATCH 06/29] Remove redundant ChipTop reset synchronizer --- generators/chipyard/src/main/scala/Clocks.scala | 4 +--- .../chipyard/src/main/scala/clocking/ResetSynchronizer.scala | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/generators/chipyard/src/main/scala/Clocks.scala b/generators/chipyard/src/main/scala/Clocks.scala index 3c9e70cd..e4d48b59 100644 --- a/generators/chipyard/src/main/scala/Clocks.scala +++ b/generators/chipyard/src/main/scala/Clocks.scala @@ -28,14 +28,12 @@ object GenerateReset { val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(async_reset_wire, "reset", abstractResetAsAsync = true) - val reset_wire = ResetCatchAndSync(clock, async_reset_wire.asBool()) - chiptop.iocells ++= resetIOCell chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => { reset_io := th.dutReset Nil }) - reset_wire + async_reset_wire } } diff --git a/generators/chipyard/src/main/scala/clocking/ResetSynchronizer.scala b/generators/chipyard/src/main/scala/clocking/ResetSynchronizer.scala index 13a593c5..2ba8e855 100644 --- a/generators/chipyard/src/main/scala/clocking/ResetSynchronizer.scala +++ b/generators/chipyard/src/main/scala/clocking/ResetSynchronizer.scala @@ -12,7 +12,7 @@ import freechips.rocketchip.util.{ResetCatchAndSync} * Instantiates a reset synchronizer on all clock-reset pairs in a clock group */ class ClockGroupResetSynchronizer(implicit p: Parameters) extends LazyModule { - val node = ClockGroupIdentityNode() + val node = ClockGroupAdapterNode() lazy val module = new LazyRawModuleImp(this) { (node.out zip node.in).map { case ((oG, _), (iG, _)) => (oG.member.data zip iG.member.data).foreach { case (o, i) => From 7b83da054a4609202578168a8796df40a21ccc1d Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 28 Oct 2020 16:18:22 -0700 Subject: [PATCH 07/29] Clean up HarnessBinders --- .../src/main/scala/HarnessBinders.scala | 72 ++++++++----------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/generators/chipyard/src/main/scala/HarnessBinders.scala b/generators/chipyard/src/main/scala/HarnessBinders.scala index 2ff8ad94..02ab3732 100644 --- a/generators/chipyard/src/main/scala/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/HarnessBinders.scala @@ -27,19 +27,22 @@ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvon import scala.reflect.{ClassTag} -case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]]( - Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => Nil) +case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Unit]]( + Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Unit]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => ()) ) object ApplyHarnessBinders { - def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters) = { + def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters): Unit = { val pm = portMap.withDefaultValue(Nil) - p(HarnessBinders).map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) } + p(HarnessBinders).foreach { case (s, f) => + f(sys, th, pm(s)) + f(sys.module, th, pm(s)) + } } } // The ClassTags here are necessary to overcome issues arising from type erasure -class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Seq[Any]) => (T, S, Seq[U]) => Seq[Any])(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => { +class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Unit) => (T, S, Seq[U]) => Unit)(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => { case HarnessBinders => up(HarnessBinders, site) + (systemTag.runtimeClass.toString -> ((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => { val pts = ports.collect({case p: U => p}) @@ -49,71 +52,68 @@ class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T case th: S => t match { case system: T => composer(upfn)(system, th, pts) - case _ => Nil + case _ => } - case _ => Nil + case _ => } }) ) }) -class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any]) +class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Unit) (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) - extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => fn) + extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => fn) -class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any]) +class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Unit) (implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) - extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => (t, th, p) => upfn(t, th, p) ++ fn(t, th, p)) + extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => (t, th, p) => { + upfn(t, th, p) + fn(t, th, p) + }) class WithGPIOTiedOff extends OverrideHarnessBinder({ - (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Analog]) => { + (system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => { ports.foreach { _ <> AnalogConst(0) } - Nil } }) // DOC include start: WithUARTAdapter class WithUARTAdapter extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { + (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => { UARTAdapter.connect(ports)(system.p) - Nil } }) // DOC include end: WithUARTAdapter class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({ - (system: HasPeripherySPIFlashModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { + (system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => { SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p) - Nil } }) class WithSimBlockDevice extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) } - Nil } }) class WithBlockDeviceModel extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { + (system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } } - Nil } }) class WithLoopbackNIC extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { + (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { n => withClockAndReset(n.clock, th.harnessReset) { NicLoopback.connect(Some(n.bits), p(NICKey)) } } - Nil } }) @@ -121,7 +121,6 @@ class WithSimNetwork extends OverrideHarnessBinder({ (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) } - Nil } }) @@ -135,7 +134,6 @@ class WithSimAXIMem extends OverrideHarnessBinder({ } mem.io_axi4.head <> port.bits } - Nil } }) @@ -150,7 +148,6 @@ class WithBlackBoxSimMem extends OverrideHarnessBinder({ mem.io.clock := port.clock mem.io.reset := port.reset } - Nil } }) @@ -164,26 +161,23 @@ class WithSimAXIMMIO extends OverrideHarnessBinder({ } mmio_mem.io_axi4.head <> port.bits } - Nil } }) class WithTieOffInterrupts extends OverrideHarnessBinder({ - (system: HasExtInterruptsModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UInt]) => { + (system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => { ports.foreach { _ := 0.U } - Nil } }) class WithTieOffL2FBusAXI extends OverrideHarnessBinder({ - (system: CanHaveSlaveAXI4Port, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { + (system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => { ports.foreach({ p => p := DontCare; p.bits.tieoff() }) - Nil } }) class WithSimDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebug, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { + (system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[Data]) => { implicit val p: Parameters = GetSystemParameters(system) ports.map { case d: ClockedDMIIO => @@ -195,12 +189,11 @@ class WithSimDebug extends OverrideHarnessBinder({ when (dtm_success) { th.success := true.B } val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success) } - Nil } }) class WithTiedOffDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebug, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => { + (system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[Data]) => { ports.map { case j: JTAGIO => j.TCK := true.B.asClock @@ -220,13 +213,12 @@ class WithTiedOffDebug extends OverrideHarnessBinder({ a.psel := false.B a.penable := false.B } - Nil } }) class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { implicit val p = chipyard.iobinders.GetSystemParameters(system) ports.map({ port => val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -236,7 +228,7 @@ class WithSerialAdapterTiedOff extends OverrideHarnessBinder({ }) class WithSimSerial extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { + (system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => { implicit val p = chipyard.iobinders.GetSystemParameters(system) ports.map({ port => val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset) @@ -247,15 +239,13 @@ class WithSimSerial extends OverrideHarnessBinder({ }) class WithTraceGenSuccess extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Bool]) => { + (system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => { ports.map { p => when (p) { th.success := true.B } } - Nil } }) class WithSimDromajoBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { + (system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => { ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) } - Nil } }) From 57a0bc5dfcbca2e76cbbb14caa1590ab283a2bfe Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Tue, 3 Nov 2020 12:14:02 -0500 Subject: [PATCH 08/29] Fix zsh compatibility in init-submodules-no-rv-tools (#705) --- scripts/init-submodules-no-riscv-tools-nolog.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/init-submodules-no-riscv-tools-nolog.sh b/scripts/init-submodules-no-riscv-tools-nolog.sh index cede5e47..c861658d 100755 --- a/scripts/init-submodules-no-riscv-tools-nolog.sh +++ b/scripts/init-submodules-no-riscv-tools-nolog.sh @@ -77,6 +77,6 @@ if [ ! -f ./software/firemarshal/marshal-config.yaml ]; then fi echo "# line auto-generated by init-submodules-no-riscv-tools.sh" >> env.sh -echo '__DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"' >> env.sh +echo '__DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]:-${(%):-%x}}")")"' >> env.sh echo "PATH=\$__DIR/bin:\$PATH" >> env.sh echo "PATH=\$__DIR/software/firemarshal:\$PATH" >> env.sh From 946a191221cdca685074ffe28df1a2cf0218aaa3 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Tue, 3 Nov 2020 12:14:18 -0500 Subject: [PATCH 09/29] [clocking] Provide a default div for ClockDividerN sv implementation (#706) --- generators/chipyard/src/main/resources/vsrc/ClockDividerN.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/resources/vsrc/ClockDividerN.sv b/generators/chipyard/src/main/resources/vsrc/ClockDividerN.sv index 4d940d06..1e09a078 100644 --- a/generators/chipyard/src/main/resources/vsrc/ClockDividerN.sv +++ b/generators/chipyard/src/main/resources/vsrc/ClockDividerN.sv @@ -5,7 +5,7 @@ * Duty cycle is 100 * (ceil(DIV / 2)) / DIV. */ -module ClockDividerN #(parameter DIV)(output logic clk_out = 1'b0, input clk_in); +module ClockDividerN #(parameter DIV = 1)(output logic clk_out = 1'b0, input clk_in); localparam CWIDTH = $clog2(DIV); localparam LOW_CYCLES = DIV / 2; From f387634a4128762c698fe79dde6e723ca2d3f817 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Mon, 2 Nov 2020 10:38:37 -0800 Subject: [PATCH 10/29] [clocking] Bound SimplePllConfiguration by maximum reference freq --- .../src/main/scala/clocking/DividerOnlyClockGenerator.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala index fb816c35..bbf05f38 100644 --- a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala +++ b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala @@ -16,12 +16,13 @@ import scala.collection.immutable.ListMap object FrequencyUtils { def computeReferenceFrequencyMHz( requestedOutputs: Seq[ClockParameters], - maximumAllowableDivisor: Int = 0xFFFF): ClockParameters = { + maximumAllowableFreqMHz: Double = 8000.0): ClockParameters = { require(requestedOutputs.nonEmpty) require(!requestedOutputs.contains(0.0)) val freqs = requestedOutputs.map(f => BigInt(Math.round(f.freqMHz * 1000 * 1000))) val refFreq = freqs.reduce((a, b) => a * b / a.gcd(b)).toDouble / (1000 * 1000) - assert((refFreq / freqs.min.toDouble) < maximumAllowableDivisor.toDouble) + assert(refFreq < maximumAllowableFreqMHz, + s"Reference frequency ${refFreq} exceeds maximum allowable value of ${maximumAllowableFreqMHz} MHz") ClockParameters(refFreq) } } From aa4a44925e2bdf95296f26b6bd9a474529785f77 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Mon, 2 Nov 2020 10:40:39 -0800 Subject: [PATCH 11/29] [clocking] Add ScalaTests for the divider-only PLL configurator --- .../clocking/SimplePllConfigurationSpec.scala | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala diff --git a/generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala b/generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala new file mode 100644 index 00000000..897ab0f4 --- /dev/null +++ b/generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala @@ -0,0 +1,21 @@ +//See LICENSE for license details. +package chipyard.clocking + +import freechips.rocketchip.prci._ + +class SimplePllConfigurationSpec extends org.scalatest.FlatSpec { + + def conf(freqMHz: Iterable[Double]): SimplePllConfiguration = new SimplePllConfiguration("test", + freqMHz.map({ f => ClockSinkParameters( + name = Some(s"desiredFreq_$f"), + take = Some(ClockParameters(f))) }).toSeq) + + def tryConf(freqMHz: Double*): Unit = { + val freqStr = freqMHz.mkString(", ") + it should s"configure for ${freqStr} MHz" in { conf(freqMHz) } + } + + tryConf(3200.0, 1600.0, 1000.0, 100.0) + tryConf(3200.0, 1600.0) + tryConf(3200.0, 1066.7) +} From f504b7a0f50d04eafaad400dc977c95b5398e2a5 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Tue, 3 Nov 2020 09:13:18 -0800 Subject: [PATCH 12/29] [clocking] Improve reference clock selection using a multiple-of-fastest strategy --- .../clocking/DividerOnlyClockGenerator.scala | 71 +++++++++++++++---- .../clocking/SimplePllConfigurationSpec.scala | 24 ++++--- .../firechip/src/main/scala/FireSim.scala | 1 + 3 files changed, 76 insertions(+), 20 deletions(-) diff --git a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala index bbf05f38..2b666196 100644 --- a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala +++ b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala @@ -14,21 +14,65 @@ import scala.collection.immutable.ListMap * TODO: figure out how much division is acceptable in our simulators and redefine this. */ object FrequencyUtils { - def computeReferenceFrequencyMHz( + /** + * Adds up the squared error between the generated clocks (refClock / [integer] divider) + * and the requested frequencies. + * + * @param refMHz The candidate reference clock + * @param desiredFreqMHz A list of the requested output frequencies + */ + def squaredError(refMHz: Double, desiredFreqMHz: List[Double], sum: Double = 0.0): Double = desiredFreqMHz match { + case Nil => sum + case desired :: xs => + val divider = Math.round(refMHz / desired) + val termError = ((refMHz / divider) - desired) / desired + squaredError(refMHz, xs, sum + termError * termError) + } + + /** + * Picks a candidate reference frequency by doing a brute-force search over + * multiples of the fastest requested clock. Choose the smallest multiple that + * has an RMS error (across all output frequencies) that is: + * 1) zero or failing that, + * 2) is within the relativeThreshold of the best or is less than the absoluteThreshold + * + * @param requestedOutputs The desired output frequencies in MHz + * @param maximumAllowableFreqMHz The maximum allowable reference in MHz + * @param relativeThreshold See above + * @param absoluteThreshold See above + */ + def computeReferenceAsMultipleOfFastestClock( requestedOutputs: Seq[ClockParameters], - maximumAllowableFreqMHz: Double = 8000.0): ClockParameters = { + maximumAllowableFreqMHz: Double, + relativeThreshold: Double = 1.10, + absoluteThreshold: Double = 0.01): ClockParameters = { + require(requestedOutputs.nonEmpty) require(!requestedOutputs.contains(0.0)) - val freqs = requestedOutputs.map(f => BigInt(Math.round(f.freqMHz * 1000 * 1000))) - val refFreq = freqs.reduce((a, b) => a * b / a.gcd(b)).toDouble / (1000 * 1000) - assert(refFreq < maximumAllowableFreqMHz, - s"Reference frequency ${refFreq} exceeds maximum allowable value of ${maximumAllowableFreqMHz} MHz") - ClockParameters(refFreq) + val requestedFreqs = requestedOutputs.map(_.freqMHz) + val fastestFreq = requestedFreqs.max + require(fastestFreq < maximumAllowableFreqMHz) + + val candidateFreqs = + Seq.tabulate(Math.ceil(maximumAllowableFreqMHz / fastestFreq).toInt)(i => (i + 1) * fastestFreq) + val errorTuples = candidateFreqs.map { f => + f -> Math.sqrt(squaredError(f, requestedFreqs.toList) / requestedFreqs.size) + } + val minError = errorTuples.map(_._2).min + val viableFreqs = errorTuples.collect { + case (f, error) if (error <= minError * relativeThreshold) || (minError > 0 && error < absoluteThreshold) => f + } + ClockParameters(viableFreqs.min) } } -class SimplePllConfiguration(name: String, val sinks: Seq[ClockSinkParameters]) { - val referenceFreqMHz = FrequencyUtils.computeReferenceFrequencyMHz(sinks.flatMap(_.take)).freqMHz +class SimplePllConfiguration( + name: String, + val sinks: Seq[ClockSinkParameters], + maximumAllowableFreqMHz: Double = 16000.0 ) { + val referenceFreqMHz = FrequencyUtils.computeReferenceAsMultipleOfFastestClock( + sinks.flatMap(_.take), + maximumAllowableFreqMHz).freqMHz val sinkDividerMap = ListMap((sinks.map({s => (s, Math.round(referenceFreqMHz / s.take.get.freqMHz).toInt) })):_*) private val preamble = s""" @@ -41,8 +85,10 @@ class SimplePllConfiguration(name: String, val sinks: Seq[ClockSinkParameters]) } val summaryString = preamble + outputSummaries.mkString("\n") - ElaborationArtefacts.add(s"${name}.freq-summary", summaryString) - println(summaryString) + def emitSummaries(): Unit = { + ElaborationArtefacts.add(s"${name}.freq-summary", summaryString) + println(summaryString) + } } case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName) @@ -54,7 +100,7 @@ case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValN "All output clocks in group must set their take parameters. Use a ClockGroupDealiaser") ClockSinkParameters( name = Some(s"${pllName}_reference_input"), - take = Some(FrequencyUtils.computeReferenceFrequencyMHz(u.head.members.flatMap(_.take)))) } + take = Some(ClockParameters(new SimplePllConfiguration(pllName, u.head.members).referenceFreqMHz))) } ) /** @@ -79,6 +125,7 @@ class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName val referenceFreq = refSinkParam.take.get.freqMHz val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members) + pllConfig.emitSummaries() val dividedClocks = mutable.HashMap[Int, Clock]() def instantiateDivider(div: Int): Clock = { diff --git a/generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala b/generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala index 897ab0f4..0abe7c50 100644 --- a/generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala +++ b/generators/chipyard/src/test/scala/clocking/SimplePllConfigurationSpec.scala @@ -5,17 +5,25 @@ import freechips.rocketchip.prci._ class SimplePllConfigurationSpec extends org.scalatest.FlatSpec { - def conf(freqMHz: Iterable[Double]): SimplePllConfiguration = new SimplePllConfiguration("test", + def genConf(freqMHz: Iterable[Double]): SimplePllConfiguration = new SimplePllConfiguration( + "testPLL", freqMHz.map({ f => ClockSinkParameters( name = Some(s"desiredFreq_$f"), - take = Some(ClockParameters(f))) }).toSeq) + take = Some(ClockParameters(f))) }).toSeq, + maximumAllowableFreqMHz = 16000.0) - def tryConf(freqMHz: Double*): Unit = { - val freqStr = freqMHz.mkString(", ") - it should s"configure for ${freqStr} MHz" in { conf(freqMHz) } + def trySuccessfulConf(requestedFreqs: Seq[Double], expected: Double): Unit = { + val freqStr = requestedFreqs.mkString(", ") + it should s"select a reference of ${expected} MHz for ${freqStr} MHz" in { + val conf = genConf(requestedFreqs) + conf.emitSummaries + assert(expected == conf.referenceFreqMHz) + } } - tryConf(3200.0, 1600.0, 1000.0, 100.0) - tryConf(3200.0, 1600.0) - tryConf(3200.0, 1066.7) + trySuccessfulConf(Seq(3200.0, 1600.0, 1000.0, 100.0), 16000.0) + trySuccessfulConf(Seq(3200.0, 1600.0), 3200.0) + trySuccessfulConf(Seq(3200.0, 1066.7), 3200.0) + trySuccessfulConf(Seq(100, 50, 6.67), 100) + trySuccessfulConf(Seq(1, 2, 3, 5, 7, 11, 13).map(_ * 10.0), 1560.0) } diff --git a/generators/firechip/src/main/scala/FireSim.scala b/generators/firechip/src/main/scala/FireSim.scala index acbdbc6b..ff765970 100644 --- a/generators/firechip/src/main/scala/FireSim.scala +++ b/generators/firechip/src/main/scala/FireSim.scala @@ -118,6 +118,7 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => { } val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members) + pllConfig.emitSummaries val rationalClockSpecs = for ((sinkP, division) <- pllConfig.sinkDividerMap) yield { RationalClock(sinkP.name.get, 1, division) } From 16c34e2cf3044152e231d4dbe2f8ba69b4fee740 Mon Sep 17 00:00:00 2001 From: Abraham Gonzalez Date: Wed, 4 Nov 2020 11:46:02 -0800 Subject: [PATCH 13/29] Bump Dromajo for old glibc --- tools/dromajo/dromajo-src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dromajo/dromajo-src b/tools/dromajo/dromajo-src index 56e2ff46..09fbef45 160000 --- a/tools/dromajo/dromajo-src +++ b/tools/dromajo/dromajo-src @@ -1 +1 @@ -Subproject commit 56e2ff46b70521916c362799517f4ed8e67e9e88 +Subproject commit 09fbef4565429f641a7eb93f190ad0e45e11d7f8 From 5e3d1a605d787b7bd02a2361ababd4954c7a7656 Mon Sep 17 00:00:00 2001 From: Abraham Gonzalez Date: Wed, 4 Nov 2020 11:57:23 -0800 Subject: [PATCH 14/29] Add --ignore-qemu flag to toolchains | Prepare QEMU when it builds --- scripts/build-toolchains.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/build-toolchains.sh b/scripts/build-toolchains.sh index 2685872e..9ceb8808 100755 --- a/scripts/build-toolchains.sh +++ b/scripts/build-toolchains.sh @@ -20,6 +20,7 @@ usage() { echo "Options" echo " --prefix PREFIX : Install destination. If unset, defaults to $(pwd)/riscv-tools-install" echo " or $(pwd)/esp-tools-install" + echo " --ignore-qemu : Ignore installing QEMU" echo " --help -h : Display this message" exit "$1" } @@ -34,6 +35,7 @@ die() { TOOLCHAIN="riscv-tools" EC2FASTINSTALL="false" +IGNOREQEMU="false" RISCV="" # getopts does not support long options, and is inflexible @@ -45,6 +47,9 @@ do -p | --prefix ) shift RISCV=$(realpath $1) ;; + --ignore-qemu ) + shift + IGNOREQEMU="true" ;; riscv-tools | esp-tools) TOOLCHAIN=$1 ;; ec2fast ) @@ -109,7 +114,7 @@ else *) false ;; esac; ) || die 'obsolete make version; need GNU make 4.x or later' - module_prepare riscv-gnu-toolchain qemu + module_prepare riscv-gnu-toolchain module_build riscv-gnu-toolchain --prefix="${RISCV}" --with-cmodel=medany echo '==> Building GNU/Linux toolchain' module_make riscv-gnu-toolchain linux @@ -128,7 +133,9 @@ module_all riscv-tests --prefix="${RISCV}/riscv64-unknown-elf" SRCDIR="$(pwd)/toolchains" module_all libgloss --prefix="${RISCV}/riscv64-unknown-elf" --host=riscv64-unknown-elf +if [ "${IGNOREQEMU}" = false ] ; then SRCDIR="$(pwd)/toolchains" module_all qemu --prefix="${RISCV}" --target-list=riscv64-softmmu +fi # make Dromajo git submodule update --init $CHIPYARD_DIR/tools/dromajo/dromajo-src From a2ebbee2ac21d2703995b67daea8a18cc6713271 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 4 Nov 2020 15:05:11 -0800 Subject: [PATCH 15/29] Rename Ariane to CVA6 --- .circleci/check-commit.sh | 2 +- .circleci/config.yml | 6 +- .circleci/defaults.sh | 4 +- .circleci/run-tests.sh | 2 +- .gitmodules | 6 +- README.md | 6 +- build.sbt | 4 +- common.mk | 4 +- docs/Chipyard-Basics/Chipyard-Components.rst | 4 +- docs/Customization/Custom-Core.rst | 70 +++++++++---------- docs/Generators/{Ariane.rst => CVA6.rst} | 10 +-- docs/Generators/index.rst | 2 +- generators/ariane | 1 - .../src/main/scala/ConfigFragments.scala | 4 +- .../chipyard/src/main/scala/TestSuites.scala | 3 - .../src/main/scala/config/ArianeConfigs.scala | 19 ----- .../src/main/scala/config/CVA6Configs.scala | 19 +++++ .../src/main/scala/example/TutorialTile.scala | 14 ++-- generators/cva6 | 1 + .../src/main/scala/BridgeBinders.scala | 2 +- .../src/main/scala/TargetConfigs.scala | 8 +-- .../src/test/scala/ScalaTestSuite.scala | 2 +- scripts/tutorial-patches/build.sbt.patch | 10 +-- sims/firesim | 2 +- sims/verilator/Makefile | 8 +-- 25 files changed, 105 insertions(+), 108 deletions(-) rename docs/Generators/{Ariane.rst => CVA6.rst} (59%) delete mode 160000 generators/ariane delete mode 100644 generators/chipyard/src/main/scala/config/ArianeConfigs.scala create mode 100644 generators/chipyard/src/main/scala/config/CVA6Configs.scala create mode 160000 generators/cva6 diff --git a/.circleci/check-commit.sh b/.circleci/check-commit.sh index 68cc975c..2660fa49 100755 --- a/.circleci/check-commit.sh +++ b/.circleci/check-commit.sh @@ -48,7 +48,7 @@ search () { done } -submodules=("ariane" "boom" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor") +submodules=("cva6" "boom" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor") dir="generators" if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "dev" ] then diff --git a/.circleci/config.yml b/.circleci/config.yml index 4ee84ced..6e74b9d5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -234,12 +234,12 @@ jobs: - run-tests: group-key: "group-cores" project-key: "chipyard-boom" - chipyard-ariane-run-tests: + chipyard-cva6-run-tests: executor: main-env steps: - run-tests: group-key: "group-cores" - project-key: "chipyard-ariane" + project-key: "chipyard-cva6" timeout: "30m" chipyard-sodor-run-tests: executor: main-env @@ -431,7 +431,7 @@ workflows: - chipyard-boom-run-tests: requires: - prepare-chipyard-cores - - chipyard-ariane-run-tests: + - chipyard-cva6-run-tests: requires: - prepare-chipyard-cores - chipyard-sodor-run-tests: diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh index e628de7b..c0bce62d 100755 --- a/.circleci/defaults.sh +++ b/.circleci/defaults.sh @@ -47,7 +47,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim # key value store to get the build groups declare -A grouping -grouping["group-cores"]="chipyard-ariane chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop" +grouping["group-cores"]="chipyard-cva6 chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop" grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif" grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough" grouping["group-tracegen"]="tracegen tracegen-boom" @@ -67,7 +67,7 @@ mapping["chipyard-boom"]=" CONFIG=SmallBoomConfig" mapping["chipyard-blkdev"]=" CONFIG=SimBlockDeviceRocketConfig" mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig" mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig" -mapping["chipyard-ariane"]=" CONFIG=ArianeConfig" +mapping["chipyard-cva6"]=" CONFIG=CVA6Config" mapping["chipyard-spiflashread"]=" CONFIG=LargeSPIFlashROMRocketConfig" mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig" mapping["chipyard-mmios"]=" CONFIG=MMIORocketConfig verilog" diff --git a/.circleci/run-tests.sh b/.circleci/run-tests.sh index da5029b5..5ea53c78 100755 --- a/.circleci/run-tests.sh +++ b/.circleci/run-tests.sh @@ -91,7 +91,7 @@ case $1 in tracegen-boom) run_tracegen ${mapping[$1]} ;; - chipyard-ariane) + chipyard-cva6) make run-binary-fast -C $LOCAL_SIM_DIR ${mapping[$1]} BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/multiply.riscv ;; chipyard-sodor) diff --git a/.gitmodules b/.gitmodules index f374fa1f..d9dbe85f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -113,9 +113,9 @@ [submodule "software/firemarshal"] path = software/firemarshal url = https://github.com/firesim/FireMarshal.git -[submodule "generators/ariane"] - path = generators/ariane - url = https://github.com/ucb-bar/ariane-wrapper.git +[submodule "generators/cva6"] + path = generators/cva6 + url = git@github.com:ucb-bar/cva6-wrapper.git [submodule "tools/DRAMSim2"] path = tools/DRAMSim2 url = https://github.com/firesim/DRAMSim2.git diff --git a/README.md b/README.md index ab542cf3..11f1b8d5 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ To get started using Chipyard, see the documentation on the Chipyard documentati Chipyard is an open source framework for agile development of Chisel-based systems-on-chip. It will allow you to leverage the Chisel HDL, Rocket Chip SoC generator, and other [Berkeley][berkeley] projects to produce a [RISC-V][riscv] SoC with everything from MMIO-mapped peripherals to custom accelerators. -Chipyard contains processor cores ([Rocket][rocket-chip], [BOOM][boom], [Ariane][ariane]), accelerators ([Hwacha][hwacha], [Gemmini][gemmini], [NVDLA][nvdla]), memory systems, and additional peripherals and tooling to help create a full featured SoC. +Chipyard contains processor cores ([Rocket][rocket-chip], [BOOM][boom], [CVA6][cva6]), accelerators ([Hwacha][hwacha], [Gemmini][gemmini], [NVDLA][nvdla]), memory systems, and additional peripherals and tooling to help create a full featured SoC. Chipyard supports multiple concurrent flows of agile hardware development, including software RTL simulation, FPGA-accelerated simulation ([FireSim][firesim]), automated VLSI flows ([Hammer][hammer]), and software workload generation for bare-metal and Linux-based systems ([FireMarshal][firemarshal]). Chipyard is actively developed in the [Berkeley Architecture Research Group][ucb-bar] in the [Electrical Engineering and Computer Sciences Department][eecs] at the [University of California, Berkeley][berkeley]. @@ -35,7 +35,7 @@ If used for research, please cite Chipyard by the following publication: ``` @article{chipyard, - author={Amid, Alon and Biancolin, David and Gonzalez, Abraham and Grubb, Daniel and Karandikar, Sagar and Liew, Harrison and Magyar, Albert and Mao, Howard and Ou, Albert and Pemberton, Nathan and Rigge, Paul and Schmidt, Colin and Wright, John and Zhao, Jerry and Shao, Yakun Sophia and Asanovi\'{c}, Krste and Nikoli\'{c}, Borivoje}, + author={Amid, Alon and Biancolin, David and Gonzalez, Abraham and Grubb, Daniel and Karandikar, Sagar and Liew, Harrison and Magyar, Albert and Mao, Howard and Ou, Albert and Pemberton, Nathan and Rigge, Paul and Schmidt, Colin and Wright, John and Zhao, Jerry and Shao, Yakun Sophia and Asanovi\'{c}, Krste and Nikoli\'{c}, Borivoje}, journal={IEEE Micro}, title={Chipyard: Integrated Design, Simulation, and Implementation Framework for Custom SoCs}, year={2020}, @@ -80,6 +80,6 @@ These additional publications cover many of the internal components used in Chip [rocket-chip]: https://github.com/freechipsproject/rocket-chip [boom]: https://github.com/riscv-boom/riscv-boom [firemarshal]: https://github.com/firesim/FireMarshal/ -[ariane]: https://github.com/pulp-platform/ariane/ +[cva6]: https://github.com/openhwgroup/cva6/ [gemmini]: https://github.com/ucb-bar/gemmini [nvdla]: http://nvdla.org/ diff --git a/build.sbt b/build.sbt index 750878ab..bbf7964f 100644 --- a/build.sbt +++ b/build.sbt @@ -132,7 +132,7 @@ lazy val chipyard = conditionalDependsOn(project in file("generators/chipyard")) .dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell, sha3, // On separate line to allow for cleaner tutorial-setup patches dsptools, `rocket-dsptools`, - gemmini, icenet, tracegen, ariane, nvdla, sodor) + gemmini, icenet, tracegen, cva6, nvdla, sodor) .settings(commonSettings) lazy val tracegen = conditionalDependsOn(project in file("generators/tracegen")) @@ -154,7 +154,7 @@ lazy val boom = conditionalDependsOn(project in file("generators/boom")) .dependsOn(rocketchip) .settings(commonSettings) -lazy val ariane = (project in file("generators/ariane")) +lazy val cva6 = (project in file("generators/cva6")) .dependsOn(rocketchip) .settings(commonSettings) diff --git a/common.mk b/common.mk index 8ebc262c..ca34ffce 100644 --- a/common.mk +++ b/common.mk @@ -47,7 +47,7 @@ HELP_COMMANDS += \ # include additional subproject make fragments # see HELP_COMPILATION_VARIABLES ######################################################################################### -include $(base_dir)/generators/ariane/ariane.mk +include $(base_dir)/generators/cva6/cva6.mk include $(base_dir)/generators/tracegen/tracegen.mk include $(base_dir)/generators/nvdla/nvdla.mk include $(base_dir)/tools/dromajo/dromajo.mk @@ -103,7 +103,7 @@ $(sim_files): $(call lookup_srcs,$(base_dir)/generators/utilities/src/main/scala $(FIRRTL_FILE) $(ANNO_FILE): generator_temp @echo "" > /dev/null -# AG: must re-elaborate if ariane sources have changed... otherwise just run firrtl compile +# AG: must re-elaborate if cva6 sources have changed... otherwise just run firrtl compile generator_temp: $(SCALA_SOURCES) $(sim_files) $(EXTRA_GENERATOR_REQS) mkdir -p $(build_dir) $(call run_scala_main,$(SBT_PROJECT),$(GENERATOR_PACKAGE).Generator,\ diff --git a/docs/Chipyard-Basics/Chipyard-Components.rst b/docs/Chipyard-Basics/Chipyard-Components.rst index c24f81ed..4ad39d51 100644 --- a/docs/Chipyard-Basics/Chipyard-Components.rst +++ b/docs/Chipyard-Basics/Chipyard-Components.rst @@ -20,9 +20,9 @@ Processor Cores An out-of-order RISC-V core. See :ref:`Berkeley Out-of-Order Machine (BOOM)` for more information. -**Ariane Core** +**CVA6 Core** An in-order RISC-V core written in System Verilog. - See :ref:`Ariane Core` for more information. + See :ref:`CVA6 Core` for more information. Accelerators ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index a76741ec..6da84cb7 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -6,14 +6,14 @@ Adding a custom core You may want to integrate a custom RISC-V core into the Chipyard framework. This documentation page provides step-by-step instructions on how to achieve this. -.. note:: +.. note:: RoCC is currently not supported by cores other than Rocket and BOOM. Please use Rocket or BOOM as the RoCC base core if you need to use RoCC. .. note:: - This page contains links to the files that contains important definitions in the Rocket chip repository, which is maintained separately - from Chipyard. If you find any discrepancy between the code on this page and the code in the source file, please report it through + This page contains links to the files that contains important definitions in the Rocket chip repository, which is maintained separately + from Chipyard. If you find any discrepancy between the code on this page and the code in the source file, please report it through GitHub issues! Wrap Verilog Module with Blackbox (Optional) @@ -30,15 +30,15 @@ This object is derived from``TileParams``, a trait containing the information ne their own implementation of ``InstantiableTileParams``, as well as ``CoreParams`` which is passed as a field in ``TileParams``. ``TileParams`` holds the parameters for the tile, which include parameters for all components in the tile (e.g. -core, cache, MMU, etc.), while ``CoreParams`` contains parameters specific to the core on the tile. -They must be implemented as case classes with fields that can be overridden by -other config fragments as the constructor parameters. See the appendix at the bottom of the page for a list of -variable to be implemented. You can also add custom fields to them, but standard fields should always be preferred. +core, cache, MMU, etc.), while ``CoreParams`` contains parameters specific to the core on the tile. +They must be implemented as case classes with fields that can be overridden by +other config fragments as the constructor parameters. See the appendix at the bottom of the page for a list of +variable to be implemented. You can also add custom fields to them, but standard fields should always be preferred. -``InstantiableTileParams[TileType]`` holds the constructor of ``TileType`` on top of the fields of ``TileParams``, +``InstantiableTileParams[TileType]`` holds the constructor of ``TileType`` on top of the fields of ``TileParams``, where ``TileType`` is the tile class (see the next section). All custom cores will also need to implement ``instantiate()`` in their tile parameter class to return a new instance -of the tile class ``TileType``. +of the tile class ``TileType``. ``TileParams`` (in the file `BaseTile.scala `_) , ``InstantiableTileParams`` (in the file `BaseTile.scala `_), @@ -88,7 +88,7 @@ contains the following fields: val nBreakpoints: Int // # of hardware breakpoints supported (in RISC-V debug specs) val useBPWatch: Boolean // Support hardware breakpoints val nPerfCounters: Int // # of supported performance counters - val haveBasicCounters: Boolean // Support basic counters defined in the RISC-V counter extension + val haveBasicCounters: Boolean // Support basic counters defined in the RISC-V counter extension val haveFSDirty: Boolean // If true, the core will set FS field in mstatus CSR to dirty when appropriate val misaWritable: Boolean // Support writable misa CSR (like variable instruction bits) val haveCFlush: Boolean // Rocket specific: enables Rocket's custom instruction extension to flush the cache @@ -96,7 +96,7 @@ contains the following fields: val mtvecInit: Option[BigInt] // mtvec CSR (of V extension) initial value val mtvecWritable: Boolean // If mtvec CSR is writable - // Normally, you don't need to change these values (except lrscCycles) + // Normally, you don't need to change these values (except lrscCycles) def customCSRs(implicit p: Parameters): CustomCSRs = new CustomCSRs def hasSupervisorMode: Boolean = useSupervisor || useVM @@ -113,19 +113,19 @@ contains the following fields: def eLen(xLen: Int, fLen: Int): Int = xLen max fLen def vMemDataBits: Int = 0 } - + case class FPUParams( - minFLen: Int = 32, // Minimum floating point length (no need to change) + minFLen: Int = 32, // Minimum floating point length (no need to change) fLen: Int = 64, // Maximum floating point length, use 32 if only single precision is supported divSqrt: Boolean = true, // Div/Sqrt operation supported sfmaLatency: Int = 3, // Rocket specific: Fused multiply-add pipeline latency (single precision) dfmaLatency: Int = 4 // Rocket specific: Fused multiply-add pipeline latency (double precision) ) -Most of the fields here (marked "Rocket spcific") are originally designed for the Rocket core and thus contain some -implementation-specific details, but many of them are general enough to be useful for other cores. You may ignore +Most of the fields here (marked "Rocket spcific") are originally designed for the Rocket core and thus contain some +implementation-specific details, but many of them are general enough to be useful for other cores. You may ignore any fields marked "Rocket specific" and use their default values; however, if you need to store additional information -with meaning or usage similar to these "Rocket specific" fields, it is recommended to use these fields instead of +with meaning or usage similar to these "Rocket specific" fields, it is recommended to use these fields instead of creating your own custom fields. You will also need a ``CanAttachTile`` class to add the tile config into the config system, with the following format: @@ -144,14 +144,14 @@ from the parameters in this class for every such class it found. value may break Chipyard components that rely on them (e.g. an inaccurate indication of supported ISA extension will result in an incorrect test suite being generated) as well as any custom modules that use them. ALWAYS document any fields you ignore or with altered usage in your core implementation, and if you are implementing other devices that - would look up these config values, also document them. "Rocket specific" values are generally safe to ignore, but + would look up these config values, also document them. "Rocket specific" values are generally safe to ignore, but you should document them if you use them. Create Tile Class ----------------- In Chipyard, all Tiles are diplomatically instantiated. In the first phase, diplomatic nodes which specify Tile-to-System -interconnects are evaluated, while in the second "Module Implementation" phase, hardware is elaborated. +interconnects are evaluated, while in the second "Module Implementation" phase, hardware is elaborated. See :ref:`tilelink_and_diplomacy` for more details. In this step, you will need to implement a tile class for your core, which specifies the constraints on the core's parameters and the connections with other diplomatic nodes. This class usually contains Diplomacy/TileLink code only, and Chisel RTL code should not go here. @@ -167,10 +167,10 @@ which allow the tile to accept external interrupt. A typical tile has the follow Connect TileLink Buses ---------------------- -Chipyard uses TileLink as its onboard bus protocol. If your core doesn't use TileLink, you will need to insert converters +Chipyard uses TileLink as its onboard bus protocol. If your core doesn't use TileLink, you will need to insert converters between the core's memory protocol and TileLink within the Tile module. in the tile class. Below is an example of how to connect a core using AXI4 to the TileLink bus with converters provided by -Rocket chip: +Rocket chip: .. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala :language: scala @@ -179,11 +179,11 @@ Rocket chip: Remember, you may not need all of these intermediate widgets. See :ref:`diplomatic_widgets` for the meaning of each intermediate widget. If you are using TileLink, then you only need the tap node and the TileLink node used by your components. Chipyard also -provides converters for AHB, APB and AXIS, and most of the AXI4 widgets has equivalent widget for these bus protocol; see the -source files in ``generators/rocket-chip/src/main/scala/amba`` for more info. +provides converters for AHB, APB and AXIS, and most of the AXI4 widgets has equivalent widget for these bus protocol; see the +source files in ``generators/rocket-chip/src/main/scala/amba`` for more info. If you are using some other bus protocol, you may implement your own converters, using the files in ``generators/rocket-chip/src/main/scala/amba`` -as the template, but it is not recommended unless you are familiar with TileLink. +as the template, but it is not recommended unless you are familiar with TileLink. ``memAXI4Node`` is an AXI4 master node and is defined as following in our example: @@ -215,7 +215,7 @@ The implementation class contains the parameterized, actual hardware that depend framework according to the info provided in the Tile class. This class will normally contains Chisel RTL code. If your core is in Verilog, you will need to instantiate the black box class that wraps your Verilog implementation and connect it with the buses and other components. No Diplomacy/TileLink code should be in this class; you should only connect the IO signals in TileLink -interfaces or other diplomatically defined components, which are located in the tile class. +interfaces or other diplomatically defined components, which are located in the tile class. The implementation class for your core is of the following form: @@ -234,12 +234,12 @@ If you create an AXI4 node (or equivalents), you will need to connect them to yo Connect Interrupt ----------------- -Chipyard allows a tile to either receive interrupts from other devices or initiate interrupts to notify other cores/devices. -In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and +Chipyard allows a tile to either receive interrupts from other devices or initiate interrupts to notify other cores/devices. +In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and call ``decodeCoreInterrupts()`` with the object as the argument. Note that you should call this function in the implementation class since it returns a Chisel bundle used by RTL code. You can then read the interrupt bits from the ``TileInterrupts`` bundle -we create above. The definition of ``TileInterrupts`` -(in the file `Interrupts.scala `_) is +we create above. The definition of ``TileInterrupts`` +(in the file `Interrupts.scala `_) is .. code-block:: scala @@ -247,7 +247,7 @@ we create above. The definition of ``TileInterrupts`` val debug = Bool() // debug interrupt val mtip = Bool() // Machine level timer interrupt val msip = Bool() // Machine level software interrupt - val meip = Bool() // Machine level external interrupt + val meip = Bool() // Machine level external interrupt val seip = usingSupervisor.option(Bool()) // Valid only if supervisor mode is supported val lip = Vec(coreParams.nLocalInterrupts, Bool()) // Local interrupts } @@ -261,7 +261,7 @@ Here is an example on how to connect these signals in the implementation class: Also, the tile can also notify other cores or devices for some events by calling following functions in ``SourcesExternalNotifications`` from the implementation class: -(These functions can be found in in the trait ``SourcesExternalNotifications`` in the file +(These functions can be found in in the trait ``SourcesExternalNotifications`` in the file `Interrupts.scala `_) .. code-block:: scala @@ -290,12 +290,12 @@ the current config. An example of such config will be like this: :end-before: DOC include end: Config fragment Chipyard looks up the tile parameters in the field ``TilesLocated(InSubsystem)``, whose type is a list of ``InstantiableTileParams``. -This config fragment simply appends new tile parameters to the end of this list. +This config fragment simply appends new tile parameters to the end of this list. Now you have finished all the steps to prepare your cores for Chipyard! To generate the custom core, simply follow the instructions in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`. -You can now run most desired workflows for the new config just as you would for the built-in cores (depending on the functionality your core supports). +You can now run most desired workflows for the new config just as you would for the built-in cores (depending on the functionality your core supports). -If you would like to see an example of a complete third-party Verilog core integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala`` -provides a concrete example of the Ariane core. Note that this particular example includes additional nuances with respect to the interaction of the AXI -interface with the memory coherency system. +If you would like to see an example of a complete third-party Verilog core integrated into Chipyard, ``generators/ariane/src/main/scala/CVA6Tile.scala`` +provides a concrete example of the CVA6 core. Note that this particular example includes additional nuances with respect to the interaction of the AXI +interface with the memory coherency system. diff --git a/docs/Generators/Ariane.rst b/docs/Generators/CVA6.rst similarity index 59% rename from docs/Generators/Ariane.rst rename to docs/Generators/CVA6.rst index e58f9dfc..6250c614 100644 --- a/docs/Generators/Ariane.rst +++ b/docs/Generators/CVA6.rst @@ -1,14 +1,14 @@ -Ariane Core +CVA6 Core ==================================== -`Ariane `__ is a 6-stage in-order scalar processor core, originally developed at ETH-Zurich by F. Zaruba and L. Benini. -The `Ariane core` is wrapped in an `Ariane tile` so it can be used as a component within the `Rocket Chip SoC generator`. +`CVA6 `__ is a 6-stage in-order scalar processor core, originally developed at ETH-Zurich by F. Zaruba and L. Benini. +The `CVA6 core` is wrapped in an `CVA6 tile` so it can be used as a component within the `Rocket Chip SoC generator`. The core by itself exposes an AXI interface, interrupt ports, and other misc. ports that are connected from within the tile to TileLink buses and other parameterization signals. .. Warning:: Since the core uses an AXI interface to connect to memory, it is highly recommended to use the core in a single-core setup (since AXI is a non-coherent memory interface). -While the core itself is not a generator, we expose the same parameterization that the Ariane core provides (i.e. change branch prediction parameters). +While the core itself is not a generator, we expose the same parameterization that the CVA6 core provides (i.e. change branch prediction parameters). .. Warning:: This target does not support Verilator simulation at this time. Please use VCS. -For more information, please refer to the `GitHub repository `__. +For more information, please refer to the `GitHub repository `__. diff --git a/docs/Generators/index.rst b/docs/Generators/index.rst index cebb17e5..cfc7d601 100644 --- a/docs/Generators/index.rst +++ b/docs/Generators/index.rst @@ -27,7 +27,7 @@ so changes to the generators themselves will automatically be used when building TestChipIP SiFive-Generators SHA3 - Ariane + CVA6 NVDLA Sodor diff --git a/generators/ariane b/generators/ariane deleted file mode 160000 index 3a2eed60..00000000 --- a/generators/ariane +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3a2eed602faac24e58a530db429f23f11810aae9 diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 68c41724..0db4ed4c 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -21,7 +21,7 @@ import hwacha.{Hwacha} import gemmini.{Gemmini, GemminiConfigs} import boom.common.{BoomTileAttachParams} -import ariane.{ArianeTileAttachParams} +import cva6.{CVA6TileAttachParams} import sifive.blocks.devices.gpio._ import sifive.blocks.devices.uart._ @@ -120,7 +120,7 @@ class WithTraceIO extends Config((site, here, up) => { case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( trace = true)) - case tp: ArianeTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( + case tp: CVA6TileAttachParams => tp.copy(tileParams = tp.tileParams.copy( trace = true)) case other => other } diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index 8cdfd3c9..596337c0 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -7,9 +7,6 @@ import freechips.rocketchip.tile.{XLen, TileParams} import freechips.rocketchip.config.{Parameters, Field, Config} import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite} -import boom.common.{BoomTileAttachParams} -import ariane.{ArianeTileAttachParams} - /** * A set of pre-chosen regression tests */ diff --git a/generators/chipyard/src/main/scala/config/ArianeConfigs.scala b/generators/chipyard/src/main/scala/config/ArianeConfigs.scala deleted file mode 100644 index 6e75ac54..00000000 --- a/generators/chipyard/src/main/scala/config/ArianeConfigs.scala +++ /dev/null @@ -1,19 +0,0 @@ -package chipyard - -import chisel3._ - -import freechips.rocketchip.config.{Config} - -// --------------------- -// Ariane Configs -// --------------------- - -class ArianeConfig extends Config( - new ariane.WithNArianeCores(1) ++ // single Ariane core - new chipyard.config.AbstractConfig) - -class dmiArianeConfig extends Config( - new chipyard.harness.WithSerialAdapterTiedOff ++ // Tie off the serial port, override default instantiation of SimSerial - new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port - new ariane.WithNArianeCores(1) ++ // single Ariane core - new chipyard.config.AbstractConfig) diff --git a/generators/chipyard/src/main/scala/config/CVA6Configs.scala b/generators/chipyard/src/main/scala/config/CVA6Configs.scala new file mode 100644 index 00000000..132a3009 --- /dev/null +++ b/generators/chipyard/src/main/scala/config/CVA6Configs.scala @@ -0,0 +1,19 @@ +package chipyard + +import chisel3._ + +import freechips.rocketchip.config.{Config} + +// --------------------- +// CVA6 Configs +// --------------------- + +class CVA6Config extends Config( + new cva6.WithNCVA6Cores(1) ++ // single CVA6 core + new chipyard.config.AbstractConfig) + +class dmiCVA6Config extends Config( + new chipyard.harness.WithSerialAdapterTiedOff ++ // Tie off the serial port, override default instantiation of SimSerial + new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port + new cva6.WithNCVA6Cores(1) ++ // single CVA6 core + new chipyard.config.AbstractConfig) diff --git a/generators/chipyard/src/main/scala/example/TutorialTile.scala b/generators/chipyard/src/main/scala/example/TutorialTile.scala index 1f58e5e4..9af2cb54 100644 --- a/generators/chipyard/src/main/scala/example/TutorialTile.scala +++ b/generators/chipyard/src/main/scala/example/TutorialTile.scala @@ -16,7 +16,7 @@ import freechips.rocketchip.util._ import freechips.rocketchip.tile._ import freechips.rocketchip.amba.axi4._ -// Example parameter class copied from Ariane, not included in documentation but for compile check only +// Example parameter class copied from CVA6, not included in documentation but for compile check only // If you are here for documentation, DO NOT copy MyCoreParams and MyTileParams directly - always figure // out what parameters you need before you write the parameter class case class MyCoreParams( @@ -127,9 +127,9 @@ class MyTile( // TODO: Create TileLink nodes and connections here. // DOC include end: Tile class - + // DOC include start: AXI4 node - // # of bits used in TileLink ID for master node. 4 bits can support 16 master nodes, but you can have a longer ID if you need more. + // # of bits used in TileLink ID for master node. 4 bits can support 16 master nodes, but you can have a longer ID if you need more. val idBits = 4 val memAXI4Node = AXI4MasterNode( Seq(AXI4MasterPortParameters( @@ -160,17 +160,17 @@ class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ // TODO: Create the top module of the core and connect it with the ports in "outer" - // If your core is in Verilog (assume your blackbox is called "MyCoreBlackbox"), instantiate it here like - // val core = Module(new MyCoreBlackbox(params...)) + // If your core is in Verilog (assume your blackbox is called "MyCoreBlackbox"), instantiate it here like + // val core = Module(new MyCoreBlackbox(params...)) // (as described in the blackbox tutorial) and connect appropriate signals. See the blackbox tutorial // (link on the top of the page) for more info. - // You can look at https://github.com/ucb-bar/ariane-wrapper/blob/master/src/main/scala/ArianeTile.scala + // You can look at https://github.com/ucb-bar/cva6-wrapper/blob/master/src/main/scala/CVA6Tile.scala // for a Verilog example. // If your core is in Chisel, you can simply instantiate the top module here like other Chisel module // and connect appropriate signal. You can even implement this class as your top module. // See https://github.com/riscv-boom/riscv-boom/blob/master/src/main/scala/common/tile.scala and - // https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/RocketTile.scala for + // https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/RocketTile.scala for // Chisel example. // DOC include end: Implementation class diff --git a/generators/cva6 b/generators/cva6 new file mode 160000 index 00000000..27157f7b --- /dev/null +++ b/generators/cva6 @@ -0,0 +1 @@ +Subproject commit 27157f7bbdd1ebc395fc8e22e46b3118290fa188 diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index e4f691e2..0572fabd 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -22,7 +22,7 @@ import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotatio import firesim.bridges._ import firesim.configs.MemModelKey import tracegen.{TraceGenSystemModuleImp} -import ariane.ArianeTile +import cva6.CVA6Tile import boom.common.{BoomTile} import barstools.iocell.chisel._ diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 719599f4..89ac8073 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -128,7 +128,7 @@ class FireSimQuadRocketConfig extends Config( new chipyard.QuadRocketConfig) // A stripped down configuration that should fit on all supported hosts. -// Flat to avoid having to reorganize the config class hierarchy to remove certain features +// Flat to avoid having to reorganize the config class hierarchy to remove certain features class FireSimSmallSystemConfig extends Config( new WithDefaultFireSimBridges ++ new WithDefaultMemModel ++ @@ -188,13 +188,13 @@ class SupernodeFireSimRocketConfig extends Config( new FireSimRocketConfig) //********************************************************************************** -//* Ariane Configurations +//* CVA6 Configurations //*********************************************************************************/ -class FireSimArianeConfig extends Config( +class FireSimCVA6Config extends Config( new WithDefaultFireSimBridges ++ new WithDefaultMemModel ++ new WithFireSimConfigTweaks ++ - new chipyard.ArianeConfig) + new chipyard.CVA6Config) //********************************************************************************** //* Multiclock Configurations diff --git a/generators/firechip/src/test/scala/ScalaTestSuite.scala b/generators/firechip/src/test/scala/ScalaTestSuite.scala index ea1627b7..64b9b4ba 100644 --- a/generators/firechip/src/test/scala/ScalaTestSuite.scala +++ b/generators/firechip/src/test/scala/ScalaTestSuite.scala @@ -110,7 +110,7 @@ class RocketMulticlockF1Tests extends FireSimTestSuite( "FireSimMulticlockRocketConfig", "WithSynthAsserts_BaseF1Config") -class ArianeF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimArianeConfig", "BaseF1Config") +class CVA6F1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimCVA6Config", "BaseF1Config") // This test suite only mirrors what is run in CI. CI invokes each test individually, using a testOnly call. class CITests extends Suites( diff --git a/scripts/tutorial-patches/build.sbt.patch b/scripts/tutorial-patches/build.sbt.patch index aa7f0bd4..cb289b6f 100644 --- a/scripts/tutorial-patches/build.sbt.patch +++ b/scripts/tutorial-patches/build.sbt.patch @@ -3,24 +3,24 @@ index 5d642c1..56f6fda 100644 --- a/build.sbt +++ b/build.sbt @@ -130,7 +130,7 @@ lazy val iocell = (project in file("./tools/barstools/iocell/")) - + lazy val chipyard = conditionalDependsOn(project in file("generators/chipyard")) .dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell, - sha3, // On separate line to allow for cleaner tutorial-setup patches +// sha3, // On separate line to allow for cleaner tutorial-setup patches dsptools, `rocket-dsptools`, - gemmini, icenet, tracegen, ariane, nvdla, sodor) + gemmini, icenet, tracegen, cva6, nvdla, sodor) .settings(commonSettings) -@@ -158,9 +158,9 @@ lazy val ariane = (project in file("generators/ariane")) +@@ -158,9 +158,9 @@ lazy val cva6 = (project in file("generators/cva6")) .dependsOn(rocketchip) .settings(commonSettings) - + -lazy val sha3 = (project in file("generators/sha3")) - .dependsOn(rocketchip, chisel_testers, midasTargetUtils) - .settings(commonSettings) +//lazy val sha3 = (project in file("generators/sha3")) +// .dependsOn(rocketchip, chisel_testers, midasTargetUtils) +// .settings(commonSettings) - + lazy val gemmini = (project in file("generators/gemmini")) .dependsOn(rocketchip, chisel_testers, testchipip) diff --git a/sims/firesim b/sims/firesim index 1c76c446..57efb2ec 160000 --- a/sims/firesim +++ b/sims/firesim @@ -1 +1 @@ -Subproject commit 1c76c446dab42b782f8128c3e7e56b4e9ab104d7 +Subproject commit 57efb2ec032a8c7afa2f458761cc79b2614180b5 diff --git a/sims/verilator/Makefile b/sims/verilator/Makefile index 211b5676..65e64179 100644 --- a/sims/verilator/Makefile +++ b/sims/verilator/Makefile @@ -91,7 +91,7 @@ VERILATOR_OPT_FLAGS := \ --output-split 10000 \ --output-split-cfuncs 100 -# default flags added for external IP (ariane/NVDLA) +# default flags added for external IP (cva6/NVDLA) VERILOG_IP_VERILATOR_FLAGS := \ --unroll-count 256 \ -Wno-PINCONNECTEMPTY \ @@ -103,14 +103,14 @@ VERILOG_IP_VERILATOR_FLAGS := \ -Wno-style \ -Wall -# normal flags used for chipyard builds (that are incompatible with vlog ip aka ariane/NVDLA) +# normal flags used for chipyard builds (that are incompatible with vlog ip aka cva6/NVDLA) CHIPYARD_VERILATOR_FLAGS := \ --assert -# options dependent on whether external IP (ariane/NVDLA) or just chipyard is used +# options dependent on whether external IP (cva6/NVDLA) or just chipyard is used # NOTE: defer the evaluation of this until it is used! PLATFORM_OPTS = $(shell \ - if grep -qiP "module\s+(Ariane|NVDLA)" $(build_dir)/*.*v; \ + if grep -qiP "module\s+(CVA6|NVDLA)" $(build_dir)/*.*v; \ then echo "$(VERILOG_IP_VERILATOR_FLAGS)"; \ else echo "$(CHIPYARD_VERILATOR_FLAGS)"; fi) From 94eceeb6249f477e2e257eebb8da757d4f5a345b Mon Sep 17 00:00:00 2001 From: Abraham Gonzalez Date: Wed, 4 Nov 2020 15:54:09 -0800 Subject: [PATCH 16/29] Use empty variable instead of t/f --- scripts/build-toolchains.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build-toolchains.sh b/scripts/build-toolchains.sh index 9ceb8808..84fdbd45 100755 --- a/scripts/build-toolchains.sh +++ b/scripts/build-toolchains.sh @@ -35,7 +35,7 @@ die() { TOOLCHAIN="riscv-tools" EC2FASTINSTALL="false" -IGNOREQEMU="false" +IGNOREQEMU="" RISCV="" # getopts does not support long options, and is inflexible @@ -133,7 +133,7 @@ module_all riscv-tests --prefix="${RISCV}/riscv64-unknown-elf" SRCDIR="$(pwd)/toolchains" module_all libgloss --prefix="${RISCV}/riscv64-unknown-elf" --host=riscv64-unknown-elf -if [ "${IGNOREQEMU}" = false ] ; then +if [ -z "$IGNOREQEMU" ] ; then SRCDIR="$(pwd)/toolchains" module_all qemu --prefix="${RISCV}" --target-list=riscv64-softmmu fi From fc8c5e4b3019d65fc0ec0040ffdb7477c55daf6a Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 4 Nov 2020 18:02:49 -0800 Subject: [PATCH 17/29] Use HTTPS for submodules --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index d9dbe85f..7054c14f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -115,7 +115,7 @@ url = https://github.com/firesim/FireMarshal.git [submodule "generators/cva6"] path = generators/cva6 - url = git@github.com:ucb-bar/cva6-wrapper.git + url = https://github.com/ucb-bar/cva6-wrapper.git [submodule "tools/DRAMSim2"] path = tools/DRAMSim2 url = https://github.com/firesim/DRAMSim2.git From 59c9163bd5ca201b37ff7ed6633755e3811fbb23 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 4 Nov 2020 18:37:26 -0800 Subject: [PATCH 18/29] Bump CVA6 for submodule fixes --- generators/cva6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/cva6 b/generators/cva6 index 27157f7b..3f0513a9 160000 --- a/generators/cva6 +++ b/generators/cva6 @@ -1 +1 @@ -Subproject commit 27157f7bbdd1ebc395fc8e22e46b3118290fa188 +Subproject commit 3f0513a9bd9394047c7cc1fbd50ea5077bb2e36c From 9052b41328bcc76da1d6e9718edce4b4e044face Mon Sep 17 00:00:00 2001 From: Abraham Gonzalez Date: Wed, 4 Nov 2020 20:59:14 -0800 Subject: [PATCH 19/29] Re-ignore QEMU from gnu-toolchain | Avoid piping make version in toolchain build --- scripts/build-toolchains.sh | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scripts/build-toolchains.sh b/scripts/build-toolchains.sh index 84fdbd45..1897d157 100755 --- a/scripts/build-toolchains.sh +++ b/scripts/build-toolchains.sh @@ -107,14 +107,18 @@ if [ "${EC2FASTINSTALL}" = true ] ; then git submodule deinit "${module}" || : else - "${MAKE}" --version | ( - read -r makever - case ${makever} in - 'GNU Make '[4-9]\.*|'GNU Make '[1-9][0-9]) ;; - *) false ;; - esac; ) || die 'obsolete make version; need GNU make 4.x or later' + MAKE_VER=$("${MAKE}" --version) || true + case ${MAKE_VER} in + 'GNU Make '[4-9]\.*) + ;; + 'GNU Make '[1-9][0-9]) + ;; + *) + die 'obsolete make version; need GNU make 4.x or later' + ;; + esac - module_prepare riscv-gnu-toolchain + module_prepare riscv-gnu-toolchain qemu module_build riscv-gnu-toolchain --prefix="${RISCV}" --with-cmodel=medany echo '==> Building GNU/Linux toolchain' module_make riscv-gnu-toolchain linux From 60cd99900264f57a3d075c6fc8ba214136e41c5c Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 4 Nov 2020 21:09:24 -0800 Subject: [PATCH 20/29] Bump CVA6 for Make fix --- generators/cva6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/cva6 b/generators/cva6 index 3f0513a9..e3576371 160000 --- a/generators/cva6 +++ b/generators/cva6 @@ -1 +1 @@ -Subproject commit 3f0513a9bd9394047c7cc1fbd50ea5077bb2e36c +Subproject commit e35763717b25c08df215b10334fd2d40845e1912 From 0685812c342c31d735472ad13573ce8f21ed3687 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Thu, 5 Nov 2020 10:30:00 -0800 Subject: [PATCH 21/29] Bump CVA6 --- generators/cva6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/cva6 b/generators/cva6 index e3576371..8a11e2c9 160000 --- a/generators/cva6 +++ b/generators/cva6 @@ -1 +1 @@ -Subproject commit e35763717b25c08df215b10334fd2d40845e1912 +Subproject commit 8a11e2c97627459d0449853447bfc7ca64608b82 From 2de5f7dd7e245ad3f47cbfa69a68b925c38df3af Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Thu, 5 Nov 2020 15:48:50 -0800 Subject: [PATCH 22/29] [ci skip] Note that CVA6 was called Ariane in the past --- README.md | 2 +- docs/Chipyard-Basics/Chipyard-Components.rst | 2 +- docs/Generators/CVA6.rst | 2 +- sims/firesim | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 11f1b8d5..0283da58 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ To get started using Chipyard, see the documentation on the Chipyard documentati Chipyard is an open source framework for agile development of Chisel-based systems-on-chip. It will allow you to leverage the Chisel HDL, Rocket Chip SoC generator, and other [Berkeley][berkeley] projects to produce a [RISC-V][riscv] SoC with everything from MMIO-mapped peripherals to custom accelerators. -Chipyard contains processor cores ([Rocket][rocket-chip], [BOOM][boom], [CVA6][cva6]), accelerators ([Hwacha][hwacha], [Gemmini][gemmini], [NVDLA][nvdla]), memory systems, and additional peripherals and tooling to help create a full featured SoC. +Chipyard contains processor cores ([Rocket][rocket-chip], [BOOM][boom], [CVA6 (Ariane)][cva6]), accelerators ([Hwacha][hwacha], [Gemmini][gemmini], [NVDLA][nvdla]), memory systems, and additional peripherals and tooling to help create a full featured SoC. Chipyard supports multiple concurrent flows of agile hardware development, including software RTL simulation, FPGA-accelerated simulation ([FireSim][firesim]), automated VLSI flows ([Hammer][hammer]), and software workload generation for bare-metal and Linux-based systems ([FireMarshal][firemarshal]). Chipyard is actively developed in the [Berkeley Architecture Research Group][ucb-bar] in the [Electrical Engineering and Computer Sciences Department][eecs] at the [University of California, Berkeley][berkeley]. diff --git a/docs/Chipyard-Basics/Chipyard-Components.rst b/docs/Chipyard-Basics/Chipyard-Components.rst index 4ad39d51..398b537d 100644 --- a/docs/Chipyard-Basics/Chipyard-Components.rst +++ b/docs/Chipyard-Basics/Chipyard-Components.rst @@ -21,7 +21,7 @@ Processor Cores See :ref:`Berkeley Out-of-Order Machine (BOOM)` for more information. **CVA6 Core** - An in-order RISC-V core written in System Verilog. + An in-order RISC-V core written in System Verilog. Previously called Ariane. See :ref:`CVA6 Core` for more information. Accelerators diff --git a/docs/Generators/CVA6.rst b/docs/Generators/CVA6.rst index 6250c614..bfca746a 100644 --- a/docs/Generators/CVA6.rst +++ b/docs/Generators/CVA6.rst @@ -1,7 +1,7 @@ CVA6 Core ==================================== -`CVA6 `__ is a 6-stage in-order scalar processor core, originally developed at ETH-Zurich by F. Zaruba and L. Benini. +`CVA6 `__ (previously called Ariane) is a 6-stage in-order scalar processor core, originally developed at ETH-Zurich by F. Zaruba and L. Benini. The `CVA6 core` is wrapped in an `CVA6 tile` so it can be used as a component within the `Rocket Chip SoC generator`. The core by itself exposes an AXI interface, interrupt ports, and other misc. ports that are connected from within the tile to TileLink buses and other parameterization signals. diff --git a/sims/firesim b/sims/firesim index 57efb2ec..37fe89a6 160000 --- a/sims/firesim +++ b/sims/firesim @@ -1 +1 @@ -Subproject commit 57efb2ec032a8c7afa2f458761cc79b2614180b5 +Subproject commit 37fe89a65f1c1ccd8d2cc0d1efd0c06308d0224d From a559d624df583fa1968ac52ede8cd1bfb22356be Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Sat, 7 Nov 2020 18:42:29 -0800 Subject: [PATCH 23/29] [clocking] Drive all buses directly from the asyncClockGroup --- .../src/main/scala/CustomBusTopologies.scala | 22 +++++++++++++++++-- .../chipyard/src/main/scala/Subsystem.scala | 17 ++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/CustomBusTopologies.scala b/generators/chipyard/src/main/scala/CustomBusTopologies.scala index c1c09285..db617f83 100644 --- a/generators/chipyard/src/main/scala/CustomBusTopologies.scala +++ b/generators/chipyard/src/main/scala/CustomBusTopologies.scala @@ -36,17 +36,35 @@ case class CoherentMulticlockBusTopologyParams( (SBUS, L2, TLBusWrapperConnection(xType = NoCrossing, driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()), (L2, MBUS, TLBusWrapperConnection.crossTo( xType = sbusToMbusXType, - driveClockFromMaster = Some(true), + driveClockFromMaster = None, nodeBinding = BIND_QUERY)) ) ) +// This differs from upstream only in that it does not use the legacy crossTo +// and crossFrom functions to ensure driveClockFromMaster = None +case class HierarchicalMulticlockBusTopologyParams( + pbus: PeripheryBusParams, + fbus: FrontBusParams, + cbus: PeripheryBusParams, + xTypes: SubsystemCrossingParams +) extends TLBusWrapperTopology( + instantiations = List( + (PBUS, pbus), + (FBUS, fbus), + (CBUS, cbus)), + connections = List( + (SBUS, CBUS, TLBusWrapperConnection(xType = xTypes.sbusToCbusXType, nodeBinding = BIND_STAR)()), + (CBUS, PBUS, TLBusWrapperConnection(xType = xTypes.cbusToPbusXType, nodeBinding = BIND_STAR)()), + (FBUS, SBUS, TLBusWrapperConnection(xType = xTypes.fbusToSbusXType, nodeBinding = BIND_QUERY, flipRendering = true)())) +) + // For subsystem/Configs.scala class WithMulticlockCoherentBusTopology extends Config((site, here, up) => { case TLNetworkTopologyLocated(InSubsystem) => List( JustOneBusTopologyParams(sbus = site(SystemBusKey)), - HierarchicalBusTopologyParams( + HierarchicalMulticlockBusTopologyParams( pbus = site(PeripheryBusKey), fbus = site(FrontBusKey), cbus = site(ControlBusKey), diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index 5dd6ac18..40b8cc8c 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -56,6 +56,23 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem case b: BoomTile => b.module.core.coreMonitorBundle }.toList + + // Relying on [[TLBusWrapperConnection]].driveClockFromMaster for + // bus-couplings that are not asynchronous strips the bus name from the sink + // ClockGroup. This makes it impossible to determine which clocks are driven + // by which bus based on the member names, which is problematic when there is + // a rational crossing between two buses. Instead, provide all bus clocks + // directly from the asyncClockGroupsNode in the subsystem to ensure bus + // names are always preserved in the top-level clock names. + // + // For example, using a RationalCrossing between the Sbus and Cbus, and + // driveClockFromMaster = Some(true) results in all cbus-attached device and + // bus clocks to be given names of the form "subsystem_sbus_[0-9]*". + // Conversly, if an async crossing is used, they instead receive names of the + // form "subsystem_cbus_[0-9]*". The assignment below the latter names in all cases. + Seq(PBUS, FBUS, MBUS, CBUS).foreach { loc => + tlBusWrapperLocationMap.lift(loc).foreach { _.clockGroupNode := asyncClockGroupsNode } + } override lazy val module = new ChipyardSubsystemModuleImp(this) } From 04cd6b59bdb9aff69164dc894a4704c7eabe4c36 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Sat, 7 Nov 2020 18:45:48 -0800 Subject: [PATCH 24/29] [clocking] Add a fragment to set bus clock-sink freqs more intuitively --- .../src/main/scala/ConfigFragments.scala | 30 +++++++++++++++++++ .../chipyard/src/main/scala/Subsystem.scala | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 0db4ed4c..fb706895 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -1,5 +1,6 @@ package chipyard.config +import scala.util.matching.Regex import chisel3._ import chisel3.util.{log2Up} @@ -11,6 +12,7 @@ import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, D import freechips.rocketchip.groundtest.{GroundTestSubsystem} import freechips.rocketchip.tile._ import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams} +import freechips.rocketchip.tilelink.{HasTLBusParams} import freechips.rocketchip.util.{AsyncResetReg, Symmetric} import freechips.rocketchip.prci._ @@ -183,6 +185,34 @@ class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => { case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble }) +class WithSystemBusFrequencyAsDefault extends Config((site, here, up) => { + case DefaultClockFrequencyKey => (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toDouble +}) + +class BusFrequencyAssignment[T <: HasTLBusParams](re: Regex, key: Field[T]) extends Config((site, here, up) => { + case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++ + Seq((cName: String) => site(key).dtsFrequency.flatMap { f => + re.findFirstIn(cName).map {_ => (f / (1000 * 1000)).toDouble } + }) +}) + +/** + * Provides a diplomatic frequency for all clock sinks with an unspecified + * frequency bound to each bus. + * + * For example, the L2 cache, when bound to the sbus, receives a separate + * clock that appears as "subsystem_sbus_". This fragment ensures that + * clock requests the same frequency as the sbus itself. + */ + +class WithInheritBusFrequencyAssignments extends Config( + new BusFrequencyAssignment("subsystem_sbus_\\d+".r, SystemBusKey) ++ + new BusFrequencyAssignment("subsystem_pbus_\\d+".r, PeripheryBusKey) ++ + new BusFrequencyAssignment("subsystem_cbus_\\d+".r, ControlBusKey) ++ + new BusFrequencyAssignment("subsystem_fbus_\\d+".r, FrontBusKey) ++ + new BusFrequencyAssignment("subsystem_mbus_\\d+".r, MemoryBusKey) +) + /** * Mixins to specify crossing types between the 5 traditional TL buses * diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index 40b8cc8c..09e35d95 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -69,7 +69,7 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem // driveClockFromMaster = Some(true) results in all cbus-attached device and // bus clocks to be given names of the form "subsystem_sbus_[0-9]*". // Conversly, if an async crossing is used, they instead receive names of the - // form "subsystem_cbus_[0-9]*". The assignment below the latter names in all cases. + // form "subsystem_cbus_[0-9]*". The assignment below provides the latter names in all cases. Seq(PBUS, FBUS, MBUS, CBUS).foreach { loc => tlBusWrapperLocationMap.lift(loc).foreach { _.clockGroupNode := asyncClockGroupsNode } } From 4da9e49fc169d87da4462f8d244dfba53e67ffcb Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Sat, 7 Nov 2020 21:24:04 -0800 Subject: [PATCH 25/29] [clocking] Fix up() invocations in freq specification fragments --- .../chipyard/src/main/scala/ConfigFragments.scala | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index fb706895..479120ba 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -242,16 +242,19 @@ class WithFbusToSbusCrossingType(xType: ClockCrossingType) extends Config((site, * up the diplomatic graph to the clock sources. */ class WithPeripheryBusFrequency(freqMHz: Double) extends Config((site, here, up) => { - case PeripheryBusKey => up(PeripheryBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) + case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) }) class WithMemoryBusFrequency(freqMHz: Double) extends Config((site, here, up) => { - case MemoryBusKey => up(MemoryBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) + case MemoryBusKey => up(MemoryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) }) class WithSystemBusFrequency(freqMHz: Double) extends Config((site, here, up) => { - case SystemBusKey => up(SystemBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) + case SystemBusKey => up(SystemBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) +}) +class WithFrontBusFrequency(freqMHz: Double) extends Config((site, here, up) => { + case FrontBusKey => up(FrontBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) }) class WithControlBusFrequency(freqMHz: Double) extends Config((site, here, up) => { - case ControlBusKey => up(ControlBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) + case ControlBusKey => up(ControlBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) }) class WithRationalMemoryBusCrossing extends WithSbusToMbusCrossingType(RationalCrossing(Symmetric)) From 08c31014ccae0774c4621802c8ae1e812c515db0 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Sat, 7 Nov 2020 21:29:31 -0800 Subject: [PATCH 26/29] Build out a more complete multiclock example configuration --- .../src/main/scala/CustomBusTopologies.scala | 2 +- .../main/scala/config/AbstractConfig.scala | 3 ++- .../src/main/scala/config/RocketConfigs.scala | 19 +++++++++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/generators/chipyard/src/main/scala/CustomBusTopologies.scala b/generators/chipyard/src/main/scala/CustomBusTopologies.scala index db617f83..2f6f3de7 100644 --- a/generators/chipyard/src/main/scala/CustomBusTopologies.scala +++ b/generators/chipyard/src/main/scala/CustomBusTopologies.scala @@ -42,7 +42,7 @@ case class CoherentMulticlockBusTopologyParams( ) // This differs from upstream only in that it does not use the legacy crossTo -// and crossFrom functions to ensure driveClockFromMaster = None +// and crossFrom functions, and it ensures driveClockFromMaster = None case class HierarchicalMulticlockBusTopologyParams( pbus: PeripheryBusParams, fbus: FrontBusParams, diff --git a/generators/chipyard/src/main/scala/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala index 301c03d7..347b0c06 100644 --- a/generators/chipyard/src/main/scala/config/AbstractConfig.scala +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -43,7 +43,8 @@ class AbstractConfig extends Config( new chipyard.config.WithUART ++ // add a UART new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks - new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified clocks will match the frequency specified by the pbus dtsFrequency parameter + new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set + new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set) new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index d413cc12..1afb4515 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -1,6 +1,7 @@ package chipyard import freechips.rocketchip.config.{Config} +import freechips.rocketchip.diplomacy.{AsynchronousCrossing} // -------------- // Rocket Configs @@ -175,13 +176,19 @@ class MMIORocketConfig extends Config( new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new chipyard.config.AbstractConfig) -class DividedClockRocketConfig extends Config( - new chipyard.config.WithTileFrequency(200.0) ++ - new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore +class MulticlockRocketConfig extends Config( new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new chipyard.config.WithMemoryBusFrequency(50.0) ++ - new chipyard.config.WithAsynchrousMemoryBusCrossing ++ - new testchipip.WithAsynchronousSerialSlaveCrossing ++ + // Frequency specifications + new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540 + new chipyard.config.WithSystemBusFrequency(800.0) ++ // Ditto + new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // 2x the U540 freq (appropriate for a 128b Mbus) + new chipyard.config.WithPeripheryBusFrequency(100) ++ // Retains the default pbus frequency + new chipyard.config.WithSystemBusFrequencyAsDefault ++ // All unspecified clock frequencies, notably the implicit clock, will use the sbus freq (800 MHz) + // Crossing specifications + new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS + new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS + new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore + new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS new chipyard.config.AbstractConfig) class LBWIFRocketConfig extends Config( From 098a83ce98b0bf301bf53c486086c8ccbdf67086 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Sat, 7 Nov 2020 21:57:18 -0800 Subject: [PATCH 27/29] [CI] Add a multiclock config --- .circleci/config.yml | 6 ++++++ .circleci/defaults.sh | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6e74b9d5..f18f0e62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -248,6 +248,12 @@ jobs: group-key: "group-cores" project-key: "chipyard-sodor" timeout: "30m" + chipyard-multiclock-rocket-run-tests: + executor: main-env + steps: + - run-tests: + group-key: "group-cores" + project-key: "chipyard-multiclock-rocket" chipyard-dmirocket-run-tests: executor: main-env steps: diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh index c0bce62d..e9ccdfb5 100755 --- a/.circleci/defaults.sh +++ b/.circleci/defaults.sh @@ -47,7 +47,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim # key value store to get the build groups declare -A grouping -grouping["group-cores"]="chipyard-cva6 chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop" +grouping["group-cores"]="chipyard-cva6 chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket" grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif" grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough" grouping["group-tracegen"]="tracegen tracegen-boom" @@ -75,6 +75,7 @@ mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config" mapping["tracegen-boom"]=" CONFIG=BoomTraceGenConfig" mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig" mapping["chipyard-sodor"]=" CONFIG=Sodor5StageConfig" +mapping["chipyard-multiclock-rocket"]=" CONFIG=MulticlockRocketConfig" mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests" mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests" From 230bd81e0eeebe02021f3a094ce88ce5f9a8e715 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Sun, 8 Nov 2020 11:20:24 -0800 Subject: [PATCH 28/29] [firechip] Update legacy firechip config --- generators/firechip/src/main/scala/TargetConfigs.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 89ac8073..e8f2afb5 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -201,8 +201,6 @@ class FireSimCVA6Config extends Config( //*********************************************************************************/ class FireSimMulticlockRocketConfig extends Config( new chipyard.config.WithTileFrequency(6400.0) ++ //lol - new WithDefaultFireSimBridges ++ - new WithDefaultMemModel ++ - new WithFireSimConfigTweaks ++ - new chipyard.DividedClockRocketConfig) + new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore + new FireSimRocketConfig) From 80487cc3710616c60871bf83a341ac4017607f82 Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Tue, 10 Nov 2020 11:58:53 -0800 Subject: [PATCH 29/29] Update HierarchicalMulticlockBusTopologyParams to use cross{In, Out} --- .../chipyard/src/main/scala/CustomBusTopologies.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/generators/chipyard/src/main/scala/CustomBusTopologies.scala b/generators/chipyard/src/main/scala/CustomBusTopologies.scala index 2f6f3de7..ee694d22 100644 --- a/generators/chipyard/src/main/scala/CustomBusTopologies.scala +++ b/generators/chipyard/src/main/scala/CustomBusTopologies.scala @@ -54,9 +54,9 @@ case class HierarchicalMulticlockBusTopologyParams( (FBUS, fbus), (CBUS, cbus)), connections = List( - (SBUS, CBUS, TLBusWrapperConnection(xType = xTypes.sbusToCbusXType, nodeBinding = BIND_STAR)()), - (CBUS, PBUS, TLBusWrapperConnection(xType = xTypes.cbusToPbusXType, nodeBinding = BIND_STAR)()), - (FBUS, SBUS, TLBusWrapperConnection(xType = xTypes.fbusToSbusXType, nodeBinding = BIND_QUERY, flipRendering = true)())) + (SBUS, CBUS, TLBusWrapperConnection. crossTo(xType = xTypes.sbusToCbusXType, driveClockFromMaster = None)), + (CBUS, PBUS, TLBusWrapperConnection. crossTo(xType = xTypes.cbusToPbusXType, driveClockFromMaster = None)), + (FBUS, SBUS, TLBusWrapperConnection.crossFrom(xType = xTypes.fbusToSbusXType, driveClockFromMaster = None))) ) // For subsystem/Configs.scala