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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
// SPDX-License-Identifier: Apache-2.0
package chisel3
import scala.util.Try
import scala.annotation.nowarn
import chisel3.experimental.BaseModule
import chisel3.internal._
import chisel3.internal.BaseModule.ModuleClone
import chisel3.internal.Builder._
import chisel3.internal.firrtl._
import _root_.firrtl.annotations.{IsModule, ModuleTarget}
import scala.collection.immutable.VectorBuilder
/** Abstract base class for Modules that contain Chisel RTL.
* This abstract base class is a user-defined module which does not include implicit clock and reset and supports
* multiple IO() declarations.
*/
@nowarn("msg=class Port") // delete when Port becomes private
abstract class RawModule extends BaseModule {
//
// RTL construction internals
//
// Perhaps this should be an ArrayBuffer (or ArrayBuilder), but DefModule is public and has Seq[Command]
// so our best option is to share a single Seq datastructure with that
private val _commands = new VectorBuilder[Command]()
private[chisel3] def addCommand(c: Command) = {
require(!_closed, "Can't write to module after module close")
_commands += c
}
protected def getCommands: Seq[Command] = {
require(_closed, "Can't get commands before module close")
// Unsafe cast but we know that any RawModule uses a DefModule
// _component is defined as a var on BaseModule and we cannot override mutable vars
_component.get.asInstanceOf[DefModule].commands
}
//
// Other Internal Functions
//
private var _firrtlPorts: Option[Seq[firrtl.Port]] = None
@deprecated("Use DataMirror.modulePorts instead. this API will be removed in Chisel 3.6", "Chisel 3.5")
lazy val getPorts: Seq[Port] = _firrtlPorts.get
// This could be factored into a common utility
private def canBeNamed(id: HasId): Boolean = id match {
case d: Data =>
d.binding match {
case Some(_: ConstrainedBinding) => true
case _ => false
}
case b: BaseModule => true
case m: MemBase[_] => true
// These names don't affect hardware
// case _: VerificationStatement => false
// While the above should be comprehensive, since this is used in warning we want to be careful
// to never accidentally have a match error
case _ => false
}
private[chisel3] override def generateComponent(): Option[Component] = {
require(!_closed, "Can't generate module more than once")
_closed = true
val names = nameIds(classOf[RawModule])
// Ports get first naming priority, since they are part of a Module's IO spec
namePorts(names)
// Then everything else gets named
val warnReflectiveNaming = Builder.warnReflectiveNaming
for ((node, name) <- names) {
node match {
case d: HasId if warnReflectiveNaming && canBeNamed(d) =>
val result = d._suggestNameCheck(name)
result match {
case None => // All good, no warning
case Some((oldName, oldPrefix)) =>
val prevName = buildName(oldName, oldPrefix.reverse)
val newName = buildName(name, Nil)
val msg = s"[module ${this.name}] '$prevName' is renamed by reflection to '$newName'. " +
s"Chisel 3.6 removes reflective naming so the name will remain '$prevName'."
Builder.warningNoLoc(msg)
}
// Note that unnamable things end up here (eg. literals), this is supporting backwards
// compatibility
case _ => node.suggestName(name)
}
}
// All suggestions are in, force names to every node.
for (id <- getIds) {
id match {
case id: ModuleClone[_] => id.setRefAndPortsRef(_namespace) // special handling
case id: BaseModule => id.forceName(default = id.desiredName, _namespace)
case id: MemBase[_] => id.forceName(default = "MEM", _namespace)
// removed till macros are fixed
// case id: assert.Assert => id.forceName(default = "assert", _namespace)
// case id: assume.Assume => id.forceName(default = "assume", _namespace)
// case id: cover.Cover => id.forceName(default = "cover", _namespace)
case id: printf.Printf => id.forceName(default = "printf", _namespace)
case id: Data =>
if (id.isSynthesizable) {
id.topBinding match {
case OpBinding(_, _) =>
id.forceName(default = "_T", _namespace)
case MemoryPortBinding(_, _) =>
id.forceName(default = "MPORT", _namespace)
case PortBinding(_) =>
id.forceName(default = "PORT", _namespace)
case RegBinding(_, _) =>
id.forceName(default = "REG", _namespace)
case WireBinding(_, _) =>
id.forceName(default = "_WIRE", _namespace)
case _ => // don't name literals
}
} // else, don't name unbound types
}
id._onModuleClose
}
closeUnboundIds(names)
val firrtlPorts = getModulePorts.map { port =>
// Special case Vec to make FIRRTL emit the direction of its
// element.
// Just taking the Vec's specifiedDirection is a bug in cases like
// Vec(Flipped()), since the Vec's specifiedDirection is
// Unspecified.
val direction = port match {
case v: Vec[_] =>
v.specifiedDirection match {
case SpecifiedDirection.Input => SpecifiedDirection.Input
case SpecifiedDirection.Output => SpecifiedDirection.Output
case SpecifiedDirection.Flip => SpecifiedDirection.flip(v.sample_element.specifiedDirection)
case SpecifiedDirection.Unspecified => v.sample_element.specifiedDirection
}
case _ => port.specifiedDirection
}
Port(port, direction)
}
_firrtlPorts = Some(firrtlPorts)
val component = DefModule(this, name, firrtlPorts, _commands.result())
_component = Some(component)
_component
}
private[chisel3] def initializeInParent(): Unit = {}
}
trait RequireAsyncReset extends Module {
override private[chisel3] def mkReset: AsyncReset = AsyncReset()
}
trait RequireSyncReset extends Module {
override private[chisel3] def mkReset: Bool = Bool()
}
/** Mix with a [[RawModule]] to automatically connect DontCare to the module's ports, wires, and children instance IOs. */
package object internal {
import scala.annotation.implicitNotFound
@implicitNotFound("You are trying to access a macro-only API. Please use the @public annotation instead.")
trait MacroGenerated
/** Marker trait for modules that are not true modules */
private[chisel3] trait PseudoModule extends BaseModule
/* Check if a String name is a temporary name */
def isTemp(name: String): Boolean = name.nonEmpty && name.head == '_'
/** Creates a name String from a prefix and a seed
* @param prefix The prefix associated with the seed (must be in correct order, *not* reversed)
* @param seed The seed for computing the name (if available)
*/
def buildName(seed: String, prefix: Prefix): String = {
// Don't bother copying the String if there's no prefix
if (prefix.isEmpty) {
seed
} else {
// Using Java's String builder to micro-optimize appending a String excluding 1st character
// for temporaries
val builder = new java.lang.StringBuilder()
// Starting with _ is the indicator of a temporary
val temp = isTemp(seed)
// Make sure the final result is also a temporary if this is a temporary
if (temp) {
builder.append('_')
}
prefix.foreach { p =>
builder.append(p)
builder.append('_')
}
if (temp) {
// We've moved the leading _ to the front, drop it here
builder.append(seed, 1, seed.length)
} else {
builder.append(seed)
}
builder.toString
}
}
}
|