summaryrefslogtreecommitdiff
path: root/src/test/scala/chiselTests/RecordSpec.scala
diff options
context:
space:
mode:
authormergify[bot]2022-08-16 19:04:28 +0000
committerGitHub2022-08-16 19:04:28 +0000
commit23ef9aa7ffef5bbf8fe124fc9be7683f005c3612 (patch)
tree6e9a58cc42f8f8e784d8ca8ac1e7f4ae41db19b1 /src/test/scala/chiselTests/RecordSpec.scala
parent96830a4ad502019ff1040889a89375ff1e3a6c6b (diff)
Add OpaqueType support to Records (backport #2662) (#2679)
* Add OpaqueType support to Records (#2662) OpaqueTypes are essentially type aliases that hide the underlying type. They are implemented in Chisel as Records of a single, unnamed element where the wrapping Record does not exist in the emitted FIRRTL. Co-authored-by: Jack Koenig <koenig@sifive.com> (cherry picked from commit df5afee2d41b5bcd82d4013b977965c0dfe046fd) * Fix test compilation * Fix OpaqueType tests in RecordSpec Need to implement cloneType correctly and to warn instead of error when accessing .toTarget of non-hardware types because that is a warning (not error) in 3.5. * Waive MiMa false positives Co-authored-by: Aditya Naik <91489422+adkian-sifive@users.noreply.github.com> Co-authored-by: Jack Koenig <koenig@sifive.com>
Diffstat (limited to 'src/test/scala/chiselTests/RecordSpec.scala')
-rw-r--r--src/test/scala/chiselTests/RecordSpec.scala88
1 files changed, 87 insertions, 1 deletions
diff --git a/src/test/scala/chiselTests/RecordSpec.scala b/src/test/scala/chiselTests/RecordSpec.scala
index 30b55812..5aa872b0 100644
--- a/src/test/scala/chiselTests/RecordSpec.scala
+++ b/src/test/scala/chiselTests/RecordSpec.scala
@@ -108,6 +108,58 @@ trait RecordSpecUtils {
require(DataMirror.checkTypeEquivalence(wire0, wire1))
require(!DataMirror.checkTypeEquivalence(wire1, wire2))
}
+
+ class SingleElementRecord extends Record {
+ private val underlying = UInt(8.W)
+ val elements = SeqMap("" -> underlying)
+ override def opaqueType = elements.size == 1
+ override def cloneType: this.type = (new SingleElementRecord).asInstanceOf[this.type]
+
+ def +(that: SingleElementRecord): SingleElementRecord = {
+ val _w = Wire(new SingleElementRecord)
+ _w.underlying := this.underlying + that.underlying
+ _w
+ }
+ }
+
+ class SingleElementRecordModule extends Module {
+ val in1 = IO(Input(new SingleElementRecord))
+ val in2 = IO(Input(new SingleElementRecord))
+ val out = IO(Output(new SingleElementRecord))
+
+ val r = new SingleElementRecord
+
+ out := in1 + in2
+ }
+
+ class NamedSingleElementRecord extends Record {
+ private val underlying = UInt(8.W)
+ val elements = SeqMap("unused" -> underlying)
+
+ override def opaqueType = elements.size == 1
+ override def cloneType: this.type = (new NamedSingleElementRecord).asInstanceOf[this.type]
+ }
+
+ class NamedSingleElementModule extends Module {
+ val in = IO(Input(new NamedSingleElementRecord))
+ val out = IO(Output(new NamedSingleElementRecord))
+ out := in
+ }
+
+ class ErroneousOverride extends Record {
+ private val underlyingA = UInt(8.W)
+ private val underlyingB = UInt(8.W)
+ val elements = SeqMap("x" -> underlyingA, "y" -> underlyingB)
+
+ override def opaqueType = true
+ override def cloneType: this.type = (new ErroneousOverride).asInstanceOf[this.type]
+ }
+
+ class ErroneousOverrideModule extends Module {
+ val in = IO(Input(new ErroneousOverride))
+ val out = IO(Output(new ErroneousOverride))
+ out := in
+ }
}
class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils {
@@ -133,7 +185,7 @@ class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils {
class AliasedFieldRecord extends Record {
val foo = UInt(8.W)
val elements = SeqMap("foo" -> foo, "bar" -> foo)
- override def cloneType: AliasedFieldRecord.this.type = this
+ override def cloneType: AliasedFieldRecord.this.type = (new AliasedFieldRecord).asInstanceOf[this.type]
}
val e = intercept[AliasedAggregateFieldException] {
@@ -146,6 +198,40 @@ class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils {
e.getMessage should include("contains aliased fields named (bar,foo)")
}
+ they should "be OpaqueType for maps with single unnamed elements" in {
+ val singleElementChirrtl = ChiselStage.emitChirrtl { new SingleElementRecordModule }
+ singleElementChirrtl should include("input in1 : UInt<8>")
+ singleElementChirrtl should include("input in2 : UInt<8>")
+ singleElementChirrtl should include("add(in1, in2)")
+ }
+
+ they should "throw an error when map contains a named element and opaqueType is overriden to true" in {
+ (the[Exception] thrownBy extractCause[Exception] {
+ ChiselStage.elaborate { new NamedSingleElementModule }
+ }).getMessage should include("Opaque types must have exactly one element with an empty name")
+ }
+
+ they should "throw an error when map contains more than one element and opaqueType is overriden to true" in {
+ (the[Exception] thrownBy extractCause[Exception] {
+ ChiselStage.elaborate { new ErroneousOverrideModule }
+ }).getMessage should include("Opaque types must have exactly one element with an empty name")
+ }
+
+ they should "work with .toTarget" in {
+ var m: SingleElementRecordModule = null
+ ChiselStage.elaborate { m = new SingleElementRecordModule; m }
+ val q = m.in1.toTarget.toString
+ assert(q == "~SingleElementRecordModule|SingleElementRecordModule>in1")
+ }
+
+ they should "work (but warn) with .toTarget on non-data OpaqueType Record" in {
+ var m: SingleElementRecordModule = null
+ ChiselStage.elaborate { m = new SingleElementRecordModule; m }
+ val (log, q) = grabLog(m.r.toTarget)
+ log should include(".toTarget of non-hardware Data is deprecated.")
+ assert(q.toString == "~SingleElementRecordModule|SingleElementRecordModule>r")
+ }
+
they should "follow UInt serialization/deserialization API" in {
assertTesterPasses { new RecordSerializationTest }
}