1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
// See LICENSE for license details.
package Chisel.internal
import scala.util.DynamicVariable
import scala.collection.mutable.{ArrayBuffer, HashMap}
import Chisel._
import Chisel.internal.firrtl._
private[Chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) {
private var i = 0L
private val names = collection.mutable.HashSet[String]()
private def rename(n: String) = { i += 1; s"${n}_${i}" }
def contains(elem: String): Boolean = {
keywords.contains(elem) || names.contains(elem) ||
parent.map(_ contains elem).getOrElse(false)
}
def name(elem: String): String = {
if (this contains elem) {
name(rename(elem))
} else {
names += elem
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)
}
}
}
|