From eb3a0aecf4fe7ad2d382318e5d56da4162c5c2da Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Mon, 2 Oct 2023 17:30:13 -0700 Subject: [PATCH 01/12] Add PortAPI between IO and Harness blocks --- docs/Customization/IOBinders.rst | 2 +- fpga/src/main/scala/arty/Configs.scala | 3 +- fpga/src/main/scala/arty/HarnessBinders.scala | 83 ++-- fpga/src/main/scala/arty/IOBinders.scala | 4 +- .../main/scala/arty100t/HarnessBinders.scala | 29 +- fpga/src/main/scala/vc707/Configs.scala | 4 - .../src/main/scala/vc707/HarnessBinders.scala | 35 +- fpga/src/main/scala/vc707/IOBinders.scala | 53 -- fpga/src/main/scala/vcu118/Configs.scala | 3 - .../main/scala/vcu118/HarnessBinders.scala | 33 +- fpga/src/main/scala/vcu118/IOBinders.scala | 44 -- .../main/scala/vcu118/bringup/Configs.scala | 4 +- .../scala/vcu118/bringup/HarnessBinders.scala | 56 +-- .../main/scala/vcu118/bringup/IOBinders.scala | 25 +- .../main/scala/clocking/ClockBinders.scala | 20 +- .../clocking/DividerOnlyClockGenerator.scala | 2 +- .../main/scala/config/AbstractConfig.scala | 10 +- .../main/scala/config/TracegenConfigs.scala | 3 +- .../src/main/scala/example/FlatChipTop.scala | 4 +- .../main/scala/example/FlatTestHarness.scala | 2 +- .../main/scala/harness/HarnessBinders.scala | 453 ++++++++---------- .../harness/HasHarnessInstantiators.scala | 2 +- .../scala/harness/MultiHarnessBinders.scala | 88 ++-- .../src/main/scala/harness/package.scala | 12 +- .../scala/{ => iobinders}/IOBinders.scala | 185 ++++--- .../src/main/scala/iobinders/Ports.scala | 94 ++++ .../src/main/scala/BridgeBinders.scala | 149 ++---- .../firechip/src/main/scala/FireSim.scala | 48 +- .../src/main/scala/TargetConfigs.scala | 13 +- generators/icenet | 2 +- generators/testchipip | 2 +- sims/firesim | 2 +- 32 files changed, 681 insertions(+), 788 deletions(-) delete mode 100644 fpga/src/main/scala/vc707/IOBinders.scala delete mode 100644 fpga/src/main/scala/vcu118/IOBinders.scala rename generators/chipyard/src/main/scala/{ => iobinders}/IOBinders.scala (70%) create mode 100644 generators/chipyard/src/main/scala/iobinders/Ports.scala diff --git a/docs/Customization/IOBinders.rst b/docs/Customization/IOBinders.rst index d3626a03c4..d7e652231c 100644 --- a/docs/Customization/IOBinders.rst +++ b/docs/Customization/IOBinders.rst @@ -13,7 +13,7 @@ The ``IOBinder`` functions are responsible for instantiating IO cells and IOPort For example, the ``WithUARTIOCells`` IOBinder will, for any ``System`` that might have UART ports (``HasPeripheryUARTModuleImp``, generate ports within the ``ChipTop`` (``ports``) as well as IOCells with the appropriate type and direction (``cells2d``). This function returns a the list of generated ports, and the list of generated IOCells. The list of generated ports is passed to the ``HarnessBinders`` such that they can be connected to ``TestHarness`` devices. -.. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala +.. literalinclude:: ../../generators/chipyard/src/main/scala/iobinders/IOBinders.scala :language: scala :start-after: DOC include start: WithUARTIOCells :end-before: DOC include end: WithUARTIOCells diff --git a/fpga/src/main/scala/arty/Configs.scala b/fpga/src/main/scala/arty/Configs.scala index 1cf7bfcefa..3e208060c8 100644 --- a/fpga/src/main/scala/arty/Configs.scala +++ b/fpga/src/main/scala/arty/Configs.scala @@ -17,7 +17,8 @@ import chipyard.{BuildSystem} // DOC include start: AbstractArty and Rocket class WithArtyTweaks extends Config( - new WithArtyResetHarnessBinder ++ + new WithArtyDebugResetHarnessBinder ++ + new WithArtyJTAGResetHarnessBinder ++ new WithArtyJTAGHarnessBinder ++ new WithArtyUARTHarnessBinder ++ new WithDebugResetPassthrough ++ diff --git a/fpga/src/main/scala/arty/HarnessBinders.scala b/fpga/src/main/scala/arty/HarnessBinders.scala index 1d96cecff5..5cef5f8053 100644 --- a/fpga/src/main/scala/arty/HarnessBinders.scala +++ b/fpga/src/main/scala/arty/HarnessBinders.scala @@ -11,68 +11,61 @@ import sifive.blocks.devices.pinctrl.{BasePin} import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} -import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder} -import chipyard.iobinders.JTAGChipIO +import chipyard.harness.{HarnessBinder} +import chipyard.iobinders._ -class WithArtyResetHarnessBinder extends ComposeHarnessBinder({ - (system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => { - val resetPorts = ports.collect { case b: Bool => b } - require(resetPorts.size == 2) - withClockAndReset(th.clock_32MHz, th.ck_rst) { - // Debug module reset - th.dut_ndreset := resetPorts(0) +class WithArtyDebugResetHarnessBinder extends HarnessBinder({ + case (th: ArtyFPGATestHarness, port: DebugResetPort) => { + th.dut_ndreset := port.io // Debug module reset + } +}) - // JTAG reset - resetPorts(1) := PowerOnResetFPGAOnly(th.clock_32MHz) - } +class WithArtyJTAGResetHarnessBinder extends HarnessBinder({ + case (th: ArtyFPGATestHarness, port: JTAGResetPort) => { + port.io := PowerOnResetFPGAOnly(th.clock_32MHz) // JTAG module reset } }) -class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({ - (system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => { - ports.map { - case j: JTAGChipIO => { - val jtag_wire = Wire(new JTAGIO) - jtag_wire.TDO.data := j.TDO - jtag_wire.TDO.driven := true.B - j.TCK := jtag_wire.TCK - j.TMS := jtag_wire.TMS - j.TDI := jtag_wire.TDI +class WithArtyJTAGHarnessBinder extends HarnessBinder({ + case (th: ArtyFPGATestHarness, port: JTAGPort) => { + val jtag_wire = Wire(new JTAGIO) + jtag_wire.TDO.data := port.io.TDO + jtag_wire.TDO.driven := true.B + port.io.TCK := jtag_wire.TCK + port.io.TMS := jtag_wire.TMS + port.io.TDI := jtag_wire.TDI - val io_jtag = Wire(new JTAGPins(() => new BasePin(), false)).suggestName("jtag") + val io_jtag = Wire(new JTAGPins(() => new BasePin(), false)).suggestName("jtag") - JTAGPinsFromPort(io_jtag, jtag_wire) + JTAGPinsFromPort(io_jtag, jtag_wire) - io_jtag.TCK.i.ival := IBUFG(IOBUF(th.jd_2).asClock).asBool + io_jtag.TCK.i.ival := IBUFG(IOBUF(th.jd_2).asClock).asBool - IOBUF(th.jd_5, io_jtag.TMS) - PULLUP(th.jd_5) + IOBUF(th.jd_5, io_jtag.TMS) + PULLUP(th.jd_5) - IOBUF(th.jd_4, io_jtag.TDI) - PULLUP(th.jd_4) + IOBUF(th.jd_4, io_jtag.TDI) + PULLUP(th.jd_4) - IOBUF(th.jd_0, io_jtag.TDO) + IOBUF(th.jd_0, io_jtag.TDO) - // mimic putting a pullup on this line (part of reset vote) - th.SRST_n := IOBUF(th.jd_6) - PULLUP(th.jd_6) + // mimic putting a pullup on this line (part of reset vote) + th.SRST_n := IOBUF(th.jd_6) + PULLUP(th.jd_6) - // ignore the po input - io_jtag.TCK.i.po.map(_ := DontCare) - io_jtag.TDI.i.po.map(_ := DontCare) - io_jtag.TMS.i.po.map(_ := DontCare) - io_jtag.TDO.i.po.map(_ := DontCare) - } - case b: Bool => - } + // ignore the po input + io_jtag.TCK.i.po.map(_ := DontCare) + io_jtag.TDI.i.po.map(_ := DontCare) + io_jtag.TMS.i.po.map(_ := DontCare) + io_jtag.TDO.i.po.map(_ := DontCare) } }) -class WithArtyUARTHarnessBinder extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: ArtyFPGATestHarness, ports: Seq[UARTPortIO]) => { +class WithArtyUARTHarnessBinder extends HarnessBinder({ + case (th: ArtyFPGATestHarness, port: UARTPort) => { withClockAndReset(th.clock_32MHz, th.ck_rst) { - IOBUF(th.uart_rxd_out, ports.head.txd) - ports.head.rxd := IOBUF(th.uart_txd_in) + IOBUF(th.uart_rxd_out, port.io.txd) + port.io.rxd := IOBUF(th.uart_txd_in) } } }) diff --git a/fpga/src/main/scala/arty/IOBinders.scala b/fpga/src/main/scala/arty/IOBinders.scala index da6c7318ee..c392926230 100644 --- a/fpga/src/main/scala/arty/IOBinders.scala +++ b/fpga/src/main/scala/arty/IOBinders.scala @@ -5,7 +5,7 @@ import chisel3.experimental.{IO} import freechips.rocketchip.devices.debug.{HasPeripheryDebug} -import chipyard.iobinders.{ComposeIOBinder} +import chipyard.iobinders.{ComposeIOBinder, DebugResetPort, JTAGResetPort} class WithDebugResetPassthrough extends ComposeIOBinder({ (system: HasPeripheryDebug) => { @@ -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(io_ndreset, io_sjtag_reset), Nil) + (Seq(DebugResetPort(io_ndreset), JTAGResetPort(io_sjtag_reset)), Nil) } }) diff --git a/fpga/src/main/scala/arty100t/HarnessBinders.scala b/fpga/src/main/scala/arty100t/HarnessBinders.scala index 060e3d8dd6..e313c6e176 100644 --- a/fpga/src/main/scala/arty100t/HarnessBinders.scala +++ b/fpga/src/main/scala/arty100t/HarnessBinders.scala @@ -16,33 +16,28 @@ import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} import chipyard._ import chipyard.harness._ -import chipyard.iobinders.JTAGChipIO +import chipyard.iobinders._ import testchipip._ -class WithArty100TUARTTSI(uartBaudRate: BigInt = 115200) extends OverrideHarnessBinder({ - (system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => { - implicit val p = chipyard.iobinders.GetSystemParameters(system) - require(ports.size <= 1) +class WithArty100TUARTTSI(uartBaudRate: BigInt = 115200) extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: UARTTSIPort) => { val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness] - ports.map({ port => - ath.io_uart_bb.bundle <> port.uart - ath.other_leds(1) := port.dropped - ath.other_leds(9) := port.tsi2tl_state(0) - ath.other_leds(10) := port.tsi2tl_state(1) - ath.other_leds(11) := port.tsi2tl_state(2) - ath.other_leds(12) := port.tsi2tl_state(3) - }) + ath.io_uart_bb.bundle <> port.io.uart + ath.other_leds(1) := port.io.dropped + ath.other_leds(9) := port.io.tsi2tl_state(0) + ath.other_leds(10) := port.io.tsi2tl_state(1) + ath.other_leds(11) := port.io.tsi2tl_state(2) + ath.other_leds(12) := port.io.tsi2tl_state(3) } }) -class WithArty100TDDRTL extends OverrideHarnessBinder({ - (system: CanHaveMasterTLMemPort, th: HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => { - require(ports.size == 1) +class WithArty100TDDRTL extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: TLMemPort) => { val artyTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness] val bundles = artyTh.ddrClient.out.map(_._1) val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType))) bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } - ddrClientBundle <> ports.head + ddrClientBundle <> port.io } }) diff --git a/fpga/src/main/scala/vc707/Configs.scala b/fpga/src/main/scala/vc707/Configs.scala index 55ce8e06a7..b37064ac9c 100644 --- a/fpga/src/main/scala/vc707/Configs.scala +++ b/fpga/src/main/scala/vc707/Configs.scala @@ -53,10 +53,6 @@ class WithVC707Tweaks extends Config ( new WithVC707UARTHarnessBinder ++ new WithVC707SPISDCardHarnessBinder ++ new WithVC707DDRMemHarnessBinder ++ - // io binders - new WithUARTIOPassthrough ++ - new WithSPIIOPassthrough ++ - new WithTLIOPassthrough ++ // other configuration new WithDefaultPeripherals ++ new chipyard.config.WithTLBackingMemory ++ // use TL backing memory diff --git a/fpga/src/main/scala/vc707/HarnessBinders.scala b/fpga/src/main/scala/vc707/HarnessBinders.scala index cf5bbb5e0d..25224d5726 100644 --- a/fpga/src/main/scala/vc707/HarnessBinders.scala +++ b/fpga/src/main/scala/vc707/HarnessBinders.scala @@ -11,36 +11,29 @@ import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO} import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{HasSystemXilinxVC707PCIeX1ModuleImp, XilinxVC707PCIeX1IO} import chipyard.{CanHaveMasterTLMemPort} -import chipyard.harness.{OverrideHarnessBinder} +import chipyard.harness.{HarnessBinder} +import chipyard.iobinders._ /*** UART ***/ -class WithVC707UARTHarnessBinder extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: BaseModule, ports: Seq[UARTPortIO]) => { - th match { case vc707th: VC707FPGATestHarnessImp => { - vc707th.vc707Outer.io_uart_bb.bundle <> ports.head - }} +class WithVC707UARTHarnessBinder extends HarnessBinder({ + case (th: VC707FPGATestHarnessImp, port: UARTPort) => { + th.vc707Outer.io_uart_bb.bundle <> port.io } }) /*** SPI ***/ -class WithVC707SPISDCardHarnessBinder extends OverrideHarnessBinder({ - (system: HasPeripherySPI, th: BaseModule, ports: Seq[SPIPortIO]) => { - th match { case vc707th: VC707FPGATestHarnessImp => { - vc707th.vc707Outer.io_spi_bb.bundle <> ports.head - }} +class WithVC707SPISDCardHarnessBinder extends HarnessBinder({ + case (th: VC707FPGATestHarnessImp, port: SPIPort) => { + th.vc707Outer.io_spi_bb.bundle <> port.io } }) /*** Experimental DDR ***/ -class WithVC707DDRMemHarnessBinder extends OverrideHarnessBinder({ - (system: CanHaveMasterTLMemPort, th: BaseModule, ports: Seq[HeterogeneousBag[TLBundle]]) => { - th match { case vc707th: VC707FPGATestHarnessImp => { - require(ports.size == 1) - - val bundles = vc707th.vc707Outer.ddrClient.out.map(_._1) - val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType))) - bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } - ddrClientBundle <> ports.head - }} +class WithVC707DDRMemHarnessBinder extends HarnessBinder({ + case (th: VC707FPGATestHarnessImp, port: TLMemPort) => { + val bundles = th.vc707Outer.ddrClient.out.map(_._1) + val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType))) + bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } + ddrClientBundle <> port.io } }) diff --git a/fpga/src/main/scala/vc707/IOBinders.scala b/fpga/src/main/scala/vc707/IOBinders.scala deleted file mode 100644 index ad485571f4..0000000000 --- a/fpga/src/main/scala/vc707/IOBinders.scala +++ /dev/null @@ -1,53 +0,0 @@ -package chipyard.fpga.vc707 - -import chisel3._ -import chisel3.experimental.{IO, DataMirror} - -import freechips.rocketchip.diplomacy.{ResourceBinding, Resource, ResourceAddress, InModuleBody} -import freechips.rocketchip.subsystem.{BaseSubsystem} -import freechips.rocketchip.util.{HeterogeneousBag} -import freechips.rocketchip.tilelink.{TLBundle} - -import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp} -import sifive.blocks.devices.spi.{HasPeripherySPI, HasPeripherySPIModuleImp, MMCDevice} -import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{HasSystemXilinxVC707PCIeX1ModuleImp} - -import chipyard.{CanHaveMasterTLMemPort} -import chipyard.iobinders.{OverrideIOBinder, OverrideLazyIOBinder} - -class WithUARTIOPassthrough extends OverrideIOBinder({ - (system: HasPeripheryUARTModuleImp) => { - val io_uart_pins_temp = system.uart.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"uart_$i") } - (io_uart_pins_temp zip system.uart).map { case (io, sysio) => - io <> sysio - } - (io_uart_pins_temp, Nil) - } -}) - -class WithSPIIOPassthrough extends OverrideLazyIOBinder({ - (system: HasPeripherySPI) => { - // attach resource to 1st SPI - ResourceBinding { - Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0)) - } - - InModuleBody { - system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripherySPIModuleImp => { - val io_spi_pins_temp = system.spi.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"spi_$i") } - (io_spi_pins_temp zip system.spi).map { case (io, sysio) => - io <> sysio - } - (io_spi_pins_temp, Nil) - } } - } - } -}) - -class WithTLIOPassthrough 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(io_tl_mem_pins_temp), Nil) - } -}) diff --git a/fpga/src/main/scala/vcu118/Configs.scala b/fpga/src/main/scala/vcu118/Configs.scala index bd48fb4e11..3563296130 100644 --- a/fpga/src/main/scala/vcu118/Configs.scala +++ b/fpga/src/main/scala/vcu118/Configs.scala @@ -52,9 +52,6 @@ class WithVCU118Tweaks extends Config( new WithUART ++ new WithSPISDCard ++ new WithDDRMem ++ - // io binders - new WithUARTIOPassthrough ++ - new WithSPIIOPassthrough ++ // other configuration new WithDefaultPeripherals ++ new chipyard.config.WithTLBackingMemory ++ // use TL backing memory diff --git a/fpga/src/main/scala/vcu118/HarnessBinders.scala b/fpga/src/main/scala/vcu118/HarnessBinders.scala index f17b654fc2..769e5b4209 100644 --- a/fpga/src/main/scala/vcu118/HarnessBinders.scala +++ b/fpga/src/main/scala/vcu118/HarnessBinders.scala @@ -11,35 +11,28 @@ import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO} import chipyard._ import chipyard.harness._ +import chipyard.iobinders._ /*** UART ***/ -class WithUART extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[UARTPortIO]) => { - th match { case vcu118th: VCU118FPGATestHarnessImp => { - vcu118th.vcu118Outer.io_uart_bb.bundle <> ports.head - } } +class WithUART extends HarnessBinder({ + case (th: VCU118FPGATestHarnessImp, port: UARTPort) => { + th.vcu118Outer.io_uart_bb.bundle <> port.io } }) /*** SPI ***/ -class WithSPISDCard extends OverrideHarnessBinder({ - (system: HasPeripherySPI, th: BaseModule with HasHarnessInstantiators, ports: Seq[SPIPortIO]) => { - th match { case vcu118th: VCU118FPGATestHarnessImp => { - vcu118th.vcu118Outer.io_spi_bb.bundle <> ports.head - } } +class WithSPISDCard extends HarnessBinder({ + case (th: VCU118FPGATestHarnessImp, port: SPIPort) => { + th.vcu118Outer.io_spi_bb.bundle <> port.io } }) /*** Experimental DDR ***/ -class WithDDRMem extends OverrideHarnessBinder({ - (system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => { - th match { case vcu118th: VCU118FPGATestHarnessImp => { - require(ports.size == 1) - - val bundles = vcu118th.vcu118Outer.ddrClient.out.map(_._1) - val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType))) - bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } - ddrClientBundle <> ports.head - } } +class WithDDRMem extends HarnessBinder({ + case (th: VCU118FPGATestHarnessImp, port: TLMemPort) => { + val bundles = th.vcu118Outer.ddrClient.out.map(_._1) + val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType))) + bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } + ddrClientBundle <> port.io } }) diff --git a/fpga/src/main/scala/vcu118/IOBinders.scala b/fpga/src/main/scala/vcu118/IOBinders.scala deleted file mode 100644 index 279f9865c6..0000000000 --- a/fpga/src/main/scala/vcu118/IOBinders.scala +++ /dev/null @@ -1,44 +0,0 @@ -package chipyard.fpga.vcu118 - -import chisel3._ -import chisel3.experimental.{IO, DataMirror} - -import freechips.rocketchip.diplomacy.{ResourceBinding, Resource, ResourceAddress, InModuleBody} -import freechips.rocketchip.subsystem.{BaseSubsystem} -import freechips.rocketchip.util.{HeterogeneousBag} -import freechips.rocketchip.tilelink.{TLBundle} - -import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp} -import sifive.blocks.devices.spi.{HasPeripherySPI, HasPeripherySPIModuleImp, MMCDevice} - -import chipyard.{CanHaveMasterTLMemPort} -import chipyard.iobinders.{OverrideIOBinder, OverrideLazyIOBinder} - -class WithUARTIOPassthrough extends OverrideIOBinder({ - (system: HasPeripheryUARTModuleImp) => { - val io_uart_pins_temp = system.uart.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"uart_$i") } - (io_uart_pins_temp zip system.uart).map { case (io, sysio) => - io <> sysio - } - (io_uart_pins_temp, Nil) - } -}) - -class WithSPIIOPassthrough extends OverrideLazyIOBinder({ - (system: HasPeripherySPI) => { - // attach resource to 1st SPI - ResourceBinding { - Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0)) - } - - InModuleBody { - system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripherySPIModuleImp => { - val io_spi_pins_temp = system.spi.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"spi_$i") } - (io_spi_pins_temp zip system.spi).map { case (io, sysio) => - io <> sysio - } - (io_spi_pins_temp, Nil) - } } - } - } -}) diff --git a/fpga/src/main/scala/vcu118/bringup/Configs.scala b/fpga/src/main/scala/vcu118/bringup/Configs.scala index bff715dcdc..65a23a1fba 100644 --- a/fpga/src/main/scala/vcu118/bringup/Configs.scala +++ b/fpga/src/main/scala/vcu118/bringup/Configs.scala @@ -20,6 +20,7 @@ import testchipip.{PeripheryTSIHostKey, TSIHostParams, TSIHostSerdesParams} import chipyard.{BuildSystem} import chipyard.fpga.vcu118.{WithVCU118Tweaks, WithFPGAFrequency, VCU118DDR2Size} +import chipyard.iobinders.{WithGPIOPunchthrough} class WithBringupPeripherals extends Config((site, here, up) => { case PeripheryUARTKey => up(PeripheryUARTKey, site) ++ List(UARTParams(address = BigInt(0x64003000L))) @@ -80,8 +81,7 @@ class WithBringupAdditions extends Config( new WithBringupGPIO ++ new WithBringupTSIHost ++ new WithTSITLIOPassthrough ++ - new WithI2CIOPassthrough ++ - new WithGPIOIOPassthrough ++ + new WithGPIOPunchthrough ++ new WithBringupPeripherals ++ new WithBringupVCU118System) diff --git a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala index 97d62ae20a..d60de62049 100644 --- a/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala @@ -14,56 +14,38 @@ import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp, GPIOPortIO} import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO} import chipyard.harness._ +import chipyard.iobinders._ /*** UART ***/ -class WithBringupUART extends ComposeHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[UARTPortIO]) => { - th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { - require(ports.size == 2) - - vcu118th.bringupOuter.io_fmc_uart_bb.bundle <> ports.last - } } +class WithBringupUART extends HarnessBinder({ + case (th: BringupVCU118FPGATestHarnessImp, port: UARTPort) => { + th.bringupOuter.io_fmc_uart_bb.bundle <> port.io } }) /*** I2C ***/ -class WithBringupI2C extends OverrideHarnessBinder({ - (system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[I2CPort]) => { - th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { - require(ports.size == 1) - - vcu118th.bringupOuter.io_i2c_bb.bundle <> ports.head - } } +class WithBringupI2C extends HarnessBinder({ + case (th: BringupVCU118FPGATestHarnessImp, port: chipyard.iobinders.I2CPort) => { + th.bringupOuter.io_i2c_bb.bundle <> port.io } }) /*** GPIO ***/ -class WithBringupGPIO extends OverrideHarnessBinder({ - (system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[GPIOPortIO]) => { - th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { - (vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) => - bb_io.bundle <> dut_io - } - } } +class WithBringupGPIO extends HarnessBinder({ + case (th: BringupVCU118FPGATestHarnessImp, port: GPIOPort) => { + th.bringupOuter.io_gpio_bb(port.pinId).bundle <> port.io } }) /*** TSI Host Widget ***/ -class WithBringupTSIHost extends OverrideHarnessBinder({ - (system: HasPeripheryTSIHostWidget, th: BaseModule with HasHarnessInstantiators, ports: Seq[Data]) => { - th match { case vcu118th: BringupVCU118FPGATestHarnessImp => { - require(ports.size == 2) // 1st goes to the TL mem, 2nd goes to the serial link - - ports.head match { case tlPort: HeterogeneousBag[TLBundle] => - val tsiBundles = vcu118th.bringupOuter.tsiDdrClient.out.map(_._1) - val tsiDdrClientBundle = Wire(new HeterogeneousBag(tsiBundles.map(_.cloneType))) - tsiBundles.zip(tsiDdrClientBundle).foreach { case (bundle, io) => bundle <> io } - tsiDdrClientBundle <> tlPort - } - - ports.last match { case serialPort: TSIHostWidgetIO => - vcu118th.bringupOuter.io_tsi_serial_bb.bundle <> serialPort - } - } } +class WithBringupTSIHost extends HarnessBinder({ + case (th: BringupVCU118FPGATestHarnessImp, port: TLMemPort) => { + val tsiBundles = th.bringupOuter.tsiDdrClient.out.map(_._1) + val tsiDdrClientBundle = Wire(new HeterogeneousBag(tsiBundles.map(_.cloneType))) + tsiBundles.zip(tsiDdrClientBundle).foreach { case (bundle, io) => bundle <> io } + tsiDdrClientBundle <> port.io + } + case (th: BringupVCU118FPGATestHarnessImp, port: TSIHostWidgetPort) => { + th.bringupOuter.io_tsi_serial_bb.bundle <> port.io } }) diff --git a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala index 87763cdec1..69dfbce969 100644 --- a/fpga/src/main/scala/vcu118/bringup/IOBinders.scala +++ b/fpga/src/main/scala/vcu118/bringup/IOBinders.scala @@ -11,27 +11,10 @@ import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp} import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO} -import chipyard.iobinders.{OverrideIOBinder} - -class WithGPIOIOPassthrough extends OverrideIOBinder({ - (system: HasPeripheryGPIOModuleImp) => { - val io_gpio_pins_temp = system.gpio.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"gpio_$i") } - (io_gpio_pins_temp zip system.gpio).map { case (io, sysio) => - io <> sysio - } - (io_gpio_pins_temp, Nil) - } -}) +import chipyard.iobinders.{OverrideIOBinder, Port, TLMemPort} -class WithI2CIOPassthrough extends OverrideIOBinder({ - (system: HasPeripheryI2CModuleImp) => { - val io_i2c_pins_temp = system.i2c.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"i2c_$i") } - (io_i2c_pins_temp zip system.i2c).map { case (io, sysio) => - io <> sysio - } - (io_i2c_pins_temp, Nil) - } -}) +case class TSIHostWidgetPort(val io: TSIHostWidgetIO) + extends Port[TSIHostWidgetIO] class WithTSITLIOPassthrough extends OverrideIOBinder({ (system: HasPeripheryTSIHostWidget) => { @@ -42,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(io_tsi_tl_mem_pins_temp, 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/clocking/ClockBinders.scala b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala index 412dd43df0..3ef8a61bdd 100644 --- a/generators/chipyard/src/main/scala/clocking/ClockBinders.scala +++ b/generators/chipyard/src/main/scala/clocking/ClockBinders.scala @@ -2,17 +2,13 @@ package chipyard.clocking import chisel3._ import chisel3.util._ -import chipyard.iobinders.{OverrideLazyIOBinder, GetSystemParameters, IOCellKey} +import chipyard.iobinders.{OverrideLazyIOBinder, GetSystemParameters, IOCellKey, ClockPort, ResetPort} import freechips.rocketchip.prci._ import freechips.rocketchip.diplomacy._ import freechips.rocketchip.subsystem._ import freechips.rocketchip.tilelink._ import barstools.iocell.chisel._ -class ClockWithFreq(val freqMHz: Double) extends Bundle { - val clock = Clock() -} - // This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate // the requested clocks. This also adds TileLink ClockDivider and ClockSelector // blocks, which allow memory-mapped control of clock division, and clock muxing @@ -58,13 +54,13 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({ pllCtrlSink := pllCtrl.ctrlNode InModuleBody { - val clock_wire = Wire(Input(new ClockWithFreq(100))) + val clock_wire = Wire(Input(Clock())) val reset_wire = Wire(Input(AsyncReset())) val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey)) val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey)) slowClockSource.out.unzip._1.map { o => - o.clock := clock_wire.clock + o.clock := clock_wire o.reset := reset_wire } @@ -79,7 +75,7 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({ o.reset := reset_wire } - (Seq(clock_io, reset_io), clockIOCell ++ resetIOCell) + (Seq(ClockPort(clock_io, 100), ResetPort(reset_io)), clockIOCell ++ resetIOCell) } } }) @@ -114,12 +110,12 @@ class WithPassthroughClockGenerator extends OverrideLazyIOBinder({ require(m.take.isDefined, s"""Clock ${m.name.get} has no requested frequency |Clocks: ${edge.sink.members.map(_.name.get)}""".stripMargin) val freq = m.take.get.freqMHz - val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}") - b.clock := clock_io.clock + val clock_io = IO(Input(Clock())).suggestName(s"clock_${m.name.get}") + b.clock := clock_io b.reset := reset_io - clock_io + ClockPort(clock_io, freq) }.toSeq - ((clock_ios :+ reset_io), Nil) + ((clock_ios :+ ResetPort(reset_io)), Nil) } } }) diff --git a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala index e52ec674d6..42c45db6e7 100644 --- a/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala +++ b/generators/chipyard/src/main/scala/clocking/DividerOnlyClockGenerator.scala @@ -51,7 +51,7 @@ object FrequencyUtils { require(!requestedOutputs.contains(0.0)) val requestedFreqs = requestedOutputs.map(_.freqMHz) val fastestFreq = requestedFreqs.max - require(fastestFreq <= maximumAllowableFreqMHz) + require(fastestFreq <= maximumAllowableFreqMHz, s"Fastest Freq $fastestFreq > Max Freq $maximumAllowableFreqMHz") val candidateFreqs = Seq.tabulate(Math.ceil(maximumAllowableFreqMHz / fastestFreq).toInt)(i => (i + 1) * fastestFreq) diff --git a/generators/chipyard/src/main/scala/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala index 44235cbd4c..a08abb6d63 100644 --- a/generators/chipyard/src/main/scala/config/AbstractConfig.scala +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -15,7 +15,8 @@ class AbstractConfig extends Config( new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled new chipyard.harness.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM - new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled + new chipyard.harness.WithSimJTAGDebug ++ // add SimJTAG if JTAG for debug exposed + new chipyard.harness.WithSimDMI ++ // add SimJTAG if DMI exposed new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled @@ -23,7 +24,8 @@ class AbstractConfig extends Config( new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present new chipyard.harness.WithCustomBootPinPlusArg ++ // drive custom-boot pin with a plusarg, if custom-boot-pin is present new chipyard.harness.WithSimUARTToUARTTSI ++ // connect a SimUART to the UART-TSI port - new chipyard.harness.WithClockAndResetFromHarness ++ // all Clock/Reset I/O in ChipTop should be driven by harnessClockInstantiator + new chipyard.harness.WithClockFromHarness ++ // all Clock I/O in ChipTop should be driven by harnessClockInstantiator + new chipyard.harness.WithResetFromHarness ++ // reset controlled by harness new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // generate clocks in harness with unsynthesizable ClockSourceAtFreqMHz // The IOBinders instantiate ChipTop IOs to match desired digital IOs @@ -32,11 +34,13 @@ class AbstractConfig extends Config( new chipyard.iobinders.WithDebugIOCells ++ new chipyard.iobinders.WithUARTIOCells ++ new chipyard.iobinders.WithGPIOCells ++ - new chipyard.iobinders.WithSPIIOCells ++ + new chipyard.iobinders.WithSPIFlashIOCells ++ new chipyard.iobinders.WithExtInterruptIOCells ++ new chipyard.iobinders.WithCustomBootPin ++ // The "punchthrough" IOBInders below don't generate IOCells, as these interfaces shouldn't really be mapped to ASIC IO // Instead, they directly pass through the DigitalTop ports to ports in the ChipTop + new chipyard.iobinders.WithI2CPunchthrough ++ + new chipyard.iobinders.WithSPIIOPunchthrough ++ new chipyard.iobinders.WithAXI4MemPunchthrough ++ new chipyard.iobinders.WithAXI4MMIOPunchthrough ++ new chipyard.iobinders.WithTLMemPunchthrough ++ diff --git a/generators/chipyard/src/main/scala/config/TracegenConfigs.scala b/generators/chipyard/src/main/scala/config/TracegenConfigs.scala index ab00ad24cc..55cce1b818 100644 --- a/generators/chipyard/src/main/scala/config/TracegenConfigs.scala +++ b/generators/chipyard/src/main/scala/config/TracegenConfigs.scala @@ -7,7 +7,8 @@ class AbstractTraceGenConfig extends Config( new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ new chipyard.harness.WithBlackBoxSimMem ++ new chipyard.harness.WithTraceGenSuccess ++ - new chipyard.harness.WithClockAndResetFromHarness ++ + new chipyard.harness.WithClockFromHarness ++ + new chipyard.harness.WithResetFromHarness ++ new chipyard.iobinders.WithAXI4MemPunchthrough ++ new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++ new chipyard.clocking.WithPassthroughClockGenerator ++ diff --git a/generators/chipyard/src/main/scala/example/FlatChipTop.scala b/generators/chipyard/src/main/scala/example/FlatChipTop.scala index 96e2161119..a1a1aeaa2a 100644 --- a/generators/chipyard/src/main/scala/example/FlatChipTop.scala +++ b/generators/chipyard/src/main/scala/example/FlatChipTop.scala @@ -68,13 +68,13 @@ class FlatChipTop(implicit p: Parameters) extends LazyModule { l.reset := implicit_reset }} - val clock_wire = Wire(Input(new ClockWithFreq(80))) + val clock_wire = Wire(Input(Clock())) val reset_wire = Wire(Input(AsyncReset())) val (clock_pad, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey)) val (reset_pad, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey)) slowClockSource.out.unzip._1.map { o => - o.clock := clock_wire.clock + o.clock := clock_wire o.reset := reset_wire } diff --git a/generators/chipyard/src/main/scala/example/FlatTestHarness.scala b/generators/chipyard/src/main/scala/example/FlatTestHarness.scala index 56bc9a7834..5b3168b3de 100644 --- a/generators/chipyard/src/main/scala/example/FlatTestHarness.scala +++ b/generators/chipyard/src/main/scala/example/FlatTestHarness.scala @@ -30,7 +30,7 @@ class FlatTestHarness(implicit val p: Parameters) extends Module { val clock_source = Module(new ClockSourceAtFreqFromPlusArg("slow_clk_freq_mhz")) clock_source.io.power := true.B clock_source.io.gate := false.B - dut.clock_pad.clock := clock_source.io.clk + dut.clock_pad := clock_source.io.clk // Reset dut.reset_pad := reset.asAsyncReset diff --git a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala index b670fd7404..b6409a635b 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala @@ -6,355 +6,284 @@ import chisel3.experimental.{Analog, BaseModule, DataMirror, Direction} import org.chipsalliance.cde.config.{Field, Config, Parameters} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} -import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} -import freechips.rocketchip.devices.debug._ -import freechips.rocketchip.jtag.{JTAGIO} import freechips.rocketchip.system.{SimAXIMem} import freechips.rocketchip.subsystem._ import freechips.rocketchip.util._ - -import sifive.blocks.devices.gpio._ -import sifive.blocks.devices.uart._ -import sifive.blocks.devices.spi._ - +import freechips.rocketchip.jtag.{JTAGIO} +import freechips.rocketchip.devices.debug.{SimJTAG} import barstools.iocell.chisel._ - import testchipip._ - +import icenet.{NicLoopback, SimNetwork} import chipyard._ -import chipyard.clocking.{HasChipyardPRCI, ClockWithFreq} -import chipyard.iobinders.{GetSystemParameters, JTAGChipIO} - -import tracegen.{TraceGenSystemModuleImp} -import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} - -import scala.reflect.{ClassTag} +import chipyard.clocking.{HasChipyardPRCI} +import chipyard.iobinders._ -case object HarnessBinders extends Field[HarnessBinderMap](HarnessBinderMapDefault) +case object HarnessBinders extends Field[HarnessBinderFunction]({case _ => }) object ApplyHarnessBinders { - def apply(th: HasHarnessInstantiators, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters): Unit = { - val pm = portMap.withDefaultValue(Nil) - p(HarnessBinders).foreach { case (s, f) => - f(sys, th, pm(s)) - f(sys.module, th, pm(s)) - } + def apply(th: HasHarnessInstantiators, ports: Seq[Port[_]])(implicit p: Parameters): Unit = { + ports.foreach(port => p(HarnessBinders)(th, port)) } } -// The ClassTags here are necessary to overcome issues arising from type erasure -class HarnessBinder[T, S <: HasHarnessInstantiators, 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: HasHarnessInstantiators, ports: Seq[Data]) => { - val pts = ports.collect({case p: U => p}) - require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}") - val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString) - (th, t) match { - case (th: S, system: T) => composer(upfn)(system, th, pts) - case _ => - } - }) - ) +class HarnessBinder[T <: HasHarnessInstantiators, S <: Port[_]]( + fn: => HarnessBinderFunction +) extends Config((site, here, up) => { + case HarnessBinders => fn orElse up(HarnessBinders) }) -class OverrideHarnessBinder[T, S <: HasHarnessInstantiators, 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]) => Unit) => fn) - -class ComposeHarnessBinder[T, S <: HasHarnessInstantiators, 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]) => Unit) => (t, th, p) => { - upfn(t, th, p) - fn(t, th, p) - }) - -class WithGPIOTiedOff extends OverrideHarnessBinder({ - (system: HasPeripheryGPIOModuleImp, th: HasHarnessInstantiators, ports: Seq[Analog]) => { - ports.foreach { _ <> AnalogConst(0) } +class WithGPIOTiedOff extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: GPIOPort) => { + port.io <> AnalogConst(0) } }) // DOC include start: WithUARTAdapter -class WithUARTAdapter extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: HasHarnessInstantiators, ports: Seq[UARTPortIO]) => { - UARTAdapter.connect(ports)(system.p) +class WithUARTAdapter extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: UARTPort) => { + val div = (th.getHarnessBinderClockFreqMHz / port.io.c.initBaudRate.toDouble).toInt + val uart_sim = Module(new UARTAdapter(port.uartNo, div, false)).suggestName(s"uart_sim_uartno${port.uartNo}") + uart_sim.io.uart.txd := port.io.txd + port.io.rxd := uart_sim.io.uart.rxd } }) // DOC include end: WithUARTAdapter -class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({ - (system: HasPeripherySPIFlashModuleImp, th: HasHarnessInstantiators, ports: Seq[SPIChipIO]) => { - SimSPIFlashModel.connect(ports, th.harnessBinderReset, rdOnly)(system.p) +class WithSimSPIFlashModel(rdOnly: Boolean = true) extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: SPIFlashPort) => { + val spi_mem = Module(new SimSPIFlashModel(port.params.fSize, port.spiId, rdOnly)).suggestName(s"spi_mem${port.spiId}") + spi_mem.io.sck := port.io.sck + require(port.params.csWidth == 1, "I don't know what to do with your extra CS bits. Fix me please.") + spi_mem.io.cs(0) := port.io.cs(0) + spi_mem.io.dq.zip(port.io.dq).foreach { case (x, y) => x <> y } + spi_mem.io.reset := th.harnessBinderReset } }) -class WithSimBlockDevice extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: HasHarnessInstantiators, ports: Seq[ClockedIO[BlockDeviceIO]]) => { - implicit val p: Parameters = GetSystemParameters(system) - ports.map { b => SimBlockDevice.connect(b.clock, th.harnessBinderReset.asBool, Some(b.bits)) } +class WithSimBlockDevice extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: BlockDevicePort) => { + val sim_blkdev = Module(new SimBlockDevice(port.params)) + sim_blkdev.io.bdev <> port.io.bits + sim_blkdev.io.clock := port.io.clock + sim_blkdev.io.reset := th.harnessBinderReset } }) -class WithBlockDeviceModel extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: HasHarnessInstantiators, ports: Seq[ClockedIO[BlockDeviceIO]]) => { - implicit val p: Parameters = GetSystemParameters(system) - ports.map { b => BlockDeviceModel.connect(Some(b.bits)) } +class WithBlockDeviceModel extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: BlockDevicePort) => { + val blkdev_model = Module(new BlockDeviceModel(16, port.params)) + blkdev_model.io <> port.io.bits + blkdev_model.clock := port.io.clock + blkdev_model.reset := th.harnessBinderReset } }) -class WithLoopbackNIC extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: HasHarnessInstantiators, ports: Seq[ClockedIO[NICIOvonly]]) => { - implicit val p: Parameters = GetSystemParameters(system) - ports.map { n => NicLoopback.connect(Some(n.bits), p(NICKey)) } +class WithLoopbackNIC extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: NICPort) => { + withClock(port.io.clock) { NicLoopback.connect(port.io.bits, port.params) } } }) -class WithSimNetwork extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessInstantiators, ports: Seq[ClockedIO[NICIOvonly]]) => { - implicit val p: Parameters = GetSystemParameters(system) - ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessBinderReset.asBool) } +class WithSimNetwork extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: NICPort) => { + withClock(port.io.clock) { SimNetwork.connect(Some(port.io.bits), port.io.clock, th.harnessBinderReset.asBool) } } }) -class WithSimAXIMem extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[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)) - Module(mem.module).suggestName("mem") - mem.io_axi4.head <> port.bits - } +class WithSimAXIMem extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: AXI4MemPort) => { + val mem = LazyModule(new SimAXIMem(port.edge, size=port.params.master.size)(Parameters.empty)) + withClock(port.io.clock) { Module(mem.module) } + mem.io_axi4.head <> port.io } }) -class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => { - val p: Parameters = chipyard.iobinders.GetSystemParameters(system) - (ports zip system.memAXI4Node.edges.in).map { case (port, edge) => - // TODO FIX: This currently makes each SimDRAM contain the entire memory space - val memSize = p(ExtMem).get.master.size - val memBase = p(ExtMem).get.master.base - val lineSize = p(CacheBlockBytes) - val clockFreq = p(MemoryBusKey).dtsFrequency.get - val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, memBase, edge.bundle)).suggestName("simdram") - mem.io.axi <> port.bits - // Bug in Chisel implementation. See https://github.com/chipsalliance/chisel3/pull/1781 - def Decoupled[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { - require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.") - val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits))) - d.bits := irr.bits - d.valid := irr.valid - irr.ready := d.ready - d - } - if (additionalLatency > 0) { - withClockAndReset (port.clock, port.reset) { - mem.io.axi.aw <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.aw))((t, _) => Queue(t, 1, pipe=true)) - mem.io.axi.w <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.w ))((t, _) => Queue(t, 1, pipe=true)) - port.bits.b <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.b))((t, _) => Queue(t, 1, pipe=true)) - mem.io.axi.ar <> (0 until additionalLatency).foldLeft(Decoupled(port.bits.ar))((t, _) => Queue(t, 1, pipe=true)) - port.bits.r <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.r))((t, _) => Queue(t, 1, pipe=true)) - } +class WithBlackBoxSimMem(additionalLatency: Int = 0) extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: AXI4MemPort) => { + // TODO FIX: This currently makes each SimDRAM contain the entire memory space + val memSize = port.params.master.size + val memBase = port.params.master.base + val lineSize = 64 // cache block size + val clockFreq = port.clockFreqMHz + val mem = Module(new SimDRAM(memSize, lineSize, clockFreq, memBase, port.edge.bundle)).suggestName("simdram") + + mem.io.clock := port.io.clock + mem.io.reset := th.harnessBinderReset.asAsyncReset + mem.io.axi <> port.io.bits + // Bug in Chisel implementation. See https://github.com/chipsalliance/chisel3/pull/1781 + def Decoupled[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { + require(DataMirror.directionOf(irr.bits) == Direction.Output, "Only safe to cast produced Irrevocable bits to Decoupled.") + val d = Wire(new DecoupledIO(chiselTypeOf(irr.bits))) + d.bits := irr.bits + d.valid := irr.valid + irr.ready := d.ready + d + } + if (additionalLatency > 0) { + withClock (port.io.clock) { + mem.io.axi.aw <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.aw))((t, _) => Queue(t, 1, pipe=true)) + mem.io.axi.w <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.w ))((t, _) => Queue(t, 1, pipe=true)) + port.io.bits.b <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.b ))((t, _) => Queue(t, 1, pipe=true)) + mem.io.axi.ar <> (0 until additionalLatency).foldLeft(Decoupled(port.io.bits.ar))((t, _) => Queue(t, 1, pipe=true)) + port.io.bits.r <> (0 until additionalLatency).foldLeft(Decoupled(mem.io.axi.r ))((t, _) => Queue(t, 1, pipe=true)) } - mem.io.clock := port.clock - mem.io.reset := port.reset } } }) -class WithSimAXIMMIO extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MMIOPort, th: HasHarnessInstantiators, ports: Seq[ClockedAndResetIO[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)) - withClockAndReset(port.clock, port.reset) { - Module(mmio_mem.module).suggestName("mmio_mem") - } - mmio_mem.io_axi4.head <> port.bits - } +class WithSimAXIMMIO extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: AXI4MMIOPort) => { + val mmio_mem = LazyModule(new SimAXIMem(port.edge, size = port.params.size)(Parameters.empty)) + withClock(port.io.clock) { Module(mmio_mem.module) } + mmio_mem.io_axi4.head <> port.io.bits } }) -class WithTieOffInterrupts extends OverrideHarnessBinder({ - (system: HasExtInterruptsModuleImp, th: HasHarnessInstantiators, ports: Seq[UInt]) => { - ports.foreach { _ := 0.U } +class WithTieOffInterrupts extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: ExtIntPort) => { + port.io := 0.U } }) -class WithTieOffL2FBusAXI extends OverrideHarnessBinder({ - (system: CanHaveSlaveAXI4Port, th: HasHarnessInstantiators, ports: Seq[ClockedIO[AXI4Bundle]]) => { - ports.foreach({ p => - p.bits := DontCare - p.bits.aw.valid := false.B - p.bits.w.valid := false.B - p.bits.b.ready := false.B - p.bits.ar.valid := false.B - p.bits.r.ready := false.B - }) +class WithTieOffL2FBusAXI extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: AXI4InPort) => { + port.io := DontCare + port.io.bits.aw.valid := false.B + port.io.bits.w.valid := false.B + port.io.bits.b.ready := false.B + port.io.bits.ar.valid := false.B + port.io.bits.r.ready := false.B } }) -class WithSimDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebug, th: HasHarnessInstantiators, 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 TestchipSimDTM).connect(th.harnessBinderClock, th.harnessBinderReset.asBool, d, dtm_success) - case j: JTAGChipIO => - val dtm_success = WireInit(false.B) - when (dtm_success) { th.success := true.B } - val jtag_wire = Wire(new JTAGIO) - jtag_wire.TDO.data := j.TDO - jtag_wire.TDO.driven := true.B - j.TCK := jtag_wire.TCK - j.TMS := jtag_wire.TMS - j.TDI := jtag_wire.TDI - val jtag = Module(new SimJTAG(tickDelay=3)) - jtag.connect(jtag_wire, th.harnessBinderClock, th.harnessBinderReset.asBool, ~(th.harnessBinderReset.asBool), dtm_success) - } +class WithSimJTAGDebug extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: JTAGPort) => { + val dtm_success = WireInit(false.B) + when (dtm_success) { th.success := true.B } + val jtag_wire = Wire(new JTAGIO) + jtag_wire.TDO.data := port.io.TDO + jtag_wire.TDO.driven := true.B + port.io.TCK := jtag_wire.TCK + port.io.TMS := jtag_wire.TMS + port.io.TDI := jtag_wire.TDI + val jtag = Module(new SimJTAG(tickDelay=3)) + jtag.connect(jtag_wire, th.harnessBinderClock, th.harnessBinderReset.asBool, ~(th.harnessBinderReset.asBool), dtm_success) } }) -class WithTiedOffDebug extends OverrideHarnessBinder({ - (system: HasPeripheryDebug, th: HasHarnessInstantiators, ports: Seq[Data]) => { - ports.map { - case j: JTAGChipIO => - j.TCK := true.B.asClock - j.TMS := true.B - j.TDI := true.B - case d: ClockedDMIIO => - d.dmi.req.valid := false.B - d.dmi.req.bits := DontCare - d.dmi.resp.ready := true.B - d.dmiClock := false.B.asClock - d.dmiReset := true.B - case a: ClockedAPBBundle => - a.pready := false.B - a.pslverr := false.B - a.prdata := 0.U - a.pduser := DontCare - a.clock := false.B.asClock - a.reset := true.B.asAsyncReset - a.psel := false.B - a.penable := false.B - } +class WithSimDMI extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: DMIPort) => { + val dtm_success = WireInit(false.B) + when (dtm_success) { th.success := true.B } + val dtm = Module(new TestchipSimDTM()(Parameters.empty)).connect(th.harnessBinderClock, th.harnessBinderReset.asBool, port.io, dtm_success) } }) +class WithTiedOffJTAG extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: JTAGPort) => { + port.io.TCK := true.B.asClock + port.io.TMS := true.B + port.io.TDI := true.B + } +}) -class WithSerialTLTiedOff extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => { - implicit val p = chipyard.iobinders.GetSystemParameters(system) - ports.map({ port => - val bits = port.bits - if (DataMirror.directionOf(port.clock) == Direction.Input) { - port.clock := false.B.asClock - } - port.bits.out.ready := false.B - port.bits.in.valid := false.B - port.bits.in.bits := DontCare - }) +class WithTiedOffDMI extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: DMIPort) => { + port.io.dmi.req.valid := false.B + port.io.dmi.req.bits := DontCare + port.io.dmi.resp.ready := true.B + port.io.dmiClock := false.B.asClock + port.io.dmiReset := true.B } }) -class WithSimTSIOverSerialTL extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: HasHarnessInstantiators, ports: Seq[ClockedIO[SerialIO]]) => { - implicit val p = chipyard.iobinders.GetSystemParameters(system) - ports.map({ port => - val bits = port.bits - if (DataMirror.directionOf(port.clock) == Direction.Input) { - port.clock := th.harnessBinderClock - } - val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset) - val success = SimTSI.connect(Some(ram.module.io.tsi), th.harnessBinderClock, th.harnessBinderReset.asBool) - when (success) { th.success := true.B } - }) +class WithSerialTLTiedOff extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: SerialTLPort) => { + if (DataMirror.directionOf(port.io.clock) == Direction.Input) { + port.io.clock := false.B.asClock + } + port.io.bits.out.ready := false.B + port.io.bits.in.valid := false.B + port.io.bits.in.bits := DontCare } }) -class WithSimUARTToUARTTSI extends OverrideHarnessBinder({ - (system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => { - implicit val p = chipyard.iobinders.GetSystemParameters(system) - require(ports.size <= 1) - ports.map { port => { - UARTAdapter.connect(Seq(port.uart), - baudrate=port.uartParams.initBaudRate, - clockFrequency=th.getHarnessBinderClockFreqHz.toInt, - forcePty=true) - assert(!port.dropped) - }} +class WithSimTSIOverSerialTL extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: SerialTLPort) => { + val bits = port.io.bits + if (DataMirror.directionOf(port.io.clock) == Direction.Input) { + port.io.clock := th.harnessBinderClock + } + val ram = LazyModule(new SerialRAM(port.serdesser)(port.serdesser.p)) + Module(ram.module) + ram.module.io.ser <> port.io.bits + val tsi = Module(new SimTSI) + tsi.io.clock := th.harnessBinderClock + tsi.io.reset := th.harnessBinderReset + tsi.io.tsi <> ram.module.io.tsi + val exit = tsi.io.exit + val success = exit === 1.U + val error = exit >= 2.U + assert(!error, "*** FAILED *** (exit code = %d)\n", exit >> 1.U) + when (success) { th.success := true.B } } }) -class WithSimTSIToUARTTSI extends OverrideHarnessBinder({ - (system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => { - implicit val p = chipyard.iobinders.GetSystemParameters(system) - require(ports.size <= 1) - ports.map({ port => - val freq = th.getHarnessBinderClockFreqHz.toInt - val uart_to_serial = Module(new UARTToSerial(freq, port.uartParams)) - val serial_width_adapter = Module(new SerialWidthAdapter(8, TSI.WIDTH)) - val success = SimTSI.connect(Some(TSIIO(serial_width_adapter.io.wide)), th.harnessBinderClock, th.harnessBinderReset) - when (success) { th.success := true.B } - assert(!uart_to_serial.io.dropped) - serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial) - uart_to_serial.io.uart.rxd := port.uart.txd - port.uart.rxd := uart_to_serial.io.uart.txd - }) +class WithSimUARTToUARTTSI extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: UARTPort) => { + UARTAdapter.connect(Seq(port.io), + baudrate=port.io.c.initBaudRate, + clockFrequency=th.getHarnessBinderClockFreqHz.toInt, + forcePty=true) } }) +class WithSimTSIToUARTTSI extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: UARTTSIPort) => { + val freq = th.getHarnessBinderClockFreqHz.toInt + val uart_to_serial = Module(new UARTToSerial(freq, port.io.uart.c)) + val serial_width_adapter = Module(new SerialWidthAdapter(8, TSI.WIDTH)) + val success = SimTSI.connect(Some(TSIIO(serial_width_adapter.io.wide)), th.harnessBinderClock, th.harnessBinderReset) + when (success) { th.success := true.B } + assert(!uart_to_serial.io.dropped) + serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial) + uart_to_serial.io.uart.rxd := port.io.uart.txd + port.io.uart.rxd := uart_to_serial.io.uart.txd + } +}) -class WithTraceGenSuccess extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: HasHarnessInstantiators, ports: Seq[Bool]) => { - ports.map { p => when (p) { th.success := true.B } } +class WithTraceGenSuccess extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: SuccessPort) => { + when (port.io) { th.success := true.B } } }) -class WithCospike extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: HasHarnessInstantiators, ports: Seq[TraceOutputTop]) => { - implicit val p = chipyard.iobinders.GetSystemParameters(system) - val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem] - val tiles = chipyardSystem.tiles - val cfg = SpikeCosimConfig( - isa = tiles.headOption.map(_.isaDTS).getOrElse(""), - vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0), - priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""), - mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)), - mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)), - pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0), - nharts = tiles.size, - 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 - ) - ports.map { p => p.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, cfg)) } +class WithCospike extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: TracePort) => { + port.io.traces.zipWithIndex.map(t => SpikeCosim(t._1, t._2, port.cosimCfg)) } }) -class WithCustomBootPinPlusArg extends OverrideHarnessBinder({ - (system: CanHavePeripheryCustomBootPin, th: HasHarnessInstantiators, ports: Seq[Bool]) => { +class WithCustomBootPinPlusArg extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: CustomBootPort) => { val pin = PlusArg("custom_boot_pin", width=1) - ports.foreach(_ := pin) + port.io := pin } }) - -class WithClockAndResetFromHarness extends OverrideHarnessBinder({ - (system: HasChipyardPRCI, th: HasHarnessInstantiators, ports: Seq[Data]) => { - implicit val p = GetSystemParameters(system) - val clocks = ports.collect { case c: ClockWithFreq => c } +class WithClockFromHarness extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: ClockPort) => { // DOC include start: HarnessClockInstantiatorEx - ports.map ({ - case c: ClockWithFreq => { - val clock = th.harnessClockInstantiator.requestClockMHz(s"clock_${c.freqMHz.toInt}MHz", c.freqMHz) - c.clock := clock - } - case r: AsyncReset => r := th.referenceReset.asAsyncReset - }) + port.io := th.harnessClockInstantiator.requestClockMHz(s"clock_${port.freqMHz}MHz", port.freqMHz) // DOC include end: HarnessClockInstantiatorEx } }) + +class WithResetFromHarness extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: ResetPort) => { + port.io := th.referenceReset.asAsyncReset + } +}) + diff --git a/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala b/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala index e79b6c4e93..9b607c1cf9 100644 --- a/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala +++ b/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala @@ -83,7 +83,7 @@ trait HasHarnessInstantiators { withClockAndReset (harnessBinderClock, harnessBinderReset) { lazyDuts.zipWithIndex.foreach { - case (d: HasIOBinders, i: Int) => ApplyHarnessBinders(this, d.lazySystem, d.portMap)(chipParameters(i)) + case (d: HasIOBinders, i: Int) => ApplyHarnessBinders(this, d.portMap.values.flatten.toSeq)(chipParameters(i)) case _ => } ApplyMultiHarnessBinders(this, lazyDuts) diff --git a/generators/chipyard/src/main/scala/harness/MultiHarnessBinders.scala b/generators/chipyard/src/main/scala/harness/MultiHarnessBinders.scala index 1c057dff81..399e64be61 100644 --- a/generators/chipyard/src/main/scala/harness/MultiHarnessBinders.scala +++ b/generators/chipyard/src/main/scala/harness/MultiHarnessBinders.scala @@ -2,6 +2,7 @@ package chipyard.harness import chisel3._ import chisel3.util._ +import chisel3.experimental.{DataMirror, Direction} import org.chipsalliance.cde.config.{Field, Config, Parameters} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} @@ -12,67 +13,58 @@ import freechips.rocketchip.util._ import testchipip._ import chipyard._ -import chipyard.clocking.{HasChipyardPRCI, ClockWithFreq} -import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasIOBinders} +import chipyard.iobinders.{GetSystemParameters, JTAGChipIO, HasIOBinders, Port, SerialTLPort} import scala.reflect.{ClassTag} -case class MultiHarnessBinders(c0: Int, c1: Int) extends Field[MultiHarnessBinderMap](MultiHarnessBinderMapDefault) - -class MultiHarnessBinder[T0, T1, S <: HasHarnessInstantiators, U0 <: Data, U1 <: Data] - (chip0: Int, chip1: Int, fn: => (T0, T1, S, Seq[U0], Seq[U1]) => Unit) - (implicit tag0: ClassTag[T0], tag1: ClassTag[T1], thtag: ClassTag[S], ptag0: ClassTag[U0], ptag1: ClassTag[U1]) - extends Config((site, here, up) => { - // Override any HarnessBinders for chip0/chip1 - case MultiChipParameters(`chip0`) => new Config( - new OverrideHarnessBinder[T0, S, U0]((system: T0, th: S, ports: Seq[U0]) => Nil) ++ - up(MultiChipParameters(chip0)) - ) - case MultiChipParameters(`chip1`) => new Config( - new OverrideHarnessBinder[T1, S, U1]((system: T1, th: S, ports: Seq[U1]) => Nil) ++ - up(MultiChipParameters(chip1)) - ) - // Set the multiharnessbinder key - case MultiHarnessBinders(`chip0`, `chip1`) => up(MultiHarnessBinders(chip0, chip1)) + - ((tag0.runtimeClass.toString, tag1.runtimeClass.toString) -> - ((c0: Any, c1: Any, th: HasHarnessInstantiators, ports0: Seq[Data], ports1: Seq[Data]) => { - val pts0 = ports0.map(_.asInstanceOf[U0]) - val pts1 = ports1.map(_.asInstanceOf[U1]) - require(pts0.size == pts1.size) - (c0, c1, th) match { - case (c0: T0, c1: T1, th: S) => fn(c0, c1, th, pts0, pts1) - case _ => - } - }) - ) - }) +case class MultiHarnessBinders(chip0: Int, chip1: Int) extends Field[Seq[MultiHarnessBinderFunction]](Nil) 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 { - case ((s0, s1), f) => { - f(l0.lazySystem , l1.lazySystem , th, l0.portMap(s0), l1.portMap(s1)) - f(l0.lazySystem.module, l1.lazySystem.module, th, l0.portMap(s0), l1.portMap(s1)) - } + case (l0: HasIOBinders, l1: HasIOBinders) => p(MultiHarnessBinders(i, j)).foreach { f => + f(l0.portMap.values.flatten.toSeq, l1.portMap.values.flatten.toSeq) } - case _ => } }} } } -class WithMultiChipSerialTL(chip0: Int, chip1: Int) extends MultiHarnessBinder(chip0, chip1, ( - (system0: CanHavePeripheryTLSerial, system1: CanHavePeripheryTLSerial, - th: HasHarnessInstantiators, - ports0: Seq[ClockedIO[SerialIO]], ports1: Seq[ClockedIO[SerialIO]] - ) => { - require(ports0.size == ports1.size) - (ports0 zip ports1).map { case (l, r) => - l.clock <> r.clock - require(l.bits.w == r.bits.w) - l.bits.flipConnect(r.bits) +class MultiHarnessBinder[T <: Port[_]]( + chip0: Int, chip1: Int, + chip0portFn: T => Boolean, chip1portFn: T => Boolean, + connectFn: (T, T) => Unit +)(implicit tag: ClassTag[T]) extends Config((site, here, up) => { + // Override any HarnessBinders for chip0/chip1 + case MultiChipParameters(`chip0`) => new Config( + new HarnessBinder({case (th, port: T) if chip0portFn(port) => }) ++ up(MultiChipParameters(chip0)) + ) + case MultiChipParameters(`chip1`) => new Config( + new HarnessBinder({case (th, port: T) if chip1portFn(port) => }) ++ up(MultiChipParameters(chip1)) + ) + // Set the multiharnessbinder key + case MultiHarnessBinders(`chip0`, `chip1`) => up(MultiHarnessBinders(chip0, chip1)) :+ { + ((chip0Ports: Seq[Port[_]], chip1Ports: Seq[Port[_]]) => { + val chip0Port: Seq[T] = chip0Ports.collect { case (p: T) if chip0portFn(p) => p } + val chip1Port: Seq[T] = chip1Ports.collect { case (p: T) if chip1portFn(p) => p } + require(chip0Port.size == 1 && chip1Port.size == 1) + connectFn(chip0Port(0), chip1Port(0)) + }) + } + }) + + +class WithMultiChipSerialTL(chip0: Int, chip1: Int, chip0portId: Int = 0, chip1portId: Int = 0) extends MultiHarnessBinder[SerialTLPort]( + chip0, chip1, + (p0: SerialTLPort) => p0.portId == chip0portId, + (p1: SerialTLPort) => p1.portId == chip1portId, + (p0: SerialTLPort, p1: SerialTLPort) => { + (DataMirror.directionOf(p0.io.clock), DataMirror.directionOf(p1.io.clock)) match { + case (Direction.Input, Direction.Output) => p0.io.clock := p1.io.clock + case (Direction.Output, Direction.Input) => p1.io.clock := p0.io.clock } + p0.io.bits.in <> p1.io.bits.out + p1.io.bits.in <> p0.io.bits.out } -)) +) diff --git a/generators/chipyard/src/main/scala/harness/package.scala b/generators/chipyard/src/main/scala/harness/package.scala index 789d1595fe..258655a7cc 100644 --- a/generators/chipyard/src/main/scala/harness/package.scala +++ b/generators/chipyard/src/main/scala/harness/package.scala @@ -5,13 +5,7 @@ import scala.collection.immutable.ListMap package object harness { - type HarnessBinderFunction = (Any, HasHarnessInstantiators, Seq[Data]) => Unit - type HarnessBinderMap = Map[String, HarnessBinderFunction] - def HarnessBinderMapDefault: HarnessBinderMap = (new ListMap[String, HarnessBinderFunction]) - .withDefaultValue((t: Any, th: HasHarnessInstantiators, d: Seq[Data]) => ()) - - type MultiHarnessBinderFunction = (Any, Any, HasHarnessInstantiators, Seq[Data], Seq[Data]) => Unit - type MultiHarnessBinderMap = Map[(String, String), MultiHarnessBinderFunction] - def MultiHarnessBinderMapDefault: MultiHarnessBinderMap = (new ListMap[(String, String), MultiHarnessBinderFunction]) - .withDefaultValue((_: Any, _: Any, _: HasHarnessInstantiators, _: Seq[Data], _: Seq[Data]) => ()) + import chipyard.iobinders.Port + type HarnessBinderFunction = PartialFunction[(HasHarnessInstantiators, Port[_]), Unit] + type MultiHarnessBinderFunction = (Seq[Port[_]], Seq[Port[_]]) => Unit } diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala similarity index 70% rename from generators/chipyard/src/main/scala/IOBinders.scala rename to generators/chipyard/src/main/scala/iobinders/IOBinders.scala index b74d8f0e34..2ce7c6f4bb 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala @@ -18,18 +18,19 @@ import freechips.rocketchip.tilelink.{TLBundle} import sifive.blocks.devices.gpio._ import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ +import sifive.blocks.devices.i2c._ import tracegen.{TraceGenSystemModuleImp} import barstools.iocell.chisel._ import testchipip._ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly} -import chipyard.{CanHaveMasterTLMemPort} +import chipyard.{CanHaveMasterTLMemPort, ChipyardSystem, ChipyardSystemModule} import scala.reflect.{ClassTag} object IOBinderTypes { - type IOBinderTuple = (Seq[Data], Seq[IOCell]) + type IOBinderTuple = (Seq[Port[_]], Seq[IOCell]) type IOBinderFunction = (Boolean, => Any) => ModuleValue[IOBinderTuple] } import IOBinderTypes._ @@ -82,7 +83,7 @@ abstract trait HasIOBinders { this: LazyModule => InModuleBody { if (p(DontTouchIOBindersPorts)) { - portMap.values.foreach(_.foreach(dontTouch(_))) + portMap.values.flatten.foreach { case (port: Port[Data]) => dontTouch(port.io) } } println("IOCells generated by IOBinders:") @@ -171,29 +172,72 @@ class WithGPIOCells extends OverrideIOBinder({ iocell.io.ie := pin.o.ie pin.i.ival := iocell.io.i iocell.io.pad <> g - (g, iocell) + (GPIOPort(g, i, j), iocell) }).unzip }).unzip - val ports: Seq[Analog] = ports2d.flatten - (ports, cells2d.flatten) + (ports2d.flatten, cells2d.flatten) + } +}) + +class WithGPIOPunchthrough extends OverrideIOBinder({ + (system: HasPeripheryGPIOModuleImp) => { + 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) + } + (ports, Nil) + } +}) + +class WithI2CPunchthrough extends OverrideIOBinder({ + (system: HasPeripheryI2CModuleImp) => { + val ports = system.i2c.zipWithIndex.map { case (i2c, i) => + val io_i2c = IO(i2c.cloneType).suggestName(s"i2c_$i") + io_i2c <> i2c + I2CPort(i2c) + } + (ports, Nil) } }) // DOC include start: WithUARTIOCells class WithUARTIOCells extends OverrideIOBinder({ (system: HasPeripheryUARTModuleImp) => { - val (ports: Seq[UARTPortIO], cells2d) = system.uart.zipWithIndex.map({ case (u, i) => + val (ports: Seq[UARTPort], cells2d) = system.uart.zipWithIndex.map({ case (u, i) => val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey), abstractResetAsAsync = true) - (port, ios) + val where = PBUS // TODO fix + val bus = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where) + val freqMHz = bus.dtsFrequency.get.toInt / 1000000000 + (UARTPort(port, i, freqMHz), ios) }).unzip (ports, cells2d.flatten) } }) // DOC include end: WithUARTIOCells -class WithSPIIOCells extends OverrideIOBinder({ +class WithSPIIOPunchthrough extends OverrideLazyIOBinder({ + (system: HasPeripherySPI) => { + // attach resource to 1st SPI + if (system.tlSpiNodes.size > 0) ResourceBinding { + Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0)) + } + InModuleBody { + val spi = system.asInstanceOf[BaseSubsystem].module.asInstanceOf[HasPeripherySPIBundle].spi + val ports = spi.zipWithIndex.map({ case (s, i) => + val io_spi = IO(s.cloneType).suggestName(s"spi_$i") + io_spi <> s + SPIPort(io_spi) + }) + (ports, Nil) + } + } +}) + +class WithSPIFlashIOCells extends OverrideIOBinder({ (system: HasPeripherySPIFlashModuleImp) => { - val (ports: Seq[SPIChipIO], cells2d) = system.qspi.zipWithIndex.map({ case (s, i) => + val (ports: Seq[SPIFlashPort], cells2d) = system.qspi.zipWithIndex.map({ case (s, i) => + val name = s"spi_${i}" val port = IO(new SPIChipIO(s.c.csWidth)).suggestName(name) val iocellBase = s"iocell_${name}" @@ -213,7 +257,7 @@ class WithSPIIOCells extends OverrideIOBinder({ iocell } - (port, dqIOs ++ csIOs ++ sckIOs) + (SPIFlashPort(port, system.p(PeripherySPIFlashKey)(i), i), dqIOs ++ csIOs ++ sckIOs) }).unzip (ports, cells2d.flatten) } @@ -223,7 +267,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(port), cells) + (Seq(ExtIntPort(port)), cells) } else { system.interrupts := DontCare // why do I have to drive this 0-wide wire??? (Nil, Nil) @@ -273,7 +317,8 @@ class WithDebugIOCells extends OverrideLazyIOBinder({ // Add IOCells for the DMI/JTAG/APB ports val dmiTuple = debug.clockeddmi.map { d => - IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true) + val (port, cells) = IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true) + (DMIPort(port), cells) } val jtagTuple = debug.systemjtag.map { j => @@ -282,14 +327,13 @@ class WithDebugIOCells extends OverrideLazyIOBinder({ j.jtag.TMS := jtag_wire.TMS j.jtag.TDI := jtag_wire.TDI jtag_wire.TDO := j.jtag.TDO.data - IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true) + val (port, cells) = IOCell.generateIOFromSignal(jtag_wire, "jtag", p(IOCellKey), abstractResetAsAsync = true) + (JTAGPort(port), cells) } - val apbTuple = debug.apb.map { a => - IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = true) - } + require(!debug.apb.isDefined) - val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq + val allTuples = (dmiTuple ++ jtagTuple).toSeq (allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq) }).getOrElse((Nil, Nil)) }}} @@ -297,20 +341,26 @@ class WithDebugIOCells extends OverrideLazyIOBinder({ }) 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), abstractResetAsAsync = true) - (Seq(port), cells) - }).getOrElse((Nil, Nil)) + (system: CanHavePeripheryTLSerial) => { + 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) + }).unzip + (ports.toSeq, cells.flatten.toSeq) + } }) class WithSerialTLPunchthrough extends OverrideIOBinder({ - (system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s => - val sys = system.asInstanceOf[BaseSubsystem] - val port = IO(s.getWrappedValue.cloneType) - port <> s.getWrappedValue - (Seq(port), Nil) - }).getOrElse((Nil, Nil)) + (system: CanHavePeripheryTLSerial) => { + val (ports, cells) = system.serial_tl.zipWithIndex.map({ case (s, id) => + val sys = system.asInstanceOf[BaseSubsystem] + val port = IO(s.getWrappedValue.cloneType) + port <> s.getWrappedValue + (SerialTLPort(port, sys.p(SerialTLKey).get, system.serdesser.get, id), Nil) + }).unzip + (ports.toSeq, cells.flatten.toSeq) + } }) class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({ @@ -321,12 +371,11 @@ class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({ def clockBundle = clockSinkNode.get.in.head._1 InModuleBody { - val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) => - val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}") - p.bits <> m - p.clock := clockBundle.clock - p.reset := clockBundle.reset - p + val ports: Seq[AXI4MemPort] = system.mem_axi4.zipWithIndex.map({ case (m, i) => + 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) }).toSeq (ports, Nil) } @@ -341,12 +390,11 @@ class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({ def clockBundle = clockSinkNode.get.in.head._1 InModuleBody { - val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) => - val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}") - p.bits <> m - p.clock := clockBundle.clock - p.reset := clockBundle.reset - p + val ports: Seq[AXI4MMIOPort] = system.mmio_axi4.zipWithIndex.map({ case (m, i) => + 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)) }).toSeq (ports, Nil) } @@ -361,11 +409,11 @@ class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({ 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 + val ports: Seq[AXI4InPort] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) => + 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) }).toSeq (ports, Nil) } @@ -374,10 +422,12 @@ class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({ class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({ (system: CanHavePeripheryBlockDevice) => { - val ports: Seq[ClockedIO[BlockDeviceIO]] = system.bdev.map({ bdev => - val p = IO(new ClockedIO(new BlockDeviceIO()(GetSystemParameters(system)))).suggestName("blockdev") - p <> bdev - p + val ports: Seq[BlockDevicePort] = system.bdev.map({ bdev => + val p = GetSystemParameters(system) + val bdParams = p(BlockDeviceKey).get + val port = IO(new ClockedIO(new BlockDeviceIO(bdParams))).suggestName("blockdev") + port <> bdev + BlockDevicePort(port, bdParams) }).toSeq (ports, Nil) } @@ -385,10 +435,11 @@ class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({ class WithNICIOPunchthrough extends OverrideIOBinder({ (system: CanHavePeripheryIceNIC) => { - val ports: Seq[ClockedIO[NICIOvonly]] = system.icenicOpt.map({ n => - val p = IO(new ClockedIO(new NICIOvonly)).suggestName("nic") - p <> n - p + val ports: Seq[NICPort] = system.icenicOpt.map({ n => + val p = GetSystemParameters(system) + val port = IO(new ClockedIO(new NICIOvonly)).suggestName("nic") + port <> n + NICPort(port, p(NICKey).get) }).toSeq (ports, Nil) } @@ -398,16 +449,30 @@ class WithTraceGenSuccessPunchthrough extends OverrideIOBinder({ (system: TraceGenSystemModuleImp) => { val success: Bool = IO(Output(Bool())).suggestName("success") success := system.success - (Seq(success), Nil) + (Seq(SuccessPort(success)), Nil) } }) class WithTraceIOPunchthrough extends OverrideIOBinder({ (system: CanHaveTraceIOModuleImp) => { - val ports: Option[TraceOutputTop] = system.traceIO.map { t => + val ports: Option[TracePort] = system.traceIO.map { t => val trace = IO(DataMirror.internal.chiselTypeClone[TraceOutputTop](t)).suggestName("trace") trace <> t - trace + val p = GetSystemParameters(system) + val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem] + val tiles = chipyardSystem.tiles + val cfg = SpikeCosimConfig( + isa = tiles.headOption.map(_.isaDTS).getOrElse(""), + vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0), + priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""), + mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)), + mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)), + pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0), + nharts = tiles.size, + 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) } (ports.toSeq, Nil) } @@ -417,7 +482,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(port), cells) + (Seq(CustomBootPort(port)), cells) }).getOrElse((Nil, Nil)) }) @@ -426,7 +491,7 @@ class WithUARTTSIPunchthrough extends OverrideIOBinder({ val sys = system.asInstanceOf[BaseSubsystem] val uart_tsi = IO(new UARTTSIIO(p.uartParams)) uart_tsi <> p - (Seq(uart_tsi), Nil) + (Seq(UARTTSIPort(uart_tsi)), Nil) }).getOrElse((Nil, Nil)) }) @@ -434,7 +499,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(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 new file mode 100644 index 0000000000..61c25a364a --- /dev/null +++ b/generators/chipyard/src/main/scala/iobinders/Ports.scala @@ -0,0 +1,94 @@ +package chipyard.iobinders + +import chisel3._ +import chisel3.experimental.{Analog} +import sifive.blocks.devices.uart.{UARTPortIO} +import sifive.blocks.devices.spi.{SPIFlashParams, SPIPortIO} +import sifive.blocks.devices.i2c.{I2CPort} +import sifive.blocks.devices.gpio.{GPIOPortIO} +import testchipip._ +import icenet.{NICIOvonly, NICConfig} +import org.chipsalliance.cde.config.{Parameters} +import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4EdgeParameters} +import freechips.rocketchip.subsystem.{MemoryPortParams, MasterPortParams, SlavePortParams} +import freechips.rocketchip.devices.debug.{ClockedDMIIO} +import freechips.rocketchip.util.{HeterogeneousBag} +import freechips.rocketchip.tilelink.{TLBundle} + +trait Port[T <: Data] { + val io: T +} + +// These case classes are generated by IOBinders, and interpreted by HarnessBinders +case class GPIOPort (val io: Analog, val gpioId: Int, val pinId: Int) + extends Port[Analog] + +case class GPIOPinsPort (val io: GPIOPortIO, val gpioId: Int) + extends Port[GPIOPortIO] + +case class I2CPort (val io: sifive.blocks.devices.i2c.I2CPort) + extends Port[sifive.blocks.devices.i2c.I2CPort] + +case class UARTPort (val io: UARTPortIO, val uartNo: Int, val freqMHz: Int) + extends Port[UARTPortIO] + +case class SPIFlashPort (val io: SPIChipIO, val params: SPIFlashParams, val spiId: Int) + extends Port[SPIChipIO] + +case class SPIPort (val io: SPIPortIO) + extends Port[SPIPortIO] + +case class BlockDevicePort (val io: ClockedIO[BlockDeviceIO], val params: BlockDeviceConfig) + extends Port[ClockedIO[BlockDeviceIO]] + +case class NICPort (val io: 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) + extends Port[ClockedIO[AXI4Bundle]] + +case class AXI4MMIOPort (val io: ClockedIO[AXI4Bundle], val params: MasterPortParams, val edge: AXI4EdgeParameters) + extends Port[ClockedIO[AXI4Bundle]] + +case class AXI4InPort (val io: ClockedIO[AXI4Bundle], val params: SlavePortParams) + extends Port[ClockedIO[AXI4Bundle]] + +case class ExtIntPort (val io: UInt) + extends Port[UInt] + +case class DMIPort (val io: ClockedDMIIO) + extends Port[ClockedDMIIO] + +case class JTAGPort (val io: JTAGChipIO) + extends Port[JTAGChipIO] + +case class SerialTLPort (val io: ClockedIO[SerialIO], val params: SerialTLParams, val serdesser: TLSerdesser, val portId: Int) + extends Port[ClockedIO[SerialIO]] + +case class UARTTSIPort (val io: UARTTSIIO) + extends Port[UARTTSIIO] + +case class SuccessPort (val io: Bool) + extends Port[Bool] + +case class TracePort (val io: TraceOutputTop, val cosimCfg: SpikeCosimConfig) + extends Port[TraceOutputTop] + +case class CustomBootPort (val io: Bool) + extends Port[Bool] + +case class ClockPort (val io: Clock, val freqMHz: Double) + extends Port[Clock] + +case class ResetPort (val io: AsyncReset) + extends Port[Reset] + +case class DebugResetPort (val io: Reset) + extends Port[Reset] + +case class JTAGResetPort (val io: Reset) + extends Port[Reset] + +case class TLMemPort (val io: HeterogeneousBag[TLBundle]) + extends Port[HeterogeneousBag[TLBundle]] + diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index db6ec2fbb8..a709ee4b9c 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -3,7 +3,6 @@ package firesim.firesim import chisel3._ -import chisel3.experimental.annotate import chisel3.experimental.{DataMirror, Direction} import chisel3.util.experimental.BoringUtils @@ -12,7 +11,6 @@ import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebug, ExportDebug, DMI} import freechips.rocketchip.amba.axi4.{AXI4Bundle} import freechips.rocketchip.subsystem._ -import freechips.rocketchip.tile.{RocketTile} import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters} import freechips.rocketchip.util.{ResetCatchAndSync} import sifive.blocks.devices.uart._ @@ -22,21 +20,19 @@ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvon import junctions.{NastiKey, NastiParameters} import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig} -import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotation} import firesim.bridges._ import firesim.configs.MemModelKey import tracegen.{TraceGenSystemModuleImp} import cva6.CVA6Tile -import boom.common.{BoomTile} import barstools.iocell.chisel._ -import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters, IOCellKey} +import chipyard.iobinders._ import chipyard._ import chipyard.harness._ object MainMemoryConsts { val regionNamePrefix = "MainMemory" - def globalName()(implicit p: Parameters) = s"${regionNamePrefix}_${p(MultiChipIdx)}" + def globalName(chipId: Int) = s"${regionNamePrefix}_$chipId" } trait Unsupported { @@ -69,130 +65,65 @@ class WithFireSimIOCellModels extends Config((site, here, up) => { case IOCellKey => FireSimIOCellParams() }) -class WithTSIBridgeAndHarnessRAMOverSerialTL extends OverrideHarnessBinder({ - (system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => { - ports.map { port => - implicit val p = GetSystemParameters(system) - val bits = port.bits - port.clock := th.harnessBinderClock - val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.harnessBinderReset) - TSIBridge(th.harnessBinderClock, ram.module.io.tsi, p(ExtMem).map(_ => MainMemoryConsts.globalName), th.harnessBinderReset.asBool) - } - Nil +class WithTSIBridgeAndHarnessRAMOverSerialTL extends HarnessBinder({ + case (th: FireSim, port: SerialTLPort) => { + val bits = port.io.bits + port.io.clock := th.harnessBinderClock + val ram = LazyModule(new SerialRAM(port.serdesser)(Parameters.empty)) + Module(ram.module) + ram.module.io.ser <> port.io.bits + TSIBridge(th.harnessBinderClock, ram.module.io.tsi, + port.params.serialTLManagerParams.map(_ => MainMemoryConsts.globalName(th.p(MultiChipIdx))), th.harnessBinderReset.asBool)(th.p) } }) -class WithNICBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => { - val p: Parameters = GetSystemParameters(system) - ports.map { n => NICBridge(n.clock, n.bits)(p) } - Nil +class WithNICBridge extends HarnessBinder({ + case (th: FireSim, port: NICPort) => { + NICBridge(port.io.clock, port.io.bits)(th.p) } }) -class WithUARTBridge extends OverrideHarnessBinder({ - (system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) => - val uartSyncClock = Wire(Clock()) - uartSyncClock := false.B.asClock - val pbusClockNode = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(PBUS).fixedClockNode - val pbusClock = pbusClockNode.in.head._1.clock - BoringUtils.bore(pbusClock, Seq(uartSyncClock)) - ports.map { p => UARTBridge(uartSyncClock, p, th.harnessBinderReset.asBool)(system.p) }; Nil +class WithUARTBridge extends HarnessBinder({ + case (th: FireSim, port: UARTPort) => + val uartSyncClock = th.harnessClockInstantiator.requestClockMHz("uart_clock", port.freqMHz) + UARTBridge(uartSyncClock, port.io, th.harnessBinderReset.asBool)(th.p) }) -class WithBlockDeviceBridge extends OverrideHarnessBinder({ - (system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => { - implicit val p: Parameters = GetSystemParameters(system) - ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessBinderReset.asBool) } - Nil +class WithBlockDeviceBridge extends HarnessBinder({ + case (th: FireSim, port: BlockDevicePort) => { + BlockDevBridge(port.io.clock, port.io.bits, th.harnessBinderReset.asBool) } }) -class WithFASEDBridge extends OverrideHarnessBinder({ - (system: CanHaveMasterAXI4MemPort, th: FireSim, ports: Seq[ClockedAndResetIO[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, - axi4.bits.ar.bits.addr.getWidth, - axi4.bits.ar.bits.id.getWidth) - system match { - case s: BaseSubsystem => FASEDBridge(axi4.clock, axi4.bits, axi4.reset.asBool, - CompleteConfig(p(firesim.configs.MemModelKey), - nastiKey, - Some(AXI4EdgeSummary(edge)), - Some(MainMemoryConsts.globalName))) - case _ => throw new Exception("Attempting to attach FASED Bridge to misconfigured design") - } - } - Nil +class WithFASEDBridge extends HarnessBinder({ + case (th: FireSim, port: AXI4MemPort) => { + val nastiKey = NastiParameters(port.io.bits.r.bits.data.getWidth, + port.io.bits.ar.bits.addr.getWidth, + port.io.bits.ar.bits.id.getWidth) + FASEDBridge(port.io.clock, port.io.bits, th.harnessBinderReset.asBool, + CompleteConfig(th.p(firesim.configs.MemModelKey), + nastiKey, + Some(AXI4EdgeSummary(port.edge)), + Some(MainMemoryConsts.globalName(th.p(MultiChipIdx)))))(th.p) } }) -class WithTracerVBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => { - ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) } - Nil +class WithTracerVBridge extends HarnessBinder({ + case (th: FireSim, port: TracePort) => { + port.io.traces.map(tileTrace => TracerVBridge(tileTrace)(th.p)) } }) -class WithCospikeBridge extends ComposeHarnessBinder({ - (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => { - implicit val p = chipyard.iobinders.GetSystemParameters(system) - val chipyardSystem = system.asInstanceOf[ChipyardSystemModule[_]].outer.asInstanceOf[ChipyardSystem] - val tiles = chipyardSystem.tiles - val cfg = SpikeCosimConfig( - isa = tiles.headOption.map(_.isaDTS).getOrElse(""), - vlen = tiles.headOption.map(_.tileParams.core.vLen).getOrElse(0), - priv = tiles.headOption.map(t => if (t.usingUser) "MSU" else if (t.usingSupervisor) "MS" else "M").getOrElse(""), - mem0_base = p(ExtMem).map(_.master.base).getOrElse(BigInt(0)), - mem0_size = p(ExtMem).map(_.master.size).getOrElse(BigInt(0)), - pmpregions = tiles.headOption.map(_.tileParams.core.nPMPs).getOrElse(0), - nharts = tiles.size, - 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 - ) - ports.map { p => p.traces.zipWithIndex.map(t => CospikeBridge(t._1, t._2, cfg)) } +class WithCospikeBridge extends HarnessBinder({ + case (th: FireSim, port: TracePort) => { + port.io.traces.zipWithIndex.map(t => CospikeBridge(t._1, t._2, port.cosimCfg)) } }) -class WithTraceGenBridge extends OverrideHarnessBinder({ - (system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) => - ports.map { p => GroundTestBridge(th.harnessBinderClock, p)(system.p) }; Nil -}) - -class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ - (system: HasTilesModuleImp) => { - system.outer.tiles.map { - case r: RocketTile => { - annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf)) - r.module.fpuOpt.foreach(fpu => annotate(MemModelAnnotation(fpu.fpuImpl.regfile))) - } - case b: BoomTile => { - val core = b.module.core - core.iregfile match { - case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile)) - } - if (core.fp_pipeline != null) core.fp_pipeline.fregfile match { - case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile)) - } - } - case _ => - } - (Nil, Nil) - } -}) - -class WithFireSimFAME5 extends ComposeIOBinder({ - (system: HasTilesModuleImp) => { - system.outer.tiles.map { - case b: BoomTile => - annotate(EnableModelMultiThreadingAnnotation(b.module)) - case r: RocketTile => - annotate(EnableModelMultiThreadingAnnotation(r.module)) - case _ => Nil - } - (Nil, Nil) +class WithSuccessBridge extends HarnessBinder({ + case (th: FireSim, port: SuccessPort) => { + GroundTestBridge(th.harnessBinderClock, port.io)(th.p) } }) diff --git a/generators/firechip/src/main/scala/FireSim.scala b/generators/firechip/src/main/scala/FireSim.scala index c20abca1fd..4cca755775 100644 --- a/generators/firechip/src/main/scala/FireSim.scala +++ b/generators/firechip/src/main/scala/FireSim.scala @@ -5,21 +5,26 @@ package firesim.firesim import scala.collection.mutable.{LinkedHashMap} import chisel3._ -import chisel3.experimental.{IO} +import chisel3.experimental.{IO, annotate} import freechips.rocketchip.prci._ -import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey} +import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey, HasTiles} import org.chipsalliance.cde.config.{Field, Config, Parameters} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, InModuleBody, ValName} import freechips.rocketchip.util.{ResetCatchAndSync, RecordMap} +import freechips.rocketchip.tile.{RocketTile} +import boom.common.{BoomTile} import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock, ResetPulseBridge, ResetPulseBridgeParameters} - +import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotation} import chipyard._ import chipyard.harness._ import chipyard.iobinders._ import chipyard.clocking._ +case object FireSimMultiCycleRegFile extends Field[Boolean](false) +case object FireSimFAME5 extends Field[Boolean](false) + /** * Under FireSim's current multiclock implementation there can be only a * single clock bridge. This requires, therefore, that it be instantiated in @@ -85,11 +90,46 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessInsta override val supportsMultiChip = true - instantiateChipTops() + val chiptops = instantiateChipTops() // Ensures FireSim-synthesized assertions and instrumentation is disabled // while resetBridge.io.reset is asserted. This ensures assertions do not fire at // time zero in the event their local reset is delayed (typically because it // has been pipelined) midas.targetutils.GlobalResetCondition(resetBridge.io.reset) + + + // FireSim multi-cycle regfile optimization + // FireSim ModelMultithreading + chiptops.foreach { + case c: ChipTop => c.lazySystem match { + case ls: HasTiles => { + if (p(FireSimMultiCycleRegFile)) ls.tiles.map { + case r: RocketTile => { + annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf)) + r.module.fpuOpt.foreach(fpu => annotate(MemModelAnnotation(fpu.fpuImpl.regfile))) + } + case b: BoomTile => { + val core = b.module.core + core.iregfile match { + case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile)) + } + if (core.fp_pipeline != null) core.fp_pipeline.fregfile match { + case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile)) + } + } + case _ => + } + if (p(FireSimFAME5)) ls.tiles.map { + case b: BoomTile => + annotate(EnableModelMultiThreadingAnnotation(b.module)) + case r: RocketTile => + annotate(EnableModelMultiThreadingAnnotation(r.module)) + case _ => Nil + } + } + case _ => + } + case _ => + } } diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index c08a028d23..9ef9b7bdc4 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -55,6 +55,16 @@ class WithScalaTestFeatures extends Config((site, here, up) => { case TracePortKey => up(TracePortKey, site).map(_.copy(print = true)) }) +// Multi-cycle regfile for rocket+boom +class WithFireSimMultiCycleRegfile extends Config((site, here, up) => { + case FireSimMultiCycleRegFile => true +}) + +// Model multithreading optimization +class WithFireSimFAME5 extends Config((site, here, up) => { + case FireSimFAME5 => true +}) + // FASED Config Aliases. This to enable config generation via "_" concatenation // which requires that all config classes be defined in the same package class DDR3FCFS extends FCFS16GBQuadRank @@ -72,7 +82,8 @@ class WithMinimalFireSimDesignTweaks extends Config( // Required*: Punch all clocks to FireSim's harness clock instantiator new WithFireSimHarnessClockBridgeInstantiator ++ new chipyard.harness.WithHarnessBinderClockFreqMHz(1000.0) ++ - new chipyard.harness.WithClockAndResetFromHarness ++ + new chipyard.harness.WithClockFromHarness ++ + new chipyard.harness.WithResetFromHarness ++ new chipyard.clocking.WithPassthroughClockGenerator ++ // Required*: When using FireSim-as-top to provide a correct path to the target bootrom source new WithBootROM ++ diff --git a/generators/icenet b/generators/icenet index 68b4c7f30f..18e88b5779 160000 --- a/generators/icenet +++ b/generators/icenet @@ -1 +1 @@ -Subproject commit 68b4c7f30f0119fe5cfab7ea99fb6927a563e112 +Subproject commit 18e88b5779ffdd7d75ca62cf9909f0ffc6fda95b diff --git a/generators/testchipip b/generators/testchipip index 177e307199..6436959d99 160000 --- a/generators/testchipip +++ b/generators/testchipip @@ -1 +1 @@ -Subproject commit 177e3071991421bdb042fec8411c51463477c7fc +Subproject commit 6436959d997d0bb578790d95078648b478ca049b diff --git a/sims/firesim b/sims/firesim index 08b565c8c6..f80c60313c 160000 --- a/sims/firesim +++ b/sims/firesim @@ -1 +1 @@ -Subproject commit 08b565c8c69f125a1de292eb8efe03ee08408d2e +Subproject commit f80c60313c7c54733affb441773874fc54560ef3 From 8fb4ba5675a16ce425eaf694e2c97e5f1889da76 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 5 Oct 2023 21:03:34 -0700 Subject: [PATCH 02/12] Fix UARTPort freqMHz --- generators/chipyard/src/main/scala/iobinders/IOBinders.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/iobinders/IOBinders.scala b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala index 2ce7c6f4bb..7cbce516c7 100644 --- a/generators/chipyard/src/main/scala/iobinders/IOBinders.scala +++ b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala @@ -208,7 +208,7 @@ class WithUARTIOCells extends OverrideIOBinder({ val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey), abstractResetAsAsync = true) val where = PBUS // TODO fix val bus = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where) - val freqMHz = bus.dtsFrequency.get.toInt / 1000000000 + val freqMHz = bus.dtsFrequency.get.toInt / 1000000 (UARTPort(port, i, freqMHz), ios) }).unzip (ports, cells2d.flatten) From e6203bb25c055e9135ee0371d95accb88108b0be Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 5 Oct 2023 23:56:29 -0700 Subject: [PATCH 03/12] Fix fsim supernode memmodel --- generators/firechip/src/main/scala/TargetConfigs.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 9ef9b7bdc4..6f2a02913d 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -300,6 +300,7 @@ class FireSimLeanGemminiPrintfRocketConfig extends Config( //********************************************************************************** class SupernodeFireSimRocketConfig extends Config( new WithFireSimHarnessClockBridgeInstantiator ++ + new WithDefaultMemModel ++ // this is a global for all the multi-chip configs new chipyard.harness.WithHomogeneousMultiChip(n=4, new Config( new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 8L) ++ // 8GB DRAM per node new FireSimRocketConfig))) From a4cb114657bece161410febaf50a3807b54bf090 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 6 Oct 2023 17:00:06 -0700 Subject: [PATCH 04/12] Fix UARTAdapter divisor --- generators/chipyard/src/main/scala/harness/HarnessBinders.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala index b6409a635b..32c31840bc 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala @@ -42,7 +42,7 @@ class WithGPIOTiedOff extends HarnessBinder({ // DOC include start: WithUARTAdapter class WithUARTAdapter extends HarnessBinder({ case (th: HasHarnessInstantiators, port: UARTPort) => { - val div = (th.getHarnessBinderClockFreqMHz / port.io.c.initBaudRate.toDouble).toInt + val div = (th.getHarnessBinderClockFreqMHz * 1000000 / port.io.c.initBaudRate.toDouble).toInt val uart_sim = Module(new UARTAdapter(port.uartNo, div, false)).suggestName(s"uart_sim_uartno${port.uartNo}") uart_sim.io.uart.txd := port.io.txd port.io.rxd := uart_sim.io.uart.rxd From b949324d5aa031e405e0f2c8ad6bb318edba3e33 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 6 Oct 2023 17:55:14 -0700 Subject: [PATCH 05/12] Fix FireSim UARTBridge --- generators/firechip/src/main/scala/BridgeBinders.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index a709ee4b9c..7982a75d58 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -86,7 +86,7 @@ class WithNICBridge extends HarnessBinder({ class WithUARTBridge extends HarnessBinder({ case (th: FireSim, port: UARTPort) => val uartSyncClock = th.harnessClockInstantiator.requestClockMHz("uart_clock", port.freqMHz) - UARTBridge(uartSyncClock, port.io, th.harnessBinderReset.asBool)(th.p) + UARTBridge(uartSyncClock, port.io, th.harnessBinderReset.asBool, port.freqMHz)(th.p) }) class WithBlockDeviceBridge extends HarnessBinder({ From 5145f4f2435beb262e43d02e7451d4e69ed34fde Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 6 Oct 2023 17:55:49 -0700 Subject: [PATCH 06/12] Bump firesim --- sims/firesim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sims/firesim b/sims/firesim index f80c60313c..73fe6a51b2 160000 --- a/sims/firesim +++ b/sims/firesim @@ -1 +1 @@ -Subproject commit f80c60313c7c54733affb441773874fc54560ef3 +Subproject commit 73fe6a51b28a2dbbe3f307bdbc6ba2407b311a27 From 8d11dde7cb180d7ac776c71b158e4ce5da555711 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sat, 7 Oct 2023 00:27:15 -0700 Subject: [PATCH 07/12] Fix UARTPort freqMHz --- generators/chipyard/src/main/scala/iobinders/IOBinders.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/iobinders/IOBinders.scala b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala index 7cbce516c7..773f3d3919 100644 --- a/generators/chipyard/src/main/scala/iobinders/IOBinders.scala +++ b/generators/chipyard/src/main/scala/iobinders/IOBinders.scala @@ -208,8 +208,8 @@ class WithUARTIOCells extends OverrideIOBinder({ val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey), abstractResetAsAsync = true) val where = PBUS // TODO fix val bus = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(where) - val freqMHz = bus.dtsFrequency.get.toInt / 1000000 - (UARTPort(port, i, freqMHz), ios) + val freqMHz = bus.dtsFrequency.get / 1000000 + (UARTPort(port, i, freqMHz.toInt), ios) }).unzip (ports, cells2d.flatten) } From 0ebab140ffefc7be845a90c5d2d25be57bc66389 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Mon, 9 Oct 2023 11:49:38 -0700 Subject: [PATCH 08/12] Update nexysvideo to Port api --- .../scala/nexysvideo/HarnessBinders.scala | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/fpga/src/main/scala/nexysvideo/HarnessBinders.scala b/fpga/src/main/scala/nexysvideo/HarnessBinders.scala index 3a035a1049..4027cbcf2a 100644 --- a/fpga/src/main/scala/nexysvideo/HarnessBinders.scala +++ b/fpga/src/main/scala/nexysvideo/HarnessBinders.scala @@ -14,30 +14,26 @@ import chipyard._ import chipyard.harness._ import testchipip._ +import chipyard.iobinders._ -class WithNexysVideoUARTTSI(uartBaudRate: BigInt = 115200) extends OverrideHarnessBinder({ - (system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => { - implicit val p = chipyard.iobinders.GetSystemParameters(system) - require(ports.size <= 1) +class WithNexysVideoUARTTSI(uartBaudRate: BigInt = 115200) extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: UARTTSIPort) => { val nexysvideoth = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[NexysVideoHarness] - ports.map({ port => - nexysvideoth.io_uart_bb.bundle <> port.uart - nexysvideoth.other_leds(1) := port.dropped - nexysvideoth.other_leds(2) := port.tsi2tl_state(0) - nexysvideoth.other_leds(3) := port.tsi2tl_state(1) - nexysvideoth.other_leds(4) := port.tsi2tl_state(2) - nexysvideoth.other_leds(5) := port.tsi2tl_state(3) - }) + nexysvideoth.io_uart_bb.bundle <> port.io.uart + nexysvideoth.other_leds(1) := port.io.dropped + nexysvideoth.other_leds(2) := port.io.tsi2tl_state(0) + nexysvideoth.other_leds(3) := port.io.tsi2tl_state(1) + nexysvideoth.other_leds(4) := port.io.tsi2tl_state(2) + nexysvideoth.other_leds(5) := port.io.tsi2tl_state(3) } }) -class WithNexysVideoDDRTL extends OverrideHarnessBinder({ - (system: CanHaveMasterTLMemPort, th: HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => { - require(ports.size == 1) +class WithNexysVideoDDRTL extends HarnessBinder({ + case (th: HasHarnessInstantiators, port: TLMemPort) => { val nexysTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[NexysVideoHarness] val bundles = nexysTh.ddrClient.get.out.map(_._1) val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType))) bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io } - ddrClientBundle <> ports.head + ddrClientBundle <> port.io } }) From 894ee630619263fa0274277e3c83a036a12d972c Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 11 Oct 2023 14:59:49 -0700 Subject: [PATCH 09/12] Make chipParameters not private --- .../src/main/scala/harness/HasHarnessInstantiators.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala b/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala index 9b607c1cf9..48f63e04de 100644 --- a/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala +++ b/generators/chipyard/src/main/scala/harness/HasHarnessInstantiators.scala @@ -63,7 +63,7 @@ trait HasHarnessInstantiators { val supportsMultiChip: Boolean = false - private val chipParameters = p(MultiChipNChips) match { + val chipParameters = p(MultiChipNChips) match { case Some(n) => (0 until n).map { i => p(MultiChipParameters(i)).alterPartial { case TargetDirKey => p(TargetDirKey) // hacky fix case MultiChipIdx => i From 3cbcf6b6e82846274248ad6a52b50f43c0b15644 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 11 Oct 2023 15:01:39 -0700 Subject: [PATCH 10/12] Fix TSIBridge loadmem param --- generators/firechip/src/main/scala/BridgeBinders.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index 7982a75d58..e4169ec26e 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -72,8 +72,13 @@ class WithTSIBridgeAndHarnessRAMOverSerialTL extends HarnessBinder({ val ram = LazyModule(new SerialRAM(port.serdesser)(Parameters.empty)) Module(ram.module) ram.module.io.ser <> port.io.bits - TSIBridge(th.harnessBinderClock, ram.module.io.tsi, - port.params.serialTLManagerParams.map(_ => MainMemoryConsts.globalName(th.p(MultiChipIdx))), th.harnessBinderReset.asBool)(th.p) + + // This assumes that: + // If ExtMem for the target is defined, then FASED bridge will be attached + // If FASED bridge is attached, loadmem widget is present + val hasMainMemory = th.chipParameters(th.p(MultiChipIdx))(ExtMem).isDefined + val mainMemoryName = Option.when(hasMainMemory)(MainMemoryConsts.globalName(th.p(MultiChipIdx))) + TSIBridge(th.harnessBinderClock, ram.module.io.tsi, mainMemoryName, th.harnessBinderReset.asBool)(th.p) } }) From deab3b11b66119db896aa0c5ae763f56433d836b Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 12 Oct 2023 15:37:03 -0700 Subject: [PATCH 11/12] Fix UARTAdapter div bits --- generators/chipyard/src/main/scala/harness/HarnessBinders.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala index 32c31840bc..0446b78357 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala @@ -42,7 +42,7 @@ class WithGPIOTiedOff extends HarnessBinder({ // DOC include start: WithUARTAdapter class WithUARTAdapter extends HarnessBinder({ case (th: HasHarnessInstantiators, port: UARTPort) => { - val div = (th.getHarnessBinderClockFreqMHz * 1000000 / port.io.c.initBaudRate.toDouble).toInt + val div = (th.getHarnessBinderClockFreqMHz.toDouble * 1000000 / port.io.c.initBaudRate.toDouble).toInt val uart_sim = Module(new UARTAdapter(port.uartNo, div, false)).suggestName(s"uart_sim_uartno${port.uartNo}") uart_sim.io.uart.txd := port.io.txd port.io.rxd := uart_sim.io.uart.rxd From 6bd2e9dddbf4901bece51ae38408d101f3d8f1b4 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 13 Oct 2023 17:36:41 -0700 Subject: [PATCH 12/12] [ci skip] Re-add suggestName for axi4 mmio mem --- generators/chipyard/src/main/scala/harness/HarnessBinders.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala index 0446b78357..8530bb3395 100644 --- a/generators/chipyard/src/main/scala/harness/HarnessBinders.scala +++ b/generators/chipyard/src/main/scala/harness/HarnessBinders.scala @@ -135,7 +135,7 @@ class WithBlackBoxSimMem(additionalLatency: Int = 0) extends HarnessBinder({ class WithSimAXIMMIO extends HarnessBinder({ case (th: HasHarnessInstantiators, port: AXI4MMIOPort) => { val mmio_mem = LazyModule(new SimAXIMem(port.edge, size = port.params.size)(Parameters.empty)) - withClock(port.io.clock) { Module(mmio_mem.module) } + withClock(port.io.clock) { Module(mmio_mem.module).suggestName("mmio_mem") } mmio_mem.io_axi4.head <> port.io.bits } })