2016-08-19 20:08:35 +02:00
|
|
|
// See LICENSE for license details.
|
|
|
|
|
|
|
|
package uncore.tilelink2
|
|
|
|
|
|
|
|
import Chisel._
|
2016-09-08 23:41:08 +02:00
|
|
|
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo}
|
2016-08-19 20:08:35 +02:00
|
|
|
|
2016-08-31 19:25:46 +02:00
|
|
|
abstract class LazyModule
|
2016-08-19 20:08:35 +02:00
|
|
|
{
|
2016-09-02 20:13:43 +02:00
|
|
|
protected[tilelink2] var bindings = List[() => Unit]()
|
|
|
|
protected[tilelink2] var children = List[LazyModule]()
|
2016-09-08 23:41:08 +02:00
|
|
|
protected[tilelink2] var nodes = List[RootNode]()
|
2016-09-02 20:13:43 +02:00
|
|
|
protected[tilelink2] var info: SourceInfo = UnlocatableSourceInfo
|
|
|
|
protected[tilelink2] val parent = LazyModule.stack.headOption
|
|
|
|
|
|
|
|
LazyModule.stack = this :: LazyModule.stack
|
|
|
|
parent.foreach(p => p.children = this :: p.children)
|
2016-08-19 20:08:35 +02:00
|
|
|
|
2016-08-31 19:43:34 +02:00
|
|
|
// Use as: connect(source -> sink, source2 -> sink2, ...)
|
2016-09-08 20:30:04 +02:00
|
|
|
def connect[PO, PI, EO, EI, B <: Data](edges: (BaseNode[PO, PI, EO, EI, B], BaseNode[PO, PI, EO, EI, B])*)(implicit sourceInfo: SourceInfo) = {
|
2016-09-09 08:06:59 +02:00
|
|
|
edges.foreach { case (source, sink) => sink := source }
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
2016-09-08 23:41:08 +02:00
|
|
|
def name = getClass.getName.split('.').last
|
2016-09-09 06:11:31 +02:00
|
|
|
def line = sourceLine(info)
|
2016-09-08 23:41:08 +02:00
|
|
|
|
2016-08-31 19:25:46 +02:00
|
|
|
def module: LazyModuleImp
|
2016-08-19 20:08:35 +02:00
|
|
|
|
|
|
|
protected[tilelink2] def instantiate() = {
|
2016-09-02 20:13:43 +02:00
|
|
|
children.reverse.foreach { c =>
|
|
|
|
// !!! fix chisel3 so we can pass the desired sourceInfo
|
|
|
|
// implicit val sourceInfo = c.module.outer.info
|
|
|
|
Module(c.module)
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
2016-09-02 20:13:43 +02:00
|
|
|
bindings.reverse.foreach { f => f () }
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
2016-09-02 20:13:43 +02:00
|
|
|
}
|
2016-09-01 01:45:18 +02:00
|
|
|
|
2016-09-02 20:13:43 +02:00
|
|
|
object LazyModule
|
|
|
|
{
|
|
|
|
protected[tilelink2] var stack = List[LazyModule]()
|
|
|
|
|
|
|
|
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
|
2016-09-09 06:11:31 +02:00
|
|
|
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)}")
|
2016-09-02 20:13:43 +02:00
|
|
|
stack = stack.tail
|
|
|
|
bc.info = sourceInfo
|
|
|
|
bc
|
|
|
|
}
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|
|
|
|
|
2016-09-07 08:46:44 +02:00
|
|
|
abstract class LazyModuleImp(outer: LazyModule) extends Module
|
2016-08-30 02:53:31 +02:00
|
|
|
{
|
2016-09-02 20:13:43 +02:00
|
|
|
// .module had better not be accessed while LazyModules are still being built!
|
2016-09-09 06:11:31 +02:00
|
|
|
require (LazyModule.stack.isEmpty, s"${outer.name}.module was constructed before LazyModule() was run on ${LazyModule.stack.head.name}")
|
2016-09-02 20:13:43 +02:00
|
|
|
|
2016-09-08 23:41:08 +02:00
|
|
|
override def desiredName = outer.name
|
2016-08-31 19:25:46 +02:00
|
|
|
outer.instantiate()
|
2016-08-19 20:08:35 +02:00
|
|
|
}
|