diff options
| author | Jim Lawson | 2016-06-20 11:08:46 -0700 |
|---|---|---|
| committer | Jim Lawson | 2016-06-20 11:08:46 -0700 |
| commit | d408d73a171535bd7c2ba9d0037c194022b8a62f (patch) | |
| tree | 81885a99ec56e89532bc3fa338f22b163dcc4d1f /chiselFrontend/src/main/scala/chisel3/internal/Builder.scala | |
| parent | b5a534914795d9d17f4dfe623525f1b804e4c60f (diff) | |
Rename chisel3 package.
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/internal/Builder.scala')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/Builder.scala | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala new file mode 100644 index 00000000..01628105 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -0,0 +1,129 @@ +// See LICENSE for license details. + +package chisel.internal + +import scala.util.DynamicVariable +import scala.collection.mutable.{ArrayBuffer, HashMap} + +import chisel._ +import core._ +import firrtl._ + +private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) { + private val names = collection.mutable.HashMap[String, Long]() + for (keyword <- keywords) + names(keyword) = 1 + + private def rename(n: String): String = { + val index = names.getOrElse(n, 1L) + val tryName = s"${n}_${index}" + names(n) = index + 1 + if (this contains tryName) rename(n) else tryName + } + + def contains(elem: String): Boolean = { + names.contains(elem) || parent.map(_ contains elem).getOrElse(false) + } + + def name(elem: String): String = { + if (this contains elem) { + name(rename(elem)) + } else { + names(elem) = 1 + elem + } + } + + def child(kws: Set[String]): Namespace = new Namespace(Some(this), kws) + def child: Namespace = child(Set()) +} + +private[chisel] class IdGen { + private var counter = -1L + def next: Long = { + counter += 1 + counter + } +} + +private[chisel] trait HasId { + private[chisel] def _onModuleClose {} // scalastyle:ignore method.name + private[chisel] val _parent = Builder.dynamicContext.currentModule + _parent.foreach(_.addId(this)) + + private[chisel] val _id = Builder.idGen.next + override def hashCode: Int = _id.toInt + override def equals(that: Any): Boolean = that match { + case x: HasId => _id == x._id + case _ => false + } + + // Facilities for 'suggesting' a name to this. + // Post-name hooks called to carry the suggestion to other candidates as needed + private var suggested_name: Option[String] = None + private val postname_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + // Only takes the first suggestion! + def suggestName(name: =>String): this.type = { + if(suggested_name.isEmpty) suggested_name = Some(name) + for(hook <- postname_hooks) { hook(name) } + this + } + private[chisel] def addPostnameHook(hook: String=>Unit): Unit = postname_hooks += hook + + // Uses a namespace to convert suggestion into a true name + // Will not do any naming if the reference already assigned. + // (e.g. tried to suggest a name to part of a Bundle) + private[chisel] def forceName(default: =>String, namespace: Namespace): Unit = + if(_ref.isEmpty) { + val candidate_name = suggested_name.getOrElse(default) + val available_name = namespace.name(candidate_name) + setRef(Ref(available_name)) + } + + private var _ref: Option[Arg] = None + private[chisel] def setRef(imm: Arg): Unit = _ref = Some(imm) + private[chisel] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) + private[chisel] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) + private[chisel] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) + private[chisel] def getRef: Arg = _ref.get +} + +private[chisel] class DynamicContext { + val idGen = new IdGen + val globalNamespace = new Namespace(None, Set()) + val components = ArrayBuffer[Component]() + var currentModule: Option[Module] = None + val errors = new ErrorLog +} + +private[chisel] object Builder { + // All global mutable state must be referenced via dynamicContextVar!! + private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None) + + def dynamicContext: DynamicContext = + dynamicContextVar.value getOrElse (new DynamicContext) + def idGen: IdGen = dynamicContext.idGen + def globalNamespace: Namespace = dynamicContext.globalNamespace + def components: ArrayBuffer[Component] = dynamicContext.components + + def pushCommand[T <: Command](c: T): T = { + dynamicContext.currentModule.foreach(_._commands += c) + c + } + def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id + + def errors: ErrorLog = dynamicContext.errors + def error(m: => String): Unit = errors.error(m) + + def build[T <: Module](f: => T): Circuit = { + dynamicContextVar.withValue(Some(new DynamicContext)) { + errors.info("Elaborating design...") + val mod = f + mod.forceName(mod.name, globalNamespace) + errors.checkpoint() + errors.info("Done elaborating.") + + Circuit(components.last.name, components) + } + } +} |
