diff --git a/.circleci/config.yml b/.circleci/config.yml index 6e74b9d5..f18f0e62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -248,6 +248,12 @@ jobs: group-key: "group-cores" project-key: "chipyard-sodor" timeout: "30m" + chipyard-multiclock-rocket-run-tests: + executor: main-env + steps: + - run-tests: + group-key: "group-cores" + project-key: "chipyard-multiclock-rocket" chipyard-dmirocket-run-tests: executor: main-env steps: diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh index c0bce62d..e9ccdfb5 100755 --- a/.circleci/defaults.sh +++ b/.circleci/defaults.sh @@ -47,7 +47,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim # key value store to get the build groups declare -A grouping -grouping["group-cores"]="chipyard-cva6 chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop" +grouping["group-cores"]="chipyard-cva6 chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket" grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif" grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough" grouping["group-tracegen"]="tracegen tracegen-boom" @@ -75,6 +75,7 @@ mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config" mapping["tracegen-boom"]=" CONFIG=BoomTraceGenConfig" mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig" mapping["chipyard-sodor"]=" CONFIG=Sodor5StageConfig" +mapping["chipyard-multiclock-rocket"]=" CONFIG=MulticlockRocketConfig" mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests" mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests" diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 0db4ed4c..479120ba 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -1,5 +1,6 @@ package chipyard.config +import scala.util.matching.Regex import chisel3._ import chisel3.util.{log2Up} @@ -11,6 +12,7 @@ import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, D import freechips.rocketchip.groundtest.{GroundTestSubsystem} import freechips.rocketchip.tile._ import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams} +import freechips.rocketchip.tilelink.{HasTLBusParams} import freechips.rocketchip.util.{AsyncResetReg, Symmetric} import freechips.rocketchip.prci._ @@ -183,6 +185,34 @@ class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => { case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble }) +class WithSystemBusFrequencyAsDefault extends Config((site, here, up) => { + case DefaultClockFrequencyKey => (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toDouble +}) + +class BusFrequencyAssignment[T <: HasTLBusParams](re: Regex, key: Field[T]) extends Config((site, here, up) => { + case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++ + Seq((cName: String) => site(key).dtsFrequency.flatMap { f => + re.findFirstIn(cName).map {_ => (f / (1000 * 1000)).toDouble } + }) +}) + +/** + * Provides a diplomatic frequency for all clock sinks with an unspecified + * frequency bound to each bus. + * + * For example, the L2 cache, when bound to the sbus, receives a separate + * clock that appears as "subsystem_sbus_". This fragment ensures that + * clock requests the same frequency as the sbus itself. + */ + +class WithInheritBusFrequencyAssignments extends Config( + new BusFrequencyAssignment("subsystem_sbus_\\d+".r, SystemBusKey) ++ + new BusFrequencyAssignment("subsystem_pbus_\\d+".r, PeripheryBusKey) ++ + new BusFrequencyAssignment("subsystem_cbus_\\d+".r, ControlBusKey) ++ + new BusFrequencyAssignment("subsystem_fbus_\\d+".r, FrontBusKey) ++ + new BusFrequencyAssignment("subsystem_mbus_\\d+".r, MemoryBusKey) +) + /** * Mixins to specify crossing types between the 5 traditional TL buses * @@ -212,16 +242,19 @@ class WithFbusToSbusCrossingType(xType: ClockCrossingType) extends Config((site, * up the diplomatic graph to the clock sources. */ class WithPeripheryBusFrequency(freqMHz: Double) extends Config((site, here, up) => { - case PeripheryBusKey => up(PeripheryBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) + case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) }) class WithMemoryBusFrequency(freqMHz: Double) extends Config((site, here, up) => { - case MemoryBusKey => up(MemoryBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) + case MemoryBusKey => up(MemoryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) }) class WithSystemBusFrequency(freqMHz: Double) extends Config((site, here, up) => { - case SystemBusKey => up(SystemBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) + case SystemBusKey => up(SystemBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) +}) +class WithFrontBusFrequency(freqMHz: Double) extends Config((site, here, up) => { + case FrontBusKey => up(FrontBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) }) class WithControlBusFrequency(freqMHz: Double) extends Config((site, here, up) => { - case ControlBusKey => up(ControlBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) + case ControlBusKey => up(ControlBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong))) }) class WithRationalMemoryBusCrossing extends WithSbusToMbusCrossingType(RationalCrossing(Symmetric)) diff --git a/generators/chipyard/src/main/scala/CustomBusTopologies.scala b/generators/chipyard/src/main/scala/CustomBusTopologies.scala index c1c09285..2f6f3de7 100644 --- a/generators/chipyard/src/main/scala/CustomBusTopologies.scala +++ b/generators/chipyard/src/main/scala/CustomBusTopologies.scala @@ -36,17 +36,35 @@ case class CoherentMulticlockBusTopologyParams( (SBUS, L2, TLBusWrapperConnection(xType = NoCrossing, driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()), (L2, MBUS, TLBusWrapperConnection.crossTo( xType = sbusToMbusXType, - driveClockFromMaster = Some(true), + driveClockFromMaster = None, nodeBinding = BIND_QUERY)) ) ) +// This differs from upstream only in that it does not use the legacy crossTo +// and crossFrom functions, and it ensures driveClockFromMaster = None +case class HierarchicalMulticlockBusTopologyParams( + pbus: PeripheryBusParams, + fbus: FrontBusParams, + cbus: PeripheryBusParams, + xTypes: SubsystemCrossingParams +) extends TLBusWrapperTopology( + instantiations = List( + (PBUS, pbus), + (FBUS, fbus), + (CBUS, cbus)), + connections = List( + (SBUS, CBUS, TLBusWrapperConnection(xType = xTypes.sbusToCbusXType, nodeBinding = BIND_STAR)()), + (CBUS, PBUS, TLBusWrapperConnection(xType = xTypes.cbusToPbusXType, nodeBinding = BIND_STAR)()), + (FBUS, SBUS, TLBusWrapperConnection(xType = xTypes.fbusToSbusXType, nodeBinding = BIND_QUERY, flipRendering = true)())) +) + // For subsystem/Configs.scala class WithMulticlockCoherentBusTopology extends Config((site, here, up) => { case TLNetworkTopologyLocated(InSubsystem) => List( JustOneBusTopologyParams(sbus = site(SystemBusKey)), - HierarchicalBusTopologyParams( + HierarchicalMulticlockBusTopologyParams( pbus = site(PeripheryBusKey), fbus = site(FrontBusKey), cbus = site(ControlBusKey), diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index 5dd6ac18..09e35d95 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -56,6 +56,23 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem case b: BoomTile => b.module.core.coreMonitorBundle }.toList + + // Relying on [[TLBusWrapperConnection]].driveClockFromMaster for + // bus-couplings that are not asynchronous strips the bus name from the sink + // ClockGroup. This makes it impossible to determine which clocks are driven + // by which bus based on the member names, which is problematic when there is + // a rational crossing between two buses. Instead, provide all bus clocks + // directly from the asyncClockGroupsNode in the subsystem to ensure bus + // names are always preserved in the top-level clock names. + // + // For example, using a RationalCrossing between the Sbus and Cbus, and + // driveClockFromMaster = Some(true) results in all cbus-attached device and + // bus clocks to be given names of the form "subsystem_sbus_[0-9]*". + // Conversly, if an async crossing is used, they instead receive names of the + // form "subsystem_cbus_[0-9]*". The assignment below provides the latter names in all cases. + Seq(PBUS, FBUS, MBUS, CBUS).foreach { loc => + tlBusWrapperLocationMap.lift(loc).foreach { _.clockGroupNode := asyncClockGroupsNode } + } override lazy val module = new ChipyardSubsystemModuleImp(this) } diff --git a/generators/chipyard/src/main/scala/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala index 301c03d7..347b0c06 100644 --- a/generators/chipyard/src/main/scala/config/AbstractConfig.scala +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -43,7 +43,8 @@ class AbstractConfig extends Config( new chipyard.config.WithUART ++ // add a UART new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks - new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified clocks will match the frequency specified by the pbus dtsFrequency parameter + new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set + new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set) new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index d413cc12..1afb4515 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -1,6 +1,7 @@ package chipyard import freechips.rocketchip.config.{Config} +import freechips.rocketchip.diplomacy.{AsynchronousCrossing} // -------------- // Rocket Configs @@ -175,13 +176,19 @@ class MMIORocketConfig extends Config( new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new chipyard.config.AbstractConfig) -class DividedClockRocketConfig extends Config( - new chipyard.config.WithTileFrequency(200.0) ++ - new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore +class MulticlockRocketConfig extends Config( new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new chipyard.config.WithMemoryBusFrequency(50.0) ++ - new chipyard.config.WithAsynchrousMemoryBusCrossing ++ - new testchipip.WithAsynchronousSerialSlaveCrossing ++ + // Frequency specifications + new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540 + new chipyard.config.WithSystemBusFrequency(800.0) ++ // Ditto + new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // 2x the U540 freq (appropriate for a 128b Mbus) + new chipyard.config.WithPeripheryBusFrequency(100) ++ // Retains the default pbus frequency + new chipyard.config.WithSystemBusFrequencyAsDefault ++ // All unspecified clock frequencies, notably the implicit clock, will use the sbus freq (800 MHz) + // Crossing specifications + new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS + new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS + new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore + new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS new chipyard.config.AbstractConfig) class LBWIFRocketConfig extends Config( diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 89ac8073..e8f2afb5 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -201,8 +201,6 @@ class FireSimCVA6Config extends Config( //*********************************************************************************/ class FireSimMulticlockRocketConfig extends Config( new chipyard.config.WithTileFrequency(6400.0) ++ //lol - new WithDefaultFireSimBridges ++ - new WithDefaultMemModel ++ - new WithFireSimConfigTweaks ++ - new chipyard.DividedClockRocketConfig) + new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore + new FireSimRocketConfig)