diff --git a/fpga/src/main/scala/arty/IOBinders.scala b/fpga/src/main/scala/arty/IOBinders.scala index c3929262..eb3185f9 100644 --- a/fpga/src/main/scala/arty/IOBinders.scala +++ b/fpga/src/main/scala/arty/IOBinders.scala @@ -18,6 +18,6 @@ class WithDebugResetPassthrough extends ComposeIOBinder({ val io_sjtag_reset: Bool = IO(Input(Bool())).suggestName("sjtag_reset") sjtag.reset := io_sjtag_reset - (Seq(DebugResetPort(io_ndreset), JTAGResetPort(io_sjtag_reset)), Nil) + (Seq(DebugResetPort(() => io_ndreset), JTAGResetPort(() => io_sjtag_reset)), Nil) } }) diff --git a/fpga/src/main/scala/arty/TestHarness.scala b/fpga/src/main/scala/arty/TestHarness.scala index 2d524fe3..0a81740a 100644 --- a/fpga/src/main/scala/arty/TestHarness.scala +++ b/fpga/src/main/scala/arty/TestHarness.scala @@ -9,7 +9,6 @@ import org.chipsalliance.cde.config.{Parameters} import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell} import chipyard.harness.{HasHarnessInstantiators} -import chipyard.iobinders.{HasIOBinders} class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessInstantiators { // Convert harness resets from Bool to Reset type. diff --git a/fpga/src/main/scala/arty100t/Harness.scala b/fpga/src/main/scala/arty100t/Harness.scala index 47ffe7e0..a535e65f 100644 --- a/fpga/src/main/scala/arty100t/Harness.scala +++ b/fpga/src/main/scala/arty100t/Harness.scala @@ -17,7 +17,6 @@ import sifive.blocks.devices.uart._ import chipyard._ import chipyard.harness._ -import chipyard.iobinders.{HasIOBinders} class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell { def dp = designParameters diff --git a/fpga/src/main/scala/nexysvideo/Harness.scala b/fpga/src/main/scala/nexysvideo/Harness.scala index 0cfb7110..a68cf24e 100644 --- a/fpga/src/main/scala/nexysvideo/Harness.scala +++ b/fpga/src/main/scala/nexysvideo/Harness.scala @@ -16,7 +16,6 @@ import sifive.blocks.devices.uart._ import chipyard._ import chipyard.harness._ -import chipyard.iobinders.{HasIOBinders} class NexysVideoHarness(override implicit val p: Parameters) extends NexysVideoShell { def dp = designParameters diff --git a/fpga/src/main/scala/vc707/TestHarness.scala b/fpga/src/main/scala/vc707/TestHarness.scala index 008e2399..1ed7ab33 100644 --- a/fpga/src/main/scala/vc707/TestHarness.scala +++ b/fpga/src/main/scala/vc707/TestHarness.scala @@ -18,7 +18,6 @@ import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTPortIO} import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO} import chipyard._ -import chipyard.iobinders.{HasIOBinders} import chipyard.harness._ class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707Shell { outer => diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index 6bffc9a7..733c5167 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -18,7 +18,6 @@ import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTPortIO} import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO} import chipyard._ -import chipyard.iobinders.{HasIOBinders} import chipyard.harness._ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays { diff --git a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala index 69dfbce9..155f2647 100644 --- a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala @@ -13,7 +13,7 @@ import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO} import chipyard.iobinders.{OverrideIOBinder, Port, TLMemPort} -case class TSIHostWidgetPort(val io: TSIHostWidgetIO) +case class TSIHostWidgetPort(val getIO: () => TSIHostWidgetIO) extends Port[TSIHostWidgetIO] class WithTSITLIOPassthrough extends OverrideIOBinder({ @@ -25,6 +25,6 @@ class WithTSITLIOPassthrough extends OverrideIOBinder({ require(system.tsiSerial.size == 1) val io_tsi_serial_pins_temp = IO(DataMirror.internal.chiselTypeClone[TSIHostWidgetIO](system.tsiSerial.head)).suggestName("tsi_serial") io_tsi_serial_pins_temp <> system.tsiSerial.head - (Seq(TLMemPort(io_tsi_tl_mem_pins_temp), TSIHostWidgetPort(io_tsi_serial_pins_temp)), Nil) + (Seq(TLMemPort(() => io_tsi_tl_mem_pins_temp), TSIHostWidgetPort(() => io_tsi_serial_pins_temp)), Nil) } }) diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala index 150221b6..20709667 100644 --- a/generators/chipyard/src/main/scala/ChipTop.scala +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -8,7 +8,7 @@ import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, C import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey} import org.chipsalliance.cde.config.{Parameters, Field} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike, BindingScope} -import freechips.rocketchip.util.{ResetCatchAndSync} +import freechips.rocketchip.util.{DontTouch} import chipyard.iobinders._ import barstools.iocell.chisel._ @@ -31,5 +31,5 @@ class ChipTop(implicit p: Parameters) extends LazyModule with BindingScope // of ChipTop (ex: ClockGroup) do not receive clock or reset. // However. anonymous children of ChipTop should not need an implicit Clock or Reset // anyways, they probably need to be explicitly clocked. - lazy val module: LazyModuleImpLike = new LazyRawModuleImp(this) { } + lazy val module: LazyModuleImpLike = new LazyRawModuleImp(this) with DontTouch { } } diff --git a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala index 3ef8a61b..36d1fa2f 100644 --- a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala +++ b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala @@ -75,11 +75,11 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({ o.reset := reset_wire } - (Seq(ClockPort(clock_io, 100), ResetPort(reset_io)), clockIOCell ++ resetIOCell) + (Seq(ClockPort(() => clock_io, 100), ResetPort(() => reset_io)), clockIOCell ++ resetIOCell) } } }) - + // This passes all clocks through to the TestHarness class WithPassthroughClockGenerator extends OverrideLazyIOBinder({ (system: HasChipyardPRCI) => { @@ -113,9 +113,9 @@ class WithPassthroughClockGenerator extends OverrideLazyIOBinder({ val clock_io = IO(Input(Clock())).suggestName(s"clock_${m.name.get}") b.clock := clock_io b.reset := reset_io - ClockPort(clock_io, freq) + ClockPort(() => clock_io, freq) }.toSeq - ((clock_ios :+ ResetPort(reset_io)), Nil) + ((clock_ios :+ ResetPort(() => reset_io)), Nil) } } }) diff --git a/generators/chipyard/src/main/scala/config/ChipConfigs.scala b/generators/chipyard/src/main/scala/config/ChipConfigs.scala index cc61794c..c9ff068d 100644 --- a/generators/chipyard/src/main/scala/config/ChipConfigs.scala +++ b/generators/chipyard/src/main/scala/config/ChipConfigs.scala @@ -43,6 +43,10 @@ class ChipLikeRocketConfig extends Config( new chipyard.config.AbstractConfig) +class FlatChipTopChipLikeRocketConfig extends Config( + new chipyard.example.WithFlatChipTop ++ + new chipyard.ChipLikeRocketConfig) + // A simple config demonstrating a "bringup prototype" to bringup the ChipLikeRocketconfig class ChipBringupHostConfig extends Config( //============================= diff --git a/generators/chipyard/src/main/scala/config/MMIOAcceleratorConfigs.scala b/generators/chipyard/src/main/scala/config/MMIOAcceleratorConfigs.scala index 16e6b313..8d6f1063 100644 --- a/generators/chipyard/src/main/scala/config/MMIOAcceleratorConfigs.scala +++ b/generators/chipyard/src/main/scala/config/MMIOAcceleratorConfigs.scala @@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy.{AsynchronousCrossing} // DOC include start: FFTRocketConfig class FFTRocketConfig extends Config( - new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC + new chipyard.harness.WithDontTouchChipTopPorts(false) ++ // TODO: hack around dontTouch not working in SFC new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers. new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new chipyard.config.AbstractConfig) @@ -59,7 +59,7 @@ class LargeNVDLARocketConfig extends Config( new chipyard.config.AbstractConfig) class ManyMMIOAcceleratorRocketConfig extends Config( - new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC + new chipyard.harness.WithDontTouchChipTopPorts(false) ++ // TODO: hack around dontTouch not working in SFC new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers. new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough new chipyard.example.WithStreamingFIR ++ // use top with tilelink-controlled streaming FIR diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index c45fb6f2..798b086d 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -12,7 +12,7 @@ class RocketConfig extends Config( new chipyard.config.AbstractConfig) class TinyRocketConfig extends Config( - new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO FIX: Don't dontTouch the ports + new chipyard.harness.WithDontTouchChipTopPorts(false) ++ // TODO FIX: Don't dontTouch the ports new freechips.rocketchip.subsystem.WithIncoherentBusTopology ++ // use incoherent bus topology new freechips.rocketchip.subsystem.WithNBanks(0) ++ // remove L2$ new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove backing memory @@ -97,6 +97,7 @@ class MulticlockRocketConfig extends Config( new chipyard.config.AbstractConfig) class CustomIOChipTopRocketConfig extends Config( + new chipyard.example.WithBrokenOutUARTIO ++ new chipyard.example.WithCustomChipTop ++ new chipyard.example.WithCustomIOCells ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core diff --git a/generators/chipyard/src/main/scala/config/TutorialConfigs.scala b/generators/chipyard/src/main/scala/config/TutorialConfigs.scala index daa08265..edd9c438 100644 --- a/generators/chipyard/src/main/scala/config/TutorialConfigs.scala +++ b/generators/chipyard/src/main/scala/config/TutorialConfigs.scala @@ -77,7 +77,7 @@ class TutorialSha3BlackBoxConfig extends Config( // Tutorial Phase 5: Map a multicore heterogeneous SoC with multiple cores and memory-mapped accelerators class TutorialNoCConfig extends Config( - new chipyard.iobinders.WithDontTouchIOBinders(false) ++ + new chipyard.harness.WithDontTouchChipTopPorts(false) ++ // Try changing the dimensions of the Mesh topology new constellation.soc.WithGlobalNoC(constellation.soc.GlobalNoCParams( NoCParams( diff --git a/generators/chipyard/src/main/scala/example/CustomChipTop.scala b/generators/chipyard/src/main/scala/example/CustomChipTop.scala index f2ebfc33..f710ccab 100644 --- a/generators/chipyard/src/main/scala/example/CustomChipTop.scala +++ b/generators/chipyard/src/main/scala/example/CustomChipTop.scala @@ -5,9 +5,11 @@ import chipyard.iobinders._ import org.chipsalliance.cde.config._ import freechips.rocketchip.diplomacy.{InModuleBody} +import freechips.rocketchip.subsystem.{PBUS, HasTileLinkLocations} import barstools.iocell.chisel._ import chipyard._ import chipyard.harness.{BuildTop} +import sifive.blocks.devices.uart._ // A "custom" IOCell with additional I/O // The IO don't do anything here in this example @@ -63,3 +65,21 @@ class WithCustomIOCells extends Config((site, here, up) => { class WithCustomChipTop extends Config((site, here, up) => { case BuildTop => (p: Parameters) => new CustomChipTop()(p) }) + +class WithBrokenOutUARTIO extends OverrideIOBinder({ + (system: HasPeripheryUARTModuleImp) => { + val uart_txd = IO(Output(Bool())) + val uart_rxd = IO(Input(Bool())) + system.uart(0).rxd := uart_rxd + uart_txd := system.uart(0).txd + val where = PBUS // TODO fix + val bus = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where) + val freqMHz = bus.dtsFrequency.get / 1000000 + (Seq(UARTPort(() => { + val uart_wire = Wire(new UARTPortIO(system.uart(0).c)) + uart_wire.txd := uart_txd + uart_rxd := uart_wire.rxd + uart_wire + }, 0, freqMHz.toInt)), Nil) + } +}) diff --git a/generators/chipyard/src/main/scala/example/FlatChipTop.scala b/generators/chipyard/src/main/scala/example/FlatChipTop.scala index a1a1aeaa..b51a66cd 100644 --- a/generators/chipyard/src/main/scala/example/FlatChipTop.scala +++ b/generators/chipyard/src/main/scala/example/FlatChipTop.scala @@ -2,22 +2,28 @@ package chipyard.example import chisel3._ -import org.chipsalliance.cde.config.{Field, Parameters} +import org.chipsalliance.cde.config.{Config, Field, Parameters} import freechips.rocketchip.diplomacy._ import freechips.rocketchip.prci._ import freechips.rocketchip.util._ +import freechips.rocketchip.subsystem.{PBUS, HasTileLinkLocations} import freechips.rocketchip.devices.debug.{ExportDebug, JtagDTMKey, Debug} import freechips.rocketchip.tilelink.{TLBuffer, TLFragmenter} import chipyard.{BuildSystem, DigitalTop} +import chipyard.harness.{BuildTop} import chipyard.clocking._ -import chipyard.iobinders.{IOCellKey, JTAGChipIO} +import chipyard.iobinders._ import barstools.iocell.chisel._ +import testchipip.{SerialTLKey} +class WithFlatChipTop extends Config((site, here, up) => { + case BuildTop => (p: Parameters) => new FlatChipTop()(p) +}) // This "FlatChipTop" uses no IOBinders, so all the IO have // to be explicitly constructed. // This only supports the base "DigitalTop" -class FlatChipTop(implicit p: Parameters) extends LazyModule { +class FlatChipTop(implicit p: Parameters) extends LazyModule with HasChipyardPorts { override lazy val desiredName = "ChipTop" val system = LazyModule(p(BuildSystem)(p)).suggestName("system").asInstanceOf[DigitalTop] @@ -56,6 +62,8 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule { debugClockSinkNode := system.locateTLBusWrapper(p(ExportDebug).slaveWhere).fixedClockNode def debugClockBundle = debugClockSinkNode.in.head._1 + var ports: Seq[Port[_]] = Nil + override lazy val module = new FlatChipTopImpl class FlatChipTopImpl extends LazyRawModuleImp(this) { //========================= @@ -78,6 +86,9 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule { o.reset := reset_wire } + ports = ports :+ ClockPort(() => clock_pad, 100.0) + ports = ports :+ ResetPort(() => reset_pad) + // For a real chip you should replace this ClockSourceAtFreqFromPlusArg // with a blackbox of whatever PLL is being integrated val fake_pll = Module(new ClockSourceAtFreqFromPlusArg("pll_freq_mhz")) @@ -93,11 +104,13 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule { // Custom Boot //========================= val (custom_boot_pad, customBootIOCell) = IOCell.generateIOFromSignal(system.custom_boot_pin.get.getWrappedValue, "custom_boot", p(IOCellKey)) + ports = ports :+ CustomBootPort(() => custom_boot_pad) //========================= // Serialized TileLink //========================= val (serial_tl_pad, serialTLIOCells) = IOCell.generateIOFromSignal(system.serial_tl.get.getWrappedValue, "serial_tl", p(IOCellKey)) + ports = ports :+ SerialTLPort(() => serial_tl_pad, p(SerialTLKey).get, system.serdesser.get, 0) //========================= // JTAG/Debug @@ -136,12 +149,17 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule { IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true) }.get + ports = ports :+ JTAGPort(() => jtag_pad) + //========================== // UART //========================== require(system.uarts.size == 1) val (uart_pad, uartIOCells) = IOCell.generateIOFromSignal(system.module.uart.head, "uart_0", p(IOCellKey)) - + val where = PBUS // TODO fix + val bus = system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where) + val freqMHz = bus.dtsFrequency.get / 1000000 + ports = ports :+ UARTPort(() => uart_pad, 0, freqMHz.toInt) //========================== // External interrupts (tie off) diff --git a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala index 0f58f33b..cfc1cad4 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessClocks.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessClocks.scala @@ -10,7 +10,6 @@ import freechips.rocketchip.util.{ResetCatchAndSync} import freechips.rocketchip.prci._ import chipyard.harness.{ApplyHarnessBinders, HarnessBinders, HarnessClockInstantiatorKey} -import chipyard.iobinders.HasIOBinders import chipyard.clocking.{SimplePllConfiguration, ClockDividerN} diff --git a/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala b/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala index 48f63e04..35331715 100644 --- a/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala +++ b/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala @@ -5,12 +5,12 @@ import chisel3._ import scala.collection.mutable.{ArrayBuffer, LinkedHashMap} import freechips.rocketchip.diplomacy.{LazyModule} import org.chipsalliance.cde.config.{Field, Parameters, Config} -import freechips.rocketchip.util.{ResetCatchAndSync} +import freechips.rocketchip.util.{ResetCatchAndSync, DontTouch} import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters} import chipyard.stage.phases.TargetDirKey import chipyard.harness.{ApplyHarnessBinders, HarnessBinders} -import chipyard.iobinders.HasIOBinders +import chipyard.iobinders.HasChipyardPorts import chipyard.clocking.{SimplePllConfiguration, ClockDividerN} import chipyard.{ChipTop} @@ -24,6 +24,7 @@ case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator]() case object HarnessBinderClockFrequencyKey extends Field[Double](100.0) // MHz case object MultiChipIdx extends Field[Int](0) +case object DontTouchChipTopPorts extends Field[Boolean](true) class WithMultiChip(id: Int, p: Parameters) extends Config((site, here, up) => { case MultiChipParameters(`id`) => p @@ -39,6 +40,10 @@ class WithHarnessBinderClockFreqMHz(freqMHz: Double) extends Config((site, here, case HarnessBinderClockFrequencyKey => freqMHz }) +class WithDontTouchChipTopPorts(b: Boolean = true) extends Config((site, here, up) => { + case DontTouchChipTopPorts => b +}) + // A TestHarness mixing this in will // - use the HarnessClockInstantiator clock provide trait HasHarnessInstantiators { @@ -83,12 +88,20 @@ trait HasHarnessInstantiators { withClockAndReset (harnessBinderClock, harnessBinderReset) { lazyDuts.zipWithIndex.foreach { - case (d: HasIOBinders, i: Int) => ApplyHarnessBinders(this, d.portMap.values.flatten.toSeq)(chipParameters(i)) + case (d: HasChipyardPorts, i: Int) => { + ApplyHarnessBinders(this, d.ports)(chipParameters(i)) + } case _ => } ApplyMultiHarnessBinders(this, lazyDuts) } + if (p(DontTouchChipTopPorts)) { + duts.map(_ match { + case d: DontTouch => d.dontTouchPorts() + }) + } + val harnessBinderClk = harnessClockInstantiator.requestClockMHz("harnessbinder_clock", getHarnessBinderClockFreqMHz) println(s"Harness binder clock is $harnessBinderClockFreq") harnessBinderClock := harnessBinderClk diff --git a/generators/chipyard/src/main/scala/harness/MultiHarnessBinders.scala b/generators/chipyard/src/main/scala/harness/MultiHarnessBinders.scala index 399e64be..1200208c 100644 --- a/generators/chipyard/src/main/scala/harness/MultiHarnessBinders.scala +++ b/generators/chipyard/src/main/scala/harness/MultiHarnessBinders.scala @@ -13,7 +13,7 @@ import freechips.rocketchip.util._ import testchipip._ import chipyard._ -import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasIOBinders, Port, SerialTLPort} +import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasChipyardPorts, Port, SerialTLPort} import scala.reflect.{ClassTag} @@ -23,8 +23,8 @@ object ApplyMultiHarnessBinders { def apply(th: HasHarnessInstantiators, chips: Seq[LazyModule])(implicit p: Parameters): Unit = { Seq.tabulate(chips.size, chips.size) { case (i, j) => if (i != j) { (chips(i), chips(j)) match { - case (l0: HasIOBinders, l1: HasIOBinders) => p(MultiHarnessBinders(i, j)).foreach { f => - f(l0.portMap.values.flatten.toSeq, l1.portMap.values.flatten.toSeq) + case (l0: HasChipyardPorts, l1: HasChipyardPorts) => p(MultiHarnessBinders(i, j)).foreach { f => + f(l0.ports, l1.ports) } } }} diff --git a/generators/chipyard/src/main/scala/harness/TestHarness.scala b/generators/chipyard/src/main/scala/harness/TestHarness.scala index 459c6511..43bf2dd0 100644 --- a/generators/chipyard/src/main/scala/harness/TestHarness.scala +++ b/generators/chipyard/src/main/scala/harness/TestHarness.scala @@ -9,7 +9,6 @@ import freechips.rocketchip.util.{ResetCatchAndSync} import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters} import chipyard.harness.{ApplyHarnessBinders, HarnessBinders} -import chipyard.iobinders.HasIOBinders import chipyard.clocking.{SimplePllConfiguration, ClockDividerN} import chipyard.{ChipTop} diff --git a/generators/chipyard/src/main/scala/iobinders/IOBinders.scala b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala index 34be9bb7..7401452f 100644 --- a/generators/chipyard/src/main/scala/iobinders/IOBinders.scala +++ b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala @@ -51,13 +51,7 @@ case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]]( Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil) ) -case object DontTouchIOBindersPorts extends Field[Boolean](true) - -class WithDontTouchIOBinders(b: Boolean = true) extends Config((site, here, up) => { - case DontTouchIOBindersPorts => b -}) - -abstract trait HasIOBinders { this: LazyModule => +abstract trait HasIOBinders extends HasChipyardPorts { 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 @@ -81,11 +75,9 @@ abstract trait HasIOBinders { this: LazyModule => // A mapping between stringified DigitalSystem traits and their corresponding ChipTop iocells val iocellMap = InModuleBody { iobinders.keys.map(k => k -> (lzyFlattened(k)._2 ++ impFlattened(k)._2)).toMap } - InModuleBody { - if (p(DontTouchIOBindersPorts)) { - portMap.values.flatten.foreach { case (port: Port[Data]) => dontTouch(port.io) } - } + def ports = portMap.getWrappedValue.values.flatten.toSeq + InModuleBody { println("IOCells generated by IOBinders:") for ((k, v) <- iocellMap) { if (!v.isEmpty) { @@ -172,7 +164,7 @@ class WithGPIOCells extends OverrideIOBinder({ iocell.io.ie := pin.o.ie pin.i.ival := iocell.io.i iocell.io.pad <> g - (GPIOPort(g, i, j), iocell) + (GPIOPort(() => g, i, j), iocell) }).unzip }).unzip (ports2d.flatten, cells2d.flatten) @@ -184,7 +176,7 @@ class WithGPIOPunchthrough extends OverrideIOBinder({ val ports = system.gpio.zipWithIndex.map { case (gpio, i) => val io_gpio = IO(gpio.cloneType).suggestName(s"gpio_$i") io_gpio <> gpio - GPIOPinsPort(io_gpio, i) + GPIOPinsPort(() => io_gpio, i) } (ports, Nil) } @@ -195,7 +187,7 @@ class WithI2CPunchthrough extends OverrideIOBinder({ val ports = system.i2c.zipWithIndex.map { case (i2c, i) => val io_i2c = IO(i2c.cloneType).suggestName(s"i2c_$i") io_i2c <> i2c - I2CPort(i2c) + I2CPort(() => i2c) } (ports, Nil) } @@ -209,7 +201,7 @@ class WithUARTIOCells extends OverrideIOBinder({ val where = PBUS // TODO fix val bus = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where) val freqMHz = bus.dtsFrequency.get / 1000000 - (UARTPort(port, i, freqMHz.toInt), ios) + (UARTPort(() => port, i, freqMHz.toInt), ios) }).unzip (ports, cells2d.flatten) } @@ -227,7 +219,7 @@ class WithSPIIOPunchthrough extends OverrideLazyIOBinder({ val ports = spi.zipWithIndex.map({ case (s, i) => val io_spi = IO(s.cloneType).suggestName(s"spi_$i") io_spi <> s - SPIPort(io_spi) + SPIPort(() => io_spi) }) (ports, Nil) } @@ -257,7 +249,7 @@ class WithSPIFlashIOCells extends OverrideIOBinder({ iocell } - (SPIFlashPort(port, system.p(PeripherySPIFlashKey)(i), i), dqIOs ++ csIOs ++ sckIOs) + (SPIFlashPort(() => port, system.p(PeripherySPIFlashKey)(i), i), dqIOs ++ csIOs ++ sckIOs) }).unzip (ports, cells2d.flatten) } @@ -267,7 +259,7 @@ class WithExtInterruptIOCells extends OverrideIOBinder({ (system: HasExtInterruptsModuleImp) => { if (system.outer.nExtInterrupts > 0) { val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey), abstractResetAsAsync = true) - (Seq(ExtIntPort(port)), cells) + (Seq(ExtIntPort(() => port)), cells) } else { system.interrupts := DontCare // why do I have to drive this 0-wide wire??? (Nil, Nil) @@ -318,7 +310,7 @@ class WithDebugIOCells extends OverrideLazyIOBinder({ // Add IOCells for the DMI/JTAG/APB ports val dmiTuple = debug.clockeddmi.map { d => val (port, cells) = IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true) - (DMIPort(port), cells) + (DMIPort(() => port), cells) } val jtagTuple = debug.systemjtag.map { j => @@ -328,7 +320,7 @@ class WithDebugIOCells extends OverrideLazyIOBinder({ j.jtag.TDI := jtag_wire.TDI jtag_wire.TDO := j.jtag.TDO.data val (port, cells) = IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true) - (JTAGPort(port), cells) + (JTAGPort(() => port), cells) } require(!debug.apb.isDefined) @@ -345,7 +337,7 @@ class WithSerialTLIOCells extends OverrideIOBinder({ val (ports, cells) = system.serial_tl.zipWithIndex.map({ case (s, id) => val sys = system.asInstanceOf[BaseSubsystem] val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey), abstractResetAsAsync = true) - (SerialTLPort(port, sys.p(SerialTLKey).get, system.serdesser.get, id), cells) + (SerialTLPort(() => port, sys.p(SerialTLKey).get, system.serdesser.get, id), cells) }).unzip (ports.toSeq, cells.flatten.toSeq) } @@ -357,7 +349,7 @@ class WithSerialTLPunchthrough extends OverrideIOBinder({ val sys = system.asInstanceOf[BaseSubsystem] val port = IO(chiselTypeOf(s.getWrappedValue)) port <> s.getWrappedValue - (SerialTLPort(port, sys.p(SerialTLKey).get, system.serdesser.get, id), Nil) + (SerialTLPort(() => port, sys.p(SerialTLKey).get, system.serdesser.get, id), Nil) }).unzip (ports.toSeq, cells.flatten.toSeq) } @@ -375,7 +367,7 @@ class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({ val port = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}") port.bits <> m port.clock := clockBundle.clock - AXI4MemPort(port, p(ExtMem).get, system.memAXI4Node.edges.in(i), p(MemoryBusKey).dtsFrequency.get.toInt) + AXI4MemPort(() => port, p(ExtMem).get, system.memAXI4Node.edges.in(i), p(MemoryBusKey).dtsFrequency.get.toInt) }).toSeq (ports, Nil) } @@ -394,7 +386,7 @@ class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({ val port = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}") port.bits <> m port.clock := clockBundle.clock - AXI4MMIOPort(port, p(ExtBus).get, system.mmioAXI4Node.edges.in(i)) + AXI4MMIOPort(() => port, p(ExtBus).get, system.mmioAXI4Node.edges.in(i)) }).toSeq (ports, Nil) } @@ -413,7 +405,7 @@ class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({ val port = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}") m <> port.bits port.clock := clockBundle.clock - AXI4InPort(port, p(ExtIn).get) + AXI4InPort(() => port, p(ExtIn).get) }).toSeq (ports, Nil) } @@ -427,7 +419,7 @@ class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({ val bdParams = p(BlockDeviceKey).get val port = IO(new ClockedIO(new BlockDeviceIO(bdParams))).suggestName("blockdev") port <> bdev - BlockDevicePort(port, bdParams) + BlockDevicePort(() => port, bdParams) }).toSeq (ports, Nil) } @@ -439,7 +431,7 @@ class WithNICIOPunchthrough extends OverrideIOBinder({ val p = GetSystemParameters(system) val port = IO(new ClockedIO(new NICIOvonly)).suggestName("nic") port <> n - NICPort(port, p(NICKey).get) + NICPort(() => port, p(NICKey).get) }).toSeq (ports, Nil) } @@ -449,7 +441,7 @@ class WithTraceGenSuccessPunchthrough extends OverrideIOBinder({ (system: TraceGenSystemModuleImp) => { val success: Bool = IO(Output(Bool())).suggestName("success") success := system.success - (Seq(SuccessPort(success)), Nil) + (Seq(SuccessPort(() => success)), Nil) } }) @@ -472,7 +464,7 @@ class WithTraceIOPunchthrough extends OverrideIOBinder({ bootrom = chipyardSystem.bootROM.map(_.module.contents.toArray.mkString(" ")).getOrElse(""), has_dtm = p(ExportDebug).protocols.contains(DMI) // assume that exposing clockeddmi means we will connect SimDTM ) - TracePort(trace, cfg) + TracePort(() => trace, cfg) } (ports.toSeq, Nil) } @@ -482,7 +474,7 @@ class WithCustomBootPin extends OverrideIOBinder({ (system: CanHavePeripheryCustomBootPin) => system.custom_boot_pin.map({ p => val sys = system.asInstanceOf[BaseSubsystem] val (port, cells) = IOCell.generateIOFromSignal(p.getWrappedValue, "custom_boot", sys.p(IOCellKey), abstractResetAsAsync = true) - (Seq(CustomBootPort(port)), cells) + (Seq(CustomBootPort(() => port)), cells) }).getOrElse((Nil, Nil)) }) @@ -491,7 +483,7 @@ class WithUARTTSIPunchthrough extends OverrideIOBinder({ val sys = system.asInstanceOf[BaseSubsystem] val uart_tsi = IO(new UARTTSIIO(p.uartParams)) uart_tsi <> p - (Seq(UARTTSIPort(uart_tsi)), Nil) + (Seq(UARTTSIPort(() => uart_tsi)), Nil) }).getOrElse((Nil, Nil)) }) @@ -499,7 +491,7 @@ class WithTLMemPunchthrough extends OverrideIOBinder({ (system: CanHaveMasterTLMemPort) => { val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.mem_tl)).suggestName("tl_slave") io_tl_mem_pins_temp <> system.mem_tl - (Seq(TLMemPort(io_tl_mem_pins_temp)), Nil) + (Seq(TLMemPort(() => io_tl_mem_pins_temp)), Nil) } }) diff --git a/generators/chipyard/src/main/scala/iobinders/Ports.scala b/generators/chipyard/src/main/scala/iobinders/Ports.scala index 61c25a36..c5c9f19e 100644 --- a/generators/chipyard/src/main/scala/iobinders/Ports.scala +++ b/generators/chipyard/src/main/scala/iobinders/Ports.scala @@ -16,79 +16,85 @@ import freechips.rocketchip.util.{HeterogeneousBag} import freechips.rocketchip.tilelink.{TLBundle} trait Port[T <: Data] { - val io: T + val getIO: () => T + // port.io should only be called in the TestHarness context + lazy val io = getIO() +} + +trait HasChipyardPorts { + def ports: Seq[Port[_]] } // These case classes are generated by IOBinders, and interpreted by HarnessBinders -case class GPIOPort (val io: Analog, val gpioId: Int, val pinId: Int) +case class GPIOPort (val getIO: () => Analog, val gpioId: Int, val pinId: Int) extends Port[Analog] -case class GPIOPinsPort (val io: GPIOPortIO, val gpioId: Int) +case class GPIOPinsPort (val getIO: () => GPIOPortIO, val gpioId: Int) extends Port[GPIOPortIO] -case class I2CPort (val io: sifive.blocks.devices.i2c.I2CPort) +case class I2CPort (val getIO: () => sifive.blocks.devices.i2c.I2CPort) extends Port[sifive.blocks.devices.i2c.I2CPort] -case class UARTPort (val io: UARTPortIO, val uartNo: Int, val freqMHz: Int) +case class UARTPort (val getIO: () => UARTPortIO, val uartNo: Int, val freqMHz: Int) extends Port[UARTPortIO] -case class SPIFlashPort (val io: SPIChipIO, val params: SPIFlashParams, val spiId: Int) +case class SPIFlashPort (val getIO: () => SPIChipIO, val params: SPIFlashParams, val spiId: Int) extends Port[SPIChipIO] -case class SPIPort (val io: SPIPortIO) +case class SPIPort (val getIO: () => SPIPortIO) extends Port[SPIPortIO] -case class BlockDevicePort (val io: ClockedIO[BlockDeviceIO], val params: BlockDeviceConfig) +case class BlockDevicePort (val getIO: () => ClockedIO[BlockDeviceIO], val params: BlockDeviceConfig) extends Port[ClockedIO[BlockDeviceIO]] -case class NICPort (val io: ClockedIO[NICIOvonly], val params: NICConfig) +case class NICPort (val getIO: () => ClockedIO[NICIOvonly], val params: NICConfig) extends Port[ClockedIO[NICIOvonly]] -case class AXI4MemPort (val io: ClockedIO[AXI4Bundle], val params: MemoryPortParams, val edge: AXI4EdgeParameters, val clockFreqMHz: Int) +case class AXI4MemPort (val getIO: () => ClockedIO[AXI4Bundle], val params: MemoryPortParams, val edge: AXI4EdgeParameters, val clockFreqMHz: Int) extends Port[ClockedIO[AXI4Bundle]] -case class AXI4MMIOPort (val io: ClockedIO[AXI4Bundle], val params: MasterPortParams, val edge: AXI4EdgeParameters) +case class AXI4MMIOPort (val getIO: () => ClockedIO[AXI4Bundle], val params: MasterPortParams, val edge: AXI4EdgeParameters) extends Port[ClockedIO[AXI4Bundle]] -case class AXI4InPort (val io: ClockedIO[AXI4Bundle], val params: SlavePortParams) +case class AXI4InPort (val getIO: () => ClockedIO[AXI4Bundle], val params: SlavePortParams) extends Port[ClockedIO[AXI4Bundle]] -case class ExtIntPort (val io: UInt) +case class ExtIntPort (val getIO: () => UInt) extends Port[UInt] -case class DMIPort (val io: ClockedDMIIO) +case class DMIPort (val getIO: () => ClockedDMIIO) extends Port[ClockedDMIIO] -case class JTAGPort (val io: JTAGChipIO) +case class JTAGPort (val getIO: () => JTAGChipIO) extends Port[JTAGChipIO] -case class SerialTLPort (val io: ClockedIO[SerialIO], val params: SerialTLParams, val serdesser: TLSerdesser, val portId: Int) +case class SerialTLPort (val getIO: () => ClockedIO[SerialIO], val params: SerialTLParams, val serdesser: TLSerdesser, val portId: Int) extends Port[ClockedIO[SerialIO]] -case class UARTTSIPort (val io: UARTTSIIO) +case class UARTTSIPort (val getIO: () => UARTTSIIO) extends Port[UARTTSIIO] -case class SuccessPort (val io: Bool) +case class SuccessPort (val getIO: () => Bool) extends Port[Bool] -case class TracePort (val io: TraceOutputTop, val cosimCfg: SpikeCosimConfig) +case class TracePort (val getIO: () => TraceOutputTop, val cosimCfg: SpikeCosimConfig) extends Port[TraceOutputTop] -case class CustomBootPort (val io: Bool) +case class CustomBootPort (val getIO: () => Bool) extends Port[Bool] -case class ClockPort (val io: Clock, val freqMHz: Double) +case class ClockPort (val getIO: () => Clock, val freqMHz: Double) extends Port[Clock] -case class ResetPort (val io: AsyncReset) +case class ResetPort (val getIO: () => AsyncReset) extends Port[Reset] -case class DebugResetPort (val io: Reset) +case class DebugResetPort (val getIO: () => Reset) extends Port[Reset] -case class JTAGResetPort (val io: Reset) +case class JTAGResetPort (val getIO: () => Reset) extends Port[Reset] -case class TLMemPort (val io: HeterogeneousBag[TLBundle]) +case class TLMemPort (val getIO: () => HeterogeneousBag[TLBundle]) extends Port[HeterogeneousBag[TLBundle]]