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

AXI Memory Over TL Serial Link #812

Merged
merged 34 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
79eccce
Small comments to Clocks.scala
abejgonzalez Feb 27, 2021
a3e22c7
First attempt at getting Offchip AXI port
abejgonzalez Feb 28, 2021
1d287be
Enlarge serial width | Bugfix loadmem disable | Add TracerV
abejgonzalez Mar 3, 2021
f850df7
General renaming / cleanup
abejgonzalez Mar 3, 2021
c52fce7
Fix FireChip compilation | Remove extra DefaultSerialTL in bridges
abejgonzalez Mar 3, 2021
3d96218
Cleanup | Fix BlockDevice clocking issues
abejgonzalez Mar 3, 2021
3d9cd61
Slightly cleaner implementation
abejgonzalez Mar 4, 2021
d2a6dd6
Add support for harness pll
abejgonzalez Mar 5, 2021
60a616e
1st pass at connecting to harness PLL | Put UART adapter on harnessCl…
abejgonzalez Mar 5, 2021
2b7e359
Cleanup config + fragments | Remove reference clk div/rst catch in ha…
abejgonzalez Mar 5, 2021
562d8e5
Distinguish between implicit clock/reset and reference harnessClock/R…
abejgonzalez Mar 6, 2021
6ab8f8f
Update FireSim to support harness clocks | Small config renaming
abejgonzalez Mar 8, 2021
e4ccfe1
Renaming updates | Have FireSim clocks request frequency by default
abejgonzalez Mar 8, 2021
ade8457
First doc pass (no updated imgs) [ci skip]
abejgonzalez Mar 9, 2021
d5d547d
Update doc images [ci skip]
abejgonzalez Mar 9, 2021
ed6d10a
Merge remote-tracking branch 'origin/dev' into offchip-axi-setup
abejgonzalez Mar 9, 2021
6e1b942
Fix docs harness binders reference
abejgonzalez Mar 9, 2021
d204ccd
Clean up the chip communication docs a bit more [ci skip]
abejgonzalez Mar 10, 2021
1ebc0f7
Allow the PLL to request the max freq
abejgonzalez Mar 11, 2021
30c9b63
More clarifications on harness clocks
abejgonzalez Mar 11, 2021
6476c7e
Small renaming/cleanup | Use LinkedHashMaps
abejgonzalez Mar 15, 2021
3439266
Small renaming in docs
abejgonzalez Mar 15, 2021
5301723
Use def instead of var Option for ref frequency
abejgonzalez Mar 17, 2021
7b7bcf7
Merge remote-tracking branch 'origin/dev' into offchip-axi-setup
abejgonzalez Mar 19, 2021
4a56508
Small spacing fixes
abejgonzalez Mar 19, 2021
0d6e971
Update docs/Advanced-Concepts/Chip-Communication.rst
abejgonzalez Mar 19, 2021
1e42113
Splitting up FireSim default frequencies into a separate config frag.
abejgonzalez Mar 20, 2021
b729a5f
Allow run-asm/bmark debug make targets to specify random seed
abejgonzalez Mar 20, 2021
87fa481
Fix TileResetCtrl so that tiles come out of reset after rest of uncore
abejgonzalez Mar 20, 2021
d24bd11
Merge branch 'offchip-axi-setup' of github.com:ucb-bar/chipyard into …
abejgonzalez Mar 20, 2021
f59a790
Bump testchipip
abejgonzalez Mar 20, 2021
5526397
Use async queue to connect serdesser + other components
abejgonzalez Mar 20, 2021
5ffad32
Bump testchipip
abejgonzalez Mar 21, 2021
09ef82c
Update harnessClk/Rst naming to buildtop | Small docs cleanup
abejgonzalez Mar 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion generators/chipyard/src/main/scala/ChipTop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ChipTop(implicit p: Parameters) extends LazyModule with BindingScope
// The system module specified by BuildSystem
lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")

// The implicitClockSinkNode provides the implicit clock and reset for the System
// The implicitClockSinkNode provides the implicit clock and reset for the system (connected by clocking scheme)
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))

// Generate Clocks and Reset
Expand Down
15 changes: 13 additions & 2 deletions generators/chipyard/src/main/scala/Clocks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ case object ClockingSchemeKey extends Field[ChipTop => Unit](ClockingSchemeGener
*/
case object ClockFrequencyAssignersKey extends Field[Seq[(String) => Option[Double]]](Seq.empty)
case object DefaultClockFrequencyKey extends Field[Double]()
case object ReferenceClockTrackerKey extends Field[ReferenceClockTracker](new ReferenceClockTracker)
class ReferenceClockTracker {
abejgonzalez marked this conversation as resolved.
Show resolved Hide resolved
private var _refFreqMHz: Option[Double] = None
def set(freqMHz: Double): Unit = { _refFreqMHz = Some(freqMHz) }
def get: Option[Double] = { _refFreqMHz }
}

class ClockNameMatchesAssignment(name: String, fMHz: Double) extends Config((site, here, up) => {
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
Expand Down Expand Up @@ -75,28 +81,33 @@ object ClockingSchemeGenerators {
}

val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
// provides the implicit clock to the system
(chiptop.implicitClockSinkNode
:= ClockGroup()
:= aggregator)
// provides the system clock (ex. the bus clocks)
(systemAsyncClockGroup
:*= resetSetter
:*= ClockGroupNamePrefixer()
:*= aggregator)

val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
val dividerOnlyClkGenerator = DividerOnlyClockGenerator()
// provides all the divided clocks (from the top-level clock)
(aggregator
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
:= ClockGroupResetSynchronizer()
:= DividerOnlyClockGenerator()
:= dividerOnlyClkGenerator.node
:= referenceClockSource)


InModuleBody {
val clock_wire = Wire(Input(Clock()))
val reset_wire = GenerateReset(chiptop, clock_wire)
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock")
chiptop.iocells ++= clockIOCell

p(ReferenceClockTrackerKey).set(dividerOnlyClkGenerator.module.referenceFreq)

abejgonzalez marked this conversation as resolved.
Show resolved Hide resolved
referenceClockSource.out.unzip._1.map { o =>
o.clock := clock_wire
o.reset := reset_wire
Expand Down
15 changes: 14 additions & 1 deletion generators/chipyard/src/main/scala/ConfigFragments.scala
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,20 @@ class WithTLBackingMemory extends Config((site, here, up) => {
case ExtTLMem => up(ExtMem, site) // enable TL backing memory
})

class WithTileFrequency(fMHz: Double) extends ClockNameContainsAssignment("core", fMHz)
class WithSerialTLBackingMemory extends Config((site, here, up) => {
case ExtMem => None
case SerialTLKey => up(SerialTLKey, site).map { k => k.copy(
memParams = {
val memPortParams = up(ExtMem, site).get
require(memPortParams.nMemoryChannels == 1)
colinschmidt marked this conversation as resolved.
Show resolved Hide resolved
memPortParams.master
},
isMemoryDevice = true
)}
})

class WithTileFrequency(fMHz: Double) extends ClockNameContainsAssignment("tile", fMHz)
abejgonzalez marked this conversation as resolved.
Show resolved Hide resolved
class WithSpecificTileFrequency(hartId: Int, fMHz: Double) extends chipyard.ClockNameContainsAssignment(s"tile_$hartId", fMHz)

class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble
Expand Down
46 changes: 44 additions & 2 deletions generators/chipyard/src/main/scala/HarnessBinders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import barstools.iocell.chisel._

import testchipip._

import chipyard.HasHarnessSignalReferences
import chipyard.{HasHarnessSignalReferences, HarnessClockInstantiatorKey}
import chipyard.iobinders.GetSystemParameters

import tracegen.{TraceGenSystemModuleImp}
Expand Down Expand Up @@ -83,7 +83,9 @@ class WithGPIOTiedOff extends OverrideHarnessBinder({
// DOC include start: WithUARTAdapter
class WithUARTAdapter extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
UARTAdapter.connect(ports)(system.p)
withClockAndReset(th.harnessClock, th.harnessReset) {
UARTAdapter.connect(ports)(system.p)
abejgonzalez marked this conversation as resolved.
Show resolved Hide resolved
}
}
})
// DOC include end: WithUARTAdapter
Expand Down Expand Up @@ -139,6 +141,46 @@ class WithSimAXIMem extends OverrideHarnessBinder({
}
})

class WithSimAXIMemOverSerialTL extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)

p(SerialTLKey).map({ sVal =>
// currently only the harness AXI port supports a passthrough clock
require(sVal.axiMemOverSerialTLParams.isDefined)
val axiDomainParams = sVal.axiMemOverSerialTLParams.get

val memFreq: Double = axiDomainParams.axiClockParams match {
case Some(clkParams) => clkParams.clockFreqMHz * 1000000
case None => {
// get freq. from what the master of the serial link specifies
system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(p(SerialTLAttachKey).masterWhere).dtsFrequency.get.toDouble
}
}

ports.map({ port =>
val harnessMultiClockAXIRAM = SerialAdapter.connectHarnessMultiClockAXIRAM(
system.serdesser.get,
port,
p(HarnessClockInstantiatorKey).getClockBundleWire("mem_over_serial_tl_clock", memFreq),
th.harnessReset)
val success = SerialAdapter.connectSimSerial(harnessMultiClockAXIRAM.module.io.tsi_ser, port.clock, th.harnessReset.asBool)
when (success) { th.success := true.B }

// connect SimDRAM from the AXI port coming from the harness multi clock axi ram
(harnessMultiClockAXIRAM.mem_axi4 zip harnessMultiClockAXIRAM.memNode.edges.in).map { case (axi_port, edge) =>
val memSize = sVal.memParams.size
val lineSize = p(CacheBlockBytes)
val mem = Module(new SimDRAM(memSize, lineSize, BigInt(memFreq.toInt), edge.bundle)).suggestName("simdram")
mem.io.axi <> axi_port.bits
mem.io.clock := axi_port.clock
mem.io.reset := axi_port.reset
}
})
})
}
})

class WithBlackBoxSimMem(additionalLatency: Int = 0) extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
Expand Down
1 change: 0 additions & 1 deletion generators/chipyard/src/main/scala/IOBinders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ class WithSerialTLIOCells extends OverrideIOBinder({
}).getOrElse((Nil, Nil))
})


class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
(system: CanHaveMasterAXI4MemPort) => {
implicit val p: Parameters = GetSystemParameters(system)
Expand Down
61 changes: 56 additions & 5 deletions generators/chipyard/src/main/scala/TestHarness.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package chipyard

import chisel3._
import scala.collection.mutable.{ArrayBuffer}

import scala.collection.mutable.{ArrayBuffer, HashMap}
import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.util.{ResetCatchAndSync}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters}

import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
import chipyard.iobinders.HasIOBinders
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}

// -------------------------------
// Chipyard Test Harness
Expand All @@ -25,6 +29,47 @@ trait HasHarnessSignalReferences {
def success: Bool
}

class HarnessClockInstantiator {
private var _clockMap: HashMap[String, (Double, ClockBundle)] = HashMap.empty
Copy link
Contributor

Choose a reason for hiding this comment

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

I think in general it is better to use a SortedMap that keeps orderings when building Chisel hardware to keep names stable.
See: chipsalliance/rocket-chip@f86489b for example

I can't quite tell if this will be an issue in this case but I don't think it will hurt.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, erring on the side of ordered maps is a good idea in general. It's not like these things are performance critical. Probably just a LinkedHashMap would do.


abejgonzalez marked this conversation as resolved.
Show resolved Hide resolved
// request a clock bundle at a particular frequency
def getClockBundleWire(name: String, freqRequested: Double): ClockBundle = {
val clockBundle = Wire(new ClockBundle(ClockBundleParameters()))
_clockMap(name) = (freqRequested, clockBundle)
clockBundle
}

// connect all clock wires specified to a divider only PLL
def instantiateHarnessDividerPLL(refClock: ClockBundle): Unit = {
val sinks = _clockMap.map({ case (name, (freq, bundle)) =>
ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq/1000000)),name=Some(name))
}).toSeq

val pllConfig = new SimplePllConfiguration("harnessDividerOnlyClockGenerator", sinks)
pllConfig.emitSummaries()

val dividedClocks = HashMap[Int, Clock]()
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this HashMap is ok because we don't iterate over it to create hardware.

def instantiateDivider(div: Int): Clock = {
val divider = Module(new ClockDividerN(div))
divider.suggestName(s"ClockDivideBy${div}")
divider.io.clk_in := refClock.clock
dividedClocks(div) = divider.io.clk_out
divider.io.clk_out
}

// TODO: on the implicit clock just create a passthrough (don't instantiate a divider + reset catch)
// connect wires to clock source
for (sinkParams <- sinks) {
val div = pllConfig.sinkDividerMap(sinkParams)
val divClock = dividedClocks.getOrElse(div, instantiateDivider(div))
_clockMap(sinkParams.name.get)._2.clock := divClock
_clockMap(sinkParams.name.get)._2.reset := ResetCatchAndSync(divClock, refClock.reset.asBool)
}
}
}

case object HarnessClockInstantiatorKey extends Field[HarnessClockInstantiator](new HarnessClockInstantiator)

class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSignalReferences {
val io = IO(new Bundle {
val success = Output(Bool())
Expand All @@ -34,17 +79,23 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign
val dut = Module(lazyDut.module)
io.success := false.B

val harnessClock = clock
val harnessReset = WireInit(reset)
val (harnessClock, harnessReset, dutReset) = {
val freqMHz = p(ReferenceClockTrackerKey).get.getOrElse(100.0) // default to 100MHz
val bundle = p(HarnessClockInstantiatorKey).getClockBundleWire("implicit_harness_clock", freqMHz*1000000.0)
(bundle.clock, WireInit(bundle.reset), bundle.reset.asAsyncReset)
}
val success = io.success

val dutReset = reset.asAsyncReset

lazyDut match { case d: HasTestHarnessFunctions =>
d.harnessFunctions.foreach(_(this))
}
lazyDut match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}

val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := clock
implicitHarnessClockBundle.reset := reset
p(HarnessClockInstantiatorKey).instantiateHarnessDividerPLL(implicitHarnessClockBundle)
}

Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,5 @@ class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName
}

object DividerOnlyClockGenerator {
def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new DividerOnlyClockGenerator(valName.name)).node
def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new DividerOnlyClockGenerator(valName.name))
Copy link
Contributor

Choose a reason for hiding this comment

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

Just delete this helper object if we have to reference the module after construction

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, or leave the return type as a node, which is the convention for LazyModule companion object apply methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll probably just delete the helper object.

}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,3 @@ class AbstractConfig extends Config(
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts
new chipyard.WithMulticlockCoherentBusTopology ++ // hierarchical buses including mbus+l2
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system

22 changes: 21 additions & 1 deletion generators/chipyard/src/main/scala/config/RocketConfigs.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package chipyard

import freechips.rocketchip.config.{Config}
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
import freechips.rocketchip.diplomacy.{AsynchronousCrossing, RationalCrossing}
import freechips.rocketchip.util.{SlowToFast}

// --------------
// Rocket Configs
Expand Down Expand Up @@ -212,3 +213,22 @@ class LBWIFRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove AXI4 backing memory
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)

class MulticlockAXIOverSerialConfig extends Config(
new chipyard.config.WithFbusToSbusCrossingType(RationalCrossing(SlowToFast)) ++

new chipyard.config.WithSystemBusFrequencyAsDefault ++
new chipyard.config.WithSystemBusFrequency(4000) ++
new chipyard.config.WithPeripheryBusFrequency(4000) ++
abejgonzalez marked this conversation as resolved.
Show resolved Hide resolved
new chipyard.config.WithMemoryBusFrequency(4000) ++

new chipyard.config.WithFrontBusFrequency(4000 / 2) ++

new chipyard.config.WithFbusToSbusCrossingType(RationalCrossing(SlowToFast)) ++
new testchipip.WithAsynchronousSerialSlaveCrossing ++

new chipyard.harness.WithSimAXIMemOverSerialTL ++ // add SimDRAM DRAM model for axi4 backing memory over the SerDes link, if axi4 mem is enabled
new chipyard.config.WithSerialTLBackingMemory ++ // remove axi4 mem port in favor of SerialTL memory

new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
35 changes: 34 additions & 1 deletion generators/firechip/src/main/scala/BridgeBinders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,40 @@ class WithUARTBridge extends OverrideHarnessBinder({
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.harnessReset.toBool) }
ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.asBool) }
Nil
colinschmidt marked this conversation as resolved.
Show resolved Hide resolved
}
})

class WithAXIOverSerialTLCombinedBridges extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[SerialAndPassthroughClockResetIO]) => {
implicit val p = GetSystemParameters(system)

p(SerialTLKey).map({ sVal =>
// require having memory over the serdes link
require(sVal.isMemoryDevice)

ports.map({ port =>
val offchipNetwork = SerialAdapter.connectHarnessMultiClockAXIRAM(system.serdesser.get, port, th.harnessReset)
SerialBridge(port.clocked_serial.clock, offchipNetwork.module.io.tsi_ser, Some(MainMemoryConsts.globalName))

// connect SimAxiMem
(offchipNetwork.mem_axi4 zip offchipNetwork.memAXI4Node.edges.in).map { case (axi4, edge) =>
val nastiKey = NastiParameters(axi4.r.bits.data.getWidth,
axi4.ar.bits.addr.getWidth,
axi4.ar.bits.id.getWidth)
system match {
case s: BaseSubsystem => FASEDBridge(port.passthrough_clock_reset.clock, axi4, port.passthrough_clock_reset.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
}
})
Expand Down
Loading