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-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
|
|
|
|
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
|
|
|
|
|
|
|
trait HasCrossingHelper extends LazyScope
|
|
|
|
{
|
|
|
|
this: LazyModule =>
|
|
|
|
val crossing: CoreplexClockCrossing
|
2017-10-20 07:19:19 +02:00
|
|
|
|
2017-10-23 18:39:01 +02:00
|
|
|
def cross(x: TLCrossableNode): TLOutwardNode = {
|
2017-10-20 03:51:22 +02:00
|
|
|
val out = x.node.parentsOut.exists(_ eq this) // is the crossing exiting the wrapper?
|
|
|
|
crossing match {
|
|
|
|
case SynchronousCrossing(params) => {
|
2017-10-23 18:39:01 +02:00
|
|
|
// !!! Why does star resolution fail for tile with no slave devices?
|
|
|
|
// this { TLBuffer(params)(x.node) }
|
|
|
|
x.node
|
2017-10-20 03:51:22 +02:00
|
|
|
}
|
|
|
|
case RationalCrossing(direction) => {
|
|
|
|
def sourceGen = LazyModule(new TLRationalCrossingSource)
|
|
|
|
def sinkGen = LazyModule(new TLRationalCrossingSink(direction))
|
|
|
|
val source = if (out) this { sourceGen } else sourceGen
|
|
|
|
val sink = if (out) sinkGen else this { sinkGen }
|
2017-10-23 18:39:01 +02:00
|
|
|
source.node :=? x.node
|
|
|
|
sink.node :=? source.node
|
2017-10-20 03:51:22 +02:00
|
|
|
sink.node
|
|
|
|
}
|
|
|
|
case AsynchronousCrossing(depth, sync) => {
|
2017-10-20 07:19:19 +02:00
|
|
|
def sourceGen = LazyModule(new TLAsyncCrossingSource(sync))
|
2017-10-20 03:51:22 +02:00
|
|
|
def sinkGen = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
|
|
|
val source = if (out) this { sourceGen } else sourceGen
|
|
|
|
val sink = if (out) sinkGen else this { sinkGen }
|
2017-10-23 18:39:01 +02:00
|
|
|
source.node :=? x.node
|
|
|
|
sink.node :=? source.node
|
2017-10-20 03:51:22 +02:00
|
|
|
sink.node
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-20 07:19:19 +02:00
|
|
|
|
2017-10-23 18:39:01 +02:00
|
|
|
def cross(
|
|
|
|
name: Option[String] = None,
|
|
|
|
alreadyRegistered: Boolean = false,
|
|
|
|
overrideCrossing: Option[CoreplexClockCrossing] = None)
|
|
|
|
(x: IntCrossableNode): IntOutwardNode = {
|
2017-10-20 07:19:19 +02:00
|
|
|
val out = x.node.parentsOut.exists(_ eq this) // is the crossing exiting the wrapper?
|
2017-10-23 18:39:01 +02:00
|
|
|
overrideCrossing.getOrElse(crossing) match {
|
2017-10-20 07:19:19 +02:00
|
|
|
case SynchronousCrossing(_) => {
|
|
|
|
def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
|
|
|
def sinkGen = LazyModule(new IntSyncCrossingSink(0))
|
|
|
|
val source = if (out) this { sourceGen } else sourceGen
|
|
|
|
val sink = if (out) sinkGen else this { sinkGen }
|
2017-10-23 18:39:01 +02:00
|
|
|
name.map(_ + "SyncSource").foreach(source.suggestName)
|
|
|
|
name.map(_ + "SyncSink").foreach(sink.suggestName)
|
|
|
|
source.node :=? x.node
|
|
|
|
sink.node :=? source.node
|
2017-10-20 07:19:19 +02:00
|
|
|
sink.node
|
|
|
|
}
|
|
|
|
case RationalCrossing(_) => {
|
|
|
|
def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
|
|
|
def sinkGen = LazyModule(new IntSyncCrossingSink(1))
|
|
|
|
val source = if (out) this { sourceGen } else sourceGen
|
|
|
|
val sink = if (out) sinkGen else this { sinkGen }
|
2017-10-23 18:39:01 +02:00
|
|
|
name.map(_ + "SyncSource").foreach(source.suggestName)
|
|
|
|
name.map(_ + "SyncSink").foreach(sink.suggestName)
|
|
|
|
source.node :=? x.node
|
|
|
|
sink.node :=? source.node
|
2017-10-20 07:19:19 +02:00
|
|
|
sink.node
|
|
|
|
}
|
|
|
|
case AsynchronousCrossing(_, sync) => {
|
|
|
|
def sourceGen = LazyModule(new IntSyncCrossingSource(alreadyRegistered))
|
|
|
|
def sinkGen = LazyModule(new IntSyncCrossingSink(sync))
|
|
|
|
val source = if (out) this { sourceGen } else sourceGen
|
|
|
|
val sink = if (out) sinkGen else this { sinkGen }
|
2017-10-23 18:39:01 +02:00
|
|
|
name.map(_ + "SyncSource").foreach(source.suggestName)
|
|
|
|
name.map(_ + "SyncSink").foreach(sink.suggestName)
|
|
|
|
source.node :=? x.node
|
|
|
|
sink.node :=? source.node
|
2017-10-20 07:19:19 +02:00
|
|
|
sink.node
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-20 03:51:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class CrossingWrapper(val crossing: CoreplexClockCrossing)(implicit p: Parameters) extends SimpleLazyModule with HasCrossingHelper
|