Skip to content

Commit 673aad2

Browse files
committed
Merge branch 'master' into release
2 parents 51b4acd + c313e13 commit 673aad2

20 files changed

+392
-39
lines changed

build.sbt

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def javacOptionsVersion(scalaVersion: String): Seq[String] = {
3232

3333
lazy val commonSettings = Seq (
3434
organization := "edu.berkeley.cs",
35-
version := "3.0-SNAPSHOT_2017-10-06",
35+
version := "3.0.0-RC1",
3636
git.remoteRepo := "[email protected]:freechipsproject/chisel3.git",
3737
autoAPIMappings := true,
3838
scalaVersion := "2.11.11",
@@ -92,7 +92,7 @@ lazy val publishSettings = Seq (
9292
}
9393
)
9494

95-
val defaultVersions = Map("firrtl" -> "1.0-SNAPSHOT_2017-10-06")
95+
val defaultVersions = Map("firrtl" -> "1.0.0-RC1")
9696

9797
lazy val chiselSettings = Seq (
9898
name := "chisel3",

chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala

+9-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,15 @@ sealed abstract class Aggregate extends Data {
6767
def getElements: Seq[Data]
6868

6969
private[chisel3] def width: Width = getElements.map(_.width).foldLeft(0.W)(_ + _)
70-
private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
71-
pushCommand(BulkConnect(sourceInfo, this.lref, that.lref))
70+
private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
71+
// If the source is a DontCare, generate a DefInvalid for the sink,
72+
// otherwise, issue a Connect.
73+
if (that == DontCare) {
74+
pushCommand(DefInvalid(sourceInfo, this.lref))
75+
} else {
76+
pushCommand(BulkConnect(sourceInfo, this.lref, that.lref))
77+
}
78+
}
7279

7380
override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = {
7481
SeqUtils.do_asUInt(flatten.map(_.asUInt()))

chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala

+78-9
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
package chisel3.core
44

5-
import chisel3.internal.Builder
65
import chisel3.internal.Builder.pushCommand
7-
import chisel3.internal.firrtl.{Attach, Connect}
8-
import chisel3.internal.throwException
6+
import chisel3.internal.firrtl.{Connect, DefInvalid}
97
import scala.language.experimental.macros
108
import chisel3.internal.sourceinfo._
119

@@ -46,6 +44,8 @@ object BiConnect {
4644
BiConnectException(s": Left ($left) and Right ($right) have different types.")
4745
def AttachAlreadyBulkConnectedException(sourceInfo: SourceInfo) =
4846
BiConnectException(sourceInfo.makeMessage(": Analog previously bulk connected at " + _))
47+
def DontCareCantBeSink =
48+
BiConnectException(": DontCare cannot be a connection sink (LHS)")
4949

5050

5151
/** This function is what recursively tries to connect a left and right together
@@ -54,7 +54,7 @@ object BiConnect {
5454
* during the recursive decent and then rethrow them with extra information added.
5555
* This gives the user a 'path' to where in the connections things went wrong.
5656
*/
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 = {
5858
(left, right) match {
5959
// Handle element case (root case)
6060
case (left_a: Analog, right_a: Analog) =>
@@ -69,9 +69,11 @@ object BiConnect {
6969
// TODO(twigg): Verify the element-level classes are connectable
7070
}
7171
// 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) {
7577
try {
7678
implicit val compileOptions = connectCompileOptions
7779
connect(sourceInfo, connectCompileOptions, left_v(idx), right_v(idx), context_mod)
@@ -80,6 +82,28 @@ object BiConnect {
8082
}
8183
}
8284
}
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+
}
83107
// Handle Records defined in Chisel._ code (change to NotStrict)
84108
case (left_r: Record, right_r: Record) => (left_r.compileOptions, right_r.compileOptions) match {
85109
case (ExplicitCompileOptions.NotStrict, _) =>
@@ -89,9 +113,40 @@ object BiConnect {
89113
case _ => recordConnect(sourceInfo, connectCompileOptions, left_r, right_r, context_mod)
90114
}
91115

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+
92146
// Left and right are different subtypes of Data so fail
93147
case (left, right) => throw MismatchedException(left.toString, right.toString)
94148
}
149+
}
95150

96151
// Do connection of two Records
97152
def recordConnect(sourceInfo: SourceInfo,
@@ -128,11 +183,25 @@ object BiConnect {
128183
// These functions (finally) issue the connection operation
129184
// Issue with right as sink, left as source
130185
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+
}
132194
}
133195
// Issue with left as sink, right as source
134196
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+
}
136205
}
137206

138207
// This function checks if element-level connection operation allowed.

chiselFrontend/src/main/scala/chisel3/core/Binding.scala

+3
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,6 @@ case class WireBinding(enclosure: UserModule) extends ConstrainedBinding
104104
case class ChildBinding(parent: Data) extends Binding {
105105
def location = parent.binding.location
106106
}
107+
// A DontCare element has a specific Binding, somewhat like a literal.
108+
// It is a source (RHS). It may only be connected/applied to sinks.
109+
case class DontCareBinding() extends UnconstrainedBinding

chiselFrontend/src/main/scala/chisel3/core/Bits.scala

+10-3
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,15 @@ abstract class Element(private[chisel3] val width: Width) extends Data {
3232
def widthKnown: Boolean = width.known
3333
def name: String = getRef.name
3434

35-
private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
36-
pushCommand(Connect(sourceInfo, this.lref, that.ref))
35+
private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
36+
// If the source is a DontCare, generate a DefInvalid for the sink,
37+
// otherwise, issue a Connect.
38+
if (that == DontCare) {
39+
pushCommand(DefInvalid(sourceInfo, this.lref))
40+
} else {
41+
pushCommand(Connect(sourceInfo, this.lref, that.ref))
42+
}
43+
}
3744
}
3845

3946
/** Exists to unify common interfaces of [[Bits]] and [[Reset]]
@@ -799,7 +806,7 @@ sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint, lit
799806
new FixedPoint(w, binaryPoint).asInstanceOf[this.type]
800807

801808
override def connect (that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match {
802-
case _: FixedPoint => super.connect(that)
809+
case _: FixedPoint|DontCare => super.connect(that)
803810
case _ => this badConnect that
804811
}
805812

chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala

+9-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ trait CompileOptions {
1818
val dontAssumeDirectionality: Boolean
1919
// Check that referenced Data have actually been declared.
2020
val checkSynthesizable: Boolean
21+
// Require explicit assignment of DontCare to generate "x is invalid"
22+
val explicitInvalidate: Boolean
2123
}
2224

2325
object CompileOptions {
@@ -44,7 +46,9 @@ object ExplicitCompileOptions {
4446
// If connection directionality is not explicit, do not use heuristics to attempt to determine it.
4547
val dontAssumeDirectionality: Boolean,
4648
// Check that referenced Data have actually been declared.
47-
val checkSynthesizable: Boolean
49+
val checkSynthesizable: Boolean,
50+
// Require an explicit DontCare assignment to generate a firrtl DefInvalid
51+
val explicitInvalidate: Boolean
4852
) extends CompileOptions
4953

5054
// Collection of "not strict" connection compile options.
@@ -55,7 +59,8 @@ object ExplicitCompileOptions {
5559
declaredTypeMustBeUnbound = false,
5660
dontTryConnectionsSwapped = false,
5761
dontAssumeDirectionality = false,
58-
checkSynthesizable = false
62+
checkSynthesizable = false,
63+
explicitInvalidate = false
5964
)
6065

6166
// Collection of "strict" connection compile options, preferred for new code.
@@ -65,6 +70,7 @@ object ExplicitCompileOptions {
6570
declaredTypeMustBeUnbound = true,
6671
dontTryConnectionsSwapped = true,
6772
dontAssumeDirectionality = true,
68-
checkSynthesizable = true
73+
checkSynthesizable = true,
74+
explicitInvalidate = true
6975
)
7076
}

chiselFrontend/src/main/scala/chisel3/core/Data.scala

+33-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import chisel3.internal._
88
import chisel3.internal.Builder.{pushCommand, pushOp}
99
import chisel3.internal.firrtl._
1010
import chisel3.internal.sourceinfo._
11+
import chisel3.core.BiConnect.DontCareCantBeSink
1112

1213
/** User-specified directions.
1314
*/
@@ -33,8 +34,8 @@ object SpecifiedDirection {
3334
case Input => Output
3435
}
3536

36-
/** Returns the effective UserDirection of this node given the parent's effective UserDirection
37-
* and the user-specified UserDirection of this node.
37+
/** Returns the effective SpecifiedDirection of this node given the parent's effective SpecifiedDirection
38+
* and the user-specified SpecifiedDirection of this node.
3839
*/
3940
def fromParent(parentDirection: SpecifiedDirection, thisDirection: SpecifiedDirection) =
4041
(parentDirection, thisDirection) match {
@@ -222,7 +223,7 @@ abstract class Data extends HasId {
222223
_specifiedDirection = direction
223224
}
224225

225-
/** This overwrites a relative UserDirection with an explicit one, and is used to implement
226+
/** This overwrites a relative SpecifiedDirection with an explicit one, and is used to implement
226227
* the compatibility layer where, at the elements, Flip is Input and unspecified is Output.
227228
* DO NOT USE OUTSIDE THIS PURPOSE. THIS OPERATION IS DANGEROUS!
228229
*/
@@ -311,6 +312,8 @@ abstract class Data extends HasId {
311312
requireIsHardware(that, s"data to be bulk-connected")
312313
(this.topBinding, that.topBinding) match {
313314
case (_: ReadOnlyBinding, _: ReadOnlyBinding) => throwException(s"Both $this and $that are read-only")
315+
// DontCare cannot be a sink (LHS)
316+
case (_: DontCareBinding, _) => throw DontCareCantBeSink
314317
case _ => // fine
315318
}
316319
try {
@@ -425,7 +428,9 @@ trait WireFactory {
425428
x.bind(WireBinding(Builder.forcedUserModule))
426429

427430
pushCommand(DefWire(sourceInfo, x))
428-
pushCommand(DefInvalid(sourceInfo, x.ref))
431+
if (!compileOptions.explicitInvalidate) {
432+
pushCommand(DefInvalid(sourceInfo, x.ref))
433+
}
429434

430435
x
431436
}
@@ -454,3 +459,27 @@ object WireInit {
454459
x
455460
}
456461
}
462+
463+
/** RHS (source) for Invalidate API.
464+
* Causes connection logic to emit a DefInvalid when connected to an output port (or wire).
465+
*/
466+
object DontCare extends Element(width = UnknownWidth()) {
467+
// This object should be initialized before we execute any user code that refers to it,
468+
// otherwise this "Chisel" object will end up on the UserModule's id list.
469+
470+
bind(DontCareBinding(), SpecifiedDirection.Output)
471+
override def cloneType = DontCare
472+
473+
def toPrintable: Printable = PString("DONTCARE")
474+
475+
private[core] def connectFromBits(that: chisel3.core.Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = {
476+
Builder.error("connectFromBits: DontCare cannot be a connection sink (LHS)")
477+
}
478+
479+
def do_asUInt(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: CompileOptions): chisel3.core.UInt = {
480+
Builder.error("DontCare does not have a UInt representation")
481+
0.U
482+
}
483+
// DontCare's only match themselves.
484+
private[core] def typeEquivalent(that: chisel3.core.Data): Boolean = that == DontCare
485+
}

chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala

+33-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
package chisel3.core
44

55
import chisel3.internal.Builder.pushCommand
6-
import chisel3.internal.firrtl.Connect
6+
import chisel3.internal.firrtl.{Connect, DefInvalid}
77
import scala.language.experimental.macros
88
import chisel3.internal.sourceinfo.SourceInfo
99

@@ -48,6 +48,8 @@ object MonoConnect {
4848
MonoConnectException(s": Source Record missing field ($field).")
4949
def MismatchedException(sink: String, source: String) =
5050
MonoConnectException(s": Sink ($sink) and Source ($source) have different types.")
51+
def DontCareCantBeSink =
52+
MonoConnectException(": DontCare cannot be a connection sink (LHS)")
5153

5254
/** This function is what recursively tries to connect a sink and source together
5355
*
@@ -89,6 +91,16 @@ object MonoConnect {
8991
case MonoConnectException(message) => throw MonoConnectException(s"($idx)$message")
9092
}
9193
}
94+
// Handle Vec connected to DontCare. Apply the DontCare to individual elements.
95+
case (sink_v: Vec[Data @unchecked], DontCare) =>
96+
for(idx <- 0 until sink_v.length) {
97+
try {
98+
implicit val compileOptions = connectCompileOptions
99+
connect(sourceInfo, connectCompileOptions, sink_v(idx), source, context_mod)
100+
} catch {
101+
case MonoConnectException(message) => throw MonoConnectException(s"($idx)$message")
102+
}
103+
}
92104

93105
// Handle Record case
94106
case (sink_r: Record, source_r: Record) =>
@@ -107,14 +119,33 @@ object MonoConnect {
107119
case MonoConnectException(message) => throw MonoConnectException(s".$field$message")
108120
}
109121
}
122+
// Handle Record connected to DontCare. Apply the DontCare to individual elements.
123+
case (sink_r: Record, DontCare) =>
124+
// For each field, descend with right
125+
for((field, sink_sub) <- sink_r.elements) {
126+
try {
127+
connect(sourceInfo, connectCompileOptions, sink_sub, source, context_mod)
128+
} catch {
129+
case MonoConnectException(message) => throw MonoConnectException(s".$field$message")
130+
}
131+
}
110132

133+
// Source is DontCare - it may be connected to anything. It generates a defInvalid for the sink.
134+
case (sink, DontCare) => pushCommand(DefInvalid(sourceInfo, sink.lref))
135+
// DontCare as a sink is illegal.
136+
case (DontCare, _) => throw DontCareCantBeSink
111137
// Sink and source are different subtypes of data so fail
112138
case (sink, source) => throw MismatchedException(sink.toString, source.toString)
113139
}
114140

115141
// This function (finally) issues the connection operation
116142
private def issueConnect(sink: Element, source: Element)(implicit sourceInfo: SourceInfo): Unit = {
117-
pushCommand(Connect(sourceInfo, sink.lref, source.ref))
143+
// If the source is a DontCare, generate a DefInvalid for the sink,
144+
// otherwise, issue a Connect.
145+
source.binding match {
146+
case b: DontCareBinding => pushCommand(DefInvalid(sourceInfo, sink.lref))
147+
case _ => pushCommand(Connect(sourceInfo, sink.lref, source.ref))
148+
}
118149
}
119150

120151
// This function checks if element-level connection operation allowed.

0 commit comments

Comments
 (0)