2016-11-28 01:16:37 +01:00
|
|
|
// See LICENSE.SiFive for license details.
|
2016-08-19 20:08:35 +02:00
|
|
|
|
2017-07-07 19:48:16 +02:00
|
|
|
package freechips.rocketchip.tilelink
|
2016-08-19 20:08:35 +02:00
|
|
|
|
|
|
|
import Chisel._
|
2016-08-31 19:37:30 +02:00
|
|
|
import chisel3.internal.sourceinfo.SourceInfo
|
2017-07-07 19:48:16 +02:00
|
|
|
import freechips.rocketchip.config.{Field, Parameters}
|
|
|
|
import freechips.rocketchip.diplomacy._
|
|
|
|
import freechips.rocketchip.util.RationalDirection
|
2016-10-04 00:17:36 +02:00
|
|
|
import scala.collection.mutable.ListBuffer
|
2016-08-19 20:08:35 +02:00
|
|
|
|
2017-09-12 21:12:49 +02:00
|
|
|
case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => new TLMonitor(args))
|
2017-09-07 22:41:26 +02:00
|
|
|
case object TLCombinationalCheck extends Field[Boolean](false)
|
2016-12-02 04:04:31 +01:00
|
|
|
|
2016-10-04 00:17:36 +02:00
|
|
|
object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle]
|
2016-09-29 23:30:19 +02:00
|
|
|
{
|
2017-09-14 03:06:03 +02:00
|
|
|
def edgeO(pd: TLClientPortParameters, pu: TLManagerPortParameters, p: Parameters): TLEdgeOut = new TLEdgeOut(pd, pu, p)
|
|
|
|
def edgeI(pd: TLClientPortParameters, pu: TLManagerPortParameters, p: Parameters): TLEdgeIn = new TLEdgeIn(pd, pu, p)
|
2017-01-20 03:36:39 +01:00
|
|
|
|
2017-02-23 02:05:22 +01:00
|
|
|
def bundleO(eo: TLEdgeOut): TLBundle = TLBundle(eo.bundle)
|
|
|
|
def bundleI(ei: TLEdgeIn): TLBundle = TLBundle(ei.bundle)
|
2016-09-29 23:30:19 +02:00
|
|
|
|
2016-10-04 00:17:36 +02:00
|
|
|
def colour = "#000000" // black
|
2016-10-28 23:00:55 +02:00
|
|
|
override def labelI(ei: TLEdgeIn) = (ei.manager.beatBytes * 8).toString
|
|
|
|
override def labelO(eo: TLEdgeOut) = (eo.manager.beatBytes * 8).toString
|
|
|
|
|
2017-06-29 06:48:10 +02:00
|
|
|
override def connect(edges: () => Seq[TLEdgeIn], bundles: () => Seq[(TLBundle, TLBundle)], enableMonitoring: Boolean)
|
|
|
|
(implicit p: Parameters, sourceInfo: SourceInfo): (Option[TLMonitorBase], () => Unit) = {
|
2017-09-12 21:12:49 +02:00
|
|
|
val monitor = if (enableMonitoring) Some(LazyModule(p(TLMonitorBuilder)(TLMonitorArgs(edges, sourceInfo, p)))) else None
|
2016-10-09 21:34:10 +02:00
|
|
|
(monitor, () => {
|
2017-05-17 05:51:55 +02:00
|
|
|
val eval = bundles ()
|
2017-05-17 15:46:07 +02:00
|
|
|
monitor.foreach { m => (eval zip m.module.io.in) foreach { case ((i,o), m) => m := TLBundleSnoop(o,i) } }
|
|
|
|
eval.foreach { case (bi, bo) =>
|
2017-01-30 02:25:14 +01:00
|
|
|
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
|
|
|
|
}
|
2016-10-13 06:02:31 +02:00
|
|
|
}
|
2016-10-04 00:17:36 +02:00
|
|
|
})
|
|
|
|
}
|
2016-09-29 23:30:19 +02:00
|
|
|
|
2016-10-04 00:17:36 +02:00
|
|
|
override def mixO(pd: TLClientPortParameters, node: OutwardNode[TLClientPortParameters, TLManagerPortParameters, TLBundle]): TLClientPortParameters =
|
2016-10-15 01:18:57 +02:00
|
|
|
pd.copy(clients = pd.clients.map { c => c.copy (nodePath = node +: c.nodePath) })
|
2016-10-04 00:17:36 +02:00
|
|
|
override def mixI(pu: TLManagerPortParameters, node: InwardNode[TLClientPortParameters, TLManagerPortParameters, TLBundle]): TLManagerPortParameters =
|
2016-10-15 01:18:57 +02:00
|
|
|
pu.copy(managers = pu.managers.map { m => m.copy (nodePath = node +: m.nodePath) })
|
|
|
|
override def getO(pu: TLManagerPortParameters): Option[BaseNode] = {
|
|
|
|
val head = pu.managers.map(_.nodePath.headOption)
|
|
|
|
if (head.exists(!_.isDefined) || head.map(_.get).distinct.size != 1) {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
val subproblem = pu.copy(managers = pu.managers.map(m => m.copy(nodePath = m.nodePath.tail)))
|
|
|
|
getO(subproblem) match {
|
|
|
|
case Some(x) => Some(x)
|
|
|
|
case None => Some(head(0).get)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-04 00:17:36 +02:00
|
|
|
}
|
2016-09-08 23:41:08 +02:00
|
|
|
|
2017-09-12 08:33:44 +02:00
|
|
|
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)
|
2016-09-26 10:18:53 +02:00
|
|
|
|
2016-10-04 00:17:36 +02:00
|
|
|
case class TLAdapterNode(
|
2017-09-14 03:06:03 +02:00
|
|
|
clientFn: TLClientPortParameters => TLClientPortParameters = { s => s },
|
|
|
|
managerFn: TLManagerPortParameters => TLManagerPortParameters = { s => s },
|
2017-09-12 08:33:44 +02:00
|
|
|
num: Range.Inclusive = 0 to 999)(
|
|
|
|
implicit valName: ValName)
|
2017-01-30 00:17:52 +01:00
|
|
|
extends AdapterNode(TLImp)(clientFn, managerFn, num)
|
|
|
|
|
2017-09-14 03:06:03 +02:00
|
|
|
case class TLIdentityNode()(implicit valName: ValName) extends IdentityNode(TLImp)()
|
|
|
|
|
2017-01-30 00:17:52 +01:00
|
|
|
case class TLNexusNode(
|
2016-10-04 00:17:36 +02:00
|
|
|
clientFn: Seq[TLClientPortParameters] => TLClientPortParameters,
|
|
|
|
managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters,
|
2017-01-30 00:17:52 +01:00
|
|
|
numClientPorts: Range.Inclusive = 1 to 999,
|
2017-09-12 08:33:44 +02:00
|
|
|
numManagerPorts: Range.Inclusive = 1 to 999)(
|
|
|
|
implicit valName: ValName)
|
2017-01-30 00:17:52 +01:00
|
|
|
extends NexusNode(TLImp)(clientFn, managerFn, numClientPorts, numManagerPorts)
|
2016-10-04 00:17:36 +02:00
|
|
|
|
2017-05-20 02:29:22 +02:00
|
|
|
abstract class TLCustomNode(
|
|
|
|
numClientPorts: Range.Inclusive,
|
2017-09-12 08:33:44 +02:00
|
|
|
numManagerPorts: Range.Inclusive)(
|
|
|
|
implicit valName: ValName)
|
2017-05-20 02:29:22 +02:00
|
|
|
extends CustomNode(TLImp)(numClientPorts, numManagerPorts)
|
|
|
|
|
2017-09-14 03:06:03 +02:00
|
|
|
// Asynchronous crossings
|
2016-09-29 23:30:19 +02:00
|
|
|
|
2016-10-04 00:17:36 +02:00
|
|
|
object TLAsyncImp extends NodeImp[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncEdgeParameters, TLAsyncEdgeParameters, TLAsyncBundle]
|
2016-09-29 23:30:19 +02:00
|
|
|
{
|
2017-09-14 03:06:03 +02:00
|
|
|
def edgeO(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters, p: Parameters): TLAsyncEdgeParameters = TLAsyncEdgeParameters(pd, pu, p)
|
|
|
|
def edgeI(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters, p: Parameters): TLAsyncEdgeParameters = TLAsyncEdgeParameters(pd, pu, p)
|
2017-01-20 03:36:39 +01:00
|
|
|
|
2017-02-23 02:05:22 +01:00
|
|
|
def bundleO(eo: TLAsyncEdgeParameters): TLAsyncBundle = new TLAsyncBundle(eo.bundle)
|
|
|
|
def bundleI(ei: TLAsyncEdgeParameters): TLAsyncBundle = new TLAsyncBundle(ei.bundle)
|
2016-09-09 06:11:31 +02:00
|
|
|
|
2016-10-04 00:17:36 +02:00
|
|
|
def colour = "#ff0000" // red
|
2016-10-28 23:00:55 +02:00
|
|
|
override def labelI(ei: TLAsyncEdgeParameters) = ei.manager.depth.toString
|
|
|
|
override def labelO(eo: TLAsyncEdgeParameters) = eo.manager.depth.toString
|
|
|
|
|
2016-10-04 00:17:36 +02:00
|
|
|
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) }))
|
|
|
|
override def mixI(pu: TLAsyncManagerPortParameters, node: InwardNode[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]): TLAsyncManagerPortParameters =
|
|
|
|
pu.copy(base = pu.base.copy(managers = pu.base.managers.map { m => m.copy (nodePath = node +: m.nodePath) }))
|
2016-08-31 04:26:01 +02:00
|
|
|
}
|
|
|
|
|
2017-09-14 03:06:03 +02:00
|
|
|
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 TLAsyncIdentityNode()(implicit valName: ValName) extends IdentityNode(TLAsyncImp)()
|
2016-10-04 00:17:36 +02:00
|
|
|
|
2017-09-12 08:33:44 +02:00
|
|
|
case class TLAsyncSourceNode(sync: Int)(implicit valName: ValName)
|
2017-01-30 00:17:52 +01:00
|
|
|
extends MixedAdapterNode(TLImp, TLAsyncImp)(
|
|
|
|
dFn = { p => TLAsyncClientPortParameters(p) },
|
|
|
|
uFn = { p => p.base.copy(minLatency = sync+1) }) // discard cycles in other clock domain
|
2016-10-04 00:17:36 +02:00
|
|
|
|
2017-09-12 08:33:44 +02:00
|
|
|
case class TLAsyncSinkNode(depth: Int, sync: Int)(implicit valName: ValName)
|
2017-01-30 00:17:52 +01:00
|
|
|
extends MixedAdapterNode(TLAsyncImp, TLImp)(
|
|
|
|
dFn = { p => p.base.copy(minLatency = sync+1) },
|
|
|
|
uFn = { p => TLAsyncManagerPortParameters(depth, p) })
|
2017-01-27 00:15:48 +01:00
|
|
|
|
2017-09-14 03:06:03 +02:00
|
|
|
// Rationally related crossings
|
|
|
|
|
2017-02-17 04:19:00 +01:00
|
|
|
object TLRationalImp extends NodeImp[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalEdgeParameters, TLRationalEdgeParameters, TLRationalBundle]
|
2017-01-27 00:15:48 +01:00
|
|
|
{
|
2017-09-14 03:06:03 +02:00
|
|
|
def edgeO(pd: TLRationalClientPortParameters, pu: TLRationalManagerPortParameters, p: Parameters): TLRationalEdgeParameters = TLRationalEdgeParameters(pd, pu, p)
|
|
|
|
def edgeI(pd: TLRationalClientPortParameters, pu: TLRationalManagerPortParameters, p: Parameters): TLRationalEdgeParameters = TLRationalEdgeParameters(pd, pu, p)
|
2017-01-27 00:15:48 +01:00
|
|
|
|
2017-02-23 02:05:22 +01:00
|
|
|
def bundleO(eo: TLRationalEdgeParameters): TLRationalBundle = new TLRationalBundle(eo.bundle)
|
|
|
|
def bundleI(ei: TLRationalEdgeParameters): TLRationalBundle = new TLRationalBundle(ei.bundle)
|
2017-01-27 00:15:48 +01:00
|
|
|
|
|
|
|
def colour = "#00ff00" // green
|
|
|
|
|
2017-02-17 04:19:00 +01:00
|
|
|
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) }))
|
|
|
|
override def mixI(pu: TLRationalManagerPortParameters, node: InwardNode[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle]): TLRationalManagerPortParameters =
|
|
|
|
pu.copy(base = pu.base.copy(managers = pu.base.managers.map { m => m.copy (nodePath = node +: m.nodePath) }))
|
2017-01-27 00:15:48 +01:00
|
|
|
}
|
|
|
|
|
2017-09-14 03:06:03 +02:00
|
|
|
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 TLRationalIdentityNode()(implicit valName: ValName) extends IdentityNode(TLRationalImp)()
|
2017-01-27 00:15:48 +01:00
|
|
|
|
2017-09-12 08:33:44 +02:00
|
|
|
case class TLRationalSourceNode()(implicit valName: ValName)
|
2017-01-30 00:17:52 +01:00
|
|
|
extends MixedAdapterNode(TLImp, TLRationalImp)(
|
2017-02-17 04:19:00 +01:00
|
|
|
dFn = { p => TLRationalClientPortParameters(p) },
|
|
|
|
uFn = { p => p.base.copy(minLatency = 1) }) // discard cycles from other clock domain
|
2017-01-30 00:17:52 +01:00
|
|
|
|
2017-09-12 08:33:44 +02:00
|
|
|
case class TLRationalSinkNode(direction: RationalDirection)(implicit valName: ValName)
|
2017-01-30 00:17:52 +01:00
|
|
|
extends MixedAdapterNode(TLRationalImp, TLImp)(
|
2017-02-17 04:19:00 +01:00
|
|
|
dFn = { p => p.base.copy(minLatency = 1) },
|
|
|
|
uFn = { p => TLRationalManagerPortParameters(direction, p) })
|