diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 969230b7..327db301 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -18,8 +18,31 @@ import tracegen.{HasTraceGenTilesModuleImp} import scala.reflect.{ClassTag, classTag} +// 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. +// +// You could just as well create a custom harness module that instantiates +// bridges explicitly, or add methods to +// your target traits that instantiate the bridge there (i.e., akin to +// SimAXI4Mem). Since cake traits live in Rocket Chip it was easiest to match +// on the types rather than change trait code. + + + +// A map of partial functions that match on the type the DUT (_not_ it's +// IO) to generate an appropriate bridge. You can add your own binder by adding +// a new (key, fn) pair. You should override existing pairs in this map when +// using a custom IOBinder + +// Since we also want to compose this structure like the existing config system, +// use the scala string representation of the matched trait as a key + case object IOBinders extends Field[Map[String, (Clock, Bool, Bool, Any) => Seq[Any]]](Map()) + +// This macro overrides previous matches on some Top mixin. This is useful for +// binders which modify IO, since those typically cannot be composed class RegisterIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> ((clock: Clock, reset: Bool, success: Bool, t: Any) => { @@ -31,6 +54,19 @@ class RegisterIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit ta ) }) +// This macro composes with previous matches on some Top mixin. This is useful for +// annotation-like binders, since those can typically be composed +class RegisterBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { + case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> + ((clock: Clock, reset: Bool, success: Bool, t: Any) => { + t match { + case top: T => fn(clock, reset, success, top) ++ + up(IOBinders, site).getOrElse(tag.runtimeClass.toString, (c: Clock, r: Bool, s: Bool, t: Any) => Nil)(clock, reset, success, top) + } + }) + ) +}) + class WithGPIOTiedOff extends RegisterIOBinder({ (c, r, s, top: HasPeripheryGPIOModuleImp) => top.gpio.map(gpio => gpio.pins.map(p => p.i.ival := false.B)); Nil }) diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index 3005d095..8561d7a1 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -24,7 +24,7 @@ import tracegen.HasTraceGenTilesModuleImp import boom.common.{BoomTile} -import chipyard.iobinders.{IOBinders, RegisterIOBinder} +import chipyard.iobinders.{IOBinders, RegisterIOBinder, RegisterBinder} import chipyard.HasBoomAndRocketTilesModuleImp class WithSerialBridge extends RegisterIOBinder({ @@ -66,7 +66,7 @@ class WithTraceGenBridge extends RegisterIOBinder({ (c, r, s, target: HasTraceGenTilesModuleImp) => Seq(GroundTestBridge(target.success)(target.p)) }) -class WithFireSimMultiCycleRegfile extends RegisterIOBinder({ +class WithFireSimMultiCycleRegfile extends RegisterBinder({ (c, r, s, target: HasBoomAndRocketTilesModuleImp) => { target.outer.tiles.map { case r: RocketTile => {