2016-09-08 20:30:35 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
|
|
|
package uncore.tilelink2
|
|
|
|
|
|
|
|
import Chisel._
|
2016-10-04 00:17:36 +02:00
|
|
|
import chisel3.internal.sourceinfo.SourceInfo
|
|
|
|
import diplomacy._
|
2016-09-08 20:30:35 +02:00
|
|
|
import scala.collection.mutable.ListBuffer
|
|
|
|
import scala.math.max
|
|
|
|
|
2016-09-09 03:51:43 +02:00
|
|
|
// A potentially empty half-open range; [start, end)
|
|
|
|
case class IntRange(start: Int, end: Int)
|
|
|
|
{
|
|
|
|
require (start >= 0)
|
|
|
|
require (start <= end)
|
|
|
|
def size = end - start
|
|
|
|
def overlaps(x: IntRange) = start < x.end && x.start < end
|
|
|
|
def offset(x: Int) = IntRange(x+start, x+end)
|
|
|
|
}
|
|
|
|
object IntRange
|
|
|
|
{
|
|
|
|
implicit def apply(end: Int): IntRange = apply(0, end)
|
|
|
|
}
|
|
|
|
|
2016-09-17 22:56:35 +02:00
|
|
|
case class IntSourceParameters(
|
|
|
|
range: IntRange,
|
2016-09-29 23:34:52 +02:00
|
|
|
nodePath: Seq[BaseNode] = Seq())
|
2016-09-17 22:56:35 +02:00
|
|
|
{
|
|
|
|
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
|
|
|
|
}
|
|
|
|
|
|
|
|
case class IntSinkParameters(
|
2016-09-29 23:34:52 +02:00
|
|
|
nodePath: Seq[BaseNode] = Seq())
|
2016-09-17 22:56:35 +02:00
|
|
|
{
|
|
|
|
val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected")
|
|
|
|
}
|
2016-09-08 20:30:35 +02:00
|
|
|
|
|
|
|
case class IntSourcePortParameters(sources: Seq[IntSourceParameters])
|
|
|
|
{
|
2016-09-09 03:51:43 +02:00
|
|
|
val num = sources.map(_.range.size).sum
|
|
|
|
// The interrupts mapping must not overlap
|
|
|
|
sources.map(_.range).combinations(2).foreach { case Seq(a, b) => require (!a.overlaps(b)) }
|
|
|
|
// The interrupts must perfectly cover the range
|
|
|
|
require (sources.map(_.range.end).max == num)
|
2016-09-08 20:30:35 +02:00
|
|
|
}
|
2016-09-17 22:56:35 +02:00
|
|
|
|
|
|
|
case class IntSinkPortParameters(sinks: Seq[IntSinkParameters])
|
|
|
|
|
2016-09-08 20:30:35 +02:00
|
|
|
case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters)
|
|
|
|
|
|
|
|
object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, IntEdge, Vec[Bool]]
|
|
|
|
{
|
2016-09-29 23:30:19 +02:00
|
|
|
def edgeO(pd: IntSourcePortParameters, pu: IntSinkPortParameters): IntEdge = IntEdge(pd, pu)
|
|
|
|
def edgeI(pd: IntSourcePortParameters, pu: IntSinkPortParameters): IntEdge = IntEdge(pd, pu)
|
2016-09-08 20:30:35 +02:00
|
|
|
def bundleO(eo: Seq[IntEdge]): Vec[Vec[Bool]] = {
|
|
|
|
if (eo.isEmpty) Vec(0, Vec(0, Bool())) else
|
|
|
|
Vec(eo.size, Vec(eo.map(_.source.num).max, Bool()))
|
|
|
|
}
|
|
|
|
def bundleI(ei: Seq[IntEdge]): Vec[Vec[Bool]] = {
|
|
|
|
require (!ei.isEmpty)
|
2016-10-26 02:47:32 +02:00
|
|
|
Vec(ei.size, Vec(ei.map(_.source.num).max, Bool()))
|
2016-09-08 20:30:35 +02:00
|
|
|
}
|
|
|
|
|
2016-10-03 23:07:28 +02:00
|
|
|
def colour = "#0000ff" // blue
|
2016-10-28 23:00:55 +02:00
|
|
|
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
|
|
|
|
|
2016-09-29 23:30:19 +02:00
|
|
|
def connect(bo: => Vec[Bool], bi: => Vec[Bool], ei: => IntEdge)(implicit sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
2016-09-21 21:08:05 +02:00
|
|
|
(None, () => {
|
|
|
|
// Cannot use bulk connect, because the widths could differ
|
|
|
|
(bo zip bi) foreach { case (o, i) => i := o }
|
|
|
|
})
|
2016-09-08 20:30:35 +02:00
|
|
|
}
|
2016-09-17 22:56:35 +02:00
|
|
|
|
2016-09-29 23:30:19 +02:00
|
|
|
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) })
|
|
|
|
override def mixI(pu: IntSinkPortParameters, node: InwardNode[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]]): IntSinkPortParameters =
|
|
|
|
pu.copy(sinks = pu.sinks.map { s => s.copy (nodePath = node +: s.nodePath) })
|
2016-09-08 20:30:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case class IntIdentityNode() extends IdentityNode(IntImp)
|
2016-09-17 22:56:35 +02:00
|
|
|
case class IntSourceNode(num: Int) extends SourceNode(IntImp)(
|
|
|
|
IntSourcePortParameters(Seq(IntSourceParameters(num))), (if (num == 0) 0 else 1) to 1)
|
|
|
|
case class IntSinkNode() extends SinkNode(IntImp)(
|
|
|
|
IntSinkPortParameters(Seq(IntSinkParameters())))
|
2016-09-08 20:30:35 +02:00
|
|
|
|
|
|
|
case class IntAdapterNode(
|
|
|
|
sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters,
|
|
|
|
sinkFn: Seq[IntSinkPortParameters] => IntSinkPortParameters,
|
|
|
|
numSourcePorts: Range.Inclusive = 1 to 1,
|
|
|
|
numSinkPorts: Range.Inclusive = 1 to 1)
|
|
|
|
extends InteriorNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts)
|
|
|
|
|
2016-10-29 06:20:49 +02:00
|
|
|
case class IntOutputNode() extends OutputNode(IntImp)
|
|
|
|
case class IntInputNode() extends InputNode(IntImp)
|
|
|
|
|
|
|
|
case class IntBlindOutputNode() extends BlindOutputNode(IntImp)(IntSinkPortParameters(Seq(IntSinkParameters())))
|
|
|
|
case class IntBlindInputNode(num: Int) extends BlindInputNode(IntImp)(IntSourcePortParameters(Seq(IntSourceParameters(num))))
|
|
|
|
|
|
|
|
case class IntInternalOutputNode() extends InternalOutputNode(IntImp)(IntSinkPortParameters(Seq(IntSinkParameters())))
|
|
|
|
case class IntInternalInputNode(num: Int) extends InternalInputNode(IntImp)(IntSourcePortParameters(Seq(IntSourceParameters(num))))
|
|
|
|
|
2016-09-08 20:30:35 +02:00
|
|
|
class IntXbar extends LazyModule
|
|
|
|
{
|
|
|
|
val intnode = IntAdapterNode(
|
|
|
|
numSourcePorts = 1 to 1, // does it make sense to have more than one interrupt sink?
|
2016-10-29 06:20:49 +02:00
|
|
|
numSinkPorts = 0 to 128,
|
2016-09-17 22:56:35 +02:00
|
|
|
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) },
|
2016-09-09 03:51:43 +02:00
|
|
|
sourceFn = { seq =>
|
|
|
|
IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map {
|
|
|
|
case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o)))
|
|
|
|
}.flatten)
|
|
|
|
})
|
2016-09-08 20:30:35 +02:00
|
|
|
|
|
|
|
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 }
|
|
|
|
}
|
|
|
|
}
|
2016-10-29 06:20:49 +02:00
|
|
|
|
|
|
|
class IntXing extends LazyModule
|
|
|
|
{
|
|
|
|
val intnode = IntIdentityNode()
|
|
|
|
|
|
|
|
lazy val module = new LazyModuleImp(this) {
|
|
|
|
val io = new Bundle {
|
|
|
|
val in = intnode.bundleIn
|
|
|
|
val out = intnode.bundleOut
|
|
|
|
}
|
|
|
|
|
|
|
|
io.out := RegNext(RegNext(RegNext(io.in)))
|
|
|
|
}
|
|
|
|
}
|