1
0

Merge pull request #993 from freechipsproject/auto-diplomacy-bundles

Auto diplomacy bundles
This commit is contained in:
Wesley W. Terpstra 2017-09-27 17:39:53 -07:00 committed by GitHub
commit e315a7aaa7
101 changed files with 1021 additions and 1371 deletions

View File

@ -0,0 +1,23 @@
// See LICENSE.SiFive for license details.
package freechips.rocketchip.macros
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
case class ValNameImpl(name: String)
object ValNameImpl
{
implicit def materialize: ValNameImpl = macro detail
def detail(c: Context): c.Expr[ValNameImpl] = {
import c.universe._
def allOwners(s: c.Symbol): Seq[c.Symbol] =
if (s == `NoSymbol`) Nil else s +: allOwners(s.owner)
val terms = allOwners(c.internal.enclosingOwner).filter(_.isTerm).map(_.asTerm)
terms.filter(_.isVal).map(_.name.toString).find(_(0) != '$').map { s =>
val trim = s.replaceAll("\\s", "")
c.Expr[ValNameImpl] { q"_root_.freechips.rocketchip.macros.ValNameImpl(${trim})" }
}.getOrElse(c.abort(c.enclosingPosition, "Not a valid application."))
}
}

View File

@ -21,7 +21,8 @@ object BuildSettings extends Build {
lazy val chisel = project in file("chisel3")
lazy val hardfloat = project.dependsOn(chisel)
lazy val rocketchip = (project in file(".")).settings(chipSettings).dependsOn(chisel, hardfloat)
lazy val macros = project in file("macros")
lazy val rocketchip = (project in file(".")).settings(chipSettings).dependsOn(chisel, hardfloat, macros)
lazy val addons = settingKey[Seq[String]]("list of addons used for this build")
lazy val make = inputKey[Unit]("trigger backend-specific makefile command")

View File

@ -4,19 +4,14 @@ package freechips.rocketchip.amba.ahb
import Chisel._
import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBEdgeParameters, AHBBundle]
object AHBImp extends SimpleNodeImp[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle]
{
def edgeO(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters): AHBEdgeParameters = AHBEdgeParameters(pd, pu)
def edgeI(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters): AHBEdgeParameters = AHBEdgeParameters(pd, pu)
def bundleO(eo: AHBEdgeParameters): AHBBundle = AHBBundle(eo.bundle)
def bundleI(ei: AHBEdgeParameters): AHBBundle = AHBBundle(ei.bundle)
def colour = "#00ccff" // bluish
override def labelI(ei: AHBEdgeParameters) = (ei.slave.beatBytes * 8).toString
override def labelO(eo: AHBEdgeParameters) = (eo.slave.beatBytes * 8).toString
def edge(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = AHBEdgeParameters(pd, pu, p, sourceInfo)
def bundle(e: AHBEdgeParameters) = AHBBundle(e.bundle)
def render(e: AHBEdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, label = (e.slave.beatBytes * 8).toString)
override def mixO(pd: AHBMasterPortParameters, node: OutwardNode[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle]): AHBMasterPortParameters =
pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) })
@ -25,23 +20,14 @@ object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, A
}
// Nodes implemented inside modules
case class AHBIdentityNode() extends IdentityNode(AHBImp)
case class AHBMasterNode(portParams: Seq[AHBMasterPortParameters]) extends SourceNode(AHBImp)(portParams)
case class AHBSlaveNode(portParams: Seq[AHBSlavePortParameters]) extends SinkNode(AHBImp)(portParams)
case class AHBMasterNode(portParams: Seq[AHBMasterPortParameters])(implicit valName: ValName) extends SourceNode(AHBImp)(portParams)
case class AHBSlaveNode(portParams: Seq[AHBSlavePortParameters])(implicit valName: ValName) extends SinkNode(AHBImp)(portParams)
case class AHBNexusNode(
masterFn: Seq[AHBMasterPortParameters] => AHBMasterPortParameters,
slaveFn: Seq[AHBSlavePortParameters] => AHBSlavePortParameters,
numMasterPorts: Range.Inclusive = 1 to 999,
numSlavePorts: Range.Inclusive = 1 to 999)
numSlavePorts: Range.Inclusive = 1 to 999)(
implicit valName: ValName)
extends NexusNode(AHBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
// Nodes passed from an inner module
case class AHBOutputNode() extends OutputNode(AHBImp)
case class AHBInputNode() extends InputNode(AHBImp)
// Nodes used for external ports
case class AHBBlindOutputNode(portParams: Seq[AHBSlavePortParameters]) extends BlindOutputNode(AHBImp)(portParams)
case class AHBBlindInputNode(portParams: Seq[AHBMasterPortParameters]) extends BlindInputNode(AHBImp)(portParams)
case class AHBInternalOutputNode(portParams: Seq[AHBSlavePortParameters]) extends InternalOutputNode(AHBImp)(portParams)
case class AHBInternalInputNode(portParams: Seq[AHBMasterPortParameters]) extends InternalInputNode(AHBImp)(portParams)
case class AHBIdentityNode()(implicit valName: ValName) extends IdentityNode(AHBImp)()

View File

@ -3,6 +3,8 @@
package freechips.rocketchip.amba.ahb
import Chisel._
import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import scala.math.max
@ -90,7 +92,9 @@ object AHBBundleParameters
case class AHBEdgeParameters(
master: AHBMasterPortParameters,
slave: AHBSlavePortParameters)
slave: AHBSlavePortParameters,
params: Parameters,
sourceInfo: SourceInfo)
{
val bundle = AHBBundleParameters(master, slave)
}

View File

@ -10,8 +10,8 @@ import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.{HeterogeneousBag, MaskGen}
import scala.math.{min,max}
class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
extends AHBSlaveNode(Seq(AHBSlavePortParameters(
case class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)(implicit valName: ValName)
extends SinkNode(AHBImp)(Seq(AHBSlavePortParameters(
Seq(AHBSlaveParameters(
address = Seq(address),
executable = executable,
@ -24,7 +24,7 @@ class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
// Calling this method causes the matching AHB bundle to be
// configured to route all requests to the listed RegFields.
def regmap(mapping: RegField.Map*) = {
val ahb = bundleIn(0)
val (ahb, _) = this.in(0)
val indexBits = log2Up((address.mask+1)/beatBytes)
val params = RegMapperParams(indexBits, beatBytes, 1)
@ -67,12 +67,6 @@ class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
}
}
object AHBRegisterNode
{
def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) =
new AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable)
}
// These convenience methods below combine to make it possible to create a AHB
// register mapped device from a totally abstract register mapped device.
@ -82,13 +76,11 @@ abstract class AHBRegisterRouterBase(address: AddressSet, interrupts: Int, concu
val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts))
}
case class AHBRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[AHBBundle])(implicit val p: Parameters)
case class AHBRegBundleArg()(implicit val p: Parameters)
class AHBRegBundleBase(arg: AHBRegBundleArg) extends Bundle
{
implicit val p = arg.p
val interrupts = arg.interrupts
val in = arg.in
}
class AHBRegBundle[P](val params: P, arg: AHBRegBundleArg) extends AHBRegBundleBase(arg)
@ -96,8 +88,8 @@ class AHBRegBundle[P](val params: P, arg: AHBRegBundleArg) extends AHBRegBundleB
class AHBRegModule[P, B <: AHBRegBundleBase](val params: P, bundleBuilder: => B, router: AHBRegisterRouterBase)
extends LazyModuleImp(router) with HasRegMap
{
val io = bundleBuilder
val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0)
val io = IO(bundleBuilder)
val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1
def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*)
}
@ -110,5 +102,5 @@ class AHBRegisterRouter[B <: AHBRegBundleBase, M <: LazyModuleImp]
require (isPow2(size))
// require (size >= 4096) ... not absolutely required, but highly recommended
lazy val module = moduleBuilder(bundleBuilder(AHBRegBundleArg(intnode.bundleOut, node.bundleIn)), this)
lazy val module = moduleBuilder(bundleBuilder(AHBRegBundleArg()), this)
}

View File

@ -22,15 +22,11 @@ class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4
require ((address.mask & (beatBytes-1)) == beatBytes-1)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] =
if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail)
val mask = bigBits(address.mask >> log2Ceil(beatBytes))
val in = io.in(0)
val (in, _) = node.in(0)
// The mask and address during the address phase
val a_access = in.htrans === AHBParameters.TRANS_NONSEQ || in.htrans === AHBParameters.TRANS_SEQ

View File

@ -21,7 +21,7 @@ class AHBFuzzNative(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L
{
val fuzz = LazyModule(new TLFuzzer(txns))
val model = LazyModule(new TLRAMModel("AHBFuzzNative"))
var xbar = LazyModule(new AHBFanout)
val xbar = LazyModule(new AHBFanout)
val ram = LazyModule(new AHBRAM(AddressSet(0x0, 0xff)))
val gpio = LazyModule(new RRTest0(0x100))
@ -30,7 +30,7 @@ class AHBFuzzNative(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L
ram.node := xbar.node
gpio.node := xbar.node
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}
@ -42,7 +42,7 @@ class AHBNativeTest(aFlow: Boolean, txns: Int = 5000, timeout: Int = 500000)(imp
class AHBFuzzMaster(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends LazyModule
{
val node = AHBOutputNode()
val node = AHBIdentityNode()
val fuzz = LazyModule(new TLFuzzer(txns))
val model = LazyModule(new TLRAMModel("AHBFuzzMaster"))
@ -55,10 +55,9 @@ class AHBFuzzMaster(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L
model.node))))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val out = node.bundleOut
val io = IO(new Bundle {
val finished = Bool(OUTPUT)
}
})
io.finished := fuzz.module.io.finished
}
@ -66,7 +65,7 @@ class AHBFuzzMaster(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L
class AHBFuzzSlave()(implicit p: Parameters) extends LazyModule
{
val node = AHBInputNode()
val node = AHBIdentityNode()
val ram = LazyModule(new TLTestRAM(AddressSet(0x0, 0xfff)))
ram.node :=
@ -77,11 +76,7 @@ class AHBFuzzSlave()(implicit p: Parameters) extends LazyModule
AHBToTL()(
node)))))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
}
lazy val module = new LazyModuleImp(this) { }
}
class AHBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends LazyModule
@ -91,7 +86,7 @@ class AHBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L
slave.node := master.node
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := master.module.io.finished
}
}

View File

@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.MaskGen
case class AHBToTLNode() extends MixedAdapterNode(AHBImp, TLImp)(
case class AHBToTLNode()(implicit valName: ValName) extends MixedAdapterNode(AHBImp, TLImp)(
dFn = { case AHBMasterPortParameters(masters) =>
TLClientPortParameters(clients = masters.map { m =>
TLClientParameters(name = m.name, nodePath = m.nodePath)
@ -41,12 +41,7 @@ class AHBToTL()(implicit p: Parameters) extends LazyModule
val node = AHBToTLNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val beatBytes = edgeOut.manager.beatBytes
val d_send = RegInit(Bool(false))

View File

@ -16,35 +16,31 @@ class AHBFanout()(implicit p: Parameters) extends LazyModule {
slaveFn = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
// Require consistent bus widths
val port0 = node.edgesOut(0).slave
node.edgesOut.foreach { edge =>
val (io_out, edgesOut) = node.out.unzip
val port0 = edgesOut(0).slave
edgesOut.foreach { edge =>
val port = edge.slave
require (port.beatBytes == port0.beatBytes,
s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}")
}
val port_addrs = node.edgesOut.map(_.slave.slaves.map(_.address).flatten)
val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten)
val routingMask = AddressDecoder(port_addrs)
val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct)
val in = io.in(0)
val (in, _) = node.in(0)
val a_sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.haddr)).reduce(_ || _)))
val d_sel = Reg(a_sel)
when (in.hready) { d_sel := a_sel }
(a_sel zip io.out) foreach { case (sel, out) =>
(a_sel zip io_out) foreach { case (sel, out) =>
out := in
out.hsel := in.hsel && sel
}
in.hreadyout := !Mux1H(d_sel, io.out.map(!_.hreadyout))
in.hresp := Mux1H(d_sel, io.out.map(_.hresp))
in.hrdata := Mux1H(d_sel, io.out.map(_.hrdata))
in.hreadyout := !Mux1H(d_sel, io_out.map(!_.hreadyout))
in.hresp := Mux1H(d_sel, io_out.map(_.hresp))
in.hrdata := Mux1H(d_sel, io_out.map(_.hrdata))
}
}

View File

@ -7,17 +7,11 @@ import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBEdgeParameters, APBBundle]
object APBImp extends SimpleNodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle]
{
def edgeO(pd: APBMasterPortParameters, pu: APBSlavePortParameters): APBEdgeParameters = APBEdgeParameters(pd, pu)
def edgeI(pd: APBMasterPortParameters, pu: APBSlavePortParameters): APBEdgeParameters = APBEdgeParameters(pd, pu)
def bundleO(eo: APBEdgeParameters): APBBundle = APBBundle(eo.bundle)
def bundleI(ei: APBEdgeParameters): APBBundle = APBBundle(ei.bundle)
def colour = "#00ccff" // bluish
override def labelI(ei: APBEdgeParameters) = (ei.slave.beatBytes * 8).toString
override def labelO(eo: APBEdgeParameters) = (eo.slave.beatBytes * 8).toString
def edge(pd: APBMasterPortParameters, pu: APBSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = APBEdgeParameters(pd, pu, p, sourceInfo)
def bundle(e: APBEdgeParameters) = APBBundle(e.bundle)
def render(e: APBEdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, (e.slave.beatBytes * 8).toString)
override def mixO(pd: APBMasterPortParameters, node: OutwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBMasterPortParameters =
pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) })
@ -25,24 +19,14 @@ object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, A
pu.copy(slaves = pu.slaves.map { m => m.copy (nodePath = node +: m.nodePath) })
}
// Nodes implemented inside modules
case class APBIdentityNode() extends IdentityNode(APBImp)
case class APBMasterNode(portParams: Seq[APBMasterPortParameters]) extends SourceNode(APBImp)(portParams)
case class APBSlaveNode(portParams: Seq[APBSlavePortParameters]) extends SinkNode(APBImp)(portParams)
case class APBMasterNode(portParams: Seq[APBMasterPortParameters])(implicit valName: ValName) extends SourceNode(APBImp)(portParams)
case class APBSlaveNode(portParams: Seq[APBSlavePortParameters])(implicit valName: ValName) extends SinkNode(APBImp)(portParams)
case class APBNexusNode(
masterFn: Seq[APBMasterPortParameters] => APBMasterPortParameters,
slaveFn: Seq[APBSlavePortParameters] => APBSlavePortParameters,
numMasterPorts: Range.Inclusive = 1 to 1,
numSlavePorts: Range.Inclusive = 1 to 1)
numSlavePorts: Range.Inclusive = 1 to 1)(
implicit valName: ValName)
extends NexusNode(APBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
// Nodes passed from an inner module
case class APBOutputNode() extends OutputNode(APBImp)
case class APBInputNode() extends InputNode(APBImp)
// Nodes used for external ports
case class APBBlindOutputNode(portParams: Seq[APBSlavePortParameters]) extends BlindOutputNode(APBImp)(portParams)
case class APBBlindInputNode(portParams: Seq[APBMasterPortParameters]) extends BlindInputNode(APBImp)(portParams)
case class APBInternalOutputNode(portParams: Seq[APBSlavePortParameters]) extends InternalOutputNode(APBImp)(portParams)
case class APBInternalInputNode(portParams: Seq[APBMasterPortParameters]) extends InternalInputNode(APBImp)(portParams)
case class APBIdentityNode()(implicit valName: ValName) extends IdentityNode(APBImp)()

View File

@ -3,6 +3,7 @@
package freechips.rocketchip.amba.apb
import Chisel._
import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import scala.math.max
@ -78,7 +79,9 @@ object APBBundleParameters
case class APBEdgeParameters(
master: APBMasterPortParameters,
slave: APBSlavePortParameters)
slave: APBSlavePortParameters,
params: Parameters,
sourceInfo: SourceInfo)
{
val bundle = APBBundleParameters(master, slave)
}

View File

@ -10,8 +10,8 @@ import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.HeterogeneousBag
import scala.math.{min,max}
class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
extends APBSlaveNode(Seq(APBSlavePortParameters(
case class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)(implicit valName: ValName)
extends SinkNode(APBImp)(Seq(APBSlavePortParameters(
Seq(APBSlaveParameters(
address = Seq(address),
executable = executable,
@ -24,7 +24,7 @@ class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
// Calling this method causes the matching APB bundle to be
// configured to route all requests to the listed RegFields.
def regmap(mapping: RegField.Map*) = {
val apb = bundleIn(0)
val (apb, _) = this.in(0)
val indexBits = log2Up((address.mask+1)/beatBytes)
val params = RegMapperParams(indexBits, beatBytes, 1)
@ -51,12 +51,6 @@ class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
}
}
object APBRegisterNode
{
def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) =
new APBRegisterNode(address, concurrency, beatBytes, undefZero, executable)
}
// These convenience methods below combine to make it possible to create a APB
// register mapped device from a totally abstract register mapped device.
@ -66,13 +60,11 @@ abstract class APBRegisterRouterBase(address: AddressSet, interrupts: Int, concu
val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts))
}
case class APBRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[APBBundle])(implicit val p: Parameters)
case class APBRegBundleArg()(implicit val p: Parameters)
class APBRegBundleBase(arg: APBRegBundleArg) extends Bundle
{
implicit val p = arg.p
val interrupts = arg.interrupts
val in = arg.in
}
class APBRegBundle[P](val params: P, arg: APBRegBundleArg) extends APBRegBundleBase(arg)
@ -80,8 +72,8 @@ class APBRegBundle[P](val params: P, arg: APBRegBundleArg) extends APBRegBundleB
class APBRegModule[P, B <: APBRegBundleBase](val params: P, bundleBuilder: => B, router: APBRegisterRouterBase)
extends LazyModuleImp(router) with HasRegMap
{
val io = bundleBuilder
val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0)
val io = IO(bundleBuilder)
val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1
def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*)
}
@ -94,5 +86,5 @@ class APBRegisterRouter[B <: APBRegBundleBase, M <: LazyModuleImp]
require (isPow2(size))
// require (size >= 4096) ... not absolutely required, but highly recommended
lazy val module = moduleBuilder(bundleBuilder(APBRegBundleArg(intnode.bundleOut, node.bundleIn)), this)
lazy val module = moduleBuilder(bundleBuilder(APBRegBundleArg()), this)
}

View File

@ -22,11 +22,7 @@ class APBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4
require ((address.mask & (beatBytes-1)) == beatBytes-1)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
val in = io.in(0)
val (in, _) = node.in(0)
def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] =
if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail)

View File

@ -20,7 +20,7 @@ class APBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L
{
val fuzz = LazyModule(new TLFuzzer(txns))
val model = LazyModule(new TLRAMModel("APBFuzzMaster"))
var xbar = LazyModule(new APBFanout)
val xbar = LazyModule(new APBFanout)
val ram = LazyModule(new APBRAM(AddressSet(0x0, 0xff)))
val gpio = LazyModule(new RRTest0(0x100))
@ -34,7 +34,7 @@ class APBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L
TLDelayer(0.2)(
model.node))))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

View File

@ -16,34 +16,30 @@ class APBFanout()(implicit p: Parameters) extends LazyModule {
slaveFn = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
val in = io.in(0)
val (in, _) = node.in(0)
// Require consistent bus widths
val port0 = node.edgesOut(0).slave
node.edgesOut.foreach { edge =>
val (io_out, edgesOut) = node.out.unzip
val port0 = edgesOut(0).slave
edgesOut.foreach { edge =>
val port = edge.slave
require (port.beatBytes == port0.beatBytes,
s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}")
}
val port_addrs = node.edgesOut.map(_.slave.slaves.map(_.address).flatten)
val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten)
val routingMask = AddressDecoder(port_addrs)
val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct)
val sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.paddr)).reduce(_ || _)))
(sel zip io.out) foreach { case (sel, out) =>
(sel zip io_out) foreach { case (sel, out) =>
out := in
out.psel := sel && in.psel
out.penable := sel && in.penable
}
in.pready := !Mux1H(sel, io.out.map(!_.pready))
in.pslverr := Mux1H(sel, io.out.map(_.pslverr))
in.prdata := Mux1H(sel, io.out.map(_.prdata))
in.pready := !Mux1H(sel, io_out.map(!_.pready))
in.pslverr := Mux1H(sel, io_out.map(_.pslverr))
in.prdata := Mux1H(sel, io_out.map(_.prdata))
}
}

View File

@ -26,11 +26,6 @@ class AXI4Buffer(
slaveFn = { p => p.copy(minLatency = p.minLatency + min(aw.latency,ar.latency) + min(r.latency,b.latency)) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
def buffer[T <: Data](config: BufferParams, data: IrrevocableIO[T]): IrrevocableIO[T] = {
if (config.isDefined) {
Queue.irrevocable(data, config.depth, pipe=config.pipe, flow=config.flow)
@ -39,7 +34,7 @@ class AXI4Buffer(
}
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
out.aw <> buffer(aw, in .aw)
out.w <> buffer(w, in .w)
in .b <> buffer(b, out.b)

View File

@ -22,12 +22,7 @@ class AXI4Deinterleaver(maxReadBytes: Int)(implicit p: Parameters) extends LazyM
})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val endId = edgeOut.master.endId
val beatBytes = edgeOut.slave.beatBytes
val beats = (maxReadBytes+beatBytes-1) / beatBytes

View File

@ -26,12 +26,7 @@ class AXI4Fragmenter()(implicit p: Parameters) extends LazyModule
slaveFn = { sp => sp.copy(slaves = sp.slaves .map(s => mapSlave(s, sp.beatBytes))) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val slave = edgeOut.slave
val slaves = slave.slaves
val beatBytes = slave.beatBytes

View File

@ -42,12 +42,7 @@ class AXI4IdIndexer(idBits: Int)(implicit p: Parameters) extends LazyModule
})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
// Leave everything mostly untouched
out.ar <> in.ar

View File

@ -7,17 +7,11 @@ import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4EdgeParameters, AXI4Bundle]
object AXI4Imp extends SimpleNodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle]
{
def edgeO(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters): AXI4EdgeParameters = AXI4EdgeParameters(pd, pu)
def edgeI(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters): AXI4EdgeParameters = AXI4EdgeParameters(pd, pu)
def bundleO(eo: AXI4EdgeParameters): AXI4Bundle = AXI4Bundle(eo.bundle)
def bundleI(ei: AXI4EdgeParameters): AXI4Bundle = AXI4Bundle(ei.bundle)
def colour = "#00ccff" // bluish
override def labelI(ei: AXI4EdgeParameters) = (ei.slave.beatBytes * 8).toString
override def labelO(eo: AXI4EdgeParameters) = (eo.slave.beatBytes * 8).toString
def edge(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = AXI4EdgeParameters(pd, pu, p, sourceInfo)
def bundle(e: AXI4EdgeParameters) = AXI4Bundle(e.bundle)
def render(e: AXI4EdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, label = (e.slave.beatBytes * 8).toString)
override def mixO(pd: AXI4MasterPortParameters, node: OutwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]): AXI4MasterPortParameters =
pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) })
@ -25,23 +19,12 @@ object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters
pu.copy(slaves = pu.slaves.map { m => m.copy (nodePath = node +: m.nodePath) })
}
// Nodes implemented inside modules
case class AXI4IdentityNode() extends IdentityNode(AXI4Imp)
case class AXI4MasterNode(portParams: Seq[AXI4MasterPortParameters]) extends SourceNode(AXI4Imp)(portParams)
case class AXI4SlaveNode(portParams: Seq[AXI4SlavePortParameters]) extends SinkNode(AXI4Imp)(portParams)
case class AXI4MasterNode(portParams: Seq[AXI4MasterPortParameters])(implicit valName: ValName) extends SourceNode(AXI4Imp)(portParams)
case class AXI4SlaveNode(portParams: Seq[AXI4SlavePortParameters])(implicit valName: ValName) extends SinkNode(AXI4Imp)(portParams)
case class AXI4AdapterNode(
masterFn: AXI4MasterPortParameters => AXI4MasterPortParameters,
slaveFn: AXI4SlavePortParameters => AXI4SlavePortParameters,
numPorts: Range.Inclusive = 0 to 999)
numPorts: Range.Inclusive = 0 to 999)(
implicit valName: ValName)
extends AdapterNode(AXI4Imp)(masterFn, slaveFn, numPorts)
// Nodes passed from an inner module
case class AXI4OutputNode() extends OutputNode(AXI4Imp)
case class AXI4InputNode() extends InputNode(AXI4Imp)
// Nodes used for external ports
case class AXI4BlindOutputNode(portParams: Seq[AXI4SlavePortParameters]) extends BlindOutputNode(AXI4Imp)(portParams)
case class AXI4BlindInputNode(portParams: Seq[AXI4MasterPortParameters]) extends BlindInputNode(AXI4Imp)(portParams)
case class AXI4InternalOutputNode(portParams: Seq[AXI4SlavePortParameters]) extends InternalOutputNode(AXI4Imp)(portParams)
case class AXI4InternalInputNode(portParams: Seq[AXI4MasterPortParameters]) extends InternalInputNode(AXI4Imp)(portParams)
case class AXI4IdentityNode()(implicit valName: ValName) extends IdentityNode(AXI4Imp)()

View File

@ -3,6 +3,7 @@
package freechips.rocketchip.amba.axi4
import Chisel._
import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import scala.math.max
@ -124,7 +125,9 @@ object AXI4BundleParameters
case class AXI4EdgeParameters(
master: AXI4MasterPortParameters,
slave: AXI4SlavePortParameters)
slave: AXI4SlavePortParameters,
params: Parameters,
sourceInfo: SourceInfo)
{
val bundle = AXI4BundleParameters(master, slave)
}

View File

@ -10,8 +10,8 @@ import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple}
import freechips.rocketchip.util.{HeterogeneousBag, MaskGen}
import scala.math.{min,max}
class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
extends AXI4SlaveNode(Seq(AXI4SlavePortParameters(
case class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)(implicit valName: ValName)
extends SinkNode(AXI4Imp)(Seq(AXI4SlavePortParameters(
Seq(AXI4SlaveParameters(
address = Seq(address),
executable = executable,
@ -26,11 +26,12 @@ class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
// Calling this method causes the matching AXI4 bundle to be
// configured to route all requests to the listed RegFields.
def regmap(mapping: RegField.Map*) = {
val ar = bundleIn(0).ar
val aw = bundleIn(0).aw
val w = bundleIn(0).w
val r = bundleIn(0).r
val b = bundleIn(0).b
val (io, _) = this.in(0)
val ar = io.ar
val aw = io.aw
val w = io.w
val r = io.r
val b = io.b
val params = RegMapperParams(log2Up((address.mask+1)/beatBytes), beatBytes, ar.bits.params.idBits + ar.bits.params.userBits)
val in = Wire(Decoupled(new RegMapperInput(params)))
@ -77,12 +78,6 @@ class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
}
}
object AXI4RegisterNode
{
def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) =
new AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable)
}
// These convenience methods below combine to make it possible to create a AXI4
// register mapped device from a totally abstract register mapped device.
@ -92,13 +87,11 @@ abstract class AXI4RegisterRouterBase(address: AddressSet, interrupts: Int, conc
val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts))
}
case class AXI4RegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[AXI4Bundle])(implicit val p: Parameters)
case class AXI4RegBundleArg()(implicit val p: Parameters)
class AXI4RegBundleBase(arg: AXI4RegBundleArg) extends Bundle
{
implicit val p = arg.p
val interrupts = arg.interrupts
val in = arg.in
}
class AXI4RegBundle[P](val params: P, arg: AXI4RegBundleArg) extends AXI4RegBundleBase(arg)
@ -106,8 +99,8 @@ class AXI4RegBundle[P](val params: P, arg: AXI4RegBundleArg) extends AXI4RegBund
class AXI4RegModule[P, B <: AXI4RegBundleBase](val params: P, bundleBuilder: => B, router: AXI4RegisterRouterBase)
extends LazyModuleImp(router) with HasRegMap
{
val io = bundleBuilder
val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0)
val io = IO(bundleBuilder)
val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1
def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*)
}
@ -120,5 +113,5 @@ class AXI4RegisterRouter[B <: AXI4RegBundleBase, M <: LazyModuleImp]
require (isPow2(size))
// require (size >= 4096) ... not absolutely required, but highly recommended
lazy val module = moduleBuilder(bundleBuilder(AXI4RegBundleArg(intnode.bundleOut, node.bundleIn)), this)
lazy val module = moduleBuilder(bundleBuilder(AXI4RegBundleArg()), this)
}

View File

@ -24,15 +24,11 @@ class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int =
require ((address.mask & (beatBytes-1)) == beatBytes-1)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] =
if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail)
val mask = bigBits(address.mask >> log2Ceil(beatBytes))
val in = io.in(0)
val (in, _) = node.in(0)
val mem = SeqMem(1 << mask.filter(b=>b).size, Vec(beatBytes, Bits(width = 8)))
val r_addr = Cat((mask zip (in.ar.bits.addr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse)

View File

@ -30,7 +30,7 @@ class AXI4LiteFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule
ram.node := AXI4UserYanker()(AXI4IdIndexer(0)(TLToAXI4(4, true )(TLFragmenter(4, 16)(xbar.node))))
gpio.node := AXI4UserYanker()(AXI4IdIndexer(0)(TLToAXI4(4, false)(TLFragmenter(4, 16)(xbar.node))))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}
@ -53,7 +53,7 @@ class AXI4FullFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule
ram.node := AXI4Fragmenter()(AXI4Deinterleaver(16)(TLToAXI4(4,false)(xbar.node)))
gpio.node := AXI4Fragmenter()(AXI4Deinterleaver(16)(TLToAXI4(4,true )(xbar.node)))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}
@ -69,7 +69,7 @@ trait HasFuzzTarget {
class AXI4FuzzMaster(txns: Int)(implicit p: Parameters) extends LazyModule with HasFuzzTarget
{
val node = AXI4OutputNode()
val node = AXI4IdentityNode()
val fuzz = LazyModule(new TLFuzzer(txns, overrideAddress = Some(fuzzAddr)))
val model = LazyModule(new TLRAMModel("AXI4FuzzMaster"))
@ -84,10 +84,9 @@ class AXI4FuzzMaster(txns: Int)(implicit p: Parameters) extends LazyModule with
model.node))))))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val out = node.bundleOut
val io = IO(new Bundle {
val finished = Bool(OUTPUT)
}
})
io.finished := fuzz.module.io.finished
}
@ -95,7 +94,7 @@ class AXI4FuzzMaster(txns: Int)(implicit p: Parameters) extends LazyModule with
class AXI4FuzzSlave()(implicit p: Parameters) extends LazyModule with HasFuzzTarget
{
val node = AXI4InputNode()
val node = AXI4IdentityNode()
val xbar = LazyModule(new TLXbar)
val ram = LazyModule(new TLRAM(fuzzAddr))
val error= LazyModule(new TLError(ErrorParams(Seq(AddressSet(0x1800, 0xff)), maxTransfer = 256)))
@ -114,11 +113,7 @@ class AXI4FuzzSlave()(implicit p: Parameters) extends LazyModule with HasFuzzTar
AXI4IdIndexer(2)(
node))))))))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
}
lazy val module = new LazyModuleImp(this) { }
}
class AXI4FuzzBridge(txns: Int)(implicit p: Parameters) extends LazyModule
@ -128,7 +123,7 @@ class AXI4FuzzBridge(txns: Int)(implicit p: Parameters) extends LazyModule
slave.node := master.node
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := master.module.io.finished
}
}

View File

@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
case class AXI4ToTLNode() extends MixedAdapterNode(AXI4Imp, TLImp)(
case class AXI4ToTLNode()(implicit valName: ValName) extends MixedAdapterNode(AXI4Imp, TLImp)(
dFn = { case AXI4MasterPortParameters(masters, userBits) =>
masters.foreach { m => require (m.maxFlight.isDefined, "AXI4 must include a transaction maximum per ID to convert to TL") }
val maxFlight = masters.map(_.maxFlight.get).max
@ -44,12 +44,7 @@ class AXI4ToTL()(implicit p: Parameters) extends LazyModule
val node = AXI4ToTLNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val numIds = edgeIn.master.endId
val beatBytes = edgeOut.manager.beatBytes
val beatCountBits = AXI4Parameters.lenBits + (1 << AXI4Parameters.sizeBits) - 1

View File

@ -22,12 +22,7 @@ class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) e
slaveFn = { sp => sp })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val bits = edgeIn.bundle.userBits
val need_bypass = edgeOut.slave.minLatency < 1
require (bits > 0) // useless UserYanker!

View File

@ -10,8 +10,10 @@ abstract class Field[T] private (val default: Option[T])
abstract class View {
final def apply[T](pname: Field[T]): T = apply(pname, this)
final def apply[T](pname: Field[T], site: View): T = find(pname, site) match {
case Some(x) => x.asInstanceOf[T]
final def apply[T](pname: Field[T], site: View): T = {
val out = find(pname, site)
require (out.isDefined, s"Key ${pname} is not defined in Parameters")
out.get
}
final def lift[T](pname: Field[T]): Option[T] = lift(pname, this)

View File

@ -21,7 +21,7 @@ abstract class BareCoreplex(implicit p: Parameters) extends LazyModule with Bind
lazy val json = JSON(bindingTree)
}
abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyMultiIOModuleImp(_outer) {
abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyModuleImp(_outer) {
val outer = _outer
ElaborationArtefacts.add("graphml", outer.graphML)
ElaborationArtefacts.add("dts", outer.dts)

View File

@ -187,14 +187,21 @@ class WithRoccExample extends Config((site, here, up) => {
Seq(
RoCCParams(
opcodes = OpcodeSet.custom0,
generator = (p: Parameters) => LazyModule(new AccumulatorExample()(p))),
generator = (p: Parameters) => {
val accumulator = LazyModule(new AccumulatorExample()(p))
accumulator}),
RoCCParams(
opcodes = OpcodeSet.custom1,
generator = (p: Parameters) => LazyModule(new TranslatorExample()(p)),
generator = (p: Parameters) => {
val translator = LazyModule(new TranslatorExample()(p))
translator},
nPTWPorts = 1),
RoCCParams(
opcodes = OpcodeSet.custom2,
generator = (p: Parameters) => LazyModule(new CharacterCountExample()(p)))
generator = (p: Parameters) => {
val counter = LazyModule(new CharacterCountExample()(p))
counter
})
))
}
})
@ -265,7 +272,7 @@ class WithNBitPeripheryBus(nBits: Int) extends Config ((site, here, up) => {
})
class WithoutTLMonitors extends Config ((site, here, up) => {
case TLMonitorBuilder => (args: TLMonitorArgs) => None
case MonitorsEnabled => false
})
class WithNExtTopInterrupts(nExtInts: Int) extends Config((site, here, up) => {

View File

@ -53,8 +53,7 @@ trait HasFrontBus extends HasSystemBus {
private val frontbusParams = p(FrontBusKey)
val frontbusBeatBytes = frontbusParams.beatBytes
val fbus = new FrontBus(frontbusParams)
sbus.fromFrontBus := fbus.toSystemBus
val fbus = LazyModule(new FrontBus(frontbusParams))
FlipRendering { implicit p => sbus.fromFrontBus := fbus.toSystemBus }
}

View File

@ -44,7 +44,7 @@ abstract trait HasExtInterrupts extends HasInterruptBus {
}
val nExtInterrupts = p(NExtTopInterrupts)
val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int))
val extInterrupts = IntSourceNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int))
}
/** This trait should be used if the External Interrupts have NOT
@ -77,9 +77,9 @@ trait HasExtInterruptsBundle {
/** This trait performs the translation from a UInt IO into Diplomatic Interrupts.
* The wiring must be done in the concrete LazyModuleImp.
*/
trait HasExtInterruptsModuleImp extends LazyMultiIOModuleImp with HasExtInterruptsBundle {
trait HasExtInterruptsModuleImp extends LazyModuleImp with HasExtInterruptsBundle {
val outer: HasExtInterrupts
val interrupts = IO(UInt(INPUT, width = outer.nExtInterrupts))
outer.extInterrupts.bundleIn.flatten.zipWithIndex.foreach { case(o, i) => o := interrupts(i) }
outer.extInterrupts.in.map(_._1).flatten.zipWithIndex.foreach { case(o, i) => o := interrupts(i) }
}

View File

@ -68,7 +68,7 @@ trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBu
private val mask = ~BigInt((nBanks-1) * memBusBlockBytes)
val memBuses = Seq.tabulate(nMemoryChannels) { channel =>
val mbus = new MemoryBus(mbusParams)
val mbus = LazyModule(new MemoryBus(mbusParams))
for (bank <- 0 until nBanksPerChannel) {
val offset = (bank * nMemoryChannels) + channel
ForceFanout(a = true) { implicit p => in := sbus.toMemoryBus }

View File

@ -45,7 +45,7 @@ trait HasPeripheryBus extends HasSystemBus {
private val pbusParams = p(PeripheryBusKey)
val pbusBeatBytes = pbusParams.beatBytes
val pbus = new PeripheryBus(pbusParams)
val pbus = LazyModule(new PeripheryBus(pbusParams))
// The peripheryBus hangs off of systemBus; here we convert TL-UH -> TL-UL
pbus.fromSystemBus := sbus.toPeripheryBus()

View File

@ -33,7 +33,7 @@ trait HasMasterAXI4MemPort extends HasMemoryBus {
private val params = p(ExtMem)
private val device = new MemoryDevice
val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(nMemoryChannels) { channel =>
val mem_axi4 = AXI4SlaveNode(Seq.tabulate(nMemoryChannels) { channel =>
val base = AddressSet(params.base, params.size-1)
val filter = AddressSet(channel * cacheBlockBytes, ~((nMemoryChannels-1) * cacheBlockBytes))
@ -69,14 +69,18 @@ trait HasMasterAXI4MemPortBundle {
val mem_axi4: HeterogeneousBag[AXI4Bundle]
val nMemoryChannels: Int
def connectSimAXIMem(dummy: Int = 1) = {
if (nMemoryChannels > 0) Module(LazyModule(new SimAXIMem(nMemoryChannels)).module).io.axi4 <> mem_axi4
if (nMemoryChannels > 0) {
val mem = LazyModule(new SimAXIMem(nMemoryChannels))
Module(mem.module).io.axi4 <> mem_axi4
}
}
}
/** Actually generates the corresponding IO in the concrete Module */
trait HasMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with HasMasterAXI4MemPortBundle {
trait HasMasterAXI4MemPortModuleImp extends LazyModuleImp with HasMasterAXI4MemPortBundle {
val outer: HasMasterAXI4MemPort
val mem_axi4 = IO(outer.mem_axi4.bundleOut)
val mem_axi4 = IO(HeterogeneousBag.fromNode(outer.mem_axi4.in))
(mem_axi4 zip outer.mem_axi4.in) foreach { case (i, (o, _)) => i <> o }
val nMemoryChannels = outer.nMemoryChannels
}
@ -84,7 +88,7 @@ trait HasMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with HasMasterA
trait HasMasterAXI4MMIOPort extends HasSystemBus {
private val params = p(ExtBus)
private val device = new SimpleBus("mmio", Nil)
val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters(
val mmio_axi4 = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
slaves = Seq(AXI4SlaveParameters(
address = List(AddressSet(params.base, params.size-1)),
resources = device.ranges,
@ -107,20 +111,22 @@ trait HasMasterAXI4MMIOPortBundle {
implicit val p: Parameters
val mmio_axi4: HeterogeneousBag[AXI4Bundle]
def connectSimAXIMMIO(dummy: Int = 1) {
Module(LazyModule(new SimAXIMem(1, 4096)).module).io.axi4 <> mmio_axi4
val mmio_mem = LazyModule(new SimAXIMem(1, 4096))
Module(mmio_mem.module).io.axi4 <> mmio_axi4
}
}
/** Actually generates the corresponding IO in the concrete Module */
trait HasMasterAXI4MMIOPortModuleImp extends LazyMultiIOModuleImp with HasMasterAXI4MMIOPortBundle {
trait HasMasterAXI4MMIOPortModuleImp extends LazyModuleImp with HasMasterAXI4MMIOPortBundle {
val outer: HasMasterAXI4MMIOPort
val mmio_axi4 = IO(outer.mmio_axi4.bundleOut)
val mmio_axi4 = IO(HeterogeneousBag.fromNode(outer.mmio_axi4.in))
(mmio_axi4 zip outer.mmio_axi4.in) foreach { case (i, (o, _)) => i <> o }
}
/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */
trait HasSlaveAXI4Port extends HasSystemBus {
private val params = p(ExtIn)
val l2FrontendAXI4Node = AXI4BlindInputNode(Seq(AXI4MasterPortParameters(
val l2FrontendAXI4Node = AXI4MasterNode(Seq(AXI4MasterPortParameters(
masters = Seq(AXI4MasterParameters(
name = "AXI4 periphery",
id = IdRange(0, 1 << params.idBits))))))
@ -151,16 +157,17 @@ trait HasSlaveAXI4PortBundle {
}
/** Actually generates the corresponding IO in the concrete Module */
trait HasSlaveAXI4PortModuleImp extends LazyMultiIOModuleImp with HasSlaveAXI4PortBundle {
trait HasSlaveAXI4PortModuleImp extends LazyModuleImp with HasSlaveAXI4PortBundle {
val outer: HasSlaveAXI4Port
val l2_frontend_bus_axi4 = IO(outer.l2FrontendAXI4Node.bundleIn)
val l2_frontend_bus_axi4 = IO(HeterogeneousBag.fromNode(outer.l2FrontendAXI4Node.out).flip)
(outer.l2FrontendAXI4Node.out zip l2_frontend_bus_axi4) foreach { case ((i, _), o) => i <> o }
}
/** Adds a TileLink port to the system intended to master an MMIO device bus */
trait HasMasterTLMMIOPort extends HasSystemBus {
private val params = p(ExtBus)
private val device = new SimpleBus("mmio", Nil)
val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters(
val mmio_tl = TLManagerNode(Seq(TLManagerPortParameters(
managers = Seq(TLManagerParameters(
address = List(AddressSet(params.base, params.size-1)),
resources = device.ranges,
@ -192,9 +199,10 @@ trait HasMasterTLMMIOPortBundle {
}
/** Actually generates the corresponding IO in the concrete Module */
trait HasMasterTLMMIOPortModuleImp extends LazyMultiIOModuleImp with HasMasterTLMMIOPortBundle {
trait HasMasterTLMMIOPortModuleImp extends LazyModuleImp with HasMasterTLMMIOPortBundle {
val outer: HasMasterTLMMIOPort
val mmio_tl = IO(outer.mmio_tl.bundleOut)
val mmio_tl = IO(HeterogeneousBag.fromNode(outer.mmio_tl.in))
(mmio_tl zip outer.mmio_tl.out) foreach { case (i, (o, _)) => i <> o }
}
/** Adds an TL port to the system intended to be a slave on an MMIO device bus.
@ -202,7 +210,7 @@ trait HasMasterTLMMIOPortModuleImp extends LazyMultiIOModuleImp with HasMasterTL
*/
trait HasSlaveTLPort extends HasSystemBus {
private val params = p(ExtIn)
val l2FrontendTLNode = TLBlindInputNode(Seq(TLClientPortParameters(
val l2FrontendTLNode = TLClientNode(Seq(TLClientPortParameters(
clients = Seq(TLClientParameters(
name = "Front Port (TL)",
sourceId = IdRange(0, 1 << params.idBits))))))
@ -229,9 +237,10 @@ trait HasSlaveTLPortBundle {
}
/** Actually generates the corresponding IO in the concrete Module */
trait HasSlaveTLPortModuleImp extends LazyMultiIOModuleImp with HasSlaveTLPortBundle {
trait HasSlaveTLPortModuleImp extends LazyModuleImp with HasSlaveTLPortBundle {
val outer: HasSlaveTLPort
val l2_frontend_bus_tl = IO(outer.l2FrontendTLNode.bundleIn)
val l2_frontend_bus_tl = IO(HeterogeneousBag.fromNode(outer.l2FrontendTLNode.out).flip)
(outer.l2FrontendTLNode.in zip l2_frontend_bus_tl) foreach { case ((i, _), o) => i <> o }
}
/** Memory with AXI port for use in elaboratable test harnesses. */
@ -241,7 +250,7 @@ class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) ex
val size = totalSize / channels
require(totalSize % channels == 0)
val node = AXI4BlindInputNode(Seq.fill(channels) {
val node = AXI4MasterNode(Seq.fill(channels) {
AXI4MasterPortParameters(Seq(AXI4MasterParameters(
name = "dut",
id = IdRange(0, 1 << config.idBits)
@ -254,8 +263,9 @@ class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) ex
}
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val axi4 = node.bundleIn
}
val io = IO(new Bundle {
val axi4 = HeterogeneousBag.fromNode(node.out).flip
})
(node.out zip io.axi4) foreach { case ((i, _), o) => i <> o }
}
}

View File

@ -3,10 +3,10 @@
package freechips.rocketchip.coreplex
import Chisel._
import freechips.rocketchip.diplomacy.{LazyMultiIOModuleImp, DTSTimebase}
import freechips.rocketchip.diplomacy.{LazyModuleImp, DTSTimebase}
import freechips.rocketchip.devices.tilelink.HasPeripheryClint
trait HasRTCModuleImp extends LazyMultiIOModuleImp {
trait HasRTCModuleImp extends LazyModuleImp {
val outer: HasPeripheryClint
private val pbusFreq = outer.p(PeripheryBusKey).frequency
private val rtcFreq = outer.p(DTSTimebase)

View File

@ -46,19 +46,19 @@ trait HasRocketTiles extends HasSystemBus
case SynchronousCrossing(params) => {
val wrapper = LazyModule(new SyncRocketTile(tp, i)(pWithExtra))
sbus.fromSyncTiles(params, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode
wrapper.slaveNode :*= pbus.toSyncSlaves(tp.name, tp.externalSlaveBuffers)
FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toSyncSlaves(tp.name, tp.externalSlaveBuffers) }
wrapper
}
case AsynchronousCrossing(depth, sync) => {
val wrapper = LazyModule(new AsyncRocketTile(tp, i)(pWithExtra))
sbus.fromAsyncTiles(depth, sync, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode
wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name, tp.externalSlaveBuffers)
FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name, tp.externalSlaveBuffers) }
wrapper
}
case RationalCrossing(direction) => {
val wrapper = LazyModule(new RationalRocketTile(tp, i)(pWithExtra))
sbus.fromRationalTiles(direction, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode
wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name, tp.externalSlaveBuffers)
FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name, tp.externalSlaveBuffers) }
wrapper
}
}
@ -86,7 +86,7 @@ trait HasRocketTiles extends HasSystemBus
wrapper.intOutputNode.foreach { case int =>
val rocketIntXing = LazyModule(new IntXing(wrapper.outputInterruptXingLatency))
rocketIntXing.intnode := int
FlipRendering { implicit p => rocketIntXing.intnode := int }
plic.intnode := rocketIntXing.intnode
}
@ -102,7 +102,7 @@ trait HasRocketTilesBundle {
val rocket_tile_inputs: Vec[ClockedRocketTileInputs]
}
trait HasRocketTilesModuleImp extends LazyMultiIOModuleImp
trait HasRocketTilesModuleImp extends LazyModuleImp
with HasRocketTilesBundle
with HasResetVectorWire
with HasPeripheryDebugModuleImp {

View File

@ -22,7 +22,7 @@ class SystemBus(params: SystemBusParams)(implicit p: Parameters) extends TLBusWr
private val master_splitter = LazyModule(new TLSplitter) // Allows cycle-free connection to external networks
master_splitter.suggestName(s"${busName}_master_TLSplitter")
inwardNode :=* master_splitter.node
def busView = master_splitter.node.edgesIn.head
def busView = master_splitter.node.edges.in.head
protected def inwardSplitNode: TLInwardNode = master_splitter.node
protected def outwardSplitNode: TLOutwardNode = master_splitter.node
@ -122,7 +122,7 @@ trait HasSystemBus extends HasInterruptBus {
private val sbusParams = p(SystemBusKey)
val sbusBeatBytes = sbusParams.beatBytes
val sbus = new SystemBus(sbusParams)
val sbus = LazyModule(new SystemBus(sbusParams))
def sharedMemoryTLEdge: TLEdge = sbus.busView
def paddrBits: Int = sbus.busView.bundle.addressBits

View File

@ -288,14 +288,12 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod
lazy val module = new LazyModuleImp(this) {
val nComponents = intnode.bundleOut.size
val nComponents = intnode.out.size
val io = new Bundle {
val io = IO(new Bundle {
val ctrl = (new DebugCtrlBundle(nComponents))
val tlIn = dmiNode.bundleIn
val debugInterrupts = intnode.bundleOut
val innerCtrl = new DecoupledIO(new DebugInternalBundle())
}
})
//----DMCONTROL (The whole point of 'Outer' is to maintain this register on dmiClock (e.g. TCK) domain, so that it
// can be written even if 'Inner' is not being clocked or is in reset. This allows halting
@ -355,8 +353,9 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod
debugIntNxt := debugIntRegs
val (intnode_out, _) = intnode.out.unzip
for (component <- 0 until nComponents) {
io.debugInterrupts(component)(0) := debugIntRegs(component)
intnode_out(component)(0) := debugIntRegs(component)
}
// Halt request registers are set & cleared by writes to DMCONTROL.haltreq
@ -393,27 +392,22 @@ class TLDebugModuleOuterAsync(device: Device)(implicit p: Parameters) extends La
val dmiXbar = LazyModule (new TLXbar())
val dmOuter = LazyModule( new TLDebugModuleOuter(device))
val intnode = IntOutputNode()
val intnode = dmOuter.intnode
val dmiInnerNode = TLAsyncOutputNode()
intnode :*= dmOuter.intnode
val dmiInnerNode = TLAsyncCrossingSource()(dmiXbar.node)
dmiXbar.node := dmi2tl.node
dmOuter.dmiNode := dmiXbar.node
dmiInnerNode := TLAsyncCrossingSource()(dmiXbar.node)
lazy val module = new LazyModuleImp(this) {
val nComponents = intnode.bundleOut.size
val nComponents = intnode.out.size
val io = new Bundle {
val io = IO(new Bundle {
val dmi = new DMIIO()(p).flip()
val dmiInner = dmiInnerNode.bundleOut
val ctrl = new DebugCtrlBundle(nComponents)
val debugInterrupts = intnode.bundleOut
val innerCtrl = new AsyncBundle(depth=1, new DebugInternalBundle())
}
})
dmi2tl.module.io.dmi <> io.dmi
@ -447,13 +441,11 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
val nComponents = getNComponents()
val io = new Bundle {
val hart_in = tlNode.bundleIn
val dmi_in = dmiNode.bundleIn
val io = IO(new Bundle {
val dmactive = Bool(INPUT)
val innerCtrl = (new DecoupledIO(new DebugInternalBundle())).flip
val debugUnavail = Vec(nComponents, Bool()).asInput
}
})
//--------------------------------------------------------------
// Import constants for shorter variable names
@ -1011,26 +1003,23 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
// Also is the Sink side of hartsel & resumereq fields of DMCONTROL.
class TLDebugModuleInnerAsync(device: Device, getNComponents: () => Int)(implicit p: Parameters) extends LazyModule{
val dmInner = LazyModule(new TLDebugModuleInner(device, getNComponents)(p))
val dmiNode = TLAsyncInputNode()
val tlNode = TLInputNode()
val dmInner = LazyModule(new TLDebugModuleInner(device, getNComponents))
val dmiXing = LazyModule(new TLAsyncCrossingSink(depth=1))
val dmiNode: TLAsyncInwardNode = dmiXing.node
val tlNode = dmInner.tlNode
dmInner.dmiNode := TLAsyncCrossingSink(depth=1)(dmiNode)
dmInner.tlNode := tlNode
dmInner.dmiNode := dmiXing.node
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
// this comes from tlClk domain.
val tl_in = tlNode.bundleIn
val io = IO(new Bundle {
// These are all asynchronous and come from Outer
val dmi_in = dmiNode.bundleIn
val dmactive = Bool(INPUT)
val innerCtrl = new AsyncBundle(1, new DebugInternalBundle()).flip
// This comes from tlClk domain.
val debugUnavail = Vec(getNComponents(), Bool()).asInput
val psd = new PSDTestMode().asInput
}
})
dmInner.module.io.innerCtrl := FromAsyncBundle(io.innerCtrl)
dmInner.module.io.dmactive := ~ResetCatchAndSync(clock, ~io.dmactive, "dmactiveSync", io.psd)
@ -1049,26 +1038,22 @@ class TLDebugModule(implicit p: Parameters) extends LazyModule {
override val alwaysExtended = true
}
val node = TLInputNode()
val intnode = IntOutputNode()
val dmOuter = LazyModule(new TLDebugModuleOuterAsync(device)(p))
val dmInner = LazyModule(new TLDebugModuleInnerAsync(device, () => {intnode.bundleOut.size})(p))
val dmInner = LazyModule(new TLDebugModuleInnerAsync(device, () => {intnode.edges.out.size})(p))
val node = dmInner.tlNode
val intnode = dmOuter.intnode
dmInner.dmiNode := dmOuter.dmiInnerNode
dmInner.tlNode := node
intnode :*= dmOuter.intnode
lazy val module = new LazyModuleImp(this) {
val nComponents = intnode.bundleOut.size
val nComponents = intnode.out.size
val io = new Bundle {
val io = IO(new Bundle {
val ctrl = new DebugCtrlBundle(nComponents)
val dmi = new ClockedDMIIO().flip
val in = node.bundleIn
val debugInterrupts = intnode.bundleOut
val psd = new PSDTestMode().asInput
}
})
dmOuter.module.io.dmi <> io.dmi.dmi
dmOuter.module.reset := io.dmi.dmiReset
@ -1102,16 +1087,14 @@ class ClockedDMIIO(implicit val p: Parameters) extends ParameterizedBundle()(p){
class DMIToTL(implicit p: Parameters) extends LazyModule {
val node = TLClientNode(TLClientParameters("debug"))
val node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters("debug")))))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val io = IO(new Bundle {
val dmi = new DMIIO()(p).flip()
val out = node.bundleOut
}
})
val tl = io.out(0)
val edge = node.edgesOut(0)
val (tl, edge) = node.out(0)
val src = Wire(init = 0.U)
val addr = Wire(init = (io.dmi.req.bits.addr << 2))

View File

@ -54,9 +54,9 @@ trait HasPeripheryDebugBundle {
}
debug.psd.foreach { _ <> psd }
}
}
trait HasPeripheryDebugModuleImp extends LazyMultiIOModuleImp with HasPeripheryDebugBundle {
trait HasPeripheryDebugModuleImp extends LazyModuleImp with HasPeripheryDebugBundle {
val outer: HasPeripheryDebug
val debug = IO(new DebugIO)

View File

@ -23,25 +23,22 @@ case object BootROMParams extends Field[BootROMParams]
class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4,
resources: Seq[Resource] = new SimpleDevice("rom", Seq("sifive,rom0")).reg("mem"))(implicit p: Parameters) extends LazyModule
{
val node = TLManagerNode(beatBytes, TLManagerParameters (
address = List(AddressSet(base, size-1)),
resources = resources,
regionType = RegionType.UNCACHED,
executable = executable,
supportsGet = TransferSizes(1, beatBytes),
fifoId = Some(0)))
val node = TLManagerNode(Seq(TLManagerPortParameters(
Seq(TLManagerParameters(
address = List(AddressSet(base, size-1)),
resources = resources,
regionType = RegionType.UNCACHED,
executable = executable,
supportsGet = TransferSizes(1, beatBytes),
fifoId = Some(0))),
beatBytes = beatBytes)))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
val contents = contentsDelayed
val wrapSize = 1 << log2Ceil(contents.size)
require (wrapSize <= size)
val in = io.in(0)
val edge = node.edgesIn(0)
val (in, edge) = node.in(0)
val words = (contents ++ Seq.fill(wrapSize-contents.size)(0.toByte)).grouped(beatBytes).toSeq
val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8})
@ -78,7 +75,7 @@ trait HasPeripheryBootROM extends HasPeripheryBus {
}
/** Coreplex will power-on running at 0x10040 (BootROM) */
trait HasPeripheryBootROMModuleImp extends LazyMultiIOModuleImp
trait HasPeripheryBootROMModuleImp extends LazyModuleImp
with HasResetVectorWire {
val outer: HasPeripheryBootROM
global_reset_vector := outer.resetVector.U

View File

@ -81,20 +81,13 @@ class BusBlocker(params: BusBlockerParams)(implicit p: Parameters) extends TLBus
beatBytes = params.controlBeatBytes)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val ctl = controlNode.bundleIn
val in = nodeIn.bundleIn
val out = nodeOut.bundleOut
}
// We need to be able to represent +1 larger than the largest populated address
val addressBits = log2Ceil(nodeOut.edgesOut(0).manager.maxAddress+1+1)
val addressBits = log2Ceil(nodeOut.edges.out(0).manager.maxAddress+1+1)
val pmps = RegInit(Vec.fill(params.pmpRegisters) { DevicePMP(addressBits, params.pageBits) })
val blocks = pmps.tail.map(_.blockPriorAddress) :+ Bool(false)
controlNode.regmap(0 -> (pmps zip blocks).map { case (p, b) => p.fields(b) }.toList.flatten)
val in = io.in(0)
val edge = nodeIn.edgesIn(0)
val (in, edge) = nodeIn.in(0)
// Determine if a request is allowed
val needW = in.a.bits.opcode =/= TLMessages.Get

View File

@ -12,14 +12,15 @@ import scala.math.min
abstract class TLBusBypassBase(beatBytes: Int)(implicit p: Parameters) extends LazyModule
{
protected val nodeIn = TLInputNode()
protected val nodeOut = TLOutputNode()
protected val nodeIn = TLIdentityNode()
protected val nodeOut = TLIdentityNode()
val node = NodeHandle(nodeIn, nodeOut)
protected val bar = LazyModule(new TLBusBypassBar)
protected val everything = Seq(AddressSet(0, BigInt("ffffffffffffffffffffffffffffffff", 16))) // 128-bit
protected val error = LazyModule(new TLError(ErrorParams(everything), beatBytes))
// order matters
bar.node := nodeIn
error.node := bar.node
nodeOut := bar.node
@ -28,11 +29,9 @@ abstract class TLBusBypassBase(beatBytes: Int)(implicit p: Parameters) extends L
class TLBusBypass(beatBytes: Int)(implicit p: Parameters) extends TLBusBypassBase(beatBytes)
{
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = nodeIn.bundleIn
val out = nodeOut.bundleOut
val io = IO(new Bundle {
val bypass = Bool(INPUT)
}
})
bar.module.io.bypass := io.bypass
}
}
@ -47,17 +46,13 @@ class TLBusBypassBar(implicit p: Parameters) extends LazyModule
managerFn = { seq => seq(1) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
val io = IO(new Bundle {
val bypass = Bool(INPUT)
}
})
val in = io.in(0)
val out0 = io.out(0)
val out1 = io.out(1)
val (in, edge) = node.in(0)
val Seq((out0,_), (out1,_)) = node.out
val edge = node.edgesIn(0)
val bce = edge.manager.anySupportAcquireB && edge.client.anySupportProbe
// We need to be locked to the given bypass direction until all transactions stop

View File

@ -53,11 +53,9 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val io = IO(new Bundle {
val rtcTick = Bool(INPUT)
val int = intnode.bundleOut
val in = node.bundleIn
}
})
val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth)))
when (io.rtcTick) {
@ -66,11 +64,12 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte
reg := newTime >> i
}
val nTiles = intnode.edgesOut.size
val nTiles = intnode.out.size
val timecmp = Seq.fill(nTiles) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) }
val ipi = Seq.fill(nTiles) { RegInit(UInt(0, width = 1)) }
io.int.zipWithIndex.foreach { case (int, i) =>
val (intnode_out, _) = intnode.out.unzip
intnode_out.zipWithIndex.foreach { case (int, i) =>
int(0) := ShiftRegister(ipi(i)(0), params.intStages) // msip
int(1) := ShiftRegister(time.asUInt >= timecmp(i).asUInt, params.intStages) // mtip
}

View File

@ -40,15 +40,10 @@ class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters) e
minLatency = 1))) // no bypass needed for this device
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
import TLMessages._
import TLPermissions._
val edge = node.edgesIn(0)
val in = io.in(0)
val (in, edge) = node.in(0)
val a = Queue(in.a, 1)
val c = Queue(in.c, 1)
val da = Wire(in.d)

View File

@ -24,21 +24,18 @@ trait HasPeripheryMaskROMSlave extends HasPeripheryBus {
class TLMaskROM(c: MaskROMParams)(implicit p: Parameters) extends LazyModule {
val beatBytes = c.width/8
val node = TLManagerNode(beatBytes, TLManagerParameters(
address = AddressSet.misaligned(c.address, c.depth*beatBytes),
resources = new SimpleDevice("rom", Seq("sifive,maskrom0")).reg("mem"),
regionType = RegionType.UNCACHED,
executable = true,
supportsGet = TransferSizes(1, beatBytes),
fifoId = Some(0))) // requests are handled in order
val node = TLManagerNode(Seq(TLManagerPortParameters(
Seq(TLManagerParameters(
address = AddressSet.misaligned(c.address, c.depth*beatBytes),
resources = new SimpleDevice("rom", Seq("sifive,maskrom0")).reg("mem"),
regionType = RegionType.UNCACHED,
executable = true,
supportsGet = TransferSizes(1, beatBytes),
fifoId = Some(0))), // requests are handled in order
beatBytes = beatBytes)))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
val in = io.in(0)
val edge = node.edgesIn(0)
val (in, edge)= node.in(0)
val rom = ROMGenerator(ROMConfig(c.name, c.depth, c.width))
rom.io.clock := clock

View File

@ -91,12 +91,12 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) })
/* Negotiated sizes */
def nDevices: Int = intnode.edgesIn.map(_.source.num).sum
def nDevices: Int = intnode.edges.in.map(_.source.num).sum
def nPriorities = min(params.maxPriorities, nDevices)
def nHarts = intnode.edgesOut.map(_.source.num).sum
def nHarts = intnode.edges.out.map(_.source.num).sum
// Assign all the devices unique ranges
lazy val sources = intnode.edgesIn.map(_.source)
lazy val sources = intnode.edges.in.map(_.source)
lazy val flatSources = (sources zip sources.map(_.num).scanLeft(0)(_+_).init).map {
case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o)))
}.flatten
@ -109,16 +109,13 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
}
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val tl_in = node.bundleIn
val devices = intnode.bundleIn
val harts = intnode.bundleOut
}
val (io_devices, edgesIn) = intnode.in.unzip
val (io_harts, _) = intnode.out.unzip
// Compact the interrupt vector the same way
val interrupts = (intnode.edgesIn zip io.devices).map { case (e, i) => i.take(e.source.num) }.flatten
val interrupts = intnode.in.map { case (i, e) => i.take(e.source.num) }.flatten
// This flattens the harts into an MSMSMSMSMS... or MMMMM.... sequence
val harts = io.harts.flatten
val harts = io_harts.flatten
println(s"Interrupt map (${nHarts} harts ${nDevices} interrupts):")
flatSources.foreach { s =>

View File

@ -29,16 +29,11 @@ class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int
require ((address.mask & (beatBytes-1)) == beatBytes-1)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] =
if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail)
val mask = bigBits(address.mask >> log2Ceil(beatBytes))
val in = io.in(0)
val edge = node.edgesIn(0)
val (in, edge) = node.in(0)
val addrBits = (mask zip edge.addr_hi(in.a.bits).toBools).filter(_._1).map(_._2)
val memAddress = Cat(addrBits.reverse)
@ -75,7 +70,7 @@ class TLRAMZeroDelay(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) exten
model.node := fuzz.node
ram.node := TLDelayer(0.25)(model.node)
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

View File

@ -24,12 +24,7 @@ class TLZero(address: AddressSet, resources: Seq[Resource], executable: Boolean
minLatency = 1))) // no bypass needed for this device
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
val in = io.in(0)
val edge = node.edgesIn(0)
val (in, edge) = node.in(0)
val a = Queue(in.a, 2)
val hasData = edge.hasData(a.bits)

View File

@ -6,6 +6,8 @@ import Chisel._
import chisel3.experimental.{BaseModule, RawModule, MultiIOModule, withClockAndReset}
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo}
import freechips.rocketchip.config.Parameters
import scala.collection.immutable.ListMap
import scala.util.matching._
abstract class LazyModule()(implicit val p: Parameters)
{
@ -13,9 +15,9 @@ abstract class LazyModule()(implicit val p: Parameters)
protected[diplomacy] var children = List[LazyModule]()
protected[diplomacy] var nodes = List[BaseNode]()
protected[diplomacy] var info: SourceInfo = UnlocatableSourceInfo
protected[diplomacy] val parent = LazyModule.stack.headOption
protected[diplomacy] val parent = LazyModule.scope
LazyModule.stack = this :: LazyModule.stack
LazyModule.scope = Some(this)
parent.foreach(p => p.children = this :: p.children)
private var suggestedName: Option[String] = None
@ -54,15 +56,6 @@ abstract class LazyModule()(implicit val p: Parameters)
def module: LazyModuleImpLike
protected[diplomacy] def instantiate() = {
children.reverse.foreach { c =>
// !!! fix chisel3 so we can pass the desired sourceInfo
// implicit val sourceInfo = c.module.outer.info
Module(c.module)
}
bindings.reverse.foreach { f => f () }
}
def omitGraphML: Boolean = !nodes.exists(!_.omitGraphML) && !children.exists(!_.omitGraphML)
lazy val graphML: String = parent.map(_.graphML).getOrElse {
val buf = new StringBuilder
@ -95,10 +88,11 @@ abstract class LazyModule()(implicit val p: Parameters)
buf ++= s"""${pad}</node>\n"""
}
private def edgesGraphML(buf: StringBuilder, pad: String) {
nodes.filter(!_.omitGraphML) foreach { n => n.outputs.filter(!_._1.omitGraphML).foreach { case (o, l) =>
nodes.filter(!_.omitGraphML) foreach { n => n.outputs.filter(!_._1.omitGraphML).foreach { case (o, edge) =>
val RenderedEdge(colour, label, flipped) = edge
buf ++= pad
buf ++= "<edge"
if (o.reverse) {
if (flipped) {
buf ++= s""" target=\"${index}::${n.index}\""""
buf ++= s""" source=\"${o.lazyModule.index}::${o.index}\">"""
} else {
@ -106,13 +100,13 @@ abstract class LazyModule()(implicit val p: Parameters)
buf ++= s""" target=\"${o.lazyModule.index}::${o.index}\">"""
}
buf ++= s"""<data key=\"e\"><y:PolyLineEdge>"""
if (o.reverse) {
if (flipped) {
buf ++= s"""<y:Arrows source=\"standard\" target=\"none\"/>"""
} else {
buf ++= s"""<y:Arrows source=\"none\" target=\"standard\"/>"""
}
buf ++= s"""<y:LineStyle color=\"${o.colour}\" type=\"line\" width=\"1.0\"/>"""
buf ++= s"""<y:EdgeLabel modelName=\"centered\" rotationAngle=\"270.0\">${l}</y:EdgeLabel>"""
buf ++= s"""<y:LineStyle color=\"${colour}\" type=\"line\" width=\"1.0\"/>"""
buf ++= s"""<y:EdgeLabel modelName=\"centered\" rotationAngle=\"270.0\">${label}</y:EdgeLabel>"""
buf ++= s"""</y:PolyLineEdge></data></edge>\n"""
} }
children.filter(!_.omitGraphML).foreach { c => c.edgesGraphML(buf, pad) }
@ -126,16 +120,16 @@ abstract class LazyModule()(implicit val p: Parameters)
object LazyModule
{
protected[diplomacy] var stack = List[LazyModule]()
protected[diplomacy] var scope: Option[LazyModule] = None
private var index = 0
def apply[T <: LazyModule](bc: T)(implicit sourceInfo: SourceInfo): T = {
// Make sure the user put LazyModule around modules in the correct order
// If this require fails, probably some grandchild was missing a LazyModule
// ... or you applied LazyModule twice
require (!stack.isEmpty, s"LazyModule() applied to ${bc.name} twice ${sourceLine(sourceInfo)}")
require (stack.head eq bc, s"LazyModule() applied to ${bc.name} before ${stack.head.name} ${sourceLine(sourceInfo)}")
stack = stack.tail
require (scope.isDefined, s"LazyModule() applied to ${bc.name} twice ${sourceLine(sourceInfo)}")
require (scope.get eq bc, s"LazyModule() applied to ${bc.name} before ${scope.get.name} ${sourceLine(sourceInfo)}")
scope = bc.parent
bc.info = sourceInfo
bc
}
@ -144,26 +138,96 @@ object LazyModule
sealed trait LazyModuleImpLike extends BaseModule
{
val wrapper: LazyModule
val auto: AutoBundle
protected[diplomacy] val dangles: Seq[Dangle]
// .module had better not be accessed while LazyModules are still being built!
require (LazyModule.stack.isEmpty, s"${wrapper.name}.module was constructed before LazyModule() was run on ${LazyModule.stack.head.name}")
require (!LazyModule.scope.isDefined, s"${wrapper.name}.module was constructed before LazyModule() was run on ${LazyModule.scope.get.name}")
override def desiredName = wrapper.moduleName
suggestName(wrapper.instanceName)
implicit val p = wrapper.p
}
abstract class LazyModuleImp(val wrapper: LazyModule) extends Module with LazyModuleImpLike {
wrapper.instantiate()
}
abstract class LazyMultiIOModuleImp(val wrapper: LazyModule) extends MultiIOModule with LazyModuleImpLike {
wrapper.instantiate()
}
abstract class LazyRawModuleImp(val wrapper: LazyModule) extends RawModule with LazyModuleImpLike {
withClockAndReset(Bool(false).asClock, Bool(true)) {
wrapper.instantiate()
protected[diplomacy] def instantiate() = {
val childDangles = wrapper.children.reverse.flatMap { c =>
implicit val sourceInfo = c.info
Module(c.module).dangles
}
val nodeDangles = wrapper.nodes.reverse.flatMap(_.instantiate())
val allDangles = nodeDangles ++ childDangles
val done = Set() ++ allDangles.groupBy(_.source).values.filter(_.size == 2).map { case Seq(a, b) =>
require (a.flipped != b.flipped)
if (a.flipped) { a.data <> b.data } else { b.data <> a.data }
a.source
}
val forward = allDangles.filter(d => !done(d.source))
val auto = IO(new AutoBundle(forward.map { d => (d.name, d.data, d.flipped) }:_*))
val dangles = (forward zip auto.elements) map { case (d, (_, io)) =>
if (d.flipped) { d.data <> io } else { io <> d.data }
d.copy(data = io, name = wrapper.valName.getOrElse("anon") + "_" + d.name)
}
wrapper.bindings.reverse.foreach { f => f () }
(auto, dangles)
}
}
class LazyModuleImp(val wrapper: LazyModule) extends MultiIOModule with LazyModuleImpLike {
val (auto, dangles) = instantiate()
}
class LazyRawModuleImp(val wrapper: LazyModule) extends RawModule with LazyModuleImpLike {
val (auto, dangles) = withClockAndReset(Bool(false).asClock, Bool(true)) {
instantiate()
}
}
class SimpleLazyModule(implicit p: Parameters) extends LazyModule
{
lazy val module = new LazyModuleImp(this)
}
trait LazyScope
{
this: LazyModule =>
def apply[T](body: => T)(implicit p: Parameters) = {
val saved = LazyModule.scope
LazyModule.scope = Some(this)
val out = body
require (LazyModule.scope.isDefined, s"LazyScope ${name} tried to exit, but scope was empty!")
require (LazyModule.scope.get eq this, s"LazyScope ${name} exited before LazyModule ${LazyModule.scope.get.name} was closed")
LazyModule.scope = saved
out
}
}
object LazyScope
{
def apply[T](name: String)(body: => T)(implicit p: Parameters) = {
val scope = LazyModule(new SimpleLazyModule with LazyScope)
scope.suggestName(name)
scope { body }
}
}
case class HalfEdge(serial: Int, index: Int)
case class Dangle(source: HalfEdge, sink: HalfEdge, flipped: Boolean, name: String, data: Data)
final class AutoBundle(elts: (String, Data, Boolean)*) extends Record {
// We need to preserve the order of elts, despite grouping by name to disambiguate things
val elements = ListMap() ++ elts.zipWithIndex.map(makeElements).groupBy(_._1).values.flatMap {
case Seq((key, element, i)) => Seq(i -> (key -> element))
case seq => seq.zipWithIndex.map { case ((key, element, i), j) => i -> (key + "_" + j -> element) }
}.toList.sortBy(_._1).map(_._2)
require (elements.size == elts.size)
private def makeElements(tuple: ((String, Data, Boolean), Int)) = {
val ((key, data, flip), i) = tuple
// trim trailing _0_1_2 stuff so that when we append _# we don't create collisions
val regex = new Regex("(_[0-9]+)*$")
val element = if (flip) data.cloneType.flip else data.cloneType
(regex.replaceAllIn(key, ""), element, i)
}
override def cloneType = (new AutoBundle(elts:_*)).asInstanceOf[this.type]
}

View File

@ -1,10 +0,0 @@
// See LICENSE.SiFive for license details.
package freechips.rocketchip.diplomacy
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine}
import freechips.rocketchip.config.Parameters
abstract class MonitorBase(implicit val sourceInfo: SourceInfo, p: Parameters) extends LazyModule()(p) {
override val module: LazyModuleImp
}

View File

@ -7,6 +7,7 @@ import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.{Parameters,Field}
import freechips.rocketchip.util.HeterogeneousBag
import scala.collection.mutable.ListBuffer
import scala.util.matching._
object CardinalityInferenceDirection {
val cases = Seq(SOURCE_TO_SINK, SINK_TO_SOURCE, NO_INFERENCE)
@ -26,7 +27,13 @@ object CardinalityInferenceDirection {
private case object CardinalityInferenceDirectionKey extends
Field[CardinalityInferenceDirection.T](CardinalityInferenceDirection.NO_INFERENCE)
private case object MonitorsEnabled extends Field[Boolean](true)
case object MonitorsEnabled extends Field[Boolean](true)
case object RenderFlipped extends Field[Boolean](false)
case class RenderedEdge(
colour: String,
label: String = "",
flipped: Boolean = false) // prefer to draw the arrow pointing the opposite direction of other edges
// DI = Downwards flowing Parameters received on the inner side of the node
// UI = Upwards flowing Parameters generated by the inner side of the node
@ -34,19 +41,16 @@ private case object MonitorsEnabled extends Field[Boolean](true)
// BI = Bundle type used when connecting to the inner side of the node
trait InwardNodeImp[DI, UI, EI, BI <: Data]
{
def edgeI(pd: DI, pu: UI): EI
def edgeI(pd: DI, pu: UI, p: Parameters, sourceInfo: SourceInfo): EI
def bundleI(ei: EI): BI
def colour: String
def reverse: Boolean = false
def connect(edges: () => Seq[EI], bundles: () => Seq[(BI, BI)], enableMonitoring: Boolean)
(implicit p: Parameters, sourceInfo: SourceInfo): (Option[MonitorBase], () => Unit) = {
(None, () => bundles().foreach { case (i, o) => i <> o })
}
// Edge functions
def monitor(bundle: BI, edge: EI) {}
def render(e: EI): RenderedEdge
// optional methods to track node graph
def mixI(pu: UI, node: InwardNode[DI, UI, BI]): UI = pu // insert node into parameters
def getO(pu: UI): Option[BaseNode] = None // most-outward common node
def labelI(ei: EI) = ""
}
// DO = Downwards flowing Parameters generated by the outer side of the node
@ -55,57 +59,80 @@ trait InwardNodeImp[DI, UI, EI, BI <: Data]
// BO = Bundle type used when connecting to the outer side of the node
trait OutwardNodeImp[DO, UO, EO, BO <: Data]
{
def edgeO(pd: DO, pu: UO): EO
def edgeO(pd: DO, pu: UO, p: Parameters, sourceInfo: SourceInfo): EO
def bundleO(eo: EO): BO
// optional methods to track node graph
def mixO(pd: DO, node: OutwardNode[DO, UO, BO]): DO = pd // insert node into parameters
def getI(pd: DO): Option[BaseNode] = None // most-inward common node
def labelO(eo: EO) = ""
}
abstract class NodeImp[D, U, EO, EI, B <: Data]
extends Object with InwardNodeImp[D, U, EI, B] with OutwardNodeImp[D, U, EO, B]
abstract class BaseNode
// If your edges have the same direction, using this saves you some typing
abstract class SimpleNodeImp[D, U, E, B <: Data]
extends NodeImp[D, U, E, E, B]
{
require (!LazyModule.stack.isEmpty, "You cannot create a node outside a LazyModule!")
def edge(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo): E
def edgeO(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo) = edge(pd, pu, p, sourceInfo)
def edgeI(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo) = edge(pd, pu, p, sourceInfo)
def bundle(e: E): B
def bundleO(e: E) = bundle(e)
def bundleI(e: E) = bundle(e)
}
val lazyModule = LazyModule.stack.head
abstract class BaseNode(implicit val valName: ValName)
{
require (LazyModule.scope.isDefined, "You cannot create a node outside a LazyModule!")
val lazyModule = LazyModule.scope.get
val index = lazyModule.nodes.size
lazyModule.nodes = this :: lazyModule.nodes
val externalIn: Boolean
val externalOut: Boolean
val serial = BaseNode.serial
BaseNode.serial = BaseNode.serial + 1
protected[diplomacy] def instantiate(): Seq[Dangle]
def nodename = getClass.getName.split('.').last
def name = lazyModule.name + "." + nodename
def name = lazyModule.name + "." + valName.name
def omitGraphML = outputs.isEmpty && inputs.isEmpty
lazy val nodedebugstring: String = ""
def wirePrefix = {
val camelCase = "([a-z])([A-Z])".r
val decamel = camelCase.replaceAllIn(valName.name, _ match { case camelCase(l, h) => l + "_" + h })
val trimNode = "_?node$".r
val name = trimNode.replaceFirstIn(decamel.toLowerCase, "")
if (name.isEmpty) "" else name + "_"
}
protected[diplomacy] def gci: Option[BaseNode] // greatest common inner
protected[diplomacy] def gco: Option[BaseNode] // greatest common outer
protected[diplomacy] def outputs: Seq[(BaseNode, String)]
protected[diplomacy] def inputs: Seq[(BaseNode, String)]
protected[diplomacy] def colour: String
protected[diplomacy] def reverse: Boolean
protected[diplomacy] def inputs: Seq[(BaseNode, RenderedEdge)]
protected[diplomacy] def outputs: Seq[(BaseNode, RenderedEdge)]
}
object BaseNode
{
protected[diplomacy] var serial = 0
}
// !!! rename the nodes we bind?
case class NodeHandle[DI, UI, BI <: Data, DO, UO, BO <: Data]
(inward: InwardNode[DI, UI, BI], outward: OutwardNode[DO, UO, BO])
(inwardHandle: InwardNodeHandle[DI, UI, BI], outwardHandle: OutwardNodeHandle[DO, UO, BO])
extends Object with InwardNodeHandle[DI, UI, BI] with OutwardNodeHandle[DO, UO, BO]
{
val inward = inwardHandle.inward
val outward = outwardHandle.outward
}
trait InwardNodeHandle[DI, UI, BI <: Data]
{
protected[diplomacy] val inward: InwardNode[DI, UI, BI]
def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] =
inward.:=(h)(p, sourceInfo)
def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] =
inward.:*=(h)(p, sourceInfo)
def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] =
inward.:=*(h)(p, sourceInfo)
def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] =
inward.:=?(h)(p, sourceInfo)
def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=(h)(p, sourceInfo) }
def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:*=(h)(p, sourceInfo) }
def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=*(h)(p, sourceInfo) }
def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=?(h)(p, sourceInfo) }
}
sealed trait NodeBinding
@ -121,7 +148,7 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI,
require (!numPI.isEmpty, s"No number of inputs would be acceptable to ${name}${lazyModule.line}")
require (numPI.start >= 0, s"${name} accepts a negative number of inputs${lazyModule.line}")
private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters)]()
private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters, SourceInfo)]()
private var iRealized = false
protected[diplomacy] def iPushed = accPI.size
@ -129,8 +156,8 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI,
val info = sourceLine(sourceInfo, " at ", "")
val noIs = numPI.size == 1 && numPI.contains(0)
require (!noIs, s"${name}${lazyModule.line} was incorrectly connected as a sink" + info)
require (!iRealized, s"${name}${lazyModule.line} was incorrectly connected as a sink after it's .module was used" + info)
accPI += ((index, node, binding, p))
require (!iRealized, s"${name}${lazyModule.line} was incorrectly connected as a sink after its .module was used" + info)
accPI += ((index, node, binding, p, sourceInfo))
}
protected[diplomacy] lazy val iBindings = { iRealized = true; accPI.result() }
@ -138,7 +165,6 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI,
protected[diplomacy] val iStar: Int
protected[diplomacy] val iPortMapping: Seq[(Int, Int)]
protected[diplomacy] val iParams: Seq[UI]
protected[diplomacy] val bundleIn: HeterogeneousBag[BI]
}
trait OutwardNodeHandle[DO, UO, BO <: Data]
@ -154,7 +180,7 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO
require (!numPO.isEmpty, s"No number of outputs would be acceptable to ${name}${lazyModule.line}")
require (numPO.start >= 0, s"${name} accepts a negative number of outputs${lazyModule.line}")
private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding, Parameters)]()
private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding, Parameters, SourceInfo)]()
private var oRealized = false
protected[diplomacy] def oPushed = accPO.size
@ -162,8 +188,8 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO
val info = sourceLine(sourceInfo, " at ", "")
val noOs = numPO.size == 1 && numPO.contains(0)
require (!noOs, s"${name}${lazyModule.line} was incorrectly connected as a source" + info)
require (!oRealized, s"${name}${lazyModule.line} was incorrectly connected as a source after it's .module was used" + info)
accPO += ((index, node, binding, p))
require (!oRealized, s"${name}${lazyModule.line} was incorrectly connected as a source after its .module was used" + info)
accPO += ((index, node, binding, p, sourceInfo))
}
protected[diplomacy] lazy val oBindings = { oRealized = true; accPO.result() }
@ -171,95 +197,150 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO
protected[diplomacy] val oStar: Int
protected[diplomacy] val oPortMapping: Seq[(Int, Int)]
protected[diplomacy] val oParams: Seq[DO]
protected[diplomacy] val bundleOut: HeterogeneousBag[BO]
}
abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
abstract class CycleException(kind: String, loop: Seq[String]) extends Exception(s"Diplomatic ${kind} cycle detected involving ${loop}")
case class StarCycleException(loop: Seq[String] = Nil) extends CycleException("star", loop)
case class DownwardCycleException(loop: Seq[String] = Nil) extends CycleException("downward", loop)
case class UpwardCycleException(loop: Seq[String] = Nil) extends CycleException("upward", loop)
case class Edges[EI, EO](in: EI, out: EO)
sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
inner: InwardNodeImp [DI, UI, EI, BI],
outer: OutwardNodeImp[DO, UO, EO, BO])(
protected[diplomacy] val numPO: Range.Inclusive,
protected[diplomacy] val numPI: Range.Inclusive)
protected[diplomacy] val numPI: Range.Inclusive)(
implicit valName: ValName)
extends BaseNode with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO]
{
protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStar: Int, oStar: Int): (Int, Int)
protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO]
protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI]
private var starCycleGuard = false
protected[diplomacy] lazy val (oPortMapping, iPortMapping, oStar, iStar) = {
val oStars = oBindings.filter { case (_,_,b,_) => b == BIND_STAR }.size
val iStars = iBindings.filter { case (_,_,b,_) => b == BIND_STAR }.size
val oKnown = oBindings.map { case (_, n, b, _) => b match {
case BIND_ONCE => 1
case BIND_QUERY => n.iStar
case BIND_STAR => 0 }}.foldLeft(0)(_+_)
val iKnown = iBindings.map { case (_, n, b, _) => b match {
case BIND_ONCE => 1
case BIND_QUERY => n.oStar
case BIND_STAR => 0 }}.foldLeft(0)(_+_)
val (iStar, oStar) = resolveStar(iKnown, oKnown, iStars, oStars)
val oSum = oBindings.map { case (_, n, b, _) => b match {
case BIND_ONCE => 1
case BIND_QUERY => n.iStar
case BIND_STAR => oStar }}.scanLeft(0)(_+_)
val iSum = iBindings.map { case (_, n, b, _) => b match {
case BIND_ONCE => 1
case BIND_QUERY => n.oStar
case BIND_STAR => iStar }}.scanLeft(0)(_+_)
val oTotal = oSum.lastOption.getOrElse(0)
val iTotal = iSum.lastOption.getOrElse(0)
require(numPO.contains(oTotal), s"${name} has ${oTotal} outputs, expected ${numPO}${lazyModule.line}")
require(numPI.contains(iTotal), s"${name} has ${iTotal} inputs, expected ${numPI}${lazyModule.line}")
(oSum.init zip oSum.tail, iSum.init zip iSum.tail, oStar, iStar)
try {
if (starCycleGuard) throw StarCycleException()
val oStars = oBindings.filter { case (_,_,b,_,_) => b == BIND_STAR }.size
val iStars = iBindings.filter { case (_,_,b,_,_) => b == BIND_STAR }.size
val oKnown = oBindings.map { case (_, n, b, _, _) => b match {
case BIND_ONCE => 1
case BIND_QUERY => n.iStar
case BIND_STAR => 0 }}.foldLeft(0)(_+_)
val iKnown = iBindings.map { case (_, n, b, _, _) => b match {
case BIND_ONCE => 1
case BIND_QUERY => n.oStar
case BIND_STAR => 0 }}.foldLeft(0)(_+_)
val (iStar, oStar) = resolveStar(iKnown, oKnown, iStars, oStars)
val oSum = oBindings.map { case (_, n, b, _, _) => b match {
case BIND_ONCE => 1
case BIND_QUERY => n.iStar
case BIND_STAR => oStar }}.scanLeft(0)(_+_)
val iSum = iBindings.map { case (_, n, b, _, _) => b match {
case BIND_ONCE => 1
case BIND_QUERY => n.oStar
case BIND_STAR => iStar }}.scanLeft(0)(_+_)
val oTotal = oSum.lastOption.getOrElse(0)
val iTotal = iSum.lastOption.getOrElse(0)
require(numPO.contains(oTotal), s"${name} has ${oTotal} outputs, expected ${numPO}${lazyModule.line}")
require(numPI.contains(iTotal), s"${name} has ${iTotal} inputs, expected ${numPI}${lazyModule.line}")
(oSum.init zip oSum.tail, iSum.init zip iSum.tail, oStar, iStar)
} catch {
case c: StarCycleException => throw c.copy(loop = s"${name}${lazyModule.line}" +: c.loop)
}
}
lazy val oPorts = oBindings.flatMap { case (i, n, _, _) =>
lazy val oPorts = oBindings.flatMap { case (i, n, _, p, s) =>
val (start, end) = n.iPortMapping(i)
(start until end) map { j => (j, n) }
(start until end) map { j => (j, n, p, s) }
}
lazy val iPorts = iBindings.flatMap { case (i, n, _, _) =>
lazy val iPorts = iBindings.flatMap { case (i, n, _, p, s) =>
val (start, end) = n.oPortMapping(i)
(start until end) map { j => (j, n) }
(start until end) map { j => (j, n, p, s) }
}
private var oParamsCycleGuard = false
protected[diplomacy] lazy val oParams: Seq[DO] = {
val o = mapParamsD(oPorts.size, iPorts.map { case (i, n) => n.oParams(i) })
require (o.size == oPorts.size, s"Bug in diplomacy; ${name} has ${o.size} != ${oPorts.size} down/up outer parameters${lazyModule.line}")
o.map(outer.mixO(_, this))
try {
if (oParamsCycleGuard) throw DownwardCycleException()
oParamsCycleGuard = true
val o = mapParamsD(oPorts.size, iPorts.map { case (i, n, _, _) => n.oParams(i) })
require (o.size == oPorts.size, s"Bug in diplomacy; ${name} has ${o.size} != ${oPorts.size} down/up outer parameters${lazyModule.line}")
o.map(outer.mixO(_, this))
} catch {
case c: DownwardCycleException => throw c.copy(loop = s"${name}${lazyModule.line}" +: c.loop)
}
}
private var iParamsCycleGuard = false
protected[diplomacy] lazy val iParams: Seq[UI] = {
val i = mapParamsU(iPorts.size, oPorts.map { case (o, n) => n.iParams(o) })
require (i.size == iPorts.size, s"Bug in diplomacy; ${name} has ${i.size} != ${iPorts.size} up/down inner parameters${lazyModule.line}")
i.map(inner.mixI(_, this))
try {
if (iParamsCycleGuard) throw UpwardCycleException()
iParamsCycleGuard = true
val i = mapParamsU(iPorts.size, oPorts.map { case (o, n, _, _) => n.iParams(o) })
require (i.size == iPorts.size, s"Bug in diplomacy; ${name} has ${i.size} != ${iPorts.size} up/down inner parameters${lazyModule.line}")
i.map(inner.mixI(_, this))
} catch {
case c: UpwardCycleException => throw c.copy(loop = s"${name}${lazyModule.line}" +: c.loop)
}
}
protected[diplomacy] def gco = if (iParams.size != 1) None else inner.getO(iParams(0))
protected[diplomacy] def gci = if (oParams.size != 1) None else outer.getI(oParams(0))
lazy val edgesOut = (oPorts zip oParams).map { case ((i, n), o) => outer.edgeO(o, n.iParams(i)) }
lazy val edgesIn = (iPorts zip iParams).map { case ((o, n), i) => inner.edgeI(n.oParams(o), i) }
lazy val externalEdgesOut = if (externalOut) {edgesOut} else { Seq() }
lazy val externalEdgesIn = if (externalIn) {edgesIn} else { Seq() }
protected[diplomacy] lazy val edgesOut = (oPorts zip oParams).map { case ((i, n, p, s), o) => outer.edgeO(o, n.iParams(i), p, s) }
protected[diplomacy] lazy val edgesIn = (iPorts zip iParams).map { case ((o, n, p, s), i) => inner.edgeI(n.oParams(o), i, p, s) }
lazy val paramsOut: Seq[Parameters] = (oPortMapping zip oBindings).flatMap { case ((s, e), b) => Seq.fill(e-s) { b._4 } }
lazy val paramsIn: Seq[Parameters] = (iPortMapping zip iBindings).flatMap { case ((s, e), b) => Seq.fill(e-s) { b._4 } }
// If you need access to the edges of a foreign Node, use this method (in/out create bundles)
lazy val edges = Edges(edgesIn, edgesOut)
val flip = false // needed for blind nodes
private def flipO(b: HeterogeneousBag[BO]) = if (flip) b.flip else b
private def flipI(b: HeterogeneousBag[BI]) = if (flip) b else b.flip
val wire = false // needed if you want to grab access to from inside a module
private def wireO(b: HeterogeneousBag[BO]) = if (wire) Wire(b) else b
private def wireI(b: HeterogeneousBag[BI]) = if (wire) Wire(b) else b
protected[diplomacy] lazy val bundleOut: Seq[BO] = edgesOut.map(e => Wire(outer.bundleO(e)))
protected[diplomacy] lazy val bundleIn: Seq[BI] = edgesIn .map(e => Wire(inner.bundleI(e)))
lazy val bundleOut = wireO(flipO(HeterogeneousBag(edgesOut.map(outer.bundleO(_)))))
lazy val bundleIn = wireI(flipI(HeterogeneousBag(edgesIn .map(inner.bundleI(_)))))
protected[diplomacy] def danglesOut: Seq[Dangle] = oPorts.zipWithIndex.map { case ((j, n, _, _), i) =>
Dangle(
source = HalfEdge(serial, i),
sink = HalfEdge(n.serial, j),
flipped= false,
name = wirePrefix + "out",
data = bundleOut(i))
}
protected[diplomacy] def danglesIn: Seq[Dangle] = iPorts.zipWithIndex.map { case ((j, n, _, _), i) =>
Dangle(
source = HalfEdge(n.serial, j),
sink = HalfEdge(serial, i),
flipped= true,
name = wirePrefix + "in",
data = bundleIn(i))
}
private var bundlesSafeNow = false
// Accessors to the result of negotiation to be used in LazyModuleImp:
def out: Seq[(BO, EO)] = {
require(bundlesSafeNow, s"${name}.out should only be called from the context of its module implementation")
bundleOut zip edgesOut
}
def in: Seq[(BI, EI)] = {
require(bundlesSafeNow, s"${name}.in should only be called from the context of its module implementation")
bundleIn zip edgesIn
}
// Used by LazyModules.module.instantiate
protected val identity = false
protected[diplomacy] def instantiate() = {
bundlesSafeNow = true
if (!identity) {
(iPorts zip in) foreach {
case ((_, _, p, _), (b, e)) => if (p(MonitorsEnabled)) inner.monitor(b, e)
} }
danglesOut ++ danglesIn
}
// connects the outward part of a node with the inward part of this node
private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)
(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = {
private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) {
val x = this // x := y
val y = h.outward
val info = sourceLine(sourceInfo, " at ", "")
require (!LazyModule.stack.isEmpty, s"${y.name} cannot be connected to ${x.name} outside of LazyModule scope" + info)
val i = x.iPushed
val o = y.oPushed
y.oPush(i, x, binding match {
@ -267,29 +348,12 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
case BIND_STAR => BIND_QUERY
case BIND_QUERY => BIND_STAR })
x.iPush(o, y, binding)
def edges() = {
val (iStart, iEnd) = x.iPortMapping(i)
val (oStart, oEnd) = y.oPortMapping(o)
require (iEnd - iStart == oEnd - oStart, s"Bug in diplomacy; ${iEnd-iStart} != ${oEnd-oStart} means port resolution failed")
Seq.tabulate(iEnd - iStart) { j => x.edgesIn(iStart+j) }
}
def bundles() = {
val (iStart, iEnd) = x.iPortMapping(i)
val (oStart, oEnd) = y.oPortMapping(o)
require (iEnd - iStart == oEnd - oStart, s"Bug in diplomacy; ${iEnd-iStart} != ${oEnd-oStart} means port resolution failed")
Seq.tabulate(iEnd - iStart) { j =>
(x.bundleIn(iStart+j), y.bundleOut(oStart+j))
}
}
val (out, newbinding) = inner.connect(edges _, bundles _, p(MonitorsEnabled))
LazyModule.stack.head.bindings = newbinding :: LazyModule.stack.head.bindings
out
}
override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE)
override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR)
override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY)
override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = {
override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_ONCE)
override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_STAR)
override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_QUERY)
override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = {
p(CardinalityInferenceDirectionKey) match {
case CardinalityInferenceDirection.SOURCE_TO_SINK => this :=* h
case CardinalityInferenceDirection.SINK_TO_SOURCE => this :*= h
@ -298,17 +362,19 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
}
// meta-data for printing the node graph
protected[diplomacy] def colour = inner.colour
protected[diplomacy] def reverse = inner.reverse
protected[diplomacy] def outputs = oPorts.map(_._2) zip edgesOut.map(e => outer.labelO(e))
protected[diplomacy] def inputs = iPorts.map(_._2) zip edgesIn .map(e => inner.labelI(e))
protected[diplomacy] def inputs = (iPorts zip edgesIn) map { case ((_, n, p, _), e) =>
val re = inner.render(e)
(n, re.copy(flipped = re.flipped != p(RenderFlipped)))
}
protected[diplomacy] def outputs = oPorts map { case (i, n, _, _) => (n, n.inputs(i)._2) }
}
abstract class MixedCustomNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
inner: InwardNodeImp [DI, UI, EI, BI],
outer: OutwardNodeImp[DO, UO, EO, BO])(
numPO: Range.Inclusive,
numPI: Range.Inclusive)
numPI: Range.Inclusive)(
implicit valName: ValName)
extends MixedNode(inner, outer)(numPO, numPI)
{
def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int)
@ -318,7 +384,8 @@ abstract class MixedCustomNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
abstract class CustomNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(
numPO: Range.Inclusive,
numPI: Range.Inclusive)
numPI: Range.Inclusive)(
implicit valName: ValName)
extends MixedCustomNode(imp, imp)(numPO, numPI)
class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
@ -326,12 +393,10 @@ class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
outer: OutwardNodeImp[DO, UO, EO, BO])(
dFn: DI => DO,
uFn: UO => UI,
num: Range.Inclusive = 0 to 999)
num: Range.Inclusive = 0 to 999)(
implicit valName: ValName)
extends MixedNode(inner, outer)(num, num)
{
val externalIn: Boolean = true
val externalOut: Boolean = true
protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = {
require (oStars + iStars <= 1, s"${name} (an adapter) appears left of a :*= ${iStars} times and right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}")
if (oStars > 0) {
@ -352,21 +417,38 @@ class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
}
}
class AdapterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(
dFn: D => D,
uFn: U => U,
num: Range.Inclusive = 0 to 999)(
implicit valName: ValName)
extends MixedAdapterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, num)
// IdentityNodes automatically connect their inputs to outputs
class IdentityNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])()(implicit valName: ValName)
extends AdapterNode(imp)({ s => s }, { s => s })
{
protected override val identity = true
override protected[diplomacy] def instantiate() = {
val dangles = super.instantiate()
(out zip in) map { case ((o, _), (i, _)) => o <> i }
dangles
}
}
class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
inner: InwardNodeImp [DI, UI, EI, BI],
outer: OutwardNodeImp[DO, UO, EO, BO])(
dFn: Seq[DI] => DO,
uFn: Seq[UO] => UI,
numPO: Range.Inclusive = 1 to 999,
numPI: Range.Inclusive = 1 to 999)
numPI: Range.Inclusive = 1 to 999)(
implicit valName: ValName)
extends MixedNode(inner, outer)(numPO, numPI)
{
// require (numPO.end >= 1, s"${name} does not accept outputs${lazyModule.line}")
// require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}")
val externalIn: Boolean = true
val externalOut: Boolean = true
protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = {
require (iStars == 0, s"${name} (a nexus) appears left of :*= (perhaps you should flip the '*' to :=*?)${lazyModule.line}")
require (oStars == 0, s"${name} (a nexus) appears right of a :=* (perhaps you should flip the '*' to :*=?)${lazyModule.line}")
@ -376,82 +458,18 @@ class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = { val a = uFn(p); Seq.fill(n)(a) }
}
class AdapterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(
dFn: D => D,
uFn: U => U,
num: Range.Inclusive = 0 to 999)
extends MixedAdapterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, num)
class NexusNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(
dFn: Seq[D] => D,
uFn: Seq[U] => U,
numPO: Range.Inclusive = 1 to 999,
numPI: Range.Inclusive = 1 to 999)
numPI: Range.Inclusive = 1 to 999)(
implicit valName: ValName)
extends MixedNexusNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, numPO, numPI)
case class SplitterArg[T](newSize: Int, ports: Seq[T])
class MixedSplitterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
inner: InwardNodeImp [DI, UI, EI, BI],
outer: OutwardNodeImp[DO, UO, EO, BO])(
dFn: SplitterArg[DI] => Seq[DO],
uFn: SplitterArg[UO] => Seq[UI],
numPO: Range.Inclusive = 1 to 999,
numPI: Range.Inclusive = 1 to 999)
extends MixedNode(inner, outer)(numPO, numPI)
{
override val externalIn: Boolean = true
override val externalOut: Boolean = true
protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = {
require (oKnown == 0, s"${name} (a splitter) appears right of a := or :*=; use a :=* instead${lazyModule.line}")
require (iStars == 0, s"${name} (a splitter) cannot appear left of a :*=; did you mean :=*?${lazyModule.line}")
(0, iKnown)
}
protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = {
require (p.size == 0 || n % p.size == 0, s"Diplomacy bug; splitter inputs do not divide outputs")
val out = dFn(SplitterArg(n, p))
require (out.size == n, s"${name} created the wrong number of outputs from inputs${lazyModule.line}")
out
}
protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = {
require (n == 0 || p.size % n == 0, s"Diplomacy bug; splitter outputs indivisable by inputs")
val out = uFn(SplitterArg(n, p))
require (out.size == n, s"${name} created the wrong number of inputs from outputs${lazyModule.line}")
out
}
}
class SplitterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(
dFn: SplitterArg[D] => Seq[D],
uFn: SplitterArg[U] => Seq[U],
numPO: Range.Inclusive = 1 to 999,
numPI: Range.Inclusive = 1 to 999)
extends MixedSplitterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, numPO, numPI)
class IdentityNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])
extends AdapterNode(imp)({s => s}, {s => s})
class OutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B]) extends IdentityNode(imp)
{
override val externalIn: Boolean = false
override val externalOut: Boolean = true
override lazy val bundleIn = bundleOut
}
class InputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B]) extends IdentityNode(imp)
{
override val externalIn: Boolean = true
override val externalOut: Boolean = false
override lazy val bundleOut = bundleIn
}
class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])
// There are no Mixed SourceNodes
class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])(implicit valName: ValName)
extends MixedNode(imp, imp)(po.size to po.size, 0 to 0)
{
override val externalIn: Boolean = false
override val externalOut: Boolean = true
protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = {
require (oStars <= 1, s"${name} (a source) appears right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}")
require (iStars == 0, s"${name} (a source) cannot appear left of a :*=${lazyModule.line}")
@ -461,16 +479,12 @@ class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq
}
protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = po
protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = Seq()
override lazy val bundleIn = { require(false, s"${name} has no bundleIn; try bundleOut?"); bundleOut }
}
class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])
// There are no Mixed SinkNodes
class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])(implicit valName: ValName)
extends MixedNode(imp, imp)(0 to 0, pi.size to pi.size)
{
override val externalIn: Boolean = true
override val externalOut: Boolean = false
protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = {
require (iStars <= 1, s"${name} (a sink) appears left of a :*= ${iStars} times; at most once is allowed${lazyModule.line}")
require (oStars == 0, s"${name} (a sink) cannot appear right of a :=*${lazyModule.line}")
@ -480,40 +494,4 @@ class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U
}
protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = Seq()
protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = pi
override lazy val bundleOut = { require(false, s"${name} has no bundleOut; try bundleIn?"); bundleIn }
}
class BlindOutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])
extends SinkNode(imp)(pi)
{
override val externalIn: Boolean = false
override val flip = true
override lazy val bundleOut = bundleIn
}
class BlindInputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])
extends SourceNode(imp)(po)
{
override val externalOut: Boolean = false
override val flip = true
override lazy val bundleIn = bundleOut
}
class InternalOutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])
extends SinkNode(imp)(pi)
{
override val externalIn: Boolean = false
override val externalOut: Boolean = false
override val wire = true
override lazy val bundleOut = bundleIn
}
class InternalInputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])
extends SourceNode(imp)(po)
{
override val externalIn: Boolean = false
override val externalOut: Boolean = false
override val wire = true
override lazy val bundleIn = bundleOut
}

View File

@ -179,7 +179,7 @@ trait BindingScope
private case class ExpandedValue(path: Seq[String], labels: Seq[String], value: Seq[ResourceValue])
private lazy val eval: Unit = {
require (LazyModule.stack.isEmpty, "May not evaluate binding while still constructing LazyModules")
require (!LazyModule.scope.isDefined, "May not evaluate binding while still constructing LazyModules")
parentScope.foreach { _.eval }
resourceBindings = parentScope.map(_.resourceBindings).getOrElse(Nil)
BindingScope.active = Some(this)
@ -224,7 +224,7 @@ trait BindingScope
object BindingScope
{
protected[diplomacy] var active: Option[BindingScope] = None
protected[diplomacy] def find(m: Option[LazyModule] = LazyModule.stack.headOption): Option[BindingScope] = m.flatMap {
protected[diplomacy] def find(m: Option[LazyModule] = LazyModule.scope): Option[BindingScope] = m.flatMap {
case s: BindingScope => Some(s)
case x => find(x.parent)
}

View File

@ -0,0 +1,13 @@
// See LICENSE.SiFive for license details.
package freechips.rocketchip.diplomacy
import scala.language.experimental.macros
import freechips.rocketchip.macros.ValNameImpl
case class ValName(name: String)
object ValName
{
implicit def materialize(implicit x: ValNameImpl): ValName = ValName(x.name)
}

View File

@ -47,4 +47,7 @@ package object diplomacy
def DisableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial {
case MonitorsEnabled => false
})
def FlipRendering[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial {
case RenderFlipped => !p(RenderFlipped)
})
}

View File

@ -5,6 +5,7 @@ package freechips.rocketchip.groundtest
import Chisel._
import freechips.rocketchip.config._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.coreplex._
import freechips.rocketchip.rocket.{HellaCache, RocketCoreParams}
import freechips.rocketchip.tile._
@ -29,7 +30,7 @@ case object GroundTestTilesKey extends Field[Seq[GroundTestTileParams]]
abstract class GroundTestTile(params: GroundTestTileParams)(implicit p: Parameters) extends BaseTile(params)(p) {
val slave = None
val dcacheOpt = params.dcache.map { dc => HellaCache(0, dc.nMSHRs == 0) }
val dcacheOpt = params.dcache.map { dc => LazyModule(HellaCache(0, dc.nMSHRs == 0)) }
dcacheOpt.foreach { tileBus.node := _.node }
override lazy val module = new GroundTestTileModule(this, () => new GroundTestTileBundle(this))

View File

@ -37,11 +37,9 @@ class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit
beatBytes = p(XLen)/8)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val tl = node.bundleIn
val interrupt = intNode.bundleOut
val io = IO(new Bundle {
val errors = t.flip
}
})
val sources = io.errors.toErrorList
val mask = sources.map(_.nonEmpty.B).asUInt
@ -61,7 +59,8 @@ class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit
}
}
io.interrupt.head(0) := (accrued & interrupt).orR
val (int_out, _) = intNode.out(0)
int_out(0) := (accrued & interrupt).orR
def reg(r: UInt) = RegField(regWidth, r)
def maskedReg(r: UInt, m: UInt) = RegField(regWidth, r, RegWriteFn((v, d) => { when (v) { r := d & m }; true }))

View File

@ -56,28 +56,22 @@ class FrontendIO(implicit p: Parameters) extends CoreBundle()(p) {
class Frontend(val icacheParams: ICacheParams, hartid: Int)(implicit p: Parameters) extends LazyModule {
lazy val module = new FrontendModule(this)
val icache = LazyModule(new ICache(icacheParams, hartid))
val masterNode = TLOutputNode()
val slaveNode = TLInputNode()
masterNode := icache.masterNode
// Avoid breaking tile dedup due to address constants in the monitor
DisableMonitors { implicit p => icache.slaveNode.map { _ := slaveNode } }
val masterNode = icache.masterNode
val slaveNode = icache.slaveNode
}
class FrontendBundle(outer: Frontend) extends CoreBundle()(outer.p)
with HasExternallyDrivenTileConstants {
val cpu = new FrontendIO().flip
val ptw = new TLBPTWIO()
val tl_out = outer.masterNode.bundleOut
val tl_in = outer.slaveNode.bundleIn
val errors = new ICacheErrors
}
class FrontendModule(outer: Frontend) extends LazyModuleImp(outer)
with HasCoreParameters
with HasL1ICacheParameters {
val io = new FrontendBundle(outer)
implicit val edge = outer.masterNode.edgesOut.head
val io = IO(new FrontendBundle(outer))
implicit val edge = outer.masterNode.edges.out(0)
val icache = outer.icache.module
require(fetchWidth*coreInstBytes == outer.icacheParams.fetchBytes)

View File

@ -176,15 +176,14 @@ class HellaCacheBundle(outer: HellaCache)(implicit p: Parameters) extends CoreBu
val hartid = UInt(INPUT, hartIdLen)
val cpu = (new HellaCacheIO).flip
val ptw = new TLBPTWIO()
val mem = outer.node.bundleOut
val errors = new DCacheErrors
}
class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer)
with HasL1HellaCacheParameters {
implicit val edge = outer.node.edgesOut(0)
val io = new HellaCacheBundle(outer)
val tl_out = io.mem(0)
implicit val edge = outer.node.edges.out(0)
val (tl_out, _) = outer.node.out(0)
val io = IO(new HellaCacheBundle(outer))
private val fifoManagers = edge.manager.managers.filter(TLFIFOFixer.allUncacheable)
fifoManagers.foreach { m =>
@ -195,8 +194,7 @@ class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer)
object HellaCache {
def apply(hartid: Int, blocking: Boolean, scratch: () => Option[AddressSet] = () => None)(implicit p: Parameters) = {
if (blocking) LazyModule(new DCache(hartid, scratch))
else LazyModule(new NonBlockingDCache(hartid))
if (blocking) new DCache(hartid, scratch) else new NonBlockingDCache(hartid)
}
}
@ -208,7 +206,7 @@ trait HasHellaCache extends HasTileLinkMasterPort with HasTileParameters {
def findScratchpadFromICache: Option[AddressSet]
val hartid: Int
var nDCachePorts = 0
val dcache = HellaCache(hartid, tileParams.dcache.get.nMSHRs == 0, findScratchpadFromICache _)
val dcache = LazyModule(HellaCache(hartid, tileParams.dcache.get.nMSHRs == 0, findScratchpadFromICache _))
tileBus.node := dcache.node
}

View File

@ -45,15 +45,15 @@ class ICacheErrors(implicit p: Parameters) extends CoreBundle()(p)
class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parameters) extends LazyModule {
lazy val module = new ICacheModule(this)
val masterNode = TLClientNode(TLClientParameters(
val masterNode = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(
sourceId = IdRange(0, 1 + icacheParams.prefetch.toInt), // 0=refill, 1=hint
name = s"Core ${hartid} ICache"))
name = s"Core ${hartid} ICache")))))
val size = icacheParams.nSets * icacheParams.nWays * icacheParams.blockBytes
val device = new SimpleDevice("itim", Seq("sifive,itim0"))
val slaveNode = icacheParams.itimAddr.map { itimAddr =>
val wordBytes = icacheParams.fetchBytes
TLManagerNode(Seq(TLManagerPortParameters(
private val wordBytes = icacheParams.fetchBytes
val slaveNode =
TLManagerNode(icacheParams.itimAddr.toSeq.map { itimAddr => TLManagerPortParameters(
Seq(TLManagerParameters(
address = Seq(AddressSet(itimAddr, size-1)),
resources = device.reg("mem"),
@ -64,8 +64,7 @@ class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parame
supportsGet = TransferSizes(1, wordBytes),
fifoId = Some(0))), // requests handled in FIFO order
beatBytes = wordBytes,
minLatency = 1)))
}
minLatency = 1)})
}
class ICacheResp(outer: ICache) extends Bundle {
@ -91,8 +90,6 @@ class ICacheBundle(outer: ICache) extends CoreBundle()(outer.p) {
val resp = Valid(new ICacheResp(outer))
val invalidate = Bool(INPUT)
val tl_out = outer.masterNode.bundleOut
val tl_in = outer.slaveNode.map(_.bundleIn)
val errors = new ICacheErrors
val perf = new ICachePerfEvents().asOutput
@ -109,11 +106,10 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
with HasL1ICacheParameters {
override val cacheParams = outer.icacheParams // Use the local parameters
val io = new ICacheBundle(outer)
val edge_out = outer.masterNode.edgesOut.head
val tl_out = io.tl_out.head
val edge_in = outer.slaveNode.map(_.edgesIn.head)
val tl_in = io.tl_in.map(_.head)
val io = IO(new ICacheBundle(outer))
val (tl_out, edge_out) = outer.masterNode.out(0)
// Option.unzip does not exist :-(
val (tl_in, edge_in) = outer.slaveNode.in.headOption.unzip
val tECC = cacheParams.tagECC
val dECC = cacheParams.dataECC

View File

@ -283,7 +283,7 @@ trait CanHavePTW extends HasHellaCache {
trait CanHavePTWModule extends HasHellaCacheModule {
val outer: CanHavePTW
val ptwPorts = ListBuffer(outer.dcache.module.io.ptw)
val ptw = Module(new PTW(outer.nPTWPorts)(outer.dcache.node.edgesOut(0), outer.p))
val ptw = Module(new PTW(outer.nPTWPorts)(outer.dcache.node.edges.out(0), outer.p))
if (outer.usingPTW)
dcachePorts += ptw.io.mem
}

View File

@ -30,13 +30,11 @@ class ScratchpadSlavePort(address: AddressSet, coreDataBytes: Int, usingAtomics:
minLatency = 1)))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val tl_in = node.bundleIn
val io = IO(new Bundle {
val dmem = new HellaCacheIO
}
})
val tl_in = io.tl_in(0)
val edge = node.edgesIn(0)
val (tl_in, edge) = node.in(0)
val s_ready :: s_wait :: s_replay :: s_grant :: Nil = Enum(UInt(), 4)
val state = Reg(init = s_ready)
@ -104,7 +102,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1), xBytes, tileParams.core.useAtomics)))
}
val intOutputNode = tileParams.core.tileControlAddr.map(dummy => IntOutputNode())
val intOutputNode = tileParams.core.tileControlAddr.map(dummy => IntIdentityNode())
val busErrorUnit = tileParams.core.tileControlAddr map { a =>
val beu = LazyModule(new BusErrorUnit(new L1BusErrors, BusErrorUnitParams(a)))
intOutputNode.get := beu.intNode
@ -112,7 +110,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
}
// connect any combination of ITIM, DTIM, and BusErrorUnit
val slaveNode = TLInputNode()
val slaveNode = TLIdentityNode()
DisableMonitors { implicit p =>
val xbarPorts =
scratch.map(lm => (lm.node, xBytes)) ++
@ -129,7 +127,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
}
def findScratchpadFromICache: Option[AddressSet] = scratch.map { s =>
val finalNode = frontend.masterNode.edgesOut.head.manager.managers.find(_.nodePath.last == s.node)
val finalNode = frontend.masterNode.edges.out.head.manager.managers.find(_.nodePath.last == s.node)
require (finalNode.isDefined, "Could not find the scratch pad; not reachable via icache?")
require (finalNode.get.address.size == 1, "Scratchpad address space was fragmented!")
finalNode.get.address(0)
@ -140,8 +138,6 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend {
trait CanHaveScratchpadBundle extends HasHellaCacheBundle with HasICacheFrontendBundle {
val outer: CanHaveScratchpad
val slave = outer.slaveNode.bundleIn
val intOutput = outer.intOutputNode.map(_.bundleOut)
}
trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontendModule {

View File

@ -66,21 +66,20 @@ abstract class BareTileBundle[+L <: BareTile](_outer: L) extends GenericParamete
abstract class BareTileModule[+L <: BareTile, +B <: BareTileBundle[L]](_outer: L, _io: () => B) extends LazyModuleImp(_outer) {
val outer = _outer
val io = _io ()
val io = IO(_io ())
}
/** Uses TileLink master port to connect caches and accelerators to the coreplex */
trait HasTileLinkMasterPort {
implicit val p: Parameters
val module: HasTileLinkMasterPortModule
val masterNode = TLOutputNode()
val masterNode = TLIdentityNode()
val tileBus = LazyModule(new TLXbar) // TileBus xbar for cache backends to connect to
masterNode := tileBus.node
}
trait HasTileLinkMasterPortBundle {
val outer: HasTileLinkMasterPort
val master = outer.masterNode.bundleOut
}
trait HasTileLinkMasterPortModule {

View File

@ -38,7 +38,6 @@ trait HasExternalInterrupts extends HasTileParameters {
trait HasExternalInterruptsBundle {
val outer: HasExternalInterrupts
val interrupts = outer.intNode.bundleIn
}
trait HasExternalInterruptsModule {
@ -57,6 +56,7 @@ trait HasExternalInterruptsModule {
val core_ips = core.lip
(async_ips ++ periph_ips ++ seip ++ core_ips).zip(io.interrupts(0)).foreach { case(c, i) => c := i }
val (interrupts, _) = outer.intNode.in(0)
(async_ips ++ periph_ips ++ seip ++ core_ips).zip(interrupts).foreach { case(c, i) => c := i }
}
}

View File

@ -60,13 +60,11 @@ class RoCCCoreIO(implicit p: Parameters) extends CoreBundle()(p) {
abstract class LazyRoCC(implicit p: Parameters) extends LazyModule {
val module: LazyRoCCModule
val atlNode: TLMixedNode = TLOutputNode()
val tlNode: TLMixedNode = TLOutputNode()
val atlNode: TLMixedNode = TLIdentityNode()
val tlNode: TLMixedNode = TLIdentityNode()
}
class RoCCIO(outer: LazyRoCC)(implicit p: Parameters) extends RoCCCoreIO()(p) {
val atl = outer.atlNode.bundleOut
val tl = outer.tlNode.bundleOut
// Should be handled differently, eventually
val ptw = Vec(p(RoccNPTWPorts), new TLBPTWIO)
val fpu_req = Decoupled(new FPInput)
@ -74,7 +72,7 @@ class RoCCIO(outer: LazyRoCC)(implicit p: Parameters) extends RoCCCoreIO()(p) {
}
class LazyRoCCModule(outer: LazyRoCC) extends LazyModuleImp(outer) {
val io = new RoCCIO(outer)
val io = IO(new RoCCIO(outer))
}
/** Mixins for including RoCC **/
@ -263,7 +261,7 @@ class TranslatorExampleModule(outer: TranslatorExample)(implicit p: Parameters)
class CharacterCountExample(implicit p: Parameters) extends LazyRoCC {
override lazy val module = new CharacterCountExampleModule(this)
override val atlNode = TLClientNode(TLClientParameters("CharacterCountRoCC"))
override val atlNode = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters("CharacterCountRoCC")))))
}
class CharacterCountExampleModule(outer: CharacterCountExample)(implicit p: Parameters) extends LazyRoCCModule(outer)
@ -286,7 +284,7 @@ class CharacterCountExampleModule(outer: CharacterCountExample)(implicit p: Para
val s_idle :: s_acq :: s_gnt :: s_check :: s_resp :: Nil = Enum(Bits(), 5)
val state = Reg(init = s_idle)
val tl_out = io.atl.head
val (tl_out, edgesOut) = outer.atlNode.out(0)
val gnt = tl_out.d.bits
val recv_data = Reg(UInt(width = cacheDataBits))
val recv_beat = Reg(UInt(width = log2Up(cacheDataBeats+1)), init = UInt(0))
@ -309,7 +307,7 @@ class CharacterCountExampleModule(outer: CharacterCountExample)(implicit p: Para
io.resp.bits.rd := resp_rd
io.resp.bits.data := count
tl_out.a.valid := (state === s_acq)
tl_out.a.bits := outer.atlNode.edgesOut(0).Get(
tl_out.a.bits := edgesOut.Get(
fromSource = UInt(0),
toAddress = addr_block << blockOffset,
lgSize = UInt(lgCacheBlockBytes))._2

View File

@ -57,7 +57,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p
val dtim = scratch.map(d => Map(
"sifive,dtim" -> ofRef(d.device))).getOrElse(Map())
val itim = if (!frontend.icache.slaveNode.isDefined) Map() else Map(
val itim = if (frontend.icache.slaveNode.edges.in.isEmpty) Map() else Map(
"sifive,itim" -> ofRef(frontend.icache.device))
val icache = rocketParams.icache.map(i => Map(
@ -82,7 +82,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p
}))
// Find all the caches
val outer = masterNode.edgesOut
val outer = masterNode.edges.out
.flatMap(_.manager.managers)
.filter(_.supportsAcquireB)
.flatMap(_.resources.headOption)
@ -115,7 +115,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p
Resource(cpuDevice, "reg").bind(ResourceInt(BigInt(hartid)))
Resource(intcDevice, "reg").bind(ResourceInt(BigInt(hartid)))
intNode.edgesIn.flatMap(_.source.sources).map { case s =>
intNode.edges.in.flatMap(_.source.sources).map { case s =>
for (i <- s.range.start until s.range.end) {
csrIntMap.lift(i).foreach { j =>
s.resources.foreach { r =>
@ -181,12 +181,10 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule {
val rocket = LazyModule(new RocketTile(rtp, hartid))
val masterNode: OutputNode[_,_,_,_,_]
val slaveNode: InputNode[_,_,_,_,_]
val intOutputNode = rocket.intOutputNode.map(dummy => IntOutputNode())
val asyncIntNode = IntInputNode()
val periphIntNode = IntInputNode()
val coreIntNode = IntInputNode()
val asyncIntNode : IntInwardNode
val periphIntNode : IntInwardNode
val coreIntNode : IntInwardNode
val intOutputNode = rocket.intOutputNode
val intXbar = LazyModule(new IntXbar)
rocket.intNode := intXbar.intnode
@ -201,33 +199,25 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p:
}
}
def optionalSlaveBuffer(in: TLOutwardNode): TLOutwardNode = {
def optionalSlaveBuffer(out: TLInwardNode): TLInwardNode = {
if (rtp.boundaryBuffers) {
val sbuf = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none, BufferParams.none, BufferParams.none, BufferParams.none))
DisableMonitors { implicit p => sbuf.node :*= in }
DisableMonitors { implicit p => out :*= sbuf.node }
sbuf.node
} else {
in
out
}
}
def outputInterruptXingLatency: Int
intOutputNode.foreach { _ := rocket.intOutputNode.get }
lazy val module = new LazyModuleImp(this) {
val io = new CoreBundle
val io = IO(new CoreBundle
with HasExternallyDrivenTileConstants
with CanHaveInstructionTracePort
with CanHaltAndCatchFire {
val master = masterNode.bundleOut
val slave = slaveNode.bundleIn
val outputInterrupts = intOutputNode.map(_.bundleOut)
val asyncInterrupts = asyncIntNode.bundleIn
val periphInterrupts = periphIntNode.bundleIn
val coreInterrupts = coreIntNode.bundleIn
val halt_and_catch_fire = rocket.module.io.halt_and_catch_fire.map(_.cloneType)
}
})
// signals that do not change based on crossing type:
rocket.module.io.hartid := io.hartid
rocket.module.io.reset_vector := io.reset_vector
@ -237,66 +227,59 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p:
}
class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
val masterNode = TLOutputNode()
masterNode :=* optionalMasterBuffer(rocket.masterNode)
val slaveNode = new TLInputNode() { override def reverse = true }
DisableMonitors { implicit p => rocket.slaveNode :*= optionalSlaveBuffer(slaveNode) }
val masterNode = optionalMasterBuffer(rocket.masterNode)
val slaveNode = optionalSlaveBuffer(rocket.slaveNode)
// Fully async interrupts need synchronizers.
// Others need no synchronization.
val xing = LazyModule(new IntXing(3))
xing.intnode := asyncIntNode
val asyncIntNode = xing.intnode
intXbar.intnode := xing.intnode
intXbar.intnode := periphIntNode
intXbar.intnode := coreIntNode
val periphIntNode = IntIdentityNode()
val coreIntNode = IntIdentityNode()
// order here matters
intXbar.intnode := xing.intnode
intXbar.intnode := periphIntNode
intXbar.intnode := coreIntNode
def outputInterruptXingLatency = 0
}
class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
val masterNode = TLAsyncOutputNode()
val source = LazyModule(new TLAsyncCrossingSource)
source.node :=* rocket.masterNode
masterNode :=* source.node
val masterNode = source.node
val slaveNode = new TLAsyncInputNode() { override def reverse = true }
val sink = LazyModule(new TLAsyncCrossingSink)
DisableMonitors { implicit p =>
rocket.slaveNode :*= sink.node
sink.node :*= slaveNode
}
DisableMonitors { implicit p => rocket.slaveNode :*= sink.node }
val slaveNode = sink.node
// Fully async interrupts need synchronizers,
// as do those coming from the periphery clock.
// Others need no synchronization.
val asyncXing = LazyModule(new IntXing(3))
val periphXing = LazyModule(new IntXing(3))
asyncXing.intnode := asyncIntNode
periphXing.intnode := periphIntNode
val asyncIntNode = asyncXing.intnode
val periphIntNode = periphXing.intnode
val coreIntNode = IntIdentityNode()
intXbar.intnode := asyncXing.intnode
intXbar.intnode := periphXing.intnode
intXbar.intnode := coreIntNode
// order here matters
intXbar.intnode := asyncXing.intnode
intXbar.intnode := periphXing.intnode
intXbar.intnode := coreIntNode
def outputInterruptXingLatency = 3
}
class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) {
val masterNode = TLRationalOutputNode()
val source = LazyModule(new TLRationalCrossingSource)
source.node :=* optionalMasterBuffer(rocket.masterNode)
masterNode :=* source.node
val masterNode = source.node
val slaveNode = new TLRationalInputNode() { override def reverse = true }
val sink = LazyModule(new TLRationalCrossingSink(SlowToFast))
DisableMonitors { implicit p =>
sink.node :*= slaveNode
rocket.slaveNode :*= optionalSlaveBuffer(sink.node)
}
DisableMonitors { implicit p => optionalSlaveBuffer(rocket.slaveNode) :*= sink.node }
val slaveNode = sink.node
// Fully async interrupts need synchronizers.
// Those coming from periphery clock need a
@ -304,12 +287,14 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet
// Others need no synchronization.
val asyncXing = LazyModule(new IntXing(3))
val periphXing = LazyModule(new IntXing(1))
asyncXing.intnode := asyncIntNode
periphXing.intnode := periphIntNode
val asyncIntNode = asyncXing.intnode
val periphIntNode = periphXing.intnode
val coreIntNode = IntIdentityNode()
intXbar.intnode := asyncXing.intnode
intXbar.intnode := periphXing.intnode
intXbar.intnode := coreIntNode
// order here matters
intXbar.intnode := asyncXing.intnode
intXbar.intnode := periphXing.intnode
intXbar.intnode := coreIntNode
def outputInterruptXingLatency = 1
}

View File

@ -13,12 +13,7 @@ class TLAsyncCrossingSource(sync: Int = 3)(implicit p: Parameters) extends LazyM
val node = TLAsyncSourceNode(sync)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val sink_reset_n = out.a.sink_reset_n
val bce = edgeIn.manager.anySupportAcquireB && edgeIn.client.anySupportProbe
val depth = edgeOut.manager.depth
@ -47,12 +42,7 @@ class TLAsyncCrossingSink(depth: Int = 8, sync: Int = 3)(implicit p: Parameters)
val node = TLAsyncSinkNode(depth, sync)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val source_reset_n = in.a.source_reset_n
val bce = edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe
@ -97,40 +87,24 @@ object TLAsyncCrossingSink
class TLAsyncCrossing(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) extends LazyModule
{
val nodeIn = TLInputNode()
val nodeOut = TLOutputNode()
val node = NodeHandle(nodeIn, nodeOut)
val source = LazyModule(new TLAsyncCrossingSource(sync))
val sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
val node = NodeHandle(source.node, sink.node)
val _ = (sink.node := source.node) // no monitor
val in = (source.node := nodeIn)
val out = (nodeOut := sink.node)
sink.node := source.node
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = nodeIn.bundleIn
val io = IO(new Bundle {
val in_clock = Clock(INPUT)
val in_reset = Bool(INPUT)
val out = nodeOut.bundleOut
val out_clock = Clock(INPUT)
val out_reset = Bool(INPUT)
}
})
source.module.clock := io.in_clock
source.module.reset := io.in_reset
in.foreach { lm =>
lm.module.clock := io.in_clock
lm.module.reset := io.in_reset
}
sink.module.clock := io.out_clock
sink.module.reset := io.out_reset
out.foreach { lm =>
lm.module.clock := io.out_clock
lm.module.reset := io.out_reset
}
}
}
@ -145,9 +119,9 @@ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule {
model.node := fuzz.node
cross.node := TLFragmenter(4, 256)(TLDelayer(0.1)(model.node))
val monitor = (ram.node := cross.node)
ram.node := cross.node
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
// Shove the RAM into another clock domain
@ -159,12 +133,6 @@ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule {
cross.module.io.in_reset := reset
cross.module.io.out_clock := clocks.io.clock_out
cross.module.io.out_reset := reset
// Push the Monitor into the right clock domain
monitor.foreach { m =>
m.module.clock := clocks.io.clock_out
m.module.reset := reset
}
}
}

View File

@ -29,12 +29,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
})})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val managers = edgeOut.manager.managers
val beatBytes = edgeOut.manager.beatBytes
@ -297,7 +292,7 @@ class TLRAMAtomicAutomata(txns: Int)(implicit p: Parameters) extends LazyModule
model.node := fuzz.node
ram.node := TLFragmenter(4, 256)(TLDelayer(0.1)(TLAtomicAutomata()(TLDelayer(0.1)(model.node))))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

View File

@ -53,12 +53,7 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa
)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val clients = edgeIn.client.clients
val managers = edgeOut.manager.managers
val lineShift = log2Ceil(lineBytes)

View File

@ -13,7 +13,7 @@ class TLBufferNode (
b: BufferParams,
c: BufferParams,
d: BufferParams,
e: BufferParams)(implicit p: Parameters) extends TLAdapterNode(
e: BufferParams)(implicit valName: ValName) extends TLAdapterNode(
clientFn = { p => p.copy(minLatency = p.minLatency + b.latency + c.latency) },
managerFn = { p => p.copy(minLatency = p.minLatency + a.latency + d.latency) }
) {
@ -35,12 +35,7 @@ class TLBuffer(
val node = new TLBufferNode(a, b, c, d, e)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
out.a <> a(in .a)
in .d <> d(out.d)
@ -79,36 +74,25 @@ object TLBuffer
}
class TLBufferChain(depth: Int)(implicit p: Parameters) extends LazyModule {
val nodeIn = TLInputNode()
val nodeOut = TLOutputNode()
val node = NodeHandle(nodeIn, nodeOut)
val buf_chain = if (depth > 0) {
val chain = List.fill(depth)(LazyModule(new TLBuffer(BufferParams.default)))
(chain.init zip chain.tail) foreach { case(prev, next) => next.node :=? prev.node }
chain
val buf_chain = List.fill(depth)(LazyModule(new TLBuffer(BufferParams.default)))
val node = if (depth > 0) {
(buf_chain.init zip buf_chain.tail) foreach { case (prev, next) => next.node :=? prev.node }
NodeHandle(buf_chain.head.node, buf_chain.last.node)
} else {
List(LazyModule(new TLBuffer(BufferParams.none)))
}
buf_chain.head.node :=? nodeIn
nodeOut :=? buf_chain.last.node
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = nodeIn.bundleIn
val out = nodeOut.bundleOut
}
TLIdentityNode()
}
lazy val module = new LazyModuleImp(this) { }
}
object TLBufferChain
{
def apply(depth: Int)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
val buffer = LazyModule(new TLBufferChain(depth))
buffer.node :=? x
buffer.node
if (depth > 0) {
val buffer = LazyModule(new TLBufferChain(depth))
buffer.node :=? x
buffer.node
} else {
x
}
}
}

View File

@ -21,7 +21,8 @@ trait TLBusParams {
def blockOffset: Int = log2Up(blockBytes)
}
abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p: Parameters) extends TLBusParams {
abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p: Parameters)
extends SimpleLazyModule with LazyScope with TLBusParams {
val beatBytes = params.beatBytes
val blockBytes = params.blockBytes
@ -71,7 +72,7 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p
SourceCardinality { implicit p =>
val chain = LazyModule(new TLBufferChain(depth))
name.foreach { n => chain.suggestName(s"${busName}_${n}_TLBufferChain")}
(chain.nodeIn, chain.nodeOut)
(chain.node, chain.node)
}
}

View File

@ -24,12 +24,7 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM
supportsAcquireT = if (m.regionType == RegionType.UNCACHED) m.supportsPutFull else m.supportsAcquireT)})})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val clients = edgeIn.client.clients
val caches = clients.filter(_.supportsProbe)
require (clients.size == 1 || caches.size == 0 || unsafe, "Only one client can safely use a TLCacheCork")

View File

@ -10,15 +10,10 @@ import freechips.rocketchip.diplomacy._
// q is the probability to delay a request
class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule
{
val node = TLIdentityNode()
val node = TLAdapterNode()
require (0.0 <= q && q < 1)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
def feed[T <: Data](sink: DecoupledIO[T], source: DecoupledIO[T], noise: T) {
val allow = UInt((q * 65535.0).toInt) <= LFSR16(source.valid)
sink.valid := source.valid && allow
@ -27,7 +22,7 @@ class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule
when (!sink.valid) { sink.bits := noise }
}
(io.in zip io.out) foreach { case (in, out) =>
(node.in zip node.out) foreach { case ((in, _), (out, _)) =>
val anoise = Wire(in.a.bits)
anoise.opcode := LFSRNoiseMaker(3)
anoise.param := LFSRNoiseMaker(3)

View File

@ -4,13 +4,16 @@ package freechips.rocketchip.tilelink
import Chisel._
import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util._
class TLEdge(
client: TLClientPortParameters,
manager: TLManagerPortParameters)
extends TLEdgeParameters(client, manager)
manager: TLManagerPortParameters,
params: Parameters,
sourceInfo: SourceInfo)
extends TLEdgeParameters(client, manager, params, sourceInfo)
{
def isAligned(address: UInt, lgSize: UInt): Bool = {
if (maxLgSize == 0) Bool(true) else {
@ -262,8 +265,10 @@ class TLEdge(
class TLEdgeOut(
client: TLClientPortParameters,
manager: TLManagerPortParameters)
extends TLEdge(client, manager)
manager: TLManagerPortParameters,
params: Parameters,
sourceInfo: SourceInfo)
extends TLEdge(client, manager, params, sourceInfo)
{
// Transfers
def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = {
@ -476,8 +481,10 @@ class TLEdgeOut(
class TLEdgeIn(
client: TLClientPortParameters,
manager: TLManagerPortParameters)
extends TLEdge(client, manager)
manager: TLManagerPortParameters,
params: Parameters,
sourceInfo: SourceInfo)
extends TLEdge(client, manager, params, sourceInfo)
{
// Transfers
def Probe(fromAddress: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt) = {

View File

@ -41,12 +41,7 @@ class TLFIFOFixer(policy: TLFIFOFixer.Policy = TLFIFOFixer.all)(implicit p: Para
})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val (fixMap, splatMap) = fifoMap(edgeOut.manager.managers)
// Do we need to serialize the request to this manager?

View File

@ -49,11 +49,9 @@ class TLFilter(
})})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
out <> in
}
io.out <> io.in
}
}

View File

@ -52,12 +52,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
managerFn = { m => m.copy(managers = m.managers.map(mapManager)) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
// All managers must share a common FIFO domain (responses might end up interleaved)
val manager = edgeOut.manager
val managers = manager.managers
@ -249,7 +244,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
val aFrag = Mux(aOrig > limit, limit, aOrig)
val aOrigOH1 = UIntToOH1(aOrig, log2Ceil(maxSize))
val aFragOH1 = UIntToOH1(aFrag, log2Up(maxDownSize))
val aHasData = node.edgesIn(0).hasData(in_a.bits)
val aHasData = edgeIn.hasData(in_a.bits)
val aMask = Mux(aHasData, UInt(0), aFragOH1)
val gennum = RegInit(UInt(0, width = counterBits))
@ -317,7 +312,7 @@ class TLRAMFragmenter(ramBeatBytes: Int, maxSize: Int, txns: Int)(implicit p: Pa
TLBuffer(BufferParams.flow)(
model.node)))))))))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

View File

@ -107,13 +107,11 @@ class TLFuzzer(
val node = TLClientNode(Seq(TLClientPortParameters(clientParams)))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val out = node.bundleOut
val io = IO(new Bundle {
val finished = Bool(OUTPUT)
}
})
val out = io.out(0)
val edge = node.edgesOut(0)
val (out, edge) = node.out(0)
// Extract useful parameters from the TL edge
val maxTransfer = edge.manager.maxTransfer
@ -242,10 +240,10 @@ class TLFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule
ram2.node := TLFragmenter(16, 256)(xbar2.node)
xbar.node := TLWidthWidget(16)(TLHintHandler()(xbar2.node))
cross.node := TLFragmenter(4, 256)(TLBuffer()(xbar.node))
val monitor = (ram.node := cross.node)
ram.node := cross.node
gpio.node := TLFragmenter(4, 32)(TLBuffer()(xbar.node))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
// Shove the RAM into another clock domain
@ -257,12 +255,6 @@ class TLFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule
cross.module.io.in_reset := reset
cross.module.io.out_clock := clocks.io.clock_out
cross.module.io.out_reset := reset
// Push the Monitor into the right clock domain
monitor.foreach { m =>
m.module.clock := clocks.io.clock_out
m.module.reset := reset
}
}
}

View File

@ -16,12 +16,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
managerFn = { m => if (!supportManagers) m else m.copy(minLatency = min(1, m.minLatency), managers = m.managers.map(_.copy(supportsHint = TransferSizes(1, m.maxTransfer)))) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
// Don't add support for clients if there is no BCE channel
val bce = edgeOut.manager.anySupportAcquireB && edgeIn.client.anySupportProbe
require (!supportClients || bce)
@ -118,7 +113,7 @@ class TLRAMHintHandler(txns: Int)(implicit p: Parameters) extends LazyModule {
model.node := fuzz.node
ram.node := TLFragmenter(4, 256)(TLDelayer(0.1)(TLHintHandler()(TLDelayer(0.1)(model.node))))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

View File

@ -61,26 +61,13 @@ object IntSinkPortSimple
Seq.fill(ports)(IntSinkPortParameters(Seq.fill(sinks)(IntSinkParameters())))
}
case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters)
case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters, params: Parameters, sourceInfo: SourceInfo)
object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, IntEdge, Vec[Bool]]
object IntImp extends SimpleNodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]]
{
def edgeO(pd: IntSourcePortParameters, pu: IntSinkPortParameters): IntEdge = IntEdge(pd, pu)
def edgeI(pd: IntSourcePortParameters, pu: IntSinkPortParameters): IntEdge = IntEdge(pd, pu)
def bundleO(eo: IntEdge): Vec[Bool] = Vec(eo.source.num, Bool())
def bundleI(ei: IntEdge): Vec[Bool] = Vec(ei.source.num, Bool())
def colour = "#0000ff" // blue
override def reverse = true
override def labelI(ei: IntEdge) = ei.source.sources.map(_.range.size).sum.toString
override def labelO(eo: IntEdge) = eo.source.sources.map(_.range.size).sum.toString
def connect(bo: => Vec[Bool], bi: => Vec[Bool], ei: => IntEdge)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
(None, () => {
// Cannot use bulk connect, because the widths could differ
(bo zip bi) foreach { case (o, i) => i := o }
})
}
def edge(pd: IntSourcePortParameters, pu: IntSinkPortParameters, p: Parameters, sourceInfo: SourceInfo) = IntEdge(pd, pu, p, sourceInfo)
def bundle(e: IntEdge) = Vec(e.source.num, Bool())
def render(e: IntEdge) = RenderedEdge(colour = "#0000ff" /* blue */, label = e.source.sources.map(_.range.size).sum.toString, flipped = true)
override def mixO(pd: IntSourcePortParameters, node: OutwardNode[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]]): IntSourcePortParameters =
pd.copy(sources = pd.sources.map { s => s.copy (nodePath = node +: s.nodePath) })
@ -88,26 +75,24 @@ object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, In
pu.copy(sinks = pu.sinks.map { s => s.copy (nodePath = node +: s.nodePath) })
}
case class IntIdentityNode() extends IdentityNode(IntImp)
case class IntSourceNode(portParams: Seq[IntSourcePortParameters]) extends SourceNode(IntImp)(portParams)
case class IntSinkNode(portParams: Seq[IntSinkPortParameters]) extends SinkNode(IntImp)(portParams)
case class IntSourceNode(portParams: Seq[IntSourcePortParameters])(implicit valName: ValName) extends SourceNode(IntImp)(portParams)
case class IntSinkNode(portParams: Seq[IntSinkPortParameters])(implicit valName: ValName) extends SinkNode(IntImp)(portParams)
case class IntAdapterNode(
sourceFn: IntSourcePortParameters => IntSourcePortParameters = { s => s },
sinkFn: IntSinkPortParameters => IntSinkPortParameters = { s => s },
num: Range.Inclusive = 0 to 999)(
implicit valName: ValName)
extends AdapterNode(IntImp)(sourceFn, sinkFn, num)
case class IntIdentityNode()(implicit valName: ValName) extends IdentityNode(IntImp)()
case class IntNexusNode(
sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters,
sinkFn: Seq[IntSinkPortParameters] => IntSinkPortParameters,
numSourcePorts: Range.Inclusive = 0 to 128,
numSinkPorts: Range.Inclusive = 0 to 128)
numSinkPorts: Range.Inclusive = 0 to 128)(
implicit valName: ValName)
extends NexusNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts)
case class IntOutputNode() extends OutputNode(IntImp)
case class IntInputNode() extends InputNode(IntImp)
case class IntBlindOutputNode(portParams: Seq[IntSinkPortParameters]) extends BlindOutputNode(IntImp)(portParams)
case class IntBlindInputNode(portParams: Seq[IntSourcePortParameters]) extends BlindInputNode(IntImp)(portParams)
case class IntInternalOutputNode(portParams: Seq[IntSinkPortParameters]) extends InternalOutputNode(IntImp)(portParams)
case class IntInternalInputNode(portParams: Seq[IntSourcePortParameters]) extends InternalInputNode(IntImp)(portParams)
class IntXbar()(implicit p: Parameters) extends LazyModule
{
val intnode = IntNexusNode(
@ -119,27 +104,17 @@ class IntXbar()(implicit p: Parameters) extends LazyModule
})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = intnode.bundleIn
val out = intnode.bundleOut
}
val cat = (intnode.edgesIn zip io.in).map{ case (e, i) => i.take(e.source.num) }.flatten
io.out.foreach { _ := cat }
val cat = intnode.in.map { case (i, e) => i.take(e.source.num) }.flatten
intnode.out.foreach { case (o, _) => o := cat }
}
}
class IntXing(sync: Int = 3)(implicit p: Parameters) extends LazyModule
{
val intnode = IntIdentityNode()
val intnode = IntAdapterNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = intnode.bundleIn
val out = intnode.bundleOut
}
(io.in zip io.out) foreach { case (in, out) =>
(intnode.in zip intnode.out) foreach { case ((in, _), (out, _)) =>
out := SynchronizerShiftReg(in, sync)
}
}

View File

@ -11,15 +11,13 @@ import freechips.rocketchip.util.AsyncBundle
// READ the comments in the TLIsolation object before you instantiate this module
class TLIsolation(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(implicit p: Parameters) extends LazyModule
{
val node = TLAsyncIdentityNode()
val node = TLAsyncAdapterNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
val io = IO(new Bundle {
val iso_out = Bool(INPUT) // Isolate from client to manager
val iso_in = Bool(INPUT) // Isolate from manager to client
}
})
def ISOo[T <: Data](x: T): T = x.fromBits(fOut(io.iso_out, x.asUInt))
def ISOi[T <: Data](x: T): T = x.fromBits(fIn (io.iso_in, x.asUInt))
@ -53,7 +51,7 @@ class TLIsolation(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(implici
y.sink_reset_n := Bool(false)
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
ABo(out.a, in .a)
ABi(in .d, out.d)

View File

@ -20,14 +20,8 @@ class TLMap(fn: AddressSet => BigInt)(implicit p: Parameters) extends LazyModule
AddressSet(fn(a), a.mask)))))})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
io.out <> io.in
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
out <> in
val convert = edgeIn.manager.managers.flatMap(_.address) zip edgeOut.manager.managers.flatMap(_.address)
def forward(x: UInt) =
convert.map { case (i, o) => Mux(i.contains(x), UInt(o.base) | (x & UInt(o.mask)), UInt(0)) }.reduce(_ | _)

View File

@ -8,26 +8,22 @@ import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.{HeterogeneousBag, PlusArg}
case class TLMonitorArgs(edge: () => Seq[TLEdge], sourceInfo: SourceInfo, p: Parameters)
case class TLMonitorArgs(edge: TLEdge)
abstract class TLMonitorBase(args: TLMonitorArgs) extends MonitorBase()(args.sourceInfo, args.p)
abstract class TLMonitorBase(args: TLMonitorArgs) extends Module
{
def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool): Unit
lazy val module = new LazyModuleImp(this) {
val edges = args.edge()
val io = new Bundle {
val in = HeterogeneousBag(edges.map(p => new TLBundleSnoop(p.bundle))).flip
}
(edges zip io.in).foreach { case (e, in) => legalize(in, e, reset) }
val io = new Bundle {
val in = new TLBundleSnoop(args.edge.bundle).flip
}
def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool): Unit
legalize(io.in, args.edge, reset)
}
class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args)
{
def extra = {
sourceInfo match {
args.edge.sourceInfo match {
case SourceLine(filename, line, col) => s" (connected at $filename:$line:$col)"
case _ => ""
}

View File

@ -7,11 +7,8 @@ import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
case class TLNodeNumbererNode(nodeAddressOffset: Option[Int] = None) extends TLCustomNode(0 to 999, 0 to 999)
case class TLNodeNumbererNode(nodeAddressOffset: Option[Int] = None)(implicit valName: ValName) extends TLCustomNode(0 to 999, 0 to 999)
{
val externalIn = true
val externalOut = true
def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = {
require (oStars + iStars <= 1, s"${name} (a custom adapter) appears left of a :*= ${iStars} times and right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}")
if (oStars > 0) {
@ -46,15 +43,10 @@ class TLNodeNumberer(nodeAddressOffset: Option[Int] = None)(implicit p: Paramete
val node = TLNodeNumbererNode(nodeAddressOffset)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
val minNodeOffset = log2Ceil(node.edgesOut.map(_.manager.maxAddress).max)
val minNodeOffset = log2Ceil(node.edges.out.map(_.manager.maxAddress).max)
val nodeOffset = nodeAddressOffset.getOrElse(minNodeOffset)
(io.in zip io.out).zipWithIndex foreach { case ((in, out), i) =>
(node.in zip node.out).zipWithIndex foreach { case (((in, _), (out, _)), i) =>
out <> in
// a&c address already get truncated
in.b.bits.address := (UInt(i+1) << nodeOffset) | out.b.bits.address

View File

@ -9,40 +9,21 @@ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.RationalDirection
import scala.collection.mutable.ListBuffer
case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => LazyModule(new TLMonitor(args)))
case object TLCombinationalCheck extends Field[Boolean](false)
case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => new TLMonitor(args))
object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle]
{
def edgeO(pd: TLClientPortParameters, pu: TLManagerPortParameters): TLEdgeOut = new TLEdgeOut(pd, pu)
def edgeI(pd: TLClientPortParameters, pu: TLManagerPortParameters): TLEdgeIn = new TLEdgeIn(pd, pu)
def edgeO(pd: TLClientPortParameters, pu: TLManagerPortParameters, p: Parameters, sourceInfo: SourceInfo) = new TLEdgeOut(pd, pu, p, sourceInfo)
def edgeI(pd: TLClientPortParameters, pu: TLManagerPortParameters, p: Parameters, sourceInfo: SourceInfo) = new TLEdgeIn (pd, pu, p, sourceInfo)
def bundleO(eo: TLEdgeOut): TLBundle = TLBundle(eo.bundle)
def bundleI(ei: TLEdgeIn): TLBundle = TLBundle(ei.bundle)
def bundleO(eo: TLEdgeOut) = TLBundle(eo.bundle)
def bundleI(ei: TLEdgeIn) = TLBundle(ei.bundle)
def colour = "#000000" // black
override def labelI(ei: TLEdgeIn) = (ei.manager.beatBytes * 8).toString
override def labelO(eo: TLEdgeOut) = (eo.manager.beatBytes * 8).toString
def render(ei: TLEdgeIn) = RenderedEdge(colour = "#000000" /* black */, label = (ei.manager.beatBytes * 8).toString)
override def connect(edges: () => Seq[TLEdgeIn], bundles: () => Seq[(TLBundle, TLBundle)], enableMonitoring: Boolean)
(implicit p: Parameters, sourceInfo: SourceInfo): (Option[TLMonitorBase], () => Unit) = {
val monitor = if (enableMonitoring) Some(p(TLMonitorBuilder)(TLMonitorArgs(edges, sourceInfo, p))) else None
(monitor, () => {
val eval = bundles ()
monitor.foreach { m => (eval zip m.module.io.in) foreach { case ((i,o), m) => m := TLBundleSnoop(o,i) } }
eval.foreach { case (bi, bo) =>
bi <> bo
if (p(TLCombinationalCheck)) {
// It is forbidden for valid to depend on ready in TL2
// If someone did that, then this will create a detectable combinational loop
bo.a.ready := bi.a.ready && bo.a.valid
bi.b.ready := bo.b.ready && bi.b.valid
bo.c.ready := bi.c.ready && bo.c.valid
bi.d.ready := bo.d.ready && bi.d.valid
bo.e.ready := bi.e.ready && bo.e.valid
}
}
})
override def monitor(bundle: TLBundle, edge: TLEdgeIn) {
val monitor = Module(edge.params(TLMonitorBuilder)(TLMonitorArgs(edge)))
monitor.io.in := TLBundleSnoop(bundle, bundle)
}
override def mixO(pd: TLClientPortParameters, node: OutwardNode[TLClientPortParameters, TLManagerPortParameters, TLBundle]): TLClientPortParameters =
@ -63,92 +44,39 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
}
}
// Nodes implemented inside modules
case class TLIdentityNode() extends IdentityNode(TLImp)
case class TLClientNode(portParams: Seq[TLClientPortParameters]) extends SourceNode(TLImp)(portParams)
case class TLManagerNode(portParams: Seq[TLManagerPortParameters]) extends SinkNode(TLImp)(portParams)
object TLClientNode
{
def apply(params: TLClientParameters) =
new TLClientNode(Seq(TLClientPortParameters(Seq(params))))
}
object TLManagerNode
{
def apply(beatBytes: Int, params: TLManagerParameters) =
new TLManagerNode(Seq(TLManagerPortParameters(Seq(params), beatBytes, minLatency = 0)))
}
case class TLClientNode(portParams: Seq[TLClientPortParameters])(implicit valName: ValName) extends SourceNode(TLImp)(portParams)
case class TLManagerNode(portParams: Seq[TLManagerPortParameters])(implicit valName: ValName) extends SinkNode(TLImp)(portParams)
case class TLAdapterNode(
clientFn: TLClientPortParameters => TLClientPortParameters,
managerFn: TLManagerPortParameters => TLManagerPortParameters,
num: Range.Inclusive = 0 to 999)
clientFn: TLClientPortParameters => TLClientPortParameters = { s => s },
managerFn: TLManagerPortParameters => TLManagerPortParameters = { s => s },
num: Range.Inclusive = 0 to 999)(
implicit valName: ValName)
extends AdapterNode(TLImp)(clientFn, managerFn, num)
case class TLIdentityNode()(implicit valName: ValName) extends IdentityNode(TLImp)()
case class TLNexusNode(
clientFn: Seq[TLClientPortParameters] => TLClientPortParameters,
managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters,
numClientPorts: Range.Inclusive = 1 to 999,
numManagerPorts: Range.Inclusive = 1 to 999)
numManagerPorts: Range.Inclusive = 1 to 999)(
implicit valName: ValName)
extends NexusNode(TLImp)(clientFn, managerFn, numClientPorts, numManagerPorts)
case class TLSplitterNode(
clientFn: SplitterArg[TLClientPortParameters] => Seq[TLClientPortParameters],
managerFn: SplitterArg[TLManagerPortParameters] => Seq[TLManagerPortParameters],
numClientPorts: Range.Inclusive = 0 to 999,
numManagerPorts: Range.Inclusive = 0 to 999)
extends SplitterNode(TLImp)(clientFn, managerFn, numClientPorts, numManagerPorts)
abstract class TLCustomNode(
numClientPorts: Range.Inclusive,
numManagerPorts: Range.Inclusive)
numManagerPorts: Range.Inclusive)(
implicit valName: ValName)
extends CustomNode(TLImp)(numClientPorts, numManagerPorts)
// Nodes passed from an inner module
case class TLOutputNode() extends OutputNode(TLImp)
case class TLInputNode() extends InputNode(TLImp)
// Asynchronous crossings
// Nodes used for external ports
case class TLBlindOutputNode(portParams: Seq[TLManagerPortParameters]) extends BlindOutputNode(TLImp)(portParams)
case class TLBlindInputNode(portParams: Seq[TLClientPortParameters]) extends BlindInputNode(TLImp)(portParams)
case class TLInternalOutputNode(portParams: Seq[TLManagerPortParameters]) extends InternalOutputNode(TLImp)(portParams)
case class TLInternalInputNode(portParams: Seq[TLClientPortParameters]) extends InternalInputNode(TLImp)(portParams)
/** Synthesizeable unit tests */
import freechips.rocketchip.unittest._
class TLInputNodeTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) {
class Acceptor extends LazyModule {
val node = TLInputNode()
val tlram = LazyModule(new TLRAM(AddressSet(0x54321000, 0xfff)))
tlram.node := node
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
}
}
val fuzzer = LazyModule(new TLFuzzer(txns))
LazyModule(new Acceptor).node := TLFragmenter(4, 64)(fuzzer.node)
io.finished := Module(fuzzer.module).io.finished
}
object TLAsyncImp extends NodeImp[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncEdgeParameters, TLAsyncEdgeParameters, TLAsyncBundle]
object TLAsyncImp extends SimpleNodeImp[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncEdgeParameters, TLAsyncBundle]
{
def edgeO(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters): TLAsyncEdgeParameters = TLAsyncEdgeParameters(pd, pu)
def edgeI(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters): TLAsyncEdgeParameters = TLAsyncEdgeParameters(pd, pu)
def bundleO(eo: TLAsyncEdgeParameters): TLAsyncBundle = new TLAsyncBundle(eo.bundle)
def bundleI(ei: TLAsyncEdgeParameters): TLAsyncBundle = new TLAsyncBundle(ei.bundle)
def colour = "#ff0000" // red
override def labelI(ei: TLAsyncEdgeParameters) = ei.manager.depth.toString
override def labelO(eo: TLAsyncEdgeParameters) = eo.manager.depth.toString
def edge(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters, p: Parameters, sourceInfo: SourceInfo) = TLAsyncEdgeParameters(pd, pu, p, sourceInfo)
def bundle(e: TLAsyncEdgeParameters) = new TLAsyncBundle(e.bundle)
def render(e: TLAsyncEdgeParameters) = RenderedEdge(colour = "#ff0000" /* red */, label = e.manager.depth.toString)
override def mixO(pd: TLAsyncClientPortParameters, node: OutwardNode[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]): TLAsyncClientPortParameters =
pd.copy(base = pd.base.copy(clients = pd.base.clients.map { c => c.copy (nodePath = node +: c.nodePath) }))
@ -156,29 +84,32 @@ object TLAsyncImp extends NodeImp[TLAsyncClientPortParameters, TLAsyncManagerPor
pu.copy(base = pu.base.copy(managers = pu.base.managers.map { m => m.copy (nodePath = node +: m.nodePath) }))
}
case class TLAsyncIdentityNode() extends IdentityNode(TLAsyncImp)
case class TLAsyncOutputNode() extends OutputNode(TLAsyncImp)
case class TLAsyncInputNode() extends InputNode(TLAsyncImp)
case class TLAsyncAdapterNode(
clientFn: TLAsyncClientPortParameters => TLAsyncClientPortParameters = { s => s },
managerFn: TLAsyncManagerPortParameters => TLAsyncManagerPortParameters = { s => s },
num: Range.Inclusive = 0 to 999)(
implicit valName: ValName)
extends AdapterNode(TLAsyncImp)(clientFn, managerFn, num)
case class TLAsyncSourceNode(sync: Int)
case class TLAsyncIdentityNode()(implicit valName: ValName) extends IdentityNode(TLAsyncImp)()
case class TLAsyncSourceNode(sync: Int)(implicit valName: ValName)
extends MixedAdapterNode(TLImp, TLAsyncImp)(
dFn = { p => TLAsyncClientPortParameters(p) },
uFn = { p => p.base.copy(minLatency = sync+1) }) // discard cycles in other clock domain
case class TLAsyncSinkNode(depth: Int, sync: Int)
case class TLAsyncSinkNode(depth: Int, sync: Int)(implicit valName: ValName)
extends MixedAdapterNode(TLAsyncImp, TLImp)(
dFn = { p => p.base.copy(minLatency = sync+1) },
uFn = { p => TLAsyncManagerPortParameters(depth, p) })
object TLRationalImp extends NodeImp[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalEdgeParameters, TLRationalEdgeParameters, TLRationalBundle]
// Rationally related crossings
object TLRationalImp extends SimpleNodeImp[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalEdgeParameters, TLRationalBundle]
{
def edgeO(pd: TLRationalClientPortParameters, pu: TLRationalManagerPortParameters): TLRationalEdgeParameters = TLRationalEdgeParameters(pd, pu)
def edgeI(pd: TLRationalClientPortParameters, pu: TLRationalManagerPortParameters): TLRationalEdgeParameters = TLRationalEdgeParameters(pd, pu)
def bundleO(eo: TLRationalEdgeParameters): TLRationalBundle = new TLRationalBundle(eo.bundle)
def bundleI(ei: TLRationalEdgeParameters): TLRationalBundle = new TLRationalBundle(ei.bundle)
def colour = "#00ff00" // green
def edge(pd: TLRationalClientPortParameters, pu: TLRationalManagerPortParameters, p: Parameters, sourceInfo: SourceInfo) = TLRationalEdgeParameters(pd, pu, p, sourceInfo)
def bundle(e: TLRationalEdgeParameters) = new TLRationalBundle(e.bundle)
def render(e: TLRationalEdgeParameters) = RenderedEdge(colour = "#00ff00" /* green */)
override def mixO(pd: TLRationalClientPortParameters, node: OutwardNode[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle]): TLRationalClientPortParameters =
pd.copy(base = pd.base.copy(clients = pd.base.clients.map { c => c.copy (nodePath = node +: c.nodePath) }))
@ -186,16 +117,21 @@ object TLRationalImp extends NodeImp[TLRationalClientPortParameters, TLRationalM
pu.copy(base = pu.base.copy(managers = pu.base.managers.map { m => m.copy (nodePath = node +: m.nodePath) }))
}
case class TLRationalIdentityNode() extends IdentityNode(TLRationalImp)
case class TLRationalOutputNode() extends OutputNode(TLRationalImp)
case class TLRationalInputNode() extends InputNode(TLRationalImp)
case class TLRationalAdapterNode(
clientFn: TLRationalClientPortParameters => TLRationalClientPortParameters = { s => s },
managerFn: TLRationalManagerPortParameters => TLRationalManagerPortParameters = { s => s },
num: Range.Inclusive = 0 to 999)(
implicit valName: ValName)
extends AdapterNode(TLRationalImp)(clientFn, managerFn, num)
case class TLRationalSourceNode()
case class TLRationalIdentityNode()(implicit valName: ValName) extends IdentityNode(TLRationalImp)()
case class TLRationalSourceNode()(implicit valName: ValName)
extends MixedAdapterNode(TLImp, TLRationalImp)(
dFn = { p => TLRationalClientPortParameters(p) },
uFn = { p => p.base.copy(minLatency = 1) }) // discard cycles from other clock domain
case class TLRationalSinkNode(direction: RationalDirection)
case class TLRationalSinkNode(direction: RationalDirection)(implicit valName: ValName)
extends MixedAdapterNode(TLRationalImp, TLImp)(
dFn = { p => p.base.copy(minLatency = 1) },
uFn = { p => TLRationalManagerPortParameters(direction, p) })

View File

@ -3,6 +3,8 @@
package freechips.rocketchip.tilelink
import Chisel._
import chisel3.internal.sourceinfo.SourceInfo
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.util.RationalDirection
import scala.math.max
@ -312,7 +314,9 @@ object TLBundleParameters
case class TLEdgeParameters(
client: TLClientPortParameters,
manager: TLManagerPortParameters)
manager: TLManagerPortParameters,
params: Parameters,
sourceInfo: SourceInfo)
{
val maxTransfer = max(client.maxTransfer, manager.maxTransfer)
val maxLgSize = log2Ceil(maxTransfer)
@ -340,7 +344,7 @@ object TLAsyncBundleParameters
def union(x: Seq[TLAsyncBundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y))
}
case class TLAsyncEdgeParameters(client: TLAsyncClientPortParameters, manager: TLAsyncManagerPortParameters)
case class TLAsyncEdgeParameters(client: TLAsyncClientPortParameters, manager: TLAsyncManagerPortParameters, params: Parameters, sourceInfo: SourceInfo)
{
val bundle = TLAsyncBundleParameters(manager.depth, TLBundleParameters(client.base, manager.base))
}
@ -348,7 +352,7 @@ case class TLAsyncEdgeParameters(client: TLAsyncClientPortParameters, manager: T
case class TLRationalManagerPortParameters(direction: RationalDirection, base: TLManagerPortParameters)
case class TLRationalClientPortParameters(base: TLClientPortParameters)
case class TLRationalEdgeParameters(client: TLRationalClientPortParameters, manager: TLRationalManagerPortParameters)
case class TLRationalEdgeParameters(client: TLRationalClientPortParameters, manager: TLRationalManagerPortParameters, params: Parameters, sourceInfo: SourceInfo)
{
val bundle = TLBundleParameters(client.base, manager.base)
}

View File

@ -38,13 +38,12 @@ class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameter
val node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(name = name)))))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val tl_out = node.bundleOut
val io = IO(new Bundle {
val run = Bool(INPUT)
val done = Bool(OUTPUT)
}
})
val edgeOut = node.edgesOut(0)
val (tl_out, edgeOut) = node.out(0)
pattern.foreach { p =>
require (p.size <= log2Ceil(edgeOut.manager.beatBytes), "Patterns must fit in a single beat")
}
@ -56,8 +55,8 @@ class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameter
val end = step === UInt(pattern.size)
io.done := end && !flight
val a = io.tl_out(0).a
val d = io.tl_out(0).d
val a = tl_out.a
val d = tl_out.d
// Expected response?
val check = Vec(pattern.map(p => Bool(p.dataIn.isDefined)))(step) holdUnless a.fire()
@ -80,8 +79,8 @@ class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameter
d.ready := Bool(true)
// Tie off unused channels
io.tl_out(0).b.ready := Bool(true)
io.tl_out(0).c.valid := Bool(false)
io.tl_out(0).e.valid := Bool(false)
tl_out.b.ready := Bool(true)
tl_out.c.valid := Bool(false)
tl_out.e.valid := Bool(false)
}
}

View File

@ -24,15 +24,10 @@ import freechips.rocketchip.util._
class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
{
val node = TLIdentityNode()
val node = TLAdapterNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val edge = edgeIn
val endAddress = edge.manager.maxAddress + 1
val endSourceId = edge.client.endSourceId

View File

@ -20,12 +20,7 @@ class TLRationalCrossingSource(implicit p: Parameters) extends LazyModule
val node = TLRationalSourceNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val bce = edgeIn.manager.anySupportAcquireB && edgeIn.client.anySupportProbe
val direction = edgeOut.manager.direction
@ -56,12 +51,7 @@ class TLRationalCrossingSink(direction: RationalDirection = Symmetric)(implicit
val node = TLRationalSinkNode(direction)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val bce = edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe
val direction = edgeIn.manager.direction
@ -109,40 +99,24 @@ object TLRationalCrossingSink
class TLRationalCrossing(direction: RationalDirection = Symmetric)(implicit p: Parameters) extends LazyModule
{
val nodeIn = TLInputNode()
val nodeOut = TLOutputNode()
val node = NodeHandle(nodeIn, nodeOut)
val source = LazyModule(new TLRationalCrossingSource)
val sink = LazyModule(new TLRationalCrossingSink(direction))
val node = NodeHandle(source.node, sink.node)
val _ = (sink.node := source.node) // no monitor
val in = (source.node := nodeIn)
val out = (nodeOut := sink.node)
sink.node := source.node
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = nodeIn.bundleIn
val io = IO(new Bundle {
val in_clock = Clock(INPUT)
val in_reset = Bool(INPUT)
val out = nodeOut.bundleOut
val out_clock = Clock(INPUT)
val out_reset = Bool(INPUT)
}
})
source.module.clock := io.in_clock
source.module.reset := io.in_reset
in.foreach { lm =>
lm.module.clock := io.in_clock
lm.module.reset := io.in_reset
}
sink.module.clock := io.out_clock
sink.module.reset := io.out_reset
out.foreach { lm =>
lm.module.clock := io.out_clock
lm.module.reset := io.out_reset
}
}
}
@ -150,7 +124,7 @@ class TLRationalCrossing(direction: RationalDirection = Symmetric)(implicit p: P
import freechips.rocketchip.unittest._
class TLRAMRationalCrossingSource(name: String, txns: Int)(implicit p: Parameters) extends LazyModule {
val node = TLRationalOutputNode()
val node = TLRationalIdentityNode()
val fuzz = LazyModule(new TLFuzzer(txns))
val model = LazyModule(new TLRAMModel(name))
@ -158,25 +132,20 @@ class TLRAMRationalCrossingSource(name: String, txns: Int)(implicit p: Parameter
node := TLRationalCrossingSource()(TLDelayer(0.25)(model.node))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val io = IO(new Bundle {
val finished = Bool(OUTPUT)
val out = node.bundleOut
}
})
io.finished := fuzz.module.io.finished
}
}
class TLRAMRationalCrossingSink(direction: RationalDirection)(implicit p: Parameters) extends LazyModule {
val node = TLRationalInputNode()
val node = TLRationalIdentityNode()
val ram = LazyModule(new TLRAM(AddressSet(0x0, 0x3ff)))
ram.node := TLFragmenter(4, 256)(TLDelayer(0.25)(TLRationalCrossingSink(direction)(node)))
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
}
lazy val module = new LazyModuleImp(this) { }
}
class TLRAMRationalCrossing(txns: Int)(implicit p: Parameters) extends LazyModule {
@ -196,7 +165,7 @@ class TLRAMRationalCrossing(txns: Int)(implicit p: Parameters) extends LazyModul
val fix_fast_sink = LazyModule(new TLRAMRationalCrossingSink(SlowToFast))
fix_fast_sink.node := fix_slow_source.node
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished :=
sym_fast_source.module.io.finished &&
sym_slow_source.module.io.finished &&

View File

@ -9,15 +9,16 @@ import freechips.rocketchip.regmapper._
import freechips.rocketchip.util.HeterogeneousBag
import scala.math.{min,max}
class TLRegisterNode(
case class TLRegisterNode(
address: Seq[AddressSet],
device: Device,
deviceKey: String = "reg/control",
concurrency: Int = 0,
beatBytes: Int = 4,
undefZero: Boolean = true,
executable: Boolean = false)
extends TLManagerNode(Seq(TLManagerPortParameters(
executable: Boolean = false)(
implicit valName: ValName)
extends SinkNode(TLImp)(Seq(TLManagerPortParameters(
Seq(TLManagerParameters(
address = address,
resources = Seq(Resource(device, deviceKey)),
@ -39,9 +40,9 @@ class TLRegisterNode(
// Calling this method causes the matching TL2 bundle to be
// configured to route all requests to the listed RegFields.
def regmap(mapping: RegField.Map*) = {
val a = bundleIn(0).a
val d = bundleIn(0).d
val edge = edgesIn(0)
val (bundleIn, edge) = this.in(0)
val a = bundleIn.a
val d = bundleIn.d
// Please forgive me ...
val baseEnd = 0
@ -75,26 +76,12 @@ class TLRegisterNode(
d.bits.opcode := Mux(out.bits.read, TLMessages.AccessAckData, TLMessages.AccessAck)
// Tie off unused channels
bundleIn(0).b.valid := Bool(false)
bundleIn(0).c.ready := Bool(true)
bundleIn(0).e.ready := Bool(true)
bundleIn.b.valid := Bool(false)
bundleIn.c.ready := Bool(true)
bundleIn.e.ready := Bool(true)
}
}
object TLRegisterNode
{
def apply(
address: Seq[AddressSet],
device: Device,
deviceKey: String = "reg/control",
concurrency: Int = 0,
beatBytes: Int = 4,
undefZero: Boolean = true,
executable: Boolean = false) =
new TLRegisterNode(address, device, deviceKey, concurrency, beatBytes, undefZero, executable)
}
// These convenience methods below combine to make it possible to create a TL2
// register mapped device from a totally abstract register mapped device.
// See GPIO.scala in this directory for an example
@ -105,13 +92,11 @@ abstract class TLRegisterRouterBase(devname: String, devcompat: Seq[String], val
val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts, resources = Seq(Resource(device, "int"))))
}
case class TLRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[TLBundle])(implicit val p: Parameters)
case class TLRegBundleArg()(implicit val p: Parameters)
class TLRegBundleBase(arg: TLRegBundleArg) extends Bundle
{
implicit val p = arg.p
val interrupts = arg.interrupts
val in = arg.in
}
class TLRegBundle[P](val params: P, arg: TLRegBundleArg)(implicit p: Parameters) extends TLRegBundleBase(arg)
@ -119,8 +104,8 @@ class TLRegBundle[P](val params: P, arg: TLRegBundleArg)(implicit p: Parameters)
class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, router: TLRegisterRouterBase)
extends LazyModuleImp(router) with HasRegMap
{
val io = bundleBuilder
val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0)
val io = IO(bundleBuilder)
val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1
val address = router.address
def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*)
}
@ -142,5 +127,7 @@ class TLRegisterRouter[B <: TLRegBundleBase, M <: LazyModuleImp](
require (isPow2(size))
// require (size >= 4096) ... not absolutely required, but highly recommended
lazy val module = moduleBuilder(bundleBuilder(TLRegBundleArg(intnode.bundleOut, node.bundleIn)), this)
lazy val module = moduleBuilder(bundleBuilder(TLRegBundleArg()), this)
}
// !!! eliminate third trait

View File

@ -3,6 +3,7 @@
package freechips.rocketchip.tilelink
import Chisel._
import chisel3.experimental.MultiIOModule
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper._
@ -222,7 +223,7 @@ trait RRTest1Bundle
{
}
trait RRTest1Module extends Module with HasRegMap
trait RRTest1Module extends MultiIOModule with HasRegMap
{
val clocks = Module(new Pow2ClockDivider(2))
@ -261,7 +262,7 @@ class FuzzRRTest0(txns: Int)(implicit p: Parameters) extends LazyModule {
rrtr.node := TLFragmenter(4, 32)(TLDelayer(0.1)(fuzz.node))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}
@ -276,7 +277,7 @@ class FuzzRRTest1(txns: Int)(implicit p: Parameters) extends LazyModule {
rrtr.node := TLFragmenter(4, 32)(TLDelayer(0.1)(fuzz.node))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

View File

@ -29,18 +29,12 @@ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4,
// We require the address range to include an entire beat (for the write mask)
require ((address.mask & (beatBytes-1)) == beatBytes-1)
lazy val module = new Implementation
@chiselName class Implementation extends LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
}
lazy val module = new LazyModuleImp(this) {
def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] =
if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail)
val mask = bigBits(address.mask >> log2Ceil(beatBytes))
val in = io.in(0)
val edge = node.edgesIn(0)
val (in, edge) = node.in(0)
val addrBits = (mask zip edge.addr_hi(in.a.bits).toBools).filter(_._1).map(_._2)
val a_legal = address.contains(in.a.bits.address)
@ -101,7 +95,7 @@ class TLRAMSimple(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends
model.node := fuzz.node
ram.node := TLDelayer(0.25)(model.node)
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

View File

@ -23,12 +23,7 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod
managerFn = { mp => mp.copy(managers = mp.managers.map(_.copy(fifoId = None))) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
// Acquires cannot pass this adapter; it makes Probes impossible
require (!edgeIn.client.anySupportProbe ||
!edgeOut.manager.anySupportAcquireB)

View File

@ -6,6 +6,34 @@ import Chisel._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
case class SplitterArg[T](newSize: Int, ports: Seq[T])
case class TLSplitterNode(
clientFn: SplitterArg[TLClientPortParameters] => Seq[TLClientPortParameters],
managerFn: SplitterArg[TLManagerPortParameters] => Seq[TLManagerPortParameters],
numClientPorts: Range.Inclusive = 0 to 999,
numManagerPorts: Range.Inclusive = 0 to 999)(
implicit valName: ValName)
extends TLCustomNode(numClientPorts, numManagerPorts)
{
def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = {
require (oKnown == 0, s"${name} (a splitter) appears right of a := or :*=; use a :=* instead${lazyModule.line}")
require (iStars == 0, s"${name} (a splitter) cannot appear left of a :*=; did you mean :=*?${lazyModule.line}")
(0, iKnown)
}
def mapParamsD(n: Int, p: Seq[TLClientPortParameters]): Seq[TLClientPortParameters] = {
require (p.size == 0 || n % p.size == 0, s"Diplomacy bug; splitter inputs do not divide outputs")
val out = clientFn(SplitterArg(n, p))
require (out.size == n, s"${name} created the wrong number of outputs from inputs${lazyModule.line}")
out
}
def mapParamsU(n: Int, p: Seq[TLManagerPortParameters]): Seq[TLManagerPortParameters] = {
require (n == 0 || p.size % n == 0, s"Diplomacy bug; splitter outputs indivisable by inputs")
val out = managerFn(SplitterArg(n, p))
require (out.size == n, s"${name} created the wrong number of inputs from outputs${lazyModule.line}")
out
}
}
class TLSplitter(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule
{
val node = TLSplitterNode(
@ -34,18 +62,14 @@ class TLSplitter(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Pa
})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
def group[T](x: Seq[T]) =
if (x.isEmpty) Nil else x.grouped(node.edgesIn.size).toList.transpose
if (x.isEmpty) Nil else x.grouped(node.in.size).toList.transpose
if (node.edgesOut.size == node.edgesIn.size) {
io.out <> io.in
} else ((node.edgesIn zip io.in) zip (group(node.edgesOut) zip group(io.out))) foreach {
case ((edgeIn, io_in), (edgesOut, io_out)) =>
if (node.out.size == node.in.size) {
(node.in zip node.out) foreach { case ((i, _), (o, _)) => o <> i }
} else (node.in zip group(node.out)) foreach {
case ((io_in, edgeIn), seq) =>
val (io_out, edgesOut) = seq.unzip
// Grab the port ID mapping
val outputIdRanges = TLXbar.mapOutputIds(edgesOut.map(_.manager))

View File

@ -11,7 +11,7 @@ import freechips.rocketchip.util._
import scala.math.{min, max}
import AHBParameters._
case class TLToAHBNode() extends MixedAdapterNode(TLImp, AHBImp)(
case class TLToAHBNode()(implicit valName: ValName) extends MixedAdapterNode(TLImp, AHBImp)(
dFn = { case TLClientPortParameters(clients, unsafeAtomics, minLatency) =>
val masters = clients.map { case c => AHBMasterParameters(name = c.name, nodePath = c.nodePath) }
AHBMasterPortParameters(masters)
@ -53,12 +53,7 @@ class TLToAHB(val aFlow: Boolean = false)(implicit p: Parameters) extends LazyMo
val node = TLToAHBNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val beatBytes = edgeOut.slave.beatBytes
val maxTransfer = edgeOut.slave.maxTransfer
val lgMax = log2Ceil(maxTransfer)

View File

@ -10,7 +10,7 @@ import freechips.rocketchip.amba.apb._
import scala.math.{min, max}
import APBParameters._
case class TLToAPBNode() extends MixedAdapterNode(TLImp, APBImp)(
case class TLToAPBNode()(implicit valName: ValName) extends MixedAdapterNode(TLImp, APBImp)(
dFn = { case TLClientPortParameters(clients, unsafeAtomics, minLatency) =>
val masters = clients.map { case c => APBMasterParameters(name = c.name, nodePath = c.nodePath) }
APBMasterPortParameters(masters)
@ -38,12 +38,7 @@ class TLToAPB(val aFlow: Boolean = true)(implicit p: Parameters) extends LazyMod
val node = TLToAPBNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val beatBytes = edgeOut.slave.beatBytes
val lgBytes = log2Ceil(beatBytes)

View File

@ -10,7 +10,7 @@ import freechips.rocketchip.util._
import freechips.rocketchip.amba.axi4._
import scala.math.{min, max}
case class TLToAXI4Node(beatBytes: Int, stripBits: Int = 0) extends MixedAdapterNode(TLImp, AXI4Imp)(
case class TLToAXI4Node(beatBytes: Int, stripBits: Int = 0)(implicit valName: ValName) extends MixedAdapterNode(TLImp, AXI4Imp)(
dFn = { p =>
p.clients.foreach { c =>
require (c.sourceId.start % (1 << stripBits) == 0 &&
@ -53,12 +53,7 @@ class TLToAXI4(val beatBytes: Int, val combinational: Boolean = true, val adapte
val node = TLToAXI4Node(beatBytes, stripBits)
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
val slaves = edgeOut.slave.slaves
// All pairs of slaves must promise that they will never interleave data

View File

@ -17,11 +17,6 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod
managerFn = { case m => m.copy(beatBytes = innerBeatBytes) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
}
def merge[T <: TLDataChannel](edgeIn: TLEdge, in: DecoupledIO[T], edgeOut: TLEdge, out: DecoupledIO[T]) = {
val inBytes = edgeIn.manager.beatBytes
val outBytes = edgeOut.manager.beatBytes
@ -154,7 +149,7 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod
}
}
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
// If the master is narrower than the slave, the D channel must be narrowed.
// This is tricky, because the D channel has no address data.
@ -220,7 +215,7 @@ class TLRAMWidthWidget(first: Int, second: Int, txns: Int)(implicit p: Parameter
TLWidthWidget(second)(
TLWidthWidget(first)(TLDelayer(0.1)(model.node)))}))
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}

View File

@ -63,22 +63,21 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame
})
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = node.bundleIn
val out = node.bundleOut
if ((node.in.size * node.out.size) > (8*32)) {
println (s"!!! WARNING !!!")
println (s" Your TLXbar ($name) is very large, with ${node.in.size} Masters and ${node.out.size} Slaves.")
println (s"!!! WARNING !!!")
}
if ((io.in.size * io.out.size) > (8*32)) {
println (s"!!! WARNING !!!")
println (s" Your TLXbar ($name) is very large, with ${io.in.size} Masters and ${io.out.size} Slaves.")
println (s"!!! WARNING !!!")
}
val (io_in, edgesIn) = node.in.unzip
val (io_out, edgesOut) = node.out.unzip
// Grab the port ID mapping
val inputIdRanges = TLXbar.mapInputIds(node.edgesIn.map(_.client))
val outputIdRanges = TLXbar.mapOutputIds(node.edgesOut.map(_.manager))
val inputIdRanges = TLXbar.mapInputIds(edgesIn.map(_.client))
val outputIdRanges = TLXbar.mapOutputIds(edgesOut.map(_.manager))
// Find a good mask for address decoding
val port_addrs = node.edgesOut.map(_.manager.managers.map(_.address).flatten)
val port_addrs = edgesOut.map(_.manager.managers.map(_.address).flatten)
val routingMask = AddressDecoder(port_addrs)
val route_addrs = port_addrs.map(seq => AddressSet.unify(seq.map(_.widen(~routingMask)).distinct))
val outputPorts = route_addrs.map(seq => (addr: UInt) => seq.map(_.contains(addr)).reduce(_ || _))
@ -97,70 +96,70 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame
// Print the ID mapping
if (false) {
println(s"XBar ${name} mapping:")
(node.edgesIn zip inputIdRanges).zipWithIndex.foreach { case ((edge, id), i) =>
(edgesIn zip inputIdRanges).zipWithIndex.foreach { case ((edge, id), i) =>
println(s"\t$i assigned ${id} for ${edge.client.clients.map(_.name).mkString(", ")}")
}
println("")
}
// We need an intermediate size of bundle with the widest possible identifiers
val wide_bundle = TLBundleParameters.union(io.in.map(_.params) ++ io.out.map(_.params))
val wide_bundle = TLBundleParameters.union(io_in.map(_.params) ++ io_out.map(_.params))
// Handle size = 1 gracefully (Chisel3 empty range is broken)
def trim(id: UInt, size: Int) = if (size <= 1) UInt(0) else id(log2Ceil(size)-1, 0)
// Transform input bundle sources (sinks use global namespace on both sides)
val in = Wire(Vec(io.in.size, TLBundle(wide_bundle)))
val in = Wire(Vec(io_in.size, TLBundle(wide_bundle)))
for (i <- 0 until in.size) {
val r = inputIdRanges(i)
in(i).a <> io.in(i).a
io.in(i).d <> in(i).d
in(i).a.bits.source := io.in(i).a.bits.source | UInt(r.start)
io.in(i).d.bits.source := trim(in(i).d.bits.source, r.size)
in(i).a <> io_in(i).a
io_in(i).d <> in(i).d
in(i).a.bits.source := io_in(i).a.bits.source | UInt(r.start)
io_in(i).d.bits.source := trim(in(i).d.bits.source, r.size)
if (node.edgesIn(i).client.anySupportProbe && node.edgesOut.exists(_.manager.anySupportAcquireB)) {
in(i).c <> io.in(i).c
in(i).e <> io.in(i).e
io.in(i).b <> in(i).b
in(i).c.bits.source := io.in(i).c.bits.source | UInt(r.start)
io.in(i).b.bits.source := trim(in(i).b.bits.source, r.size)
if (edgesIn(i).client.anySupportProbe && edgesOut.exists(_.manager.anySupportAcquireB)) {
in(i).c <> io_in(i).c
in(i).e <> io_in(i).e
io_in(i).b <> in(i).b
in(i).c.bits.source := io_in(i).c.bits.source | UInt(r.start)
io_in(i).b.bits.source := trim(in(i).b.bits.source, r.size)
} else {
in(i).c.valid := Bool(false)
in(i).e.valid := Bool(false)
in(i).b.ready := Bool(false)
io.in(i).c.ready := Bool(true)
io.in(i).e.ready := Bool(true)
io.in(i).b.valid := Bool(false)
io_in(i).c.ready := Bool(true)
io_in(i).e.ready := Bool(true)
io_in(i).b.valid := Bool(false)
}
}
// Transform output bundle sinks (sources use global namespace on both sides)
val out = Wire(Vec(io.out.size, TLBundle(wide_bundle)))
val out = Wire(Vec(io_out.size, TLBundle(wide_bundle)))
for (i <- 0 until out.size) {
val r = outputIdRanges(i)
io.out(i).a <> out(i).a
out(i).d <> io.out(i).d
out(i).d.bits.sink := io.out(i).d.bits.sink | UInt(r.map(_.start).getOrElse(0))
io_out(i).a <> out(i).a
out(i).d <> io_out(i).d
out(i).d.bits.sink := io_out(i).d.bits.sink | UInt(r.map(_.start).getOrElse(0))
if (node.edgesOut(i).manager.anySupportAcquireB && node.edgesIn.exists(_.client.anySupportProbe)) {
io.out(i).c <> out(i).c
io.out(i).e <> out(i).e
out(i).b <> io.out(i).b
io.out(i).e.bits.sink := trim(out(i).e.bits.sink, r.map(_.size).getOrElse(0))
if (edgesOut(i).manager.anySupportAcquireB && edgesIn.exists(_.client.anySupportProbe)) {
io_out(i).c <> out(i).c
io_out(i).e <> out(i).e
out(i).b <> io_out(i).b
io_out(i).e.bits.sink := trim(out(i).e.bits.sink, r.map(_.size).getOrElse(0))
} else {
out(i).c.ready := Bool(false)
out(i).e.ready := Bool(false)
out(i).b.valid := Bool(false)
io.out(i).c.valid := Bool(false)
io.out(i).e.valid := Bool(false)
io.out(i).b.ready := Bool(true)
io_out(i).c.valid := Bool(false)
io_out(i).e.valid := Bool(false)
io_out(i).b.ready := Bool(true)
}
}
val addressA = (in zip node.edgesIn) map { case (i, e) => e.address(i.a.bits) }
val addressC = (in zip node.edgesIn) map { case (i, e) => e.address(i.c.bits) }
val addressA = (in zip edgesIn) map { case (i, e) => e.address(i.a.bits) }
val addressC = (in zip edgesIn) map { case (i, e) => e.address(i.c.bits) }
val requestAIO = Vec(addressA.map { i => Vec(outputPorts.map { o => o(i) }) })
val requestCIO = Vec(addressC.map { i => Vec(outputPorts.map { o => o(i) }) })
@ -168,28 +167,28 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame
val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map { i => i.contains(o.d.bits.source) }) })
val requestEIO = Vec(in.map { i => Vec(outputIdRanges.map { o => o.map(_.contains(i.e.bits.sink)).getOrElse(Bool(false)) }) })
val beatsAI = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats1(i.a.bits) })
val beatsBO = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats1(o.b.bits) })
val beatsCI = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats1(i.c.bits) })
val beatsDO = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats1(o.d.bits) })
val beatsEI = Vec((in zip node.edgesIn) map { case (i, e) => e.numBeats1(i.e.bits) })
val beatsAI = Vec((in zip edgesIn) map { case (i, e) => e.numBeats1(i.a.bits) })
val beatsBO = Vec((out zip edgesOut) map { case (o, e) => e.numBeats1(o.b.bits) })
val beatsCI = Vec((in zip edgesIn) map { case (i, e) => e.numBeats1(i.c.bits) })
val beatsDO = Vec((out zip edgesOut) map { case (o, e) => e.numBeats1(o.d.bits) })
val beatsEI = Vec((in zip edgesIn) map { case (i, e) => e.numBeats1(i.e.bits) })
// Which pairs support support transfers
def transpose[T](x: Seq[Seq[T]]) = Seq.tabulate(x(0).size) { i => Seq.tabulate(x.size) { j => x(j)(i) } }
def filter[T](data: Seq[T], mask: Seq[Boolean]) = (data zip mask).filter(_._2).map(_._1)
// Fanout the input sources to the output sinks
val portsAOI = transpose((in zip requestAIO) map { case (i, r) => TLXbar.fanout(i.a, r, node.paramsOut.map(_(ForceFanoutKey).a)) })
val portsBIO = transpose((out zip requestBOI) map { case (o, r) => TLXbar.fanout(o.b, r, node.paramsIn .map(_(ForceFanoutKey).b)) })
val portsCOI = transpose((in zip requestCIO) map { case (i, r) => TLXbar.fanout(i.c, r, node.paramsOut.map(_(ForceFanoutKey).c)) })
val portsDIO = transpose((out zip requestDOI) map { case (o, r) => TLXbar.fanout(o.d, r, node.paramsIn .map(_(ForceFanoutKey).d)) })
val portsEOI = transpose((in zip requestEIO) map { case (i, r) => TLXbar.fanout(i.e, r, node.paramsOut.map(_(ForceFanoutKey).e)) })
val portsAOI = transpose((in zip requestAIO) map { case (i, r) => TLXbar.fanout(i.a, r, edgesOut.map(_.params(ForceFanoutKey).a)) })
val portsBIO = transpose((out zip requestBOI) map { case (o, r) => TLXbar.fanout(o.b, r, edgesIn .map(_.params(ForceFanoutKey).b)) })
val portsCOI = transpose((in zip requestCIO) map { case (i, r) => TLXbar.fanout(i.c, r, edgesOut.map(_.params(ForceFanoutKey).c)) })
val portsDIO = transpose((out zip requestDOI) map { case (o, r) => TLXbar.fanout(o.d, r, edgesIn .map(_.params(ForceFanoutKey).d)) })
val portsEOI = transpose((in zip requestEIO) map { case (i, r) => TLXbar.fanout(i.e, r, edgesOut.map(_.params(ForceFanoutKey).e)) })
// Arbitrate amongst the sources
for (o <- 0 until out.size) {
val allowI = Seq.tabulate(in.size) { i =>
node.edgesIn(i).client.anySupportProbe &&
node.edgesOut(o).manager.anySupportAcquireB
edgesIn(i).client.anySupportProbe &&
edgesOut(o).manager.anySupportAcquireB
}
TLArbiter(policy)(out(o).a, (beatsAI zip portsAOI(o) ):_*)
TLArbiter(policy)(out(o).c, filter(beatsCI zip portsCOI(o), allowI):_*)
@ -198,8 +197,8 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame
for (i <- 0 until in.size) {
val allowO = Seq.tabulate(out.size) { o =>
node.edgesIn(i).client.anySupportProbe &&
node.edgesOut(o).manager.anySupportAcquireB
edgesIn(i).client.anySupportProbe &&
edgesOut(o).manager.anySupportAcquireB
}
TLArbiter(policy)(in(i).b, filter(beatsBO zip portsBIO(i), allowO):_*)
TLArbiter(policy)(in(i).d, (beatsDO zip portsDIO(i) ):_*)
@ -264,7 +263,7 @@ class TLRAMXbar(nManagers: Int, txns: Int)(implicit p: Parameters) extends LazyM
ram.node := TLFragmenter(4, 256)(TLDelayer(0.1)(xbar.node))
}
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzz.module.io.finished
}
}
@ -287,7 +286,7 @@ class TLMulticlientXbar(nManagers: Int, nClients: Int, txns: Int)(implicit p: Pa
ram.node := TLFragmenter(4, 256)(TLDelayer(0.1)(xbar.node))
}
lazy val module = new LazyModuleImp(this) with HasUnitTestIO {
lazy val module = new LazyModuleImp(this) with UnitTestModule {
io.finished := fuzzers.last.module.io.finished
}
}

View File

@ -3,17 +3,28 @@
package freechips.rocketchip.unittest
import Chisel._
import chisel3.experimental.MultiIOModule
import freechips.rocketchip.config._
import freechips.rocketchip.util.SimpleTimer
trait HasUnitTestIO {
val io = new Bundle {
val finished = Bool(OUTPUT)
val start = Bool(INPUT)
}
trait UnitTestIO {
val finished = Bool(OUTPUT)
val start = Bool(INPUT)
}
abstract class UnitTest(val timeout: Int = 4096) extends Module with HasUnitTestIO {
trait HasUnitTestIO {
val io: UnitTestIO
}
trait UnitTestLegacyModule extends HasUnitTestIO {
val io = new Bundle with UnitTestIO
}
trait UnitTestModule extends MultiIOModule with HasUnitTestIO {
val io = IO(new Bundle with UnitTestIO)
}
abstract class UnitTest(val timeout: Int = 4096) extends Module with UnitTestLegacyModule {
val testName = this.getClass.getSimpleName
when (io.start) { printf(s"Started UnitTest $testName\n") }

View File

@ -17,3 +17,8 @@ final case class HeterogeneousBag[T <: Data](elts: Seq[T]) extends Record with c
override def hashCode: Int = super[Record].hashCode
override def equals(that: Any): Boolean = super[Record].equals(that)
}
object HeterogeneousBag
{
def fromNode[D <: Data, E](elts: Seq[(D, E)]) = new HeterogeneousBag(elts.map(_._1.cloneType))
}

Some files were not shown because too many files have changed in this diff Show More