Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for behavior of bundles with cloneType. #908

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ trait InstanceId {

}

class GetReferenceException(message: String) extends Exception(message)

private[chisel3] trait HasId extends InstanceId {
private[chisel3] def _onModuleClose: Unit = {} // scalastyle:ignore method.name
private[chisel3] val _parent: Option[BaseModule] = Builder.currentModule
Expand Down Expand Up @@ -111,7 +113,7 @@ private[chisel3] trait HasId extends InstanceId {
private[chisel3] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name))
private[chisel3] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index)))
private[chisel3] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref))
private[chisel3] def getRef: Arg = _ref.get
private[chisel3] def getRef: Arg = _ref.getOrElse(throw new GetReferenceException(s"bad .getRef on None"))
private[chisel3] def getOptionRef: Option[Arg] = _ref

// Implementation of public methods.
Expand Down
13 changes: 11 additions & 2 deletions src/main/scala/chisel3/internal/firrtl/Emitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

package chisel3.internal.firrtl
import chisel3._
import chisel3.core.{SpecifiedDirection, EnumType}
import chisel3.core.{EnumType, SpecifiedDirection}
import chisel3.experimental._
import chisel3.internal.GetReferenceException
import chisel3.internal.sourceinfo.{NoSourceInfo, SourceLine}

private[chisel3] object Emitter {
Expand All @@ -26,6 +27,7 @@ private class Emitter(circuit: Circuit) {
s"$dirString ${e.id.getRef.name} : ${emitType(e.id, clearDir)}"
}

//scalastyle:off cyclomatic.complexity
private def emitType(d: Data, clearDir: Boolean = false): String = d match {
case d: Clock => "Clock"
case d: chisel3.core.EnumType => s"UInt${d.width}"
Expand All @@ -41,7 +43,14 @@ private class Emitter(circuit: Circuit) {
case (true, _) =>
s"${elt.getRef.name} : ${emitType(elt, true)}"
case (false, SpecifiedDirection.Unspecified | SpecifiedDirection.Output) =>
s"${elt.getRef.name} : ${emitType(elt, false)}"
try {
s"${elt.getRef.name} : ${emitType(elt, false)}"
}
catch {
case getRef: GetReferenceException =>
throw new GetReferenceException(s"Cannot emit ports for ${d.className}" +
s" with fields ${d.elements.keys.mkString(",")}, perhaps you forgot a cloneType")
}
case (false, SpecifiedDirection.Flip | SpecifiedDirection.Input) =>
s"flip ${elt.getRef.name} : ${emitType(elt, false)}"
}
Expand Down
27 changes: 27 additions & 0 deletions src/test/scala/chiselTests/BundleSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package chiselTests

import chisel3._
import chisel3.core.IgnoreSeqInBundle
import chisel3.internal.GetReferenceException
import chisel3.testers.BasicTester

trait BundleSpecUtils {
Expand Down Expand Up @@ -116,3 +117,29 @@ class BundleSpec extends ChiselFlatSpec with BundleSpecUtils {
}
}
}

class BundleWithoutCloneTypeProblem extends ChiselPropSpec {
property("Bundles should not freak out if you forget cloneType") {
intercept[GetReferenceException] {
val a = new Bundle {
val b = UInt(4.W)
}

runTester(
new BasicTester {
val m = Module(new Module {
val d = Wire(new Bundle {
val e = a // forgot cloneType
})
val io = IO(new Bundle {
val c = Output(a.cloneType)
})
io.c := d.e
d.e.b := 0.U
stop()
})
}
)
}.getMessage should include("Cannot emit ports for Bundle with fields e, perhaps you forgot a cloneType")
}
}