Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make TLBusWrappers' topology a configurable Field #2327

Merged
merged 32 commits into from
Apr 17, 2020
Merged

Conversation

hcook
Copy link
Member

@hcook hcook commented Mar 10, 2020

Overview

This PR changes the selection of the topology of TLBusWrappers that are included in the BaseSubsystem layer of a Rocket-Chip-based design from being a static trait that is mixed in at compile time to a child class of BaseSubystem to being a dynamic choice driven at runtime from a configurable Field. This change means that the choice of internal network-on-chip topology no longer affects the Scala class hierarchy of Subsystems. Instead, a Field is supplied by which users can create a topology on a per-Config basis. The description of the topology is intended to be readable from a serializable format, although the current implementation maintains some programmatic escape hatches. Any number of TLBusWrappers in any connectivity network shape is possible, though the requirements of diplomatic TileLink must still be satisfied (no cycles, single apparent path to each address from each agent, etc).

A topological Config alteration is named WithCoherentBusTopology is supplied to recreate the extant, default, 5-hierarchical-crossbars topology from DefaultConfig+BaseSubsystem with HasHierarchicalBusTopology. The HasHierarchicalBusTopology trait itself is removed, and any child class that extends BaseSubsystem only to supply a different topology from that one should now be redundant (can just extend BaseSubsystem and supply a different value for the Field TLNetworkTopologyLocated(where: HierarchicalLocation). Three included example sub-topologies are included, which build on each other additively in order to recreate the original 5-xbar design. The three sub-topologies are JustOneBusTopologyParams (sbus), HierarchicalBusTopologyParams (fbus, cbus, pbus) and CoherentBusTopologyParams (adds a coherence manager and mbus).

API Additions and Changes

What is changed:

  • Use recently-added classes Location and LocationMap: These dynamic maps can store arbitrary things indexable by "location" (just a string name for now). For example, TLBusWrapper references are stored in named locations in HasTileLinkLocations .tlBusWrapperLocationMap.
  • Added trait HasTileLinkLocations: intended to be an even more generic version of the extant Attachable trait, which now extends it.
  • HasTileLinkLocations provides def locateTLBusWrapper function for child devices to locate a TLBusWrapper instance inside a parent that extends this trait based on a location label.
  • TLBusWrapperTopology is the new intended serializable entry point for describing bus topologies, see below.
  • CoherenceManagerWrapper is a new wrapper for all collateral related to attaching coherence managers within a topology, allowing use of the TLBusWrapper connectivity and clock crossing APIs. This will change the instance hierarchy of the coherence manager in existing designs by adding another module hierarchy layer wrapping it and its associated adapters together.
  • HasHierarchicalBusTopology trait is removed, but configuration equivalents WithCoherentBusTopology and WithIncoherentBusTopology are provided to be applied as alterations to DefaultConfig instead.
  • A new class of runtime error becomes possible, where a device or wrapper with a configurable attachment or connection location tries to use a location for an instance that actually does not exist in a given configured topology. So it goes with dynamic configurability...

What is not changed:

  • Accessor val members of BaseSubsystem named sbus, fbus, cbus etc. still exist; I would like to deprecate them in the near future in favor of using only the locateTLBusWrapper method.
  • @rmac-sifive's recent changes to sifive-blocks are compatible with this PR
  • Users can still make BaseSubsystem subclasses with statically defined subnetwork graphs and connect them to the dynamically-created topology. The dynamic topology can have nothing in it (though such a configuration will fail to build e.g. DefaultConfig in this repo). Set TLNetworkTopologyLocated("InSubsystem") => up(TLNetworkTopologyLocated("InSubsystem")).copy(connections = Nil) in your Config class to wire the standard bus locations together by hand.

Intended Usage

TLBusWrapperTopology is a serializable representation of a TileLink-based interconnect. A topology comprises instances of TLBusWrapper, a (previously existing) class which is an abstraction around a piece of interconnect fabric that provides some kind of connectivity between TileLink endpoints. There are currently several subtypes of TLBusWrapper, which each contain a particular crossbar, set of crossbars, chain of TL adapters, and/or internal devices. (In the future, some of these subtypes may just become parameterizations of a single base type.) TLBusWrappers have helper functions for attaching themselves to endpoint devices or to each other with configurable clock crossings.

The new TLBusWrapperTopology representation has two components, instances and connections.

Each instance is tuple that contains a Location and a TLBusWrapperInstantiationLike, where the former is a named reference to the latter, which can later be used when making connections between instances (or when attaching other things to the instance). A TLBusWrapperInstantiationLike is any class that knows how to instantiate a TLBusWrapper. The four previously-existing [Name]BusParams case classes all inherit from it and instantiate some particular TLBusWrapper subtype; the parameters are things like bus data width and parameters for internal devices and adapters' control interfaces.

Each connection is a triple that contains a pair of Locations and a TLBusWrapperConnectionLike, where the former pair identifies two previously instantiated TLBusWrappers, and the latter provides a method for actually programmatically connecting the instances. There is currently a single case class for describing parameterized connection between TLBusWrappers, named TLBusWrapperConnection.

A TLBusWrapperConnection contains the following serializable parameters:

  • xType: ClockCrossingType: what type of TL clock crossing adapter to insert between the buses. The appropriate half of the crossing adapter ends up inside each bus.
  • driveClockFromMaster: Option[Boolean]: if None, don't bind the bus's diplomatic clockGroupNode, otherwise have either the master or the slave bus bind the other one's clockGroupNode, assuming the inserted crossing type is not asynchronous.
  • nodeBinding: NodeBinding: fine-grained control of multi-edge cardinality resolution for diplomatic bindings within the connection.
  • flipRendering: Boolean: fine-grained control of the graphML rendering of the connection.
    There are also three programmatic escape hatches allowing users to inject custom node chains into the connection, or control the specific point within the TLBusWrapper that is connected to or from on either side.

Three example sub-topologies are defined, JustOneBusTopologyParams (sbus), HierarchicalBusTopologyParams (fbus, cbus, pbus) and CoherentBusTopologyParams (adds a coherence manager and mbus). These can be combined additively.

At the moment, the BaseSubsystem class looks up the TLNetworkTopologyLocated("InSubsystem") Field to discover its configurable topology. This call into the Parameters object could be replaced with reading in the topology from some serialized format. Given a topology, the subsystem first instantiates all instances, then connects all connections, passing in itself as the instantiating or connecting scope:

topology.foreach(_.instantiate(this))
topology.foreach(_.connect(this))

Related issues: #2034 #2025 #2078

Impact: API modification (but largely backward compatible)

Development Phase: implementation

Copy link
Contributor

@mwachs5 mwachs5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't fully wrapped my head around this. a little unclear which changes are things that are there to preserve backwards compatability and which are "the way to use now". Can these be marked a bit more clearly?

src/main/scala/subsystem/BusTopology.scala Show resolved Hide resolved
@hcook hcook force-pushed the config-topology branch from 1a97b46 to 99e1a12 Compare March 13, 2020 00:10
Copy link
Contributor

@rmac-sifive rmac-sifive left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed for usability and backwards compatibility and spent less time on the internal dynamic implementation. LGTM!

(SBUS, CBUS, TLBusWrapperCrossToConnection (xTypes.sbusToCbusXType)()),
(CBUS, PBUS, TLBusWrapperCrossToConnection (xTypes.cbusToPbusXType)()),
(SBUS, FBUS, TLBusWrapperCrossFromConnection(xTypes.fbusToSbusXType)()))
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉👍

src/main/scala/subsystem/BaseSubsystem.scala Show resolved Hide resolved
@hcook hcook force-pushed the config-topology branch from 99e1a12 to 33735d6 Compare March 24, 2020 01:31
@hcook hcook changed the title Make TLBusWrappers' topology a configurable Field [WIP] Make TLBusWrappers' topology a configurable Field Mar 26, 2020
@hcook hcook force-pushed the config-topology branch 5 times, most recently from e93ec18 to a944a46 Compare April 2, 2020 19:17
@hcook hcook force-pushed the config-topology branch 2 times, most recently from 93c43f6 to 5e0c5ee Compare April 8, 2020 16:40
@mwachs5
Copy link
Contributor

mwachs5 commented Apr 11, 2020

@hcook can you take a look at #2410 and see if that approach is advised given that this change is coming? Would like to get those OM changes in before this change if there is huge incompatibility. Since that PR is basically assuming BaseSubsystem has 4 bus variables wondering how it will interact with this

val pbus = tlBusWrapperLocationMap.lift(PBUS).getOrElse(sbus)
val fbus = tlBusWrapperLocationMap.lift(FBUS).getOrElse(sbus)
val mbus = tlBusWrapperLocationMap.lift(MBUS).getOrElse(sbus)
val cbus = tlBusWrapperLocationMap.lift(CBUS).getOrElse(sbus)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason there is no sbus in this list?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh NVM i see it is above

@hcook hcook force-pushed the config-topology branch 2 times, most recently from 258076a to 30cb4ea Compare April 15, 2020 19:43
@hcook hcook force-pushed the config-topology branch from 5522504 to def1061 Compare April 16, 2020 22:28
@hcook hcook merged commit 37fc327 into master Apr 17, 2020
@hcook hcook deleted the config-topology branch May 13, 2020 21:33
@DecodeTheEncoded
Copy link

is there some more detailed infomation I can get about the TLBusWrapper class?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants