summaryrefslogtreecommitdiff
path: root/src/test/scala/chiselTests
diff options
context:
space:
mode:
authorHasan Genc2019-03-22 09:39:53 -0700
committeredwardcwang2019-03-22 09:39:53 -0700
commit80aabc03ef2420e817bcbac34c78ec25227d9fbb (patch)
tree74164e690a2b2926006d6d874fbe27d3de4a48ac /src/test/scala/chiselTests
parent5574131876d8bbe73cfcd3b5ae8a1317b60142c0 (diff)
Fix enum annotations (#936)
* Turned off strong enum annotations because they weren't working with Vec indexes * Add new EnumVecAnnotation for vecs of enums and vecs of bundles with enum fields * Changed Clock's width parameter back to a fixed constant value of 1 * Fixed enum annotations for Vecs of Bundles which contain enum elements * Fixed usage of "when/otherwise" to use consistent style
Diffstat (limited to 'src/test/scala/chiselTests')
-rw-r--r--src/test/scala/chiselTests/StrongEnum.scala213
1 files changed, 163 insertions, 50 deletions
diff --git a/src/test/scala/chiselTests/StrongEnum.scala b/src/test/scala/chiselTests/StrongEnum.scala
index f5c3bc2f..6c87aee3 100644
--- a/src/test/scala/chiselTests/StrongEnum.scala
+++ b/src/test/scala/chiselTests/StrongEnum.scala
@@ -367,64 +367,177 @@ class StrongEnumSpec extends ChiselFlatSpec {
"foo(OtherEnum.otherEnum)" shouldNot compile
}
+ it should "prevent enums from being declared without names" in {
+ "object UnnamedEnum extends ChiselEnum { Value }" shouldNot compile
+ }
+
"StrongEnum FSM" should "work" in {
assertTesterPasses(new StrongEnumFSMTester)
}
}
-class StrongEnumAnnotationSpec extends ChiselFlatSpec {
+class StrongEnumAnnotator extends Module {
+ import EnumExample._
+
+ val io = IO(new Bundle{
+ val in = Input(EnumExample())
+ val out = Output(EnumExample())
+ val other = Output(OtherEnum())
+ })
+
+ class Bund extends Bundle {
+ val field = EnumExample()
+ val other = OtherEnum()
+ val vec = Vec(5, EnumExample())
+ val inner_bundle1 = new Bundle {
+ val x = UInt(4.W)
+ val y = Vec(3, UInt(4.W))
+ val e = EnumExample()
+ val v = Vec(3, EnumExample())
+ }
+ val inner_bundle2 = new Bundle {}
+ val inner_bundle3 = new Bundle {
+ val x = Bool()
+ }
+ val inner_bundle4 = new Bundle {
+ val inner_inner_bundle = new Bundle {}
+ }
+ }
+
+ val simple = Wire(EnumExample())
+ val vec = VecInit(e0, e1, e2)
+ val vec_of_vecs = VecInit(VecInit(e0, e1), VecInit(e100, e101))
+
+ val bund = Wire(new Bund())
+ val vec_of_bundles = Wire(Vec(5, new Bund()))
+
+ io.out := e101
+ io.other := OtherEnum.otherEnum
+ simple := e100
+ bund := DontCare
+ vec_of_bundles := DontCare
+
+ // Make sure that dynamically indexing into a Vec of enums will not cause an elaboration error.
+ // The components created here will not be annotated.
+ val cycle = RegInit(0.U)
+ cycle := cycle + 1.U
+
+ val indexed1 = vec_of_vecs(cycle)(cycle)
+ val indexed2 = vec_of_bundles(cycle)
+}
+
+class StrongEnumAnnotationSpec extends FreeSpec with Matchers {
import chisel3.experimental.EnumAnnotations._
- import firrtl.annotations.ComponentName
-
- ignore should "Test that strong enums annotate themselves appropriately" in {
-
- // scalastyle:off regex
- def test(): Assertion = {// scalastyle:ignore cyclomatic.complexity
- Driver.execute(Array("--target-dir", "test_run_dir"), () => new StrongEnumFSM) match {
- case ChiselExecutionSuccess(Some(circuit), emitted, _) =>
- val annos = circuit.annotations.map(_.toFirrtl)
-
- val enumDefAnnos = annos.collect { case a: EnumDefAnnotation => a }
- val enumCompAnnos = annos.collect { case a: EnumComponentAnnotation => a }
-
- // Print the annotations out onto the screen
- println("Enum definitions:")
- enumDefAnnos.foreach {
- case EnumDefAnnotation(enumTypeName, definition) => println(s"\t$enumTypeName: $definition")
- }
- println("Enum components:")
- enumCompAnnos.foreach{
- case EnumComponentAnnotation(target, enumTypeName) => println(s"\t$target => $enumTypeName")
- }
-
- // Check that the global annotation is correct
- enumDefAnnos.exists {
- case EnumDefAnnotation(name, map) =>
- name.endsWith("State") &&
- map.size == StrongEnumFSM.State.correct_annotation_map.size &&
- map.forall {
- case (k, v) =>
- val correctValue = StrongEnumFSM.State.correct_annotation_map(k)
- correctValue == v
- }
- case _ => false
- } should be(true)
-
- // Check that the component annotations are correct
- enumCompAnnos.count {
- case EnumComponentAnnotation(target, enumName) =>
- val ComponentName(targetName, _) = target
- (targetName == "state" && enumName.endsWith("State")) ||
- (targetName == "io.state" && enumName.endsWith("State"))
- case _ => false
- } should be(2)
-
- case _ =>
- assert(false)
- }
- // scalastyle:on regex
+ import firrtl.annotations.{ComponentName, Annotation}
+
+ val enumExampleName = "EnumExample"
+ val otherEnumName = "OtherEnum"
+
+ case class CorrectDefAnno(typeName: String, definition: Map[String, BigInt])
+ case class CorrectCompAnno(targetName: String, typeName: String)
+ case class CorrectVecAnno(targetName: String, typeName: String, fields: Set[Seq[String]])
+
+ val correctDefAnnos = Seq(
+ CorrectDefAnno(otherEnumName, Map("otherEnum" -> 0)),
+ CorrectDefAnno(enumExampleName, Map("e0" -> 0, "e1" -> 1, "e2" -> 2, "e100" -> 100, "e101" -> 101))
+ )
+
+ val correctCompAnnos = Seq(
+ CorrectCompAnno("io.other", otherEnumName),
+ CorrectCompAnno("io.out", enumExampleName),
+ CorrectCompAnno("io.in", enumExampleName),
+ CorrectCompAnno("simple", enumExampleName),
+ CorrectCompAnno("bund.field", enumExampleName),
+ CorrectCompAnno("bund.other", otherEnumName),
+ CorrectCompAnno("bund.inner_bundle1.e", enumExampleName)
+ )
+
+ val correctVecAnnos = Seq(
+ CorrectVecAnno("vec", enumExampleName, Set()),
+ CorrectVecAnno("vec_of_vecs", enumExampleName, Set()),
+ CorrectVecAnno("vec_of_bundles", enumExampleName, Set(Seq("field"), Seq("vec"), Seq("inner_bundle1", "e"), Seq("inner_bundle1", "v"))),
+ CorrectVecAnno("vec_of_bundles", otherEnumName, Set(Seq("other"))),
+ CorrectVecAnno("bund.vec", enumExampleName, Set()),
+ CorrectVecAnno("bund.inner_bundle1.v", enumExampleName, Set())
+ )
+
+ // scalastyle:off regex
+ def printAnnos(annos: Seq[Annotation]) {
+ println("Enum definitions:")
+ annos.foreach {
+ case EnumDefAnnotation(enumTypeName, definition) => println(s"\t$enumTypeName: $definition")
+ case _ =>
+ }
+ println("Enum components:")
+ annos.foreach{
+ case EnumComponentAnnotation(target, enumTypeName) => println(s"\t$target => $enumTypeName")
+ case _ =>
}
+ println("Enum vecs:")
+ annos.foreach{
+ case EnumVecAnnotation(target, enumTypeName, fields) => println(s"\t$target[$fields] => $enumTypeName")
+ case _ =>
+ }
+ }
+ // scalastyle:on regex
+
+ def isCorrect(anno: EnumDefAnnotation, correct: CorrectDefAnno): Boolean = {
+ (anno.typeName == correct.typeName ||
+ anno.typeName.endsWith("." + correct.typeName)) &&
+ anno.definition == correct.definition
+ }
+
+ def isCorrect(anno: EnumComponentAnnotation, correct: CorrectCompAnno): Boolean = {
+ (anno.target match {
+ case ComponentName(name, _) => name == correct.targetName
+ case _ => throw new Exception("Unknown target type in EnumComponentAnnotation")
+ }) &&
+ (anno.enumTypeName == correct.typeName || anno.enumTypeName.endsWith("." + correct.typeName))
+ }
+
+ def isCorrect(anno: EnumVecAnnotation, correct: CorrectVecAnno): Boolean = {
+ (anno.target match {
+ case ComponentName(name, _) => name == correct.targetName
+ case _ => throw new Exception("Unknown target type in EnumVecAnnotation")
+ }) &&
+ (anno.typeName == correct.typeName || anno.typeName.endsWith("." + correct.typeName)) &&
+ anno.fields.map(_.toSeq).toSet == correct.fields
+ }
+
+ def allCorrectDefs(annos: Seq[EnumDefAnnotation], corrects: Seq[CorrectDefAnno]): Boolean = {
+ corrects.forall(c => annos.exists(isCorrect(_, c))) &&
+ correctDefAnnos.length == annos.length
+ }
+
+ // Because temporary variables might be formed and annotated, we do not check that every component or vector
+ // annotation is accounted for in the correct results listed above
+ def allCorrectComps(annos: Seq[EnumComponentAnnotation], corrects: Seq[CorrectCompAnno]): Boolean =
+ corrects.forall(c => annos.exists(isCorrect(_, c)))
+
+ def allCorrectVecs(annos: Seq[EnumVecAnnotation], corrects: Seq[CorrectVecAnno]): Boolean =
+ corrects.forall(c => annos.exists(isCorrect(_, c)))
+
+ def test() {
+ Driver.execute(Array("--target-dir", "test_run_dir"), () => new StrongEnumAnnotator) match {
+ case ChiselExecutionSuccess(Some(circuit), emitted, _) =>
+ val annos = circuit.annotations.map(_.toFirrtl)
+
+ printAnnos(annos)
+
+ val enumDefAnnos = annos.collect { case a: EnumDefAnnotation => a }
+ val enumCompAnnos = annos.collect { case a: EnumComponentAnnotation => a }
+ val enumVecAnnos = annos.collect { case a: EnumVecAnnotation => a }
+
+ allCorrectDefs(enumDefAnnos, correctDefAnnos) should be(true)
+ allCorrectComps(enumCompAnnos, correctCompAnnos) should be(true)
+ allCorrectVecs(enumVecAnnos, correctVecAnnos) should be(true)
+
+ case _ =>
+ assert(false)
+ }
+ }
+ "Test that strong enums annotate themselves appropriately" in {
// We run this test twice, to test for an older bug where only the first circuit would be annotated
test()
test()