2
2
3
3
package chisel3 .core
4
4
5
- import chisel3 .internal .Builder
6
5
import chisel3 .internal .Builder .pushCommand
7
- import chisel3 .internal .firrtl .{Attach , Connect }
8
- import chisel3 .internal .throwException
6
+ import chisel3 .internal .firrtl .{Connect , DefInvalid }
9
7
import scala .language .experimental .macros
10
8
import chisel3 .internal .sourceinfo ._
11
9
@@ -46,6 +44,8 @@ object BiConnect {
46
44
BiConnectException (s " : Left ( $left) and Right ( $right) have different types. " )
47
45
def AttachAlreadyBulkConnectedException (sourceInfo : SourceInfo ) =
48
46
BiConnectException (sourceInfo.makeMessage(" : Analog previously bulk connected at " + _))
47
+ def DontCareCantBeSink =
48
+ BiConnectException (" : DontCare cannot be a connection sink (LHS)" )
49
49
50
50
51
51
/** This function is what recursively tries to connect a left and right together
@@ -54,7 +54,7 @@ object BiConnect {
54
54
* during the recursive decent and then rethrow them with extra information added.
55
55
* This gives the user a 'path' to where in the connections things went wrong.
56
56
*/
57
- def connect (sourceInfo : SourceInfo , connectCompileOptions : CompileOptions , left : Data , right : Data , context_mod : UserModule ): Unit =
57
+ def connect (sourceInfo : SourceInfo , connectCompileOptions : CompileOptions , left : Data , right : Data , context_mod : UserModule ): Unit = {
58
58
(left, right) match {
59
59
// Handle element case (root case)
60
60
case (left_a : Analog , right_a : Analog ) =>
@@ -69,9 +69,11 @@ object BiConnect {
69
69
// TODO(twigg): Verify the element-level classes are connectable
70
70
}
71
71
// Handle Vec case
72
- case (left_v : Vec [Data @ unchecked], right_v : Vec [Data @ unchecked]) => {
73
- if (left_v.length != right_v.length) { throw MismatchedVecException }
74
- for (idx <- 0 until left_v.length) {
72
+ case (left_v : Vec [Data @ unchecked], right_v : Vec [Data @ unchecked]) => {
73
+ if (left_v.length != right_v.length) {
74
+ throw MismatchedVecException
75
+ }
76
+ for (idx <- 0 until left_v.length) {
75
77
try {
76
78
implicit val compileOptions = connectCompileOptions
77
79
connect(sourceInfo, connectCompileOptions, left_v(idx), right_v(idx), context_mod)
@@ -80,6 +82,28 @@ object BiConnect {
80
82
}
81
83
}
82
84
}
85
+ // Handle Vec connected to DontCare
86
+ case (left_v : Vec [Data @ unchecked], DontCare ) => {
87
+ for (idx <- 0 until left_v.length) {
88
+ try {
89
+ implicit val compileOptions = connectCompileOptions
90
+ connect(sourceInfo, connectCompileOptions, left_v(idx), right, context_mod)
91
+ } catch {
92
+ case BiConnectException (message) => throw BiConnectException (s " ( $idx) $message" )
93
+ }
94
+ }
95
+ }
96
+ // Handle DontCare connected to Vec
97
+ case (DontCare , right_v : Vec [Data @ unchecked]) => {
98
+ for (idx <- 0 until right_v.length) {
99
+ try {
100
+ implicit val compileOptions = connectCompileOptions
101
+ connect(sourceInfo, connectCompileOptions, left, right_v(idx), context_mod)
102
+ } catch {
103
+ case BiConnectException (message) => throw BiConnectException (s " ( $idx) $message" )
104
+ }
105
+ }
106
+ }
83
107
// Handle Records defined in Chisel._ code (change to NotStrict)
84
108
case (left_r : Record , right_r : Record ) => (left_r.compileOptions, right_r.compileOptions) match {
85
109
case (ExplicitCompileOptions .NotStrict , _) =>
@@ -89,9 +113,40 @@ object BiConnect {
89
113
case _ => recordConnect(sourceInfo, connectCompileOptions, left_r, right_r, context_mod)
90
114
}
91
115
116
+ // Handle Records connected to DontCare (change to NotStrict)
117
+ case (left_r : Record , DontCare ) =>
118
+ left_r.compileOptions match {
119
+ case ExplicitCompileOptions .NotStrict =>
120
+ left.bulkConnect(right)(sourceInfo, ExplicitCompileOptions .NotStrict )
121
+ case _ =>
122
+ // For each field in left, descend with right
123
+ for ((field, left_sub) <- left_r.elements) {
124
+ try {
125
+ connect(sourceInfo, connectCompileOptions, left_sub, right, context_mod)
126
+ } catch {
127
+ case BiConnectException (message) => throw BiConnectException (s " . $field$message" )
128
+ }
129
+ }
130
+ }
131
+ case (DontCare , right_r : Record ) =>
132
+ right_r.compileOptions match {
133
+ case ExplicitCompileOptions .NotStrict =>
134
+ left.bulkConnect(right)(sourceInfo, ExplicitCompileOptions .NotStrict )
135
+ case _ =>
136
+ // For each field in left, descend with right
137
+ for ((field, right_sub) <- right_r.elements) {
138
+ try {
139
+ connect(sourceInfo, connectCompileOptions, left, right_sub, context_mod)
140
+ } catch {
141
+ case BiConnectException (message) => throw BiConnectException (s " . $field$message" )
142
+ }
143
+ }
144
+ }
145
+
92
146
// Left and right are different subtypes of Data so fail
93
147
case (left, right) => throw MismatchedException (left.toString, right.toString)
94
148
}
149
+ }
95
150
96
151
// Do connection of two Records
97
152
def recordConnect (sourceInfo : SourceInfo ,
@@ -128,11 +183,25 @@ object BiConnect {
128
183
// These functions (finally) issue the connection operation
129
184
// Issue with right as sink, left as source
130
185
private def issueConnectL2R (left : Element , right : Element )(implicit sourceInfo : SourceInfo ): Unit = {
131
- pushCommand(Connect (sourceInfo, right.lref, left.ref))
186
+ // Source and sink are ambiguous in the case of a Bi/Bulk Connect (<>).
187
+ // If either is a DontCareBinding, just issue a DefInvalid for the other,
188
+ // otherwise, issue a Connect.
189
+ (left.binding, right.binding) match {
190
+ case (lb : DontCareBinding , _) => pushCommand(DefInvalid (sourceInfo, right.lref))
191
+ case (_, rb : DontCareBinding ) => pushCommand(DefInvalid (sourceInfo, left.lref))
192
+ case (_, _) => pushCommand(Connect (sourceInfo, right.lref, left.ref))
193
+ }
132
194
}
133
195
// Issue with left as sink, right as source
134
196
private def issueConnectR2L (left : Element , right : Element )(implicit sourceInfo : SourceInfo ): Unit = {
135
- pushCommand(Connect (sourceInfo, left.lref, right.ref))
197
+ // Source and sink are ambiguous in the case of a Bi/Bulk Connect (<>).
198
+ // If either is a DontCareBinding, just issue a DefInvalid for the other,
199
+ // otherwise, issue a Connect.
200
+ (left.binding, right.binding) match {
201
+ case (lb : DontCareBinding , _) => pushCommand(DefInvalid (sourceInfo, right.lref))
202
+ case (_, rb : DontCareBinding ) => pushCommand(DefInvalid (sourceInfo, left.lref))
203
+ case (_, _) => pushCommand(Connect (sourceInfo, left.lref, right.ref))
204
+ }
136
205
}
137
206
138
207
// This function checks if element-level connection operation allowed.
0 commit comments