Merge pull request #1489 from ucb-bar/clkfixes

Improvements to chipyard clocking
This commit is contained in:
Jerry Zhao
2023-05-31 21:43:53 -07:00
committed by GitHub
7 changed files with 42 additions and 39 deletions

View File

@@ -80,7 +80,7 @@ jobs:
eval "$(conda shell.bash hook)" eval "$(conda shell.bash hook)"
mkdir ${{ env.JAVA_TMP_DIR }} mkdir ${{ env.JAVA_TMP_DIR }}
export MAKEFLAGS="-j32" export MAKEFLAGS="-j32"
./build-setup.sh -f ./build-setup.sh -f -v
run-cfg-finder: run-cfg-finder:
name: run-cfg-finder name: run-cfg-finder

View File

@@ -38,9 +38,9 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
val clockSelector = system.prci_ctrl_domain { LazyModule(new TLClockSelector(baseAddress + 0x30000, tlbus.beatBytes)) } val clockSelector = system.prci_ctrl_domain { LazyModule(new TLClockSelector(baseAddress + 0x30000, tlbus.beatBytes)) }
val pllCtrl = system.prci_ctrl_domain { LazyModule(new FakePLLCtrl (baseAddress + 0x40000, tlbus.beatBytes)) } val pllCtrl = system.prci_ctrl_domain { LazyModule(new FakePLLCtrl (baseAddress + 0x40000, tlbus.beatBytes)) }
tlbus.coupleTo("clock-div-ctrl") { clockDivider.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := TLBuffer() := _ } clockDivider.tlNode := system.prci_ctrl_bus
tlbus.coupleTo("clock-sel-ctrl") { clockSelector.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := TLBuffer() := _ } clockSelector.tlNode := system.prci_ctrl_bus
tlbus.coupleTo("pll-ctrl") { pllCtrl.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := TLBuffer() := _ } pllCtrl.tlNode := system.prci_ctrl_bus
system.allClockGroupsNode := clockDivider.clockNode := clockSelector.clockNode system.allClockGroupsNode := clockDivider.clockNode := clockSelector.clockNode

View File

@@ -36,6 +36,14 @@ trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
val prci_ctrl_domain = LazyModule(new ClockSinkDomain(name=Some("chipyard-prci-control"))) val prci_ctrl_domain = LazyModule(new ClockSinkDomain(name=Some("chipyard-prci-control")))
prci_ctrl_domain.clockNode := tlbus.fixedClockNode prci_ctrl_domain.clockNode := tlbus.fixedClockNode
val prci_ctrl_bus = prci_ctrl_domain { TLXbar() }
tlbus.coupleTo("prci_ctrl") { (prci_ctrl_bus
:= TLFIFOFixer(TLFIFOFixer.all)
:= TLFragmenter(tlbus.beatBytes, tlbus.blockBytes)
:= TLBuffer()
:= _)
}
// Aggregate all the clock groups into a single node // Aggregate all the clock groups into a single node
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
val allClockGroupsNode = ClockGroupEphemeralNode() val allClockGroupsNode = ClockGroupEphemeralNode()
@@ -71,19 +79,24 @@ trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
// diplomatic IOBinder should drive // diplomatic IOBinder should drive
val frequencySpecifier = ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey)) val frequencySpecifier = ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey))
val clockGroupCombiner = ClockGroupCombiner() val clockGroupCombiner = ClockGroupCombiner()
val resetSynchronizer = ClockGroupResetSynchronizer() val resetSynchronizer = prci_ctrl_domain { ClockGroupResetSynchronizer() }
val tileClockGater = if (prciParams.enableTileClockGating) { prci_ctrl_domain { val tileClockGater = Option.when(prciParams.enableTileClockGating) { prci_ctrl_domain {
TileClockGater(prciParams.baseAddress + 0x00000, tlbus) val clock_gater = LazyModule(new TileClockGater(prciParams.baseAddress + 0x00000, tlbus.beatBytes))
} } else { ClockGroupEphemeralNode() } clock_gater.tlNode := prci_ctrl_bus
val tileResetSetter = if (prciParams.enableTileResetSetting) { prci_ctrl_domain { clock_gater
TileResetSetter(prciParams.baseAddress + 0x10000, tlbus, tile_prci_domains.map(_.tile_reset_domain.clockNode.portParams(0).name.get), Nil) } }
} } else { ClockGroupEphemeralNode() } val tileResetSetter = Option.when(prciParams.enableTileResetSetting) { prci_ctrl_domain {
val reset_setter = LazyModule(new TileResetSetter(prciParams.baseAddress + 0x10000, tlbus.beatBytes,
tile_prci_domains.map(_.tile_reset_domain.clockNode.portParams(0).name.get), Nil))
reset_setter.tlNode := prci_ctrl_bus
reset_setter
} }
(aggregator (aggregator
:= frequencySpecifier := frequencySpecifier
:= clockGroupCombiner := clockGroupCombiner
:= resetSynchronizer := resetSynchronizer
:= tileClockGater := tileClockGater.map(_.clockNode).getOrElse(ClockGroupEphemeralNode()(ValName("temp")))
:= tileResetSetter := tileResetSetter.map(_.clockNode).getOrElse(ClockGroupEphemeralNode()(ValName("temp")))
:= allClockGroupsNode) := allClockGroupsNode)
} }

View File

@@ -26,20 +26,26 @@ class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit
val sinks = clockNode.out.head._1.member.elements.toSeq val sinks = clockNode.out.head._1.member.elements.toSeq
require (sources.size == sinks.size) require (sources.size == sinks.size)
val nSinks = sinks.size val nSinks = sinks.size
// The implicit clock of this module is the clock of the tilelink bus
// busReset is sync'd to that clock, and will be asserted longer than the
// resets coming in through the clockNode, since the busReset is derived from
// the clockNode resets in downstream PRCI nodes
val busReset = reset
val regs = (0 until nSinks) .map { i => val regs = (0 until nSinks) .map { i =>
val sinkName = sinks(i)._1 val sinkName = sinks(i)._1
val asyncReset = sources(i).reset val asyncReset = sources(i).reset
val reg = withReset (asyncReset) { val reg = Module(new AsyncResetRegVec(w=divBits, init=0))
Module(new AsyncResetRegVec(w=divBits, init=0))
}
println(s"${(address+i*4).toString(16)}: Clock domain $sinkName divider") println(s"${(address+i*4).toString(16)}: Clock domain $sinkName divider")
sinks(i)._2.clock := withClockAndReset(sources(i).clock, asyncReset) { val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl)))
val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl))) divider.io.clockIn := sources(i).clock
divider.io.divisor := reg.io.q // busReset is expected to be high for a long time, since reset will take a while to propagate
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset // to the TL bus. While reset is propagating, make sure we propagate a fast, undivided clock
divider.io.clockOut // by setting divisor=0. The divisor signal into the ClockDividerOrPass is synchronized internally
} divider.io.divisor := Mux(busReset.asBool, 0.U, reg.io.q)
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset
sinks(i)._2.clock := divider.io.clockOut
// Note this is not synchronized to the output clock, which takes time to appear // Note this is not synchronized to the output clock, which takes time to appear
// so this is still asyncreset // so this is still asyncreset

View File

@@ -46,10 +46,3 @@ class TileClockGater(address: BigInt, beatBytes: Int)(implicit p: Parameters, va
} }
} }
object TileClockGater {
def apply(address: BigInt, tlbus: TLBusWrapper)(implicit p: Parameters, v: ValName) = {
val gater = LazyModule(new TileClockGater(address, tlbus.beatBytes))
tlbus.coupleTo("clock-gater") { gater.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := TLBuffer() := _ }
gater.clockNode
}
}

View File

@@ -62,12 +62,3 @@ class TileResetSetter(address: BigInt, beatBytes: Int, tileNames: Seq[String], i
} }
} }
} }
object TileResetSetter {
def apply(address: BigInt, tlbus: TLBusWrapper, tileNames: Seq[String], initResetHarts: Seq[Int])(implicit p: Parameters, v: ValName) = {
val setter = LazyModule(new TileResetSetter(address, tlbus.beatBytes, tileNames, initResetHarts))
tlbus.coupleTo("tile-reset-setter") { setter.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := TLBuffer() := _ }
setter.clockNode
}
}