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
|
// SPDX-License-Identifier: Apache-2.0
package chisel3.experimental.hierarchy
import scala.language.experimental.macros
import chisel3._
import scala.collection.mutable.HashMap
import chisel3.internal.{Builder, DynamicContext}
import chisel3.internal.sourceinfo.{DefinitionTransform, DefinitionWrapTransform, SourceInfo}
import chisel3.experimental.BaseModule
import chisel3.internal.BaseModule.IsClone
import firrtl.annotations.{IsModule, ModuleTarget}
import firrtl.annotations.{IsModule, ModuleTarget, NoTargetAnnotation}
/** User-facing Definition type.
* Represents a definition of an object of type [[A]] which are marked as @instantiable
* Can be created using Definition.apply method.
*
* These definitions are then used to create multiple [[Instance]]s.
*
* @param underlying The internal representation of the definition, which may be either be directly the object, or a clone of an object
*/
final case class Definition[+A] private[chisel3] (private[chisel3] underlying: Underlying[A])
extends IsLookupable
with SealedHierarchy[A] {
/** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!!
* Instead, mark the field you are accessing with [[@public]]
*
* Given a selector function (that) which selects a member from the original, return the
* corresponding member from the instance.
*
* Our @instantiable and @public macros generate the calls to this apply method
*
* By calling this function, we summon the proper Lookupable typeclass from our implicit scope.
*
* @param that a user-specified lookup function
* @param lookup typeclass which contains the correct lookup function, based on the types of A and B
* @param macroGenerated a value created in the macro, to make it harder for users to use this API
*/
def _lookup[B, C](
that: A => B
)(
implicit lookup: Lookupable[B],
macroGenerated: chisel3.internal.MacroGenerated
): lookup.C = {
lookup.definitionLookup(that, this)
}
/** @return the context of any Data's return from inside the instance */
private[chisel3] def getInnerDataContext: Option[BaseModule] = proto match {
case value: BaseModule =>
val newChild = Module.do_pseudo_apply(new internal.BaseModule.DefinitionClone(value))(
chisel3.internal.sourceinfo.UnlocatableSourceInfo,
chisel3.ExplicitCompileOptions.Strict
)
newChild._circuit = value._circuit.orElse(Some(value))
newChild._parent = None
Some(newChild)
case value: IsInstantiable => None
}
override def toDefinition: Definition[A] = this
override def toInstance: Instance[A] = new Instance(underlying)
}
/** Factory methods for constructing [[Definition]]s */
object Definition extends SourceInfoDoc {
implicit class DefinitionBaseModuleExtensions[T <: BaseModule](d: Definition[T]) {
/** If this is an instance of a Module, returns the toTarget of this instance
* @return target of this instance
*/
def toTarget: ModuleTarget = d.proto.toTarget
/** If this is an instance of a Module, returns the toAbsoluteTarget of this instance
* @return absoluteTarget of this instance
*/
def toAbsoluteTarget: IsModule = d.proto.toAbsoluteTarget
}
/** A construction method to build a Definition of a Module
*
* @param proto the Module being defined
*
* @return the input module as a Definition
*/
def apply[T <: BaseModule with IsInstantiable](proto: => T): Definition[T] = macro DefinitionTransform.apply[T]
/** A construction method to build a Definition of a Module
*
* @param bc the Module being defined
*
* @return the input module as a Definition
*/
def do_apply[T <: BaseModule with IsInstantiable](
proto: => T
)(
implicit sourceInfo: SourceInfo,
compileOptions: CompileOptions
): Definition[T] = {
val dynamicContext = {
val context = Builder.captureContext()
new DynamicContext(Nil, context.throwOnFirstError, context.warnReflectiveNaming, context.warningsAsErrors)
}
Builder.globalNamespace.copyTo(dynamicContext.globalNamespace)
dynamicContext.inDefinition = true
val (ir, module) = Builder.build(Module(proto), dynamicContext, false)
Builder.components ++= ir.components
Builder.annotations ++= ir.annotations
module._circuit = Builder.currentModule
dynamicContext.globalNamespace.copyTo(Builder.globalNamespace)
new Definition(Proto(module))
}
}
/** Stores a [[Definition]] that is imported so that its Instances can be
* compiled separately.
*/
case class ImportDefinitionAnnotation[T <: BaseModule with IsInstantiable](
definition: Definition[T],
overrideDefName: Option[String] = None)
extends NoTargetAnnotation
|