2017-10-20 03:51:22 +02:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
|
|
|
|
package freechips.rocketchip.coreplex
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import freechips.rocketchip.config._
|
|
|
|
import freechips.rocketchip.diplomacy._
|
|
|
|
import freechips.rocketchip.tilelink._
|
2017-10-26 02:46:41 +02:00
|
|
|
import freechips.rocketchip.amba.axi4._
|
2017-10-20 07:19:19 +02:00
|
|
|
import freechips.rocketchip.interrupts._
|
2017-10-23 18:39:01 +02:00
|
|
|
import freechips.rocketchip.util._
|
|
|
|
|
|
|
|
/** Enumerates the three types of clock crossing between tiles and system bus */
|
|
|
|
sealed trait CoreplexClockCrossing
|
2017-10-27 08:39:56 +02:00
|
|
|
{
|
|
|
|
def sameClock = this match {
|
|
|
|
case _: SynchronousCrossing => true
|
|
|
|
case _ => false
|
|
|
|
}
|
|
|
|
}
|
2017-10-23 18:39:01 +02:00
|
|
|
case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends CoreplexClockCrossing
|
|
|
|
case class RationalCrossing(direction: RationalDirection = FastToSlow) extends CoreplexClockCrossing
|
|
|
|
case class AsynchronousCrossing(depth: Int, sync: Int = 3) extends CoreplexClockCrossing
|
2017-10-20 03:51:22 +02:00
|
|
|
|
2017-10-27 00:41:17 +02:00
|
|
|
private case class CrossingCheck(out: Boolean, source: BaseNode, sink: BaseNode)
|
|
|
|
|
|
|
|
trait HasCrossingMethods extends LazyModule with LazyScope
|
2017-10-20 03:51:22 +02:00
|
|
|
{
|
2017-10-27 00:41:17 +02:00
|
|
|
// Detect incorrect crossing connectivity
|
|
|
|
|
|
|
|
private var checks: List[CrossingCheck] = Nil
|
|
|
|
private def inside(node: BaseNode) = node.parents.exists(_ eq this)
|
|
|
|
override def instantiate() {
|
|
|
|
super.instantiate()
|
|
|
|
checks.foreach { case CrossingCheck(out, source, sink) =>
|
|
|
|
source.inputs.foreach { case (syncSource, _) =>
|
|
|
|
require (inside(syncSource) == out, s"${syncSource.name} must ${if(out)""else"not "}be inside ${name} (wrong .cross direction?)")
|
|
|
|
}
|
|
|
|
sink.outputs.foreach { case (syncSink, _) =>
|
|
|
|
require (inside(syncSink) != out, s"${syncSink.name} must ${if(out)"not "else""}be inside ${name} (wrong .cross direction?)")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-20 07:19:19 +02:00
|
|
|
|
2017-10-25 23:45:44 +02:00
|
|
|
// TileLink
|
|
|
|
|
|
|
|
def crossTLSyncInOut(out: Boolean)(params: BufferParams = BufferParams.default)(implicit p: Parameters): TLNode = {
|
2017-10-27 00:41:17 +02:00
|
|
|
val node = this { LazyModule(new TLBuffer(params)).node }
|
|
|
|
checks = CrossingCheck(out, node, node) :: checks
|
|
|
|
node
|
2017-10-25 23:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
def crossTLAsyncInOut(out: Boolean)(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): TLNode = {
|
2017-12-01 20:27:54 +01:00
|
|
|
lazy val asource = LazyModule(new TLAsyncCrossingSource(sync))
|
|
|
|
lazy val asink = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
|
|
|
val source = if (out) this { asource } else asource
|
|
|
|
val sink = if (out) asink else this { asink }
|
2017-12-02 03:28:37 +01:00
|
|
|
sink.node :*=* source.node
|
2017-10-27 00:41:17 +02:00
|
|
|
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
2017-10-25 23:45:44 +02:00
|
|
|
NodeHandle(source.node, sink.node)
|
|
|
|
}
|
|
|
|
|
|
|
|
def crossTLRationalInOut(out: Boolean)(direction: RationalDirection)(implicit p: Parameters): TLNode = {
|
2017-12-01 20:27:54 +01:00
|
|
|
lazy val rsource = LazyModule(new TLRationalCrossingSource)
|
|
|
|
lazy val rsink = LazyModule(new TLRationalCrossingSink(if (out) direction else direction.flip))
|
|
|
|
val source = if (out) this { rsource } else rsource
|
|
|
|
val sink = if (out) rsink else this { rsink }
|
2017-12-02 03:28:37 +01:00
|
|
|
sink.node :*=* source.node
|
2017-10-27 00:41:17 +02:00
|
|
|
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
2017-10-25 23:45:44 +02:00
|
|
|
NodeHandle(source.node, sink.node)
|
|
|
|
}
|
|
|
|
|
|
|
|
def crossTLSyncIn (params: BufferParams = BufferParams.default)(implicit p: Parameters): TLNode = crossTLSyncInOut(false)(params)
|
|
|
|
def crossTLSyncOut(params: BufferParams = BufferParams.default)(implicit p: Parameters): TLNode = crossTLSyncInOut(true )(params)
|
|
|
|
def crossTLAsyncIn (depth: Int = 8, sync: Int = 3)(implicit p: Parameters): TLNode = crossTLAsyncInOut(false)(depth, sync)
|
|
|
|
def crossTLAsyncOut(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): TLNode = crossTLAsyncInOut(true )(depth, sync)
|
|
|
|
def crossTLRationalIn (direction: RationalDirection)(implicit p: Parameters): TLNode = crossTLRationalInOut(false)(direction)
|
|
|
|
def crossTLRationalOut(direction: RationalDirection)(implicit p: Parameters): TLNode = crossTLRationalInOut(true )(direction)
|
|
|
|
|
|
|
|
def crossTLIn(arg: CoreplexClockCrossing)(implicit p: Parameters): TLNode = arg match {
|
|
|
|
case x: SynchronousCrossing => crossTLSyncIn(x.params)
|
|
|
|
case x: AsynchronousCrossing => crossTLAsyncIn(x.depth, x.sync)
|
|
|
|
case x: RationalCrossing => crossTLRationalIn(x.direction)
|
|
|
|
}
|
|
|
|
|
|
|
|
def crossTLOut(arg: CoreplexClockCrossing)(implicit p: Parameters): TLNode = arg match {
|
|
|
|
case x: SynchronousCrossing => crossTLSyncOut(x.params)
|
|
|
|
case x: AsynchronousCrossing => crossTLAsyncOut(x.depth, x.sync)
|
|
|
|
case x: RationalCrossing => crossTLRationalOut(x.direction)
|
|
|
|
}
|
|
|
|
|
2017-10-26 02:46:41 +02:00
|
|
|
// AXI4
|
|
|
|
|
|
|
|
def crossAXI4SyncInOut(out: Boolean)(params: BufferParams = BufferParams.default)(implicit p: Parameters): AXI4Node = {
|
2017-10-27 00:41:17 +02:00
|
|
|
val node = this { LazyModule(new AXI4Buffer(params)).node }
|
|
|
|
checks = CrossingCheck(out, node, node) :: checks
|
|
|
|
node
|
2017-10-26 02:46:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
def crossAXI4AsyncInOut(out: Boolean)(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): AXI4Node = {
|
2017-12-01 20:27:54 +01:00
|
|
|
lazy val axi4asource = LazyModule(new AXI4AsyncCrossingSource(sync))
|
|
|
|
lazy val axi4asink = LazyModule(new AXI4AsyncCrossingSink(depth, sync))
|
|
|
|
val source = if (out) this { axi4asource } else axi4asource
|
|
|
|
val sink = if (out) axi4asink else this { axi4asink }
|
2017-12-02 03:28:37 +01:00
|
|
|
sink.node :*=* source.node
|
2017-10-27 00:41:17 +02:00
|
|
|
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
2017-10-26 02:46:41 +02:00
|
|
|
NodeHandle(source.node, sink.node)
|
|
|
|
}
|
|
|
|
|
|
|
|
def crossAXI4SyncIn (params: BufferParams = BufferParams.default)(implicit p: Parameters): AXI4Node = crossAXI4SyncInOut(false)(params)
|
|
|
|
def crossAXI4SyncOut(params: BufferParams = BufferParams.default)(implicit p: Parameters): AXI4Node = crossAXI4SyncInOut(true )(params)
|
|
|
|
def crossAXI4AsyncIn (depth: Int = 8, sync: Int = 3)(implicit p: Parameters): AXI4Node = crossAXI4AsyncInOut(false)(depth, sync)
|
|
|
|
def crossAXI4AsyncOut(depth: Int = 8, sync: Int = 3)(implicit p: Parameters): AXI4Node = crossAXI4AsyncInOut(true )(depth, sync)
|
|
|
|
|
|
|
|
def crossAXI4In(arg: CoreplexClockCrossing)(implicit p: Parameters): AXI4Node = arg match {
|
|
|
|
case x: SynchronousCrossing => crossAXI4SyncIn(x.params)
|
|
|
|
case x: AsynchronousCrossing => crossAXI4AsyncIn(x.depth, x.sync)
|
|
|
|
case x: RationalCrossing => throw new IllegalArgumentException("AXI4 Rational crossing unimplemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
def crossAXI4Out(arg: CoreplexClockCrossing)(implicit p: Parameters): AXI4Node = arg match {
|
|
|
|
case x: SynchronousCrossing => crossAXI4SyncOut(x.params)
|
|
|
|
case x: AsynchronousCrossing => crossAXI4AsyncOut(x.depth, x.sync)
|
|
|
|
case x: RationalCrossing => throw new IllegalArgumentException("AXI4 Rational crossing unimplemented")
|
|
|
|
}
|
|
|
|
|
2017-10-25 23:45:44 +02:00
|
|
|
// Interrupts
|
|
|
|
|
|
|
|
def crossIntSyncInOut(out: Boolean)(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = {
|
2017-12-01 20:27:54 +01:00
|
|
|
lazy val intssource = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
|
|
|
lazy val intssink = LazyModule(new IntSyncCrossingSink(0))
|
|
|
|
val source = if (out) this { intssource } else intssource
|
|
|
|
val sink = if (out) intssink else this { intssink }
|
2017-12-02 03:28:37 +01:00
|
|
|
sink.node :*=* source.node
|
2017-10-27 00:41:17 +02:00
|
|
|
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
2017-10-25 23:45:44 +02:00
|
|
|
NodeHandle(source.node, sink.node)
|
2017-10-20 03:51:22 +02:00
|
|
|
}
|
2017-10-20 07:19:19 +02:00
|
|
|
|
2017-10-25 23:45:44 +02:00
|
|
|
def crossIntAsyncInOut(out: Boolean)(sync: Int = 3, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = {
|
2017-12-01 20:27:54 +01:00
|
|
|
lazy val intasource = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
|
|
|
lazy val intasink = LazyModule(new IntSyncCrossingSink(sync))
|
|
|
|
val source = if (out) this { intasource } else intasource
|
|
|
|
val sink = if (out) intasink else this { intasink }
|
2017-12-02 03:28:37 +01:00
|
|
|
sink.node :*=* source.node
|
2017-10-27 00:41:17 +02:00
|
|
|
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
2017-10-25 23:45:44 +02:00
|
|
|
NodeHandle(source.node, sink.node)
|
2017-10-20 07:19:19 +02:00
|
|
|
}
|
2017-10-25 23:45:44 +02:00
|
|
|
|
|
|
|
def crossIntRationalInOut(out: Boolean)(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = {
|
2017-12-01 20:27:54 +01:00
|
|
|
lazy val intrsource = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
|
|
|
lazy val intrsink = LazyModule(new IntSyncCrossingSink(1))
|
|
|
|
val source = if (out) this { intrsource } else intrsource
|
|
|
|
val sink = if (out) intrsink else this { intrsink }
|
2017-12-02 03:28:37 +01:00
|
|
|
sink.node :*=* source.node
|
2017-10-27 00:41:17 +02:00
|
|
|
checks = CrossingCheck(out, source.node, sink.node) :: checks
|
2017-10-25 23:45:44 +02:00
|
|
|
NodeHandle(source.node, sink.node)
|
|
|
|
}
|
|
|
|
|
|
|
|
def crossIntSyncIn (alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntSyncInOut(false)(alreadyRegistered)
|
|
|
|
def crossIntSyncOut(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntSyncInOut(true )(alreadyRegistered)
|
|
|
|
def crossIntAsyncIn (sync: Int = 3, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntAsyncInOut(false)(sync, alreadyRegistered)
|
|
|
|
def crossIntAsyncOut(sync: Int = 3, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntAsyncInOut(true )(sync, alreadyRegistered)
|
|
|
|
def crossIntRationalIn (alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntRationalInOut(false)(alreadyRegistered)
|
|
|
|
def crossIntRationalOut(alreadyRegistered: Boolean = false)(implicit p: Parameters): IntNode = crossIntRationalInOut(true )(alreadyRegistered)
|
|
|
|
|
|
|
|
def crossIntIn(arg: CoreplexClockCrossing, alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = arg match {
|
|
|
|
case x: SynchronousCrossing => crossIntSyncIn(alreadyRegistered)
|
|
|
|
case x: AsynchronousCrossing => crossIntAsyncIn(x.sync, alreadyRegistered)
|
|
|
|
case x: RationalCrossing => crossIntRationalIn(alreadyRegistered)
|
|
|
|
}
|
|
|
|
|
|
|
|
def crossIntOut(arg: CoreplexClockCrossing, alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = arg match {
|
|
|
|
case x: SynchronousCrossing => crossIntSyncOut(alreadyRegistered)
|
|
|
|
case x: AsynchronousCrossing => crossIntAsyncOut(x.sync, alreadyRegistered)
|
|
|
|
case x: RationalCrossing => crossIntRationalOut(alreadyRegistered)
|
|
|
|
}
|
|
|
|
|
|
|
|
def crossIntIn (arg: CoreplexClockCrossing)(implicit p: Parameters): IntNode = crossIntIn (arg, false)
|
|
|
|
def crossIntOut(arg: CoreplexClockCrossing)(implicit p: Parameters): IntNode = crossIntOut(arg, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
trait HasCrossing extends HasCrossingMethods
|
|
|
|
{
|
|
|
|
this: LazyModule =>
|
|
|
|
val crossing: CoreplexClockCrossing
|
|
|
|
|
2017-10-26 02:46:41 +02:00
|
|
|
def crossTLIn (implicit p: Parameters): TLNode = crossTLIn (crossing)
|
|
|
|
def crossTLOut (implicit p: Parameters): TLNode = crossTLOut (crossing)
|
|
|
|
def crossAXI4In (implicit p: Parameters): AXI4Node= crossAXI4In (crossing)
|
|
|
|
def crossAXI4Out(implicit p: Parameters): AXI4Node= crossAXI4Out(crossing)
|
|
|
|
def crossIntIn (implicit p: Parameters): IntNode = crossIntIn (crossing)
|
|
|
|
def crossIntOut (implicit p: Parameters): IntNode = crossIntOut (crossing)
|
|
|
|
|
2017-10-25 23:45:44 +02:00
|
|
|
def crossIntIn (alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = crossIntIn (crossing, alreadyRegistered)
|
|
|
|
def crossIntOut(alreadyRegistered: Boolean)(implicit p: Parameters): IntNode = crossIntOut(crossing, alreadyRegistered)
|
2017-10-20 03:51:22 +02:00
|
|
|
}
|
|
|
|
|
2017-10-25 23:45:44 +02:00
|
|
|
class CrossingWrapper(val crossing: CoreplexClockCrossing)(implicit p: Parameters) extends SimpleLazyModule with HasCrossing
|