Merge pull request #676 from ucb-bar/diplomatic-clocks-pll-redux
Simple Divider-Only PLL for Multiclock RTL Simulation
This commit is contained in:
42
generators/chipyard/src/main/resources/vsrc/ClockDividerN.sv
Normal file
42
generators/chipyard/src/main/resources/vsrc/ClockDividerN.sv
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unsynthesizable divide-by-N clock divider.
|
||||||
|
* Duty cycle is 100 * (ceil(DIV / 2)) / DIV.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module ClockDividerN #(parameter DIV)(output logic clk_out = 1'b0, input clk_in);
|
||||||
|
|
||||||
|
localparam CWIDTH = $clog2(DIV);
|
||||||
|
localparam LOW_CYCLES = DIV / 2;
|
||||||
|
localparam HIGH_TRANSITION = LOW_CYCLES - 1;
|
||||||
|
localparam LOW_TRANSITION = DIV - 1;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (DIV == 1) begin
|
||||||
|
// This needs to be procedural because of the assignment on declaration
|
||||||
|
always @(clk_in) begin
|
||||||
|
clk_out = clk_in;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
reg [CWIDTH - 1: 0] count = HIGH_TRANSITION[CWIDTH-1:0];
|
||||||
|
// The blocking assignment to clock out is used to conform what was done
|
||||||
|
// in RC's clock dividers.
|
||||||
|
// It should have the effect of preventing registers in the divided clock
|
||||||
|
// domain latching register updates launched by the fast clock-domain edge
|
||||||
|
// that occurs at the same simulated time (as the divided clock edge).
|
||||||
|
always @(posedge clk_in) begin
|
||||||
|
if (count == LOW_TRANSITION[CWIDTH-1:0]) begin
|
||||||
|
clk_out = 1'b0;
|
||||||
|
count <= '0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if (count == HIGH_TRANSITION[CWIDTH-1:0]) begin
|
||||||
|
clk_out = 1'b1;
|
||||||
|
end
|
||||||
|
count <= count + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule // ClockDividerN
|
||||||
@@ -31,7 +31,7 @@ class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunc
|
|||||||
val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
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
|
||||||
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters()))
|
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
||||||
|
|
||||||
// Generate Clocks and Reset
|
// Generate Clocks and Reset
|
||||||
p(ClockingSchemeKey)(this)
|
p(ClockingSchemeKey)(this)
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ import scala.collection.mutable.{ArrayBuffer}
|
|||||||
|
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
||||||
import freechips.rocketchip.config.{Parameters, Field}
|
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||||
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
|
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
|
||||||
import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider}
|
import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider}
|
||||||
|
|
||||||
import barstools.iocell.chisel._
|
import barstools.iocell.chisel._
|
||||||
|
|
||||||
|
import chipyard.clocking.{DividerOnlyClockGenerator, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chipyard provides three baseline, top-level reset schemes, set using the
|
* Chipyard provides three baseline, top-level reset schemes, set using the
|
||||||
* [[GlobalResetSchemeKey]] in a Parameters instance. These are:
|
* [[GlobalResetSchemeKey]] in a Parameters instance. These are:
|
||||||
@@ -77,99 +79,61 @@ object GenerateReset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
case object ClockingSchemeKey extends Field[ChipTop => Unit](ClockingSchemeGenerators.harnessClock)
|
case object ClockingSchemeKey extends Field[ChipTop => Unit](ClockingSchemeGenerators.dividerOnlyClockGenerator)
|
||||||
|
/*
|
||||||
|
* This is a Seq of assignment functions, that accept a clock name and return an optional frequency.
|
||||||
|
* Functions that appear later in this seq have higher precedence that earlier ones.
|
||||||
|
* If no function returns a non-empty value, the value specified in
|
||||||
|
* [[DefaultClockFrequencyKey]] will be used.
|
||||||
|
*/
|
||||||
|
case object ClockFrequencyAssignersKey extends Field[Seq[(String) => Option[Double]]](Seq.empty)
|
||||||
|
case object DefaultClockFrequencyKey extends Field[Double]()
|
||||||
|
|
||||||
|
class ClockNameMatchesAssignment(name: String, fMHz: Double) extends Config((site, here, up) => {
|
||||||
|
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
|
||||||
|
Seq((cName: String) => if (cName == name) Some(fMHz) else None)
|
||||||
|
})
|
||||||
|
|
||||||
|
class ClockNameContainsAssignment(name: String, fMHz: Double) extends Config((site, here, up) => {
|
||||||
|
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
|
||||||
|
Seq((cName: String) => if (cName.contains(name)) Some(fMHz) else None)
|
||||||
|
})
|
||||||
|
|
||||||
object ClockingSchemeGenerators {
|
object ClockingSchemeGenerators {
|
||||||
// A simple clock provider, for testing
|
val dividerOnlyClockGenerator: ChipTop => Unit = { chiptop =>
|
||||||
val harnessClock: ChipTop => Unit = { chiptop =>
|
|
||||||
implicit val p = chiptop.p
|
implicit val p = chiptop.p
|
||||||
|
|
||||||
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
|
// Requires existence of undriven asyncClockGroups in subsystem
|
||||||
chiptop.implicitClockSinkNode := implicitClockSourceNode
|
val systemAsyncClockGroup = chiptop.lazySystem match {
|
||||||
|
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) =>
|
||||||
// Drive the diplomaticclock graph of the DigitalTop (if present)
|
l.asyncClockGroupsNode
|
||||||
val simpleClockGroupSourceNode = chiptop.lazySystem match {
|
|
||||||
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
|
|
||||||
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
|
||||||
l.asyncClockGroupsNode := n
|
|
||||||
Some(n)
|
|
||||||
}
|
|
||||||
case _ => None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
|
||||||
|
chiptop.implicitClockSinkNode := ClockGroup() := aggregator
|
||||||
|
systemAsyncClockGroup := ClockGroupNamePrefixer() := aggregator
|
||||||
|
|
||||||
|
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
||||||
|
(aggregator
|
||||||
|
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||||
|
:= DividerOnlyClockGenerator()
|
||||||
|
:= referenceClockSource)
|
||||||
|
|
||||||
|
|
||||||
InModuleBody {
|
InModuleBody {
|
||||||
//this needs directionality so generateIOFromSignal works
|
|
||||||
val clock_wire = Wire(Input(Clock()))
|
val clock_wire = Wire(Input(Clock()))
|
||||||
val reset_wire = GenerateReset(chiptop, clock_wire)
|
val reset_wire = GenerateReset(chiptop, clock_wire)
|
||||||
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock")
|
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock")
|
||||||
chiptop.iocells ++= clockIOCell
|
chiptop.iocells ++= clockIOCell
|
||||||
|
|
||||||
implicitClockSourceNode.out.unzip._1.map { o =>
|
referenceClockSource.out.unzip._1.map { o =>
|
||||||
o.clock := clock_wire
|
o.clock := clock_wire
|
||||||
o.reset := reset_wire
|
o.reset := reset_wire
|
||||||
}
|
}
|
||||||
|
|
||||||
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
|
|
||||||
out.member.data.foreach { o =>
|
|
||||||
o.clock := clock_wire
|
|
||||||
o.reset := reset_wire
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
|
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
|
||||||
clock_io := th.harnessClock
|
clock_io := th.harnessClock
|
||||||
Nil
|
Nil })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val harnessDividedClock: ChipTop => Unit = { chiptop =>
|
|
||||||
implicit val p = chiptop.p
|
|
||||||
|
|
||||||
require(false, "Divided clock is broken until we fix passing onchip clocks to TestHarness objects")
|
|
||||||
|
|
||||||
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
|
|
||||||
chiptop.implicitClockSinkNode := implicitClockSourceNode
|
|
||||||
|
|
||||||
val simpleClockGroupSourceNode = chiptop.lazySystem match {
|
|
||||||
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
|
|
||||||
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
|
||||||
l.asyncClockGroupsNode := n
|
|
||||||
Some(n)
|
|
||||||
}
|
|
||||||
case _ => throw new Exception("Harness multiclock assumes BaseSubsystem")
|
|
||||||
}
|
|
||||||
|
|
||||||
InModuleBody {
|
|
||||||
// this needs directionality so generateIOFromSignal works
|
|
||||||
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
|
|
||||||
val div_clock = Pow2ClockDivider(clock_wire, 2)
|
|
||||||
|
|
||||||
implicitClockSourceNode.out.unzip._1.map { o =>
|
|
||||||
o.clock := div_clock
|
|
||||||
o.reset := reset_wire
|
|
||||||
}
|
|
||||||
|
|
||||||
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
|
|
||||||
out.member.elements.map { case (name, data) =>
|
|
||||||
// This is mega hacks, how are you actually supposed to do this?
|
|
||||||
data.clock := (if (name.contains("core")) clock_wire else div_clock)
|
|
||||||
data.reset := reset_wire
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
|
|
||||||
clock_io := th.harnessClock
|
|
||||||
Nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,7 @@ import sifive.blocks.devices.gpio._
|
|||||||
import sifive.blocks.devices.uart._
|
import sifive.blocks.devices.uart._
|
||||||
import sifive.blocks.devices.spi._
|
import sifive.blocks.devices.spi._
|
||||||
|
|
||||||
import chipyard.{BuildTop, BuildSystem, ClockingSchemeGenerators, ClockingSchemeKey, TestSuitesKey, TestSuiteHelper}
|
import chipyard._
|
||||||
|
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// Common Config Fragments
|
// Common Config Fragments
|
||||||
@@ -159,10 +158,6 @@ class WithNoSubsystemDrivenClocks extends Config((site, here, up) => {
|
|||||||
case SubsystemDriveAsyncClockGroupsKey => None
|
case SubsystemDriveAsyncClockGroupsKey => None
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithTileDividedClock extends Config((site, here, up) => {
|
|
||||||
case ClockingSchemeKey => ClockingSchemeGenerators.harnessDividedClock
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithDMIDTM extends Config((site, here, up) => {
|
class WithDMIDTM extends Config((site, here, up) => {
|
||||||
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
|
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
|
||||||
})
|
})
|
||||||
@@ -170,3 +165,10 @@ class WithDMIDTM extends Config((site, here, up) => {
|
|||||||
class WithNoDebug extends Config((site, here, up) => {
|
class WithNoDebug extends Config((site, here, up) => {
|
||||||
case DebugModuleKey => None
|
case DebugModuleKey => None
|
||||||
})
|
})
|
||||||
|
|
||||||
|
class WithTileFrequency(fMHz: Double) extends ClockNameContainsAssignment("core", fMHz)
|
||||||
|
|
||||||
|
class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
|
||||||
|
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble
|
||||||
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
|
||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util._
|
||||||
|
|
||||||
|
class ClockDividerN(div: Int) extends BlackBox(Map("DIV" -> div)) with HasBlackBoxResource {
|
||||||
|
require(div > 0);
|
||||||
|
val io = IO(new Bundle {
|
||||||
|
val clk_out = Output(Clock())
|
||||||
|
val clk_in = Input(Clock())
|
||||||
|
})
|
||||||
|
addResource("/vsrc/ClockDividerN.sv")
|
||||||
|
}
|
||||||
|
|
||||||
|
object ClockDivideByN {
|
||||||
|
def apply(clockIn: Clock, div: Int): Clock = {
|
||||||
|
val clockDivider = Module(new ClockDividerN(div))
|
||||||
|
clockDivider.io.clk_in := clockIn
|
||||||
|
clockDivider.io.clk_out
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.prci._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This sort of node can be used when it is a connectivity passthrough, but modifies
|
||||||
|
* the flow of parameters (which may result in changing the names of the underlying signals).
|
||||||
|
*/
|
||||||
|
class ClockGroupParameterModifier(
|
||||||
|
sourceFn: ClockGroupSourceParameters => ClockGroupSourceParameters = { m => m },
|
||||||
|
sinkFn: ClockGroupSinkParameters => ClockGroupSinkParameters = { s => s })(
|
||||||
|
implicit p: Parameters, v: ValName) extends LazyModule {
|
||||||
|
val node = ClockGroupAdapterNode(sourceFn, sinkFn)
|
||||||
|
lazy val module = new LazyRawModuleImp(this) {
|
||||||
|
(node.out zip node.in).map { case ((o, _), (i, _)) =>
|
||||||
|
(o.member.data zip i.member.data).foreach { case (oD, iD) => oD := iD }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes the ClockGroup's name into each member's name field as a prefix. This is
|
||||||
|
* intended to be used before a ClockGroupAggregator so that sources from
|
||||||
|
* different aggregated ClockGroups can be disambiguated by their names.
|
||||||
|
*/
|
||||||
|
object ClockGroupNamePrefixer {
|
||||||
|
def apply()(implicit p: Parameters, valName: ValName): ClockGroupAdapterNode =
|
||||||
|
LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.zipWithIndex.map { case (m, idx) =>
|
||||||
|
m.copy(name = m.name match {
|
||||||
|
// This matches what the chisel would do if the names were not modified
|
||||||
|
case Some(clockName) => Some(s"${s.name}_${clockName}")
|
||||||
|
case None => Some(s"${s.name}_${idx}")
|
||||||
|
})
|
||||||
|
})})).node
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Word from on high is that Strings are in...]
|
||||||
|
* Overrides the take field of all clocks in a group, by attempting to apply a
|
||||||
|
* series of assignment functions:
|
||||||
|
* (name: String) => freq-in-MHz: Option[Double]
|
||||||
|
* to each sink. Later functions that return non-empty values take priority.
|
||||||
|
* The default if all functions return None.
|
||||||
|
*/
|
||||||
|
object ClockGroupFrequencySpecifier {
|
||||||
|
def apply(
|
||||||
|
assigners: Seq[(String) => Option[Double]],
|
||||||
|
defaultFreq: Double)(
|
||||||
|
implicit p: Parameters, valName: ValName): ClockGroupAdapterNode = {
|
||||||
|
|
||||||
|
def lookupFrequencyForName(clock: ClockSinkParameters): ClockSinkParameters = {
|
||||||
|
require(clock.name.nonEmpty, "All clocks in clock group must have an assigned name")
|
||||||
|
val clockFreq = assigners.foldLeft(defaultFreq)(
|
||||||
|
(currentFreq, candidateFunc) => candidateFunc(clock.name.get).getOrElse(currentFreq))
|
||||||
|
|
||||||
|
clock.copy(take = clock.take match {
|
||||||
|
case Some(cp) =>
|
||||||
|
println(s"Clock ${clock.name.get}: using diplomatically specified frequency of ${cp.freqMHz}.")
|
||||||
|
Some(cp)
|
||||||
|
case None => Some(ClockParameters(clockFreq))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.map(lookupFrequencyForName)) })).node
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Parameters}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.prci._
|
||||||
|
import freechips.rocketchip.util.ElaborationArtefacts
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
import scala.collection.immutable.ListMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: figure out how much division is acceptable in our simulators and redefine this.
|
||||||
|
*/
|
||||||
|
object FrequencyUtils {
|
||||||
|
def computeReferenceFrequencyMHz(
|
||||||
|
requestedOutputs: Seq[ClockParameters],
|
||||||
|
maximumAllowableDivisor: Int = 0xFFFF): ClockParameters = {
|
||||||
|
require(requestedOutputs.nonEmpty)
|
||||||
|
require(!requestedOutputs.contains(0.0))
|
||||||
|
val freqs = requestedOutputs.map(f => BigInt(Math.round(f.freqMHz * 1000 * 1000)))
|
||||||
|
val refFreq = freqs.reduce((a, b) => a * b / a.gcd(b)).toDouble / (1000 * 1000)
|
||||||
|
assert((refFreq / freqs.min.toDouble) < maximumAllowableDivisor.toDouble)
|
||||||
|
ClockParameters(refFreq)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimplePllConfiguration(name: String, val sinks: Seq[ClockSinkParameters]) {
|
||||||
|
val referenceFreqMHz = FrequencyUtils.computeReferenceFrequencyMHz(sinks.flatMap(_.take)).freqMHz
|
||||||
|
val sinkDividerMap = ListMap((sinks.map({s => (s, Math.round(referenceFreqMHz / s.take.get.freqMHz).toInt) })):_*)
|
||||||
|
|
||||||
|
private val preamble = s"""
|
||||||
|
|${name} Frequency Summary
|
||||||
|
| Input Reference Frequency: ${referenceFreqMHz} MHz\n""".stripMargin
|
||||||
|
private val outputSummaries = sinkDividerMap.map { case (sink, division) =>
|
||||||
|
val requested = sink.take.get.freqMHz
|
||||||
|
val actual = referenceFreqMHz / division.toDouble
|
||||||
|
s" Output clock ${sink.name.get}, requested: ${requested} MHz, actual: ${actual} MHz (division of ${division})"
|
||||||
|
}
|
||||||
|
|
||||||
|
val summaryString = preamble + outputSummaries.mkString("\n")
|
||||||
|
ElaborationArtefacts.add(s"${name}.freq-summary", summaryString)
|
||||||
|
println(summaryString)
|
||||||
|
}
|
||||||
|
|
||||||
|
case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName)
|
||||||
|
extends MixedNexusNode(ClockImp, ClockGroupImp)(
|
||||||
|
dFn = { _ => ClockGroupSourceParameters() },
|
||||||
|
uFn = { u =>
|
||||||
|
require(u.size == 1)
|
||||||
|
require(!u.head.members.contains(None),
|
||||||
|
"All output clocks in group must set their take parameters. Use a ClockGroupDealiaser")
|
||||||
|
ClockSinkParameters(
|
||||||
|
name = Some(s"${pllName}_reference_input"),
|
||||||
|
take = Some(FrequencyUtils.computeReferenceFrequencyMHz(u.head.members.flatMap(_.take)))) }
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a digital-divider-only PLL model that verilator can simulate.
|
||||||
|
* Inspects all take-specified frequencies in the output ClockGroup, calculates a
|
||||||
|
* fast reference clock (roughly LCM(requested frequencies)) which is passed up the
|
||||||
|
* diplomatic graph, and then generates dividers for each unique requested
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule {
|
||||||
|
val node = DividerOnlyClockGeneratorNode(pllName)
|
||||||
|
|
||||||
|
lazy val module = new LazyRawModuleImp(this) {
|
||||||
|
require(node.out.size == 1, "Idealized PLL expects to generate a single output clock group. Use a ClockGroupAggregator")
|
||||||
|
val (refClock, ClockEdgeParameters(_, refSinkParam, _, _)) = node.in.head
|
||||||
|
val (outClocks, ClockGroupEdgeParameters(_, outSinkParams, _, _)) = node.out.head
|
||||||
|
|
||||||
|
val referenceFreq = refSinkParam.take.get.freqMHz
|
||||||
|
val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members)
|
||||||
|
|
||||||
|
val dividedClocks = mutable.HashMap[Int, Clock]()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) {
|
||||||
|
val div = pllConfig.sinkDividerMap(sinkP)
|
||||||
|
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
|
||||||
|
sinkB.reset := refClock.reset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object DividerOnlyClockGenerator {
|
||||||
|
def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new DividerOnlyClockGenerator(valName.name)).node
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ class AbstractConfig extends Config(
|
|||||||
new chipyard.config.WithUART ++ // add a UART
|
new chipyard.config.WithUART ++ // add a UART
|
||||||
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
|
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.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 freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port
|
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.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)
|
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
|
||||||
|
|||||||
@@ -174,10 +174,8 @@ class MMIORocketConfig extends Config(
|
|||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
// NOTE: This config doesn't work yet because SimWidgets in the TestHarness
|
|
||||||
// always get the TestHarness clock. The Tiles and Uncore receive the correct clocks
|
|
||||||
class DividedClockRocketConfig extends Config(
|
class DividedClockRocketConfig extends Config(
|
||||||
new chipyard.config.WithTileDividedClock ++ // Put the Tile on its own clock domain
|
new chipyard.config.WithTileFrequency(200.0) ++
|
||||||
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class AbstractTraceGenConfig extends Config(
|
|||||||
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
|
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
|
||||||
new chipyard.config.WithTracegenSystem ++
|
new chipyard.config.WithTracegenSystem ++
|
||||||
new chipyard.config.WithNoSubsystemDrivenClocks ++
|
new chipyard.config.WithNoSubsystemDrivenClocks ++
|
||||||
|
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++
|
||||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
|
||||||
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
|
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
|
||||||
|
|
||||||
|
|||||||
@@ -69,9 +69,7 @@ class WithSerialBridge extends OverrideHarnessBinder({
|
|||||||
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||||
ports.map { p =>
|
ports.map { p =>
|
||||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, p, th.harnessReset)
|
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, p, th.harnessReset)
|
||||||
withClockAndReset(p.clock, th.harnessReset) {
|
SerialBridge(p.clock, ram.module.io.tsi_ser, MainMemoryConsts.globalName)(GetSystemParameters(system))
|
||||||
SerialBridge(p.clock, ram.module.io.tsi_ser, MainMemoryConsts.globalName)(GetSystemParameters(system))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
@@ -80,7 +78,7 @@ class WithSerialBridge extends OverrideHarnessBinder({
|
|||||||
class WithNICBridge extends OverrideHarnessBinder({
|
class WithNICBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
(system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||||
val p: Parameters = GetSystemParameters(system)
|
val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { n => withClockAndReset(n.clock, th.harnessReset) { NICBridge(n.clock, n.bits)(p) } }
|
ports.map { n => NICBridge(n.clock, n.bits)(p) }
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -120,11 +118,7 @@ class WithFASEDBridge extends OverrideHarnessBinder({
|
|||||||
|
|
||||||
class WithTracerVBridge extends ComposeHarnessBinder({
|
class WithTracerVBridge extends ComposeHarnessBinder({
|
||||||
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
|
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
|
||||||
ports.map { p =>
|
ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
|
||||||
p.traces.map(
|
|
||||||
tileTrace => withClockAndReset(tileTrace.clock, tileTrace.reset) { TracerVBridge(tileTrace)(system.p) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,14 +8,15 @@ import chisel3.experimental.{IO}
|
|||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
||||||
import freechips.rocketchip.config.{Field, Config, Parameters}
|
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, InModuleBody}
|
import freechips.rocketchip.diplomacy.{LazyModule, InModuleBody, ValName}
|
||||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
import freechips.rocketchip.util.{ResetCatchAndSync, RecordMap}
|
||||||
|
|
||||||
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
|
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
|
||||||
|
|
||||||
import chipyard._
|
import chipyard._
|
||||||
import chipyard.harness._
|
import chipyard.harness._
|
||||||
import chipyard.iobinders._
|
import chipyard.iobinders._
|
||||||
|
import chipyard.clocking.{FrequencyUtils, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier, SimplePllConfiguration}
|
||||||
|
|
||||||
// Determines the number of times to instantiate the DUT in the harness.
|
// Determines the number of times to instantiate the DUT in the harness.
|
||||||
// Subsumes legacy supernode support
|
// Subsumes legacy supernode support
|
||||||
@@ -25,16 +26,6 @@ class WithNumNodes(n: Int) extends Config((pname, site, here) => {
|
|||||||
case NumNodes => n
|
case NumNodes => n
|
||||||
})
|
})
|
||||||
|
|
||||||
// Note, the main prerequisite for supporting an additional clock domain in a
|
|
||||||
// FireSim simulation is to supply an additional clock parameter
|
|
||||||
// (RationalClock) to the clock bridge (RationalClockBridge). The bridge
|
|
||||||
// produces a vector of clocks, based on the provided parameter list, which you
|
|
||||||
// may use freely without further modifications to your target design.
|
|
||||||
case class FireSimClockParameters(additionalClocks: Seq[RationalClock]) {
|
|
||||||
def numClocks(): Int = additionalClocks.size + 1
|
|
||||||
}
|
|
||||||
case object FireSimClockKey extends Field[FireSimClockParameters](FireSimClockParameters(Seq()))
|
|
||||||
|
|
||||||
// Hacky: Set before each node is generated. Ideally we'd give IO binders
|
// Hacky: Set before each node is generated. Ideally we'd give IO binders
|
||||||
// accesses to the the Harness's parameters instance. We could then alter that.
|
// accesses to the the Harness's parameters instance. We could then alter that.
|
||||||
object NodeIdx {
|
object NodeIdx {
|
||||||
@@ -43,107 +34,113 @@ object NodeIdx {
|
|||||||
def apply(): Int = idx
|
def apply(): Int = idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Under FireSim's current multiclock implementation there can be only a
|
||||||
|
* single clock bridge. This requires, therefore, that it be instantiated in
|
||||||
|
* the harness and reused across all supernode instances. This class attempts to
|
||||||
|
* memoize its instantiation such that it can be referenced from within a ClockScheme function.
|
||||||
|
*/
|
||||||
|
class ClockBridgeInstantiator {
|
||||||
|
private var _clockRecord: Option[RecordMap[Clock]] = None
|
||||||
|
|
||||||
|
def getClockRecord: RecordMap[Clock] = _clockRecord.get
|
||||||
|
|
||||||
|
def getClockRecordOrInstantiate(allClocks: Seq[RationalClock], baseClockName: String): RecordMap[Clock] = {
|
||||||
|
if (_clockRecord.isEmpty) {
|
||||||
|
require(allClocks.exists(_.name == baseClockName),
|
||||||
|
s"Provided base-clock name, ${baseClockName}, does not match a defined clock. Available clocks:\n " +
|
||||||
|
allClocks.map(_.name).mkString("\n "))
|
||||||
|
|
||||||
|
val baseClock = allClocks.find(_.name == baseClockName).get
|
||||||
|
val simplified = allClocks.map { c =>
|
||||||
|
c.copy(multiplier = c.multiplier * baseClock.divisor, divisor = c.divisor * baseClock.multiplier)
|
||||||
|
.simplify
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes clocks that have the same frequency before instantiating the
|
||||||
|
* clock bridge to avoid unnecessary BUFGCE use.
|
||||||
|
*/
|
||||||
|
val distinct = simplified.foldLeft(Seq(RationalClock(baseClockName, 1, 1))) { case (list, candidate) =>
|
||||||
|
if (list.exists { clock => clock.equalFrequency(candidate) }) list else list :+ candidate
|
||||||
|
}
|
||||||
|
|
||||||
|
val clockBridge = Module(new RationalClockBridge(distinct))
|
||||||
|
val cbVecTuples = distinct.zip(clockBridge.io.clocks)
|
||||||
|
val outputWire = Wire(RecordMap(simplified.map { c => (c.name, Clock()) }:_*))
|
||||||
|
for (parameter <- simplified) {
|
||||||
|
val (_, cbClockField) = cbVecTuples.find(_._1.equalFrequency(parameter)).get
|
||||||
|
outputWire(parameter.name).get := cbClockField
|
||||||
|
}
|
||||||
|
_clockRecord = Some(outputWire)
|
||||||
|
}
|
||||||
|
getClockRecord
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case object ClockBridgeInstantiatorKey extends Field[ClockBridgeInstantiator](new ClockBridgeInstantiator)
|
||||||
|
case object FireSimBaseClockNameKey extends Field[String]("implicit_clock")
|
||||||
|
|
||||||
class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
||||||
case ClockingSchemeKey => { chiptop: ChipTop =>
|
case ClockingSchemeKey => { chiptop: ChipTop =>
|
||||||
implicit val p = chiptop.p
|
implicit val p = chiptop.p
|
||||||
|
// Figure out what provides this in the chipyard scheme
|
||||||
|
implicit val valName = ValName("FireSimClocking")
|
||||||
|
|
||||||
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
|
// Requires existence of undriven asyncClockGroups in subsystem
|
||||||
chiptop.implicitClockSinkNode := implicitClockSourceNode
|
val systemAsyncClockGroup = chiptop.lazySystem match {
|
||||||
|
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) =>
|
||||||
// Drive the diplomaticclock graph of the DigitalTop (if present)
|
l.asyncClockGroupsNode
|
||||||
val simpleClockGroupSourceNode = chiptop.lazySystem match {
|
|
||||||
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
|
|
||||||
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
|
||||||
l.asyncClockGroupsNode := n
|
|
||||||
Some(n)
|
|
||||||
}
|
|
||||||
case _ => None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
|
||||||
|
(chiptop.implicitClockSinkNode := ClockGroup() := aggregator)
|
||||||
|
(systemAsyncClockGroup := ClockGroupNamePrefixer() := aggregator)
|
||||||
|
|
||||||
|
val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
||||||
|
|
||||||
|
(aggregator
|
||||||
|
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||||
|
:= inputClockSource)
|
||||||
|
|
||||||
|
|
||||||
InModuleBody {
|
InModuleBody {
|
||||||
val clock = IO(Input(Clock())).suggestName("clock")
|
val (clockGroupBundle, clockGroupEdge) = inputClockSource.out.head
|
||||||
|
val input_clocks = IO(Input(RecordMap((clockGroupEdge.sink.members.map { m => (m.name.get, Clock()) }):_* )))
|
||||||
|
.suggestName("clocks")
|
||||||
val reset = IO(Input(Reset())).suggestName("reset")
|
val reset = IO(Input(Reset())).suggestName("reset")
|
||||||
|
|
||||||
implicitClockSourceNode.out.unzip._1.map { o =>
|
(clockGroupBundle.member.data zip input_clocks.data).foreach { case (clockBundle, inputClock) =>
|
||||||
o.clock := clock
|
clockBundle.clock := inputClock
|
||||||
o.reset := reset
|
|
||||||
}
|
}
|
||||||
|
|
||||||
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
|
// Assign resets. The synchronization scheme is still WIP.
|
||||||
out.member.data.foreach { o =>
|
for ((name, clockBundle) <- clockGroupBundle.member.elements) {
|
||||||
o.clock := clock
|
if (name.contains("core")) {
|
||||||
o.reset := reset
|
clockBundle.reset := ResetCatchAndSync(clockBundle.clock, reset.asBool)
|
||||||
|
} else {
|
||||||
|
clockBundle.reset := reset
|
||||||
}
|
}
|
||||||
}}
|
}
|
||||||
|
|
||||||
|
val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)
|
||||||
|
val rationalClockSpecs = for ((sinkP, division) <- pllConfig.sinkDividerMap) yield {
|
||||||
|
RationalClock(sinkP.name.get, 1, division)
|
||||||
|
}
|
||||||
|
|
||||||
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
|
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
|
||||||
clock := th.harnessClock
|
|
||||||
reset := th.harnessReset
|
reset := th.harnessReset
|
||||||
Nil
|
input_clocks := p(ClockBridgeInstantiatorKey)
|
||||||
})
|
.getClockRecordOrInstantiate(rationalClockSpecs.toSeq, p(FireSimBaseClockNameKey))
|
||||||
}
|
Nil })
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithFireSimRationalTileDomain(multiplier: Int, divisor: Int) extends Config((site, here, up) => {
|
|
||||||
case FireSimClockKey => FireSimClockParameters(Seq(RationalClock("TileDomain", multiplier, divisor)))
|
|
||||||
case ClockingSchemeKey => { chiptop: ChipTop =>
|
|
||||||
implicit val p = chiptop.p
|
|
||||||
|
|
||||||
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
|
|
||||||
chiptop.implicitClockSinkNode := implicitClockSourceNode
|
|
||||||
|
|
||||||
// Drive the diplomaticclock graph of the DigitalTop (if present)
|
|
||||||
val simpleClockGroupSourceNode = chiptop.lazySystem match {
|
|
||||||
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
|
|
||||||
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
|
||||||
l.asyncClockGroupsNode := n
|
|
||||||
Some(n)
|
|
||||||
}
|
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
|
|
||||||
InModuleBody {
|
|
||||||
val uncore_clock = IO(Input(Clock())).suggestName("uncore_clock")
|
|
||||||
val tile_clock = IO(Input(Clock())).suggestName("tile_clock")
|
|
||||||
val reset = IO(Input(Reset())).suggestName("reset")
|
|
||||||
|
|
||||||
implicitClockSourceNode.out.unzip._1.map { o =>
|
|
||||||
o.clock := uncore_clock
|
|
||||||
o.reset := reset
|
|
||||||
}
|
|
||||||
|
|
||||||
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
|
|
||||||
out.member.elements.map { case (name, data) =>
|
|
||||||
// This is mega hacks, how are you actually supposed to do this?
|
|
||||||
if (name.contains("core")) {
|
|
||||||
data.clock := tile_clock
|
|
||||||
data.reset := ResetCatchAndSync(tile_clock, reset.asBool)
|
|
||||||
} else {
|
|
||||||
data.clock := uncore_clock
|
|
||||||
data.reset := reset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
|
|
||||||
uncore_clock := th.harnessClock
|
|
||||||
reset := th.harnessReset
|
|
||||||
th match {
|
|
||||||
case f: FireSim => tile_clock := f.additionalClocks(0)
|
|
||||||
case _ => throw new Exception("FireSimMultiClock must be used with FireSim")
|
|
||||||
}
|
|
||||||
Nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSignalReferences {
|
class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSignalReferences {
|
||||||
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
|
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
|
||||||
val clockBridge = Module(new RationalClockBridge(p(FireSimClockKey).additionalClocks:_*))
|
val harnessClock = Wire(Clock())
|
||||||
val harnessClock = clockBridge.io.clocks.head // This is the reference clock
|
|
||||||
val additionalClocks = clockBridge.io.clocks.tail
|
|
||||||
val harnessReset = WireInit(false.B)
|
val harnessReset = WireInit(false.B)
|
||||||
val peekPokeBridge = PeekPokeBridge(harnessClock, harnessReset)
|
val peekPokeBridge = PeekPokeBridge(harnessClock, harnessReset)
|
||||||
def dutReset = { require(false, "dutReset should not be used in Firesim"); false.B }
|
def dutReset = { require(false, "dutReset should not be used in Firesim"); false.B }
|
||||||
@@ -165,8 +162,7 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSigna
|
|||||||
d.harnessFunctions.foreach(_(this))
|
d.harnessFunctions.foreach(_(this))
|
||||||
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
|
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NodeIdx.increment()
|
NodeIdx.increment()
|
||||||
}
|
}
|
||||||
|
harnessClock := p(ClockBridgeInstantiatorKey).getClockRecord("implicit_clock").get
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class FireSimArianeConfig extends Config(
|
|||||||
//* Multiclock Configurations
|
//* Multiclock Configurations
|
||||||
//*********************************************************************************/
|
//*********************************************************************************/
|
||||||
class FireSimMulticlockRocketConfig extends Config(
|
class FireSimMulticlockRocketConfig extends Config(
|
||||||
new WithFireSimRationalTileDomain(2, 1) ++
|
new chipyard.config.WithTileFrequency(6400.0) ++ //lol
|
||||||
new WithDefaultFireSimBridges ++
|
new WithDefaultFireSimBridges ++
|
||||||
new WithDefaultMemModel ++
|
new WithDefaultMemModel ++
|
||||||
new WithFireSimConfigTweaks ++
|
new WithFireSimConfigTweaks ++
|
||||||
|
|||||||
Submodule sims/firesim updated: 3dbe8aee3f...801baeb901
Reference in New Issue
Block a user