summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Lin2017-09-26 21:05:13 -0700
committerGitHub2017-09-26 21:05:13 -0700
commite2c5c128f6509805f71aeca790809b3e9a8fe84d (patch)
treee35c402a1cda49129dc9e6ab84c6ec3db8618215
parent7af4163cb83e414a19be8484cdbb6f1b04686e99 (diff)
Disallow assignment to op results (#698)
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Binding.scala7
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala8
-rw-r--r--src/test/scala/chiselTests/MultiAssign.scala35
3 files changed, 41 insertions, 9 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
index 2b6f10f6..b09bab0e 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala
@@ -88,11 +88,14 @@ sealed trait ConstrainedBinding extends TopBinding {
def location = Some(enclosure)
}
+// A binding representing a data that cannot be (re)assigned to.
+sealed trait ReadOnlyBinding extends TopBinding
+
// TODO literal info here
-case class LitBinding() extends UnconstrainedBinding
+case class LitBinding() extends UnconstrainedBinding with ReadOnlyBinding
// TODO(twigg): Ops between unenclosed nodes can also be unenclosed
// However, Chisel currently binds all op results to a module
-case class OpBinding(enclosure: UserModule) extends ConstrainedBinding
+case class OpBinding(enclosure: UserModule) extends ConstrainedBinding with ReadOnlyBinding
case class MemoryPortBinding(enclosure: UserModule) extends ConstrainedBinding
case class PortBinding(enclosure: BaseModule) extends ConstrainedBinding
case class RegBinding(enclosure: UserModule) extends ConstrainedBinding
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index f61478c8..b5c9d319 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -267,6 +267,10 @@ abstract class Data extends HasId {
if (connectCompileOptions.checkSynthesizable) {
requireIsHardware(this, "data to be connected")
requireIsHardware(that, "data to be connected")
+ this.topBinding match {
+ case _: ReadOnlyBinding => throwException(s"Cannot reassign to read-only $this")
+ case _ => // fine
+ }
try {
MonoConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedUserModule)
} catch {
@@ -283,6 +287,10 @@ abstract class Data extends HasId {
if (connectCompileOptions.checkSynthesizable) {
requireIsHardware(this, s"data to be bulk-connected")
requireIsHardware(that, s"data to be bulk-connected")
+ (this.topBinding, that.topBinding) match {
+ case (_: ReadOnlyBinding, _: ReadOnlyBinding) => throwException(s"Both $this and $that are read-only")
+ case _ => // fine
+ }
try {
BiConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedUserModule)
} catch {
diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala
index fbe57da5..1e1d3f70 100644
--- a/src/test/scala/chiselTests/MultiAssign.scala
+++ b/src/test/scala/chiselTests/MultiAssign.scala
@@ -26,11 +26,6 @@ class LastAssignTester() extends BasicTester {
}
}
-class ReassignmentTester() extends BasicTester {
- val test = 15.U
- test := 7.U
-}
-
class MultiAssignSpec extends ChiselFlatSpec {
"The last assignment" should "be used when multiple assignments happen" in {
assertTesterPasses{ new LastAssignTester }
@@ -38,9 +33,35 @@ class MultiAssignSpec extends ChiselFlatSpec {
}
class IllegalAssignSpec extends ChiselFlatSpec {
- "Reassignments to non-wire types" should "be disallowed" in {
+ "Reassignments to literals" should "be disallowed" in {
+ intercept[chisel3.internal.ChiselException] {
+ elaborate{ new BasicTester {
+ 15.U := 7.U
+ }}
+ }
+ }
+
+ "Reassignments to ops" should "be disallowed" in {
+ intercept[chisel3.internal.ChiselException] {
+ elaborate{ new BasicTester {
+ (15.U + 1.U) := 7.U
+ }}
+ }
+ }
+
+ "Reassignments to bit slices" should "be disallowed" in {
+ intercept[chisel3.internal.ChiselException] {
+ elaborate{ new BasicTester {
+ (15.U)(1, 0) := 7.U
+ }}
+ }
+ }
+
+ "Bulk-connecting two read-only nodes" should "be disallowed" in {
intercept[chisel3.internal.ChiselException] {
- assertTesterFails{ new ReassignmentTester }
+ elaborate{ new BasicTester {
+ (15.U + 1.U) <> 7.U
+ }}
}
}
}