summaryrefslogtreecommitdiff
path: root/src/test/scala/chiselTests/experimental
diff options
context:
space:
mode:
authorJack2021-12-18 08:27:38 +0000
committerJack2021-12-18 08:27:38 +0000
commitdd9ad534771247ac16eaa47eb9794102736b5102 (patch)
treed4566d317cb8526b79017de1e438aea8217dd1d4 /src/test/scala/chiselTests/experimental
parent440edc4436fb3a8a4175ae425a0d31c4997ee60f (diff)
parentf50f74f583fba7b98e550c440df091e559ce32b8 (diff)
Merge branch 'master' into 3.5-release
Diffstat (limited to 'src/test/scala/chiselTests/experimental')
-rw-r--r--src/test/scala/chiselTests/experimental/DataView.scala123
-rw-r--r--src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala3
-rw-r--r--src/test/scala/chiselTests/experimental/TraceSpec.scala309
-rw-r--r--src/test/scala/chiselTests/experimental/Tuple.scala163
-rw-r--r--src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala12
-rw-r--r--src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala55
-rw-r--r--src/test/scala/chiselTests/experimental/hierarchy/Examples.scala53
-rw-r--r--src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala156
-rw-r--r--src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala154
9 files changed, 759 insertions, 269 deletions
diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala
index d1620e88..7c5d170b 100644
--- a/src/test/scala/chiselTests/experimental/DataView.scala
+++ b/src/test/scala/chiselTests/experimental/DataView.scala
@@ -5,7 +5,9 @@ package chiselTests.experimental
import chiselTests.ChiselFlatSpec
import chisel3._
import chisel3.experimental.dataview._
+import chisel3.experimental.conversions._
import chisel3.experimental.DataMirror.internal.chiselTypeClone
+import chisel3.experimental.HWTuple2
import chisel3.stage.ChiselStage
import chisel3.util.{Decoupled, DecoupledIO}
@@ -50,69 +52,6 @@ object FlatDecoupledDataView {
implicit val view2 = view.invert(_ => new FlatDecoupled)
}
-// This should become part of Chisel in a later PR
-object Tuple2DataProduct {
- implicit def tuple2DataProduct[A : DataProduct, B : DataProduct] = new DataProduct[(A, B)] {
- def dataIterator(tup: (A, B), path: String): Iterator[(Data, String)] = {
- val dpa = implicitly[DataProduct[A]]
- val dpb = implicitly[DataProduct[B]]
- val (a, b) = tup
- dpa.dataIterator(a, s"$path._1") ++ dpb.dataIterator(b, s"$path._2")
- }
- }
-}
-
-// This should become part of Chisel in a later PR
-object HWTuple {
- import Tuple2DataProduct._
-
- class HWTuple2[A <: Data, B <: Data](val _1: A, val _2: B) extends Bundle
-
- implicit def view[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data](
- implicit v1: DataView[T1, V1], v2: DataView[T2, V2]
- ): DataView[(T1, T2), HWTuple2[V1, V2]] =
- DataView.mapping(
- { case (a, b) => new HWTuple2(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType)},
- { case ((a, b), hwt) =>
- Seq(a.viewAs[V1] -> hwt._1,
- b.viewAs[V2] -> hwt._2)
- }
- )
-
- implicit def tuple2hwtuple[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data](
- tup: (T1, T2))(implicit v1: DataView[T1, V1], v2: DataView[T2, V2]
- ): HWTuple2[V1, V2] = tup.viewAs[HWTuple2[V1, V2]]
-}
-
-// This should become part of Chisel in a later PR
-object SeqDataProduct {
- // Should we special case Seq[Data]?
- implicit def seqDataProduct[A : DataProduct]: DataProduct[Seq[A]] = new DataProduct[Seq[A]] {
- def dataIterator(a: Seq[A], path: String): Iterator[(Data, String)] = {
- val dpa = implicitly[DataProduct[A]]
- a.iterator
- .zipWithIndex
- .flatMap { case (elt, idx) =>
- dpa.dataIterator(elt, s"$path[$idx]")
- }
- }
- }
-}
-
-object SeqToVec {
- import SeqDataProduct._
-
- // TODO this would need a better way to determine the prototype for the Vec
- implicit def seqVec[A : DataProduct, B <: Data](implicit dv: DataView[A, B]): DataView[Seq[A], Vec[B]] =
- DataView.mapping[Seq[A], Vec[B]](
- xs => Vec(xs.size, chiselTypeClone(xs.head.viewAs[B])), // xs.head is not correct in general
- { case (s, v) => s.zip(v).map { case (a, b) => a.viewAs[B] -> b } }
- )
-
- implicit def seq2Vec[A : DataProduct, B <: Data](xs: Seq[A])(implicit dv: DataView[A, B]): Vec[B] =
- xs.viewAs[Vec[B]]
-}
-
class DataViewSpec extends ChiselFlatSpec {
behavior of "DataView"
@@ -327,15 +266,14 @@ class DataViewSpec extends ChiselFlatSpec {
chirrtl should include ("z.fizz <= b.foo")
}
- // This example should be turned into a built-in feature
- it should "enable implementing \"HardwareTuple\"" in {
- import HWTuple._
-
+ it should "enable using Seq like Data" in {
class MyModule extends Module {
val a, b, c, d = IO(Input(UInt(8.W)))
val sel = IO(Input(Bool()))
val y, z = IO(Output(UInt(8.W)))
- (y, z) := Mux(sel, (a, b), (c, d))
+ // Unclear why the implicit conversion does not work in this case for Seq
+ // That being said, it's easy enough to cast via `.viewAs` with or without
+ Seq(y, z) := Mux(sel, Seq(a, b).viewAs, Seq(c, d).viewAs[Vec[UInt]])
}
// Verilog instead of CHIRRTL because the optimizations make it much prettier
val verilog = ChiselStage.emitVerilog(new MyModule)
@@ -343,25 +281,8 @@ class DataViewSpec extends ChiselFlatSpec {
verilog should include ("assign z = sel ? b : d;")
}
- it should "support nesting of tuples" in {
- import Tuple2DataProduct._
- import HWTuple._
-
- class MyModule extends Module {
- val a, b, c, d = IO(Input(UInt(8.W)))
- val w, x, y, z = IO(Output(UInt(8.W)))
- ((w, x), (y, z)) := ((a, b), (c, d))
- }
- val chirrtl = ChiselStage.emitChirrtl(new MyModule)
- chirrtl should include ("w <= a")
- chirrtl should include ("x <= b")
- chirrtl should include ("y <= c")
- chirrtl should include ("z <= d")
- }
-
// This example should be turned into a built-in feature
it should "enable viewing Seqs as Vecs" in {
- import SeqToVec._
class MyModule extends Module {
val a, b, c = IO(Input(UInt(8.W)))
@@ -376,11 +297,6 @@ class DataViewSpec extends ChiselFlatSpec {
}
it should "support recursive composition of views" in {
- import Tuple2DataProduct._
- import SeqDataProduct._
- import SeqToVec._
- import HWTuple._
-
class MyModule extends Module {
val a, b, c, d = IO(Input(UInt(8.W)))
val w, x, y, z = IO(Output(UInt(8.W)))
@@ -397,12 +313,26 @@ class DataViewSpec extends ChiselFlatSpec {
verilog should include ("assign z = d;")
}
- it should "error if you try to dynamically index a Vec view" in {
- import SeqDataProduct._
- import SeqToVec._
- import Tuple2DataProduct._
- import HWTuple._
+ it should "support dynamic indexing for Vec identity views" in {
+ class MyModule extends Module {
+ val dataIn = IO(Input(UInt(8.W)))
+ val addr = IO(Input(UInt(2.W)))
+ val dataOut = IO(Output(UInt(8.W)))
+
+ val vec = RegInit(0.U.asTypeOf(Vec(4, UInt(8.W))))
+ val view = vec.viewAs[Vec[UInt]]
+ // Dynamic indexing is more of a "generator" in Chisel3 than an individual node
+ // This style is not recommended, this is just testing the behavior
+ val selected = view(addr)
+ selected := dataIn
+ dataOut := selected
+ }
+ val chirrtl = ChiselStage.emitChirrtl(new MyModule)
+ chirrtl should include ("vec[addr] <= dataIn")
+ chirrtl should include ("dataOut <= vec[addr]")
+ }
+ it should "error if you try to dynamically index a Vec view that does not correspond to a Vec target" in {
class MyModule extends Module {
val inA, inB = IO(Input(UInt(8.W)))
val outA, outB = IO(Output(UInt(8.W)))
@@ -411,6 +341,7 @@ class DataViewSpec extends ChiselFlatSpec {
val a, b, c, d = RegInit(0.U)
// Dynamic indexing is more of a "generator" in Chisel3 than an individual node
+ // This style is not recommended, this is just testing the behavior
val selected = Seq((a, b), (c, d)).apply(idx)
selected := (inA, inB)
(outA, outB) := selected
@@ -434,7 +365,6 @@ class DataViewSpec extends ChiselFlatSpec {
}
it should "error if the mapping is non-total in the target" in {
- import Tuple2DataProduct._
implicit val dv = DataView[(UInt, UInt), UInt](_ => UInt(), _._1 -> _)
class MyModule extends Module {
val a, b = IO(Input(UInt(8.W)))
@@ -533,7 +463,6 @@ class DataViewSpec extends ChiselFlatSpec {
}
it should "NOT error if the mapping is non-total in the target" in {
- import Tuple2DataProduct._
implicit val dv = PartialDataView[(UInt, UInt), UInt](_ => UInt(), _._2 -> _)
class MyModule extends Module {
val a, b = IO(Input(UInt(8.W)))
diff --git a/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala b/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala
index 92091631..a17b0f40 100644
--- a/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala
+++ b/src/test/scala/chiselTests/experimental/DataViewTargetSpec.scala
@@ -4,8 +4,8 @@ package chiselTests.experimental
import chisel3._
import chisel3.experimental.dataview._
+import chisel3.experimental.conversions._
import chisel3.experimental.{ChiselAnnotation, annotate}
-import chisel3.stage.ChiselStage
import chiselTests.ChiselFlatSpec
object DataViewTargetSpec {
@@ -127,7 +127,6 @@ class DataViewTargetSpec extends ChiselFlatSpec {
}
it should "support annotating views that cannot be mapped to a single ReferenceTarget" in {
- import HWTuple._
class MyBundle extends Bundle {
val a, b = Input(UInt(8.W))
val c, d = Output(UInt(8.W))
diff --git a/src/test/scala/chiselTests/experimental/TraceSpec.scala b/src/test/scala/chiselTests/experimental/TraceSpec.scala
new file mode 100644
index 00000000..59548921
--- /dev/null
+++ b/src/test/scala/chiselTests/experimental/TraceSpec.scala
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package chiselTests
+
+import chisel3._
+import chisel3.experimental.ChiselEnum
+import chisel3.experimental.Trace._
+import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage, DesignAnnotation}
+import chisel3.util.experimental.InlineInstance
+import firrtl.AnnotationSeq
+import firrtl.annotations.TargetToken.{Instance, OfModule, Ref}
+import firrtl.annotations.{CompleteTarget, InstanceTarget, ReferenceTarget}
+import org.scalatest.matchers.should.Matchers
+
+class TraceSpec extends ChiselFlatSpec with Matchers {
+
+ def refTarget(topName: String, ref: String, path: Seq[(Instance, OfModule)] = Seq()) =
+ ReferenceTarget(topName, topName, path, ref, Seq())
+
+ def instTarget(topName: String, instance: String, ofModule: String, path: Seq[(Instance, OfModule)] = Seq()) =
+ InstanceTarget(topName, topName, path, instance, ofModule)
+
+ def compile(testName: String, gen: () => Module): (os.Path, AnnotationSeq) = {
+ val testDir = os.Path(createTestDirectory(testName).getAbsolutePath)
+ val annos = (new ChiselStage).execute(
+ Array("--target-dir", s"$testDir"),
+ Seq(
+ ChiselGeneratorAnnotation(gen)
+ )
+ )
+ (testDir, annos)
+ }
+
+ "TraceFromAnnotations" should "be able to get nested name." in {
+ class Bundle0 extends Bundle {
+ val a = UInt(8.W)
+ val b = Bool()
+ val c = Enum0.Type
+ }
+
+ class Bundle1 extends Bundle {
+ val a = new Bundle0
+ val b = Vec(4, Vec(4, Bool()))
+ }
+
+ class Module0 extends Module {
+ val i = IO(Input(new Bundle1))
+ val o = IO(Output(new Bundle1))
+ val r = Reg(new Bundle1)
+ o := r
+ r := i
+
+ traceName(r)
+ traceName(i)
+ traceName(o)
+ }
+
+ class Module1 extends Module {
+ val i = IO(Input(new Bundle1))
+ val m0 = Module(new Module0)
+ m0.i := i
+ m0.o := DontCare
+ }
+
+ object Enum0 extends ChiselEnum {
+ val s0, s1, s2 = Value
+ }
+
+ val (testDir, annos) = compile("TraceFromAnnotaions", () => new Module1)
+ val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[Module1]
+ // out of Builder.
+
+ val oneTarget = finalTarget(annos)(dut.m0.r.a.a).head
+ val ioTarget = finalTarget(annos)(dut.m0.i.b(1)(2)).head
+
+ val topName = "Module1"
+ oneTarget should be(refTarget(topName, "r_a_a", Seq(Instance("m0") -> OfModule("Module0"))))
+
+ ioTarget should be(refTarget(topName, "i_b_1_2", Seq(Instance("m0") -> OfModule("Module0"))))
+
+ // Below codes doesn't needs to be a FIRRTL Transform.
+ def generateVerilatorConfigFile(data: Seq[Data], annos: AnnotationSeq): String =
+ """`verilator_config
+ |lint_off -rule unused
+ |lint_off -rule declfilename
+ |""".stripMargin +
+ data
+ .flatMap(finalTarget(annos))
+ .toSet
+ .map { target: CompleteTarget =>
+ s"""public_flat_rd -module "${target.tokens.collectFirst { case OfModule(m) => m }.get}" -var "${target.tokens.collectFirst { case Ref(r) => r }.get}""""
+ }
+ .mkString("\n") + "\n"
+
+ def verilatorTemplate(data: Seq[Data], annos: AnnotationSeq): String = {
+ val vpiNames = data.flatMap(finalTarget(annos)).map { ct =>
+ s"""TOP.${ct.circuit}.${ct.path.map { case (Instance(i), _) => i }.mkString(".")}.${ct.tokens.collectFirst { case Ref(r) => r }.get}"""
+ }
+ s"""
+ |#include "V${topName}.h"
+ |#include "verilated_vpi.h"
+ |#include <memory>
+ |#include <verilated.h>
+ |
+ |int vpiGetInt(const char name[]) {
+ | vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8 *)name, NULL);
+ | if (!vh1)
+ | vl_fatal(__FILE__, __LINE__, "sim_main", "No handle found");
+ | s_vpi_value v;
+ | v.format = vpiIntVal;
+ | vpi_get_value(vh1, &v);
+ | return v.value.integer;
+ |}
+ |
+ |int main(int argc, char **argv) {
+ | const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
+ | contextp->commandArgs(argc, argv);
+ | const std::unique_ptr<V$topName> top{new V$topName{contextp.get(), "TOP"}};
+ | top->reset = 0;
+ | top->clock = 0;
+ | int a_b = 1;
+ | top->i_a_b = a_b;
+ | bool started = false;
+ | int ticks = 20;
+ | while (ticks--) {
+ | contextp->timeInc(1);
+ | top->clock = !top->clock;
+ | if (!top->clock) {
+ | if (contextp->time() > 1 && contextp->time() < 10) {
+ | top->reset = 1;
+ | } else {
+ | top->reset = 0;
+ | started = true;
+ | }
+ | a_b = a_b ? 0 : 1;
+ | top->i_a_b = a_b;
+ | }
+ | top->eval();
+ | VerilatedVpi::callValueCbs();
+ | if (started && !top->clock) {
+ | const int i = top->i_a_b;
+ | const int o = vpiGetInt("${vpiNames.head}");
+ | if (i == o)
+ | vl_fatal(__FILE__, __LINE__, "sim_main", "${vpiNames.head} should be the old value of Module1.i_a_b");
+ | printf("${vpiNames.head}=%d Module1.m0.o_a_b=%d\\n", i, o);
+ | }
+ | }
+ | top->final();
+ | return 0;
+ |}
+ |""".stripMargin
+ }
+
+ val config = os.temp(dir = testDir, contents = generateVerilatorConfigFile(Seq(dut.m0.o.a.b), annos))
+ val verilog = testDir / s"$topName.v"
+ val cpp = os.temp(dir = testDir, suffix = ".cpp", contents = verilatorTemplate(Seq(dut.m0.o.a.b), annos))
+ val exe = testDir / "obj_dir" / s"V$topName"
+ os.proc("verilator", "-Wall", "--cc", "--exe", "--build", "--vpi", s"$cpp", s"$verilog", s"$config").call(stdout = os.Inherit, stderr = os.Inherit, cwd = testDir)
+ assert(os.proc(s"$exe").call(stdout = os.Inherit, stderr = os.Inherit).exitCode == 0, "verilator should exit peacefully")
+ }
+
+ "TraceFromCollideBundle" should "work" in {
+ class CollideModule extends Module {
+ val a = IO(Input(Vec(2, new Bundle {
+ val b = Flipped(Bool())
+ val c = Vec(2, new Bundle {
+ val d = UInt(2.W)
+ val e = Flipped(UInt(3.W))
+ })
+ val c_1_e = UInt(4.W)
+ })))
+ val a_0_c = IO(Output(UInt(5.W)))
+ val a__0 = IO(Output(UInt(5.W)))
+ a_0_c := DontCare
+ a__0 := DontCare
+
+ traceName(a)
+ traceName(a_0_c)
+ traceName(a__0)
+ }
+
+ val (_, annos) = compile("TraceFromCollideBundle", () => new CollideModule)
+ val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[CollideModule]
+
+ val topName = "CollideModule"
+
+ val a0 = finalTarget(annos)(dut.a(0))
+ val a__0 = finalTarget(annos)(dut.a__0).head
+ val a__0_ref = refTarget(topName, "a__0")
+ a0.foreach(_ shouldNot be(a__0_ref))
+ a__0 should be(a__0_ref)
+
+ val a0_c = finalTarget(annos)(dut.a(0).c)
+ val a_0_c = finalTarget(annos)(dut.a_0_c).head
+ val a_0_c_ref = refTarget(topName, "a_0_c")
+ a0_c.foreach(_ shouldNot be(a_0_c_ref))
+ a_0_c should be(a_0_c_ref)
+
+ val a0_c1_e = finalTarget(annos)(dut.a(0).c(1).e).head
+ val a0_c_1_e = finalTarget(annos)(dut.a(0).c_1_e).head
+ a0_c1_e should be(refTarget(topName, "a_0_c__1_e"))
+ a0_c_1_e should be(refTarget(topName, "a_0_c_1_e"))
+ }
+
+ "Inline should work" should "work" in {
+ class Module0 extends Module {
+ val i = IO(Input(Bool()))
+ val o = IO(Output(Bool()))
+ traceName(i)
+ o := !i
+ }
+
+ class Module1 extends Module {
+ val i = IO(Input(Bool()))
+ val o = IO(Output(Bool()))
+ val m0 = Module(new Module0 with InlineInstance)
+ m0.i := i
+ o := m0.o
+ }
+
+ val (_, annos) = compile("Inline", () => new Module1)
+ val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[Module1]
+
+ val m0_i = finalTarget(annos)(dut.m0.i).head
+ m0_i should be(refTarget("Module1", "m0_i"))
+ }
+
+ "Constant Propagation" should "be turned off by traceName" in {
+ class Module0 extends Module {
+ val i = WireDefault(1.U)
+ val i0 = i + 1.U
+ val o = IO(Output(UInt(2.W)))
+ traceName(i0)
+ o := i0
+ }
+
+ val (_, annos) = compile("ConstantProp", () => new Module0)
+ val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[Module0]
+
+ val i0 = finalTarget(annos)(dut.i0).head
+ i0 should be(refTarget("Module0", "i0"))
+ }
+
+ "Nested Module" should "work" in {
+ class Io extends Bundle {
+ val i = Input(Bool())
+ val o = Output(Bool())
+ }
+
+ class Not extends Module {
+ val io = IO(new Io)
+ io.o := !io.i
+ }
+
+ class M1 extends Module {
+ val io = IO(new Io)
+ val not = Module(new Not)
+ not.io <> io
+ }
+
+ class M2 extends Module {
+ val io = IO(new Io)
+ val m1 = Module(new M1 with InlineInstance)
+ val not = Module(new Not)
+
+ m1.io.i := io.i
+ not.io.i := io.i
+
+ io.o := m1.io.o && not.io.o
+ }
+
+ class M3 extends Module {
+ val io = IO(new Io)
+ val m2 = Module(new M2)
+ io <> m2.io
+ traceName(m2.not)
+ traceName(m2.m1.not)
+ }
+
+ val (_, annos) = compile("NestedModule", () => new M3)
+ val m3 = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[M3]
+
+ val m2_m1_not = finalTarget(annos)(m3.m2.m1.not).head
+ val m2_not = finalTarget(annos)(m3.m2.not).head
+
+ m2_m1_not should be(instTarget("M3", "m1_not", "Not", Seq(Instance("m2") -> OfModule("M2"))))
+ m2_not should be(instTarget("M3", "not", "Not", Seq(Instance("m2") -> OfModule("M2"))))
+ }
+
+ "All traced signal" should "generate" in {
+ class M extends Module {
+ val a = Wire(Bool())
+ val b = Wire(Vec(2, Bool()))
+ a := DontCare
+ b := DontCare
+ Seq(a, b).foreach(traceName)
+ }
+ val (_, annos) = compile("NestedModule", () => new M)
+ val dut = annos.collectFirst { case DesignAnnotation(dut) => dut }.get.asInstanceOf[M]
+ val allTargets = finalTargetMap(annos)
+ allTargets(dut.a.toAbsoluteTarget) should be (Seq(refTarget("M", "a")))
+ allTargets(dut.b.toAbsoluteTarget) should be (Seq(
+ refTarget("M", "b_0"),
+ refTarget("M", "b_1"),
+ ))
+ allTargets(dut.b(0).toAbsoluteTarget) should be (Seq(refTarget("M", "b_0")))
+ allTargets(dut.b(1).toAbsoluteTarget) should be (Seq(refTarget("M", "b_1")))
+ }
+}
diff --git a/src/test/scala/chiselTests/experimental/Tuple.scala b/src/test/scala/chiselTests/experimental/Tuple.scala
new file mode 100644
index 00000000..5f897fbc
--- /dev/null
+++ b/src/test/scala/chiselTests/experimental/Tuple.scala
@@ -0,0 +1,163 @@
+// See LICENSE for license details.
+
+package chiselTests.experimental
+
+import chiselTests.ChiselFlatSpec
+import chisel3._
+import chisel3.experimental.conversions._
+import chisel3.stage.ChiselStage
+
+class TupleSpec extends ChiselFlatSpec {
+
+ behavior of "Tuple"
+
+ it should "enable using Tuple2 like Data" in {
+ class MyModule extends Module {
+ val a, b, c, d = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val y, z = IO(Output(UInt(8.W)))
+ (y, z) := Mux(sel, (a, b), (c, d))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ verilog should include ("assign y = sel ? a : c;")
+ verilog should include ("assign z = sel ? b : d;")
+ }
+
+ it should "support nesting of tuples" in {
+ class MyModule extends Module {
+ val a, b, c, d = IO(Input(UInt(8.W)))
+ val w, x, y, z = IO(Output(UInt(8.W)))
+ ((w, x), (y, z)) := ((a, b), (c, d))
+ }
+ val chirrtl = ChiselStage.emitChirrtl(new MyModule)
+ chirrtl should include ("w <= a")
+ chirrtl should include ("x <= b")
+ chirrtl should include ("y <= c")
+ chirrtl should include ("z <= d")
+ }
+
+ it should "enable using Tuple3 like Data" in {
+ class MyModule extends Module {
+ val a, b, c = IO(Input(UInt(8.W)))
+ val f, g, h = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val v, w, x = IO(Output(UInt(8.W)))
+ (v, w, x) := Mux(sel, (a, b, c), (f, g, h))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ verilog should include ("assign v = sel ? a : f;")
+ verilog should include ("assign w = sel ? b : g;")
+ verilog should include ("assign x = sel ? c : h;")
+ }
+
+ it should "enable using Tuple4 like Data" in {
+ class MyModule extends Module {
+ val a, b, c, d = IO(Input(UInt(8.W)))
+ val f, g, h, i = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val v, w, x, y = IO(Output(UInt(8.W)))
+ (v, w, x, y) := Mux(sel, (a, b, c, d), (f, g, h, i))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ verilog should include ("assign v = sel ? a : f;")
+ verilog should include ("assign w = sel ? b : g;")
+ verilog should include ("assign x = sel ? c : h;")
+ verilog should include ("assign y = sel ? d : i;")
+ }
+
+ it should "enable using Tuple5 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4) := Mux(sel, (a0, a1, a2, a3, a4), (b0, b1, b2, b3, b4))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 5) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple6 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5) := Mux(sel, (a0, a1, a2, a3, a4, a5), (b0, b1, b2, b3, b4, b5))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 6) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple7 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5, a6 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5, b6 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5, z6 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5, z6) := Mux(sel, (a0, a1, a2, a3, a4, a5, a6), (b0, b1, b2, b3, b4, b5, b6))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 7) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple8 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5, a6, a7 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5, b6, b7 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5, z6, z7 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5, z6, z7) := Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7), (b0, b1, b2, b3, b4, b5, b6, b7))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 8) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple9 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5, a6, a7, a8 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5, b6, b7, b8 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5, z6, z7, z8 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5, z6, z7, z8) :=
+ Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7, a8), (b0, b1, b2, b3, b4, b5, b6, b7, b8))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 9) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+ it should "enable using Tuple10 like Data" in {
+ class MyModule extends Module {
+ val a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = IO(Input(UInt(8.W)))
+ val b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 = IO(Input(UInt(8.W)))
+ val sel = IO(Input(Bool()))
+ val z0, z1, z2, z3, z4, z5, z6, z7, z8, z9 = IO(Output(UInt(8.W)))
+ (z0, z1, z2, z3, z4, z5, z6, z7, z8, z9) :=
+ Mux(sel, (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9))
+ }
+ // Verilog instead of CHIRRTL because the optimizations make it much prettier
+ val verilog = ChiselStage.emitVerilog(new MyModule)
+ for (i <- 0 until 10) {
+ verilog should include(s"assign z$i = sel ? a$i : b$i;")
+ }
+ }
+
+}
diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala b/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala
index 43111fdd..eba412f1 100644
--- a/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala
+++ b/src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala
@@ -5,24 +5,20 @@ package chiselTests.experimental.hierarchy
import _root_.firrtl.annotations._
import chisel3.experimental.{annotate, BaseModule}
import chisel3.Data
-import chisel3.experimental.hierarchy.{Instance, Definition}
+import chisel3.experimental.hierarchy.{Instance, Definition, Hierarchy}
object Annotations {
case class MarkAnnotation(target: IsMember, tag: String) extends SingleTargetAnnotation[IsMember] {
def duplicate(n: IsMember): Annotation = this.copy(target = n)
}
- case class MarkChiselInstanceAnnotation[B <: BaseModule](d: Instance[B], tag: String, isAbsolute: Boolean) extends chisel3.experimental.ChiselAnnotation {
- def toFirrtl = MarkAnnotation(d.toTarget, tag)
- }
- case class MarkChiselDefinitionAnnotation[B <: BaseModule](d: Definition[B], tag: String, isAbsolute: Boolean) extends chisel3.experimental.ChiselAnnotation {
+ case class MarkChiselHierarchyAnnotation[B <: BaseModule](d: Hierarchy[B], tag: String, isAbsolute: Boolean) extends chisel3.experimental.ChiselAnnotation {
def toFirrtl = MarkAnnotation(d.toTarget, tag)
}
case class MarkChiselAnnotation(d: Data, tag: String, isAbsolute: Boolean) extends chisel3.experimental.ChiselAnnotation {
def toFirrtl = if(isAbsolute) MarkAnnotation(d.toAbsoluteTarget, tag) else MarkAnnotation(d.toTarget, tag)
}
def mark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, false))
- def mark[B <: BaseModule](d: Instance[B], tag: String): Unit = annotate(MarkChiselInstanceAnnotation(d, tag, false))
- def mark[B <: BaseModule](d: Definition[B], tag: String): Unit = annotate(MarkChiselDefinitionAnnotation(d, tag, false))
+ def mark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true))
def amark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, true))
- def amark[B <: BaseModule](d: Instance[B], tag: String): Unit = annotate(MarkChiselInstanceAnnotation(d, tag, true))
+ def amark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true))
}
diff --git a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala
index 19261c36..f33f7869 100644
--- a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala
+++ b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala
@@ -40,6 +40,44 @@ class DefinitionSpec extends ChiselFunSpec with Utils {
val (chirrtl, _) = getFirrtlAndAnnos(new Top)
chirrtl.serialize should include ("inst i0 of HasUninferredReset")
}
+ it("0.3: module names of repeated definition should be sequential") {
+ class Top extends Module {
+ val k = Module(new AddTwoParameterized(4, (x: Int) => Seq.tabulate(x){j =>
+ val addOneDef = Definition(new AddOneParameterized(x+j))
+ val addOne = Instance(addOneDef)
+ addOne
+ }))
+ }
+ val (chirrtl, _) = getFirrtlAndAnnos(new Top)
+ chirrtl.serialize should include ("module AddOneParameterized :")
+ chirrtl.serialize should include ("module AddOneParameterized_1 :")
+ chirrtl.serialize should include ("module AddOneParameterized_2 :")
+ chirrtl.serialize should include ("module AddOneParameterized_3 :")
+ }
+ it("0.4: multiple instantiations should have sequential names") {
+ class Top extends Module {
+ val addOneDef = Definition(new AddOneParameterized(4))
+ val addOne = Instance(addOneDef)
+ val otherAddOne = Module(new AddOneParameterized(4))
+ }
+ val (chirrtl, _) = getFirrtlAndAnnos(new Top)
+ chirrtl.serialize should include ("module AddOneParameterized :")
+ chirrtl.serialize should include ("module AddOneParameterized_1 :")
+ }
+ it("0.5: nested definitions should have sequential names") {
+ class Top extends Module {
+ val k = Module(new AddTwoWithNested(4, (x: Int) => Seq.tabulate(x){j =>
+ val addOneDef = Definition(new AddOneWithNested(x+j))
+ val addOne = Instance(addOneDef)
+ addOne
+ }))
+ }
+ val (chirrtl, _) = getFirrtlAndAnnos(new Top)
+ chirrtl.serialize should include ("module AddOneWithNested :")
+ chirrtl.serialize should include ("module AddOneWithNested_1 :")
+ chirrtl.serialize should include ("module AddOneWithNested_2 :")
+ chirrtl.serialize should include ("module AddOneWithNested_3 :")
+ }
}
describe("1: Annotations on definitions in same chisel compilation") {
it("1.0: should work on a single definition, annotating the definition") {
@@ -97,7 +135,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils {
mark(definition.i1, "i0.i1")
}
val (_, annos) = getFirrtlAndAnnos(new Top)
- annos should contain(MarkAnnotation("~Top|AddTwoMixedModules/i1:AddOne_2".it, "i0.i1"))
+ annos should contain(MarkAnnotation("~Top|AddTwoMixedModules/i1:AddOne_1".it, "i0.i1"))
}
// Can you define an instantiable container? I think not.
// Instead, we can test the instantiable container in a definition
@@ -258,6 +296,17 @@ class DefinitionSpec extends ChiselFunSpec with Utils {
val (_, annos) = getFirrtlAndAnnos(new Top)
annos should contain(MarkAnnotation("~Top|HasPublicConstructorArgs>x".rt, "10"))
}
+ it("3.10: should work on unimplemented vals in abstract classes/traits") {
+ class Top() extends Module {
+ val i = Definition(new ConcreteHasBlah())
+ def f(d: Definition[HasBlah]): Unit = {
+ mark(d, d.blah.toString)
+ }
+ f(i)
+ }
+ val (_, annos) = getFirrtlAndAnnos(new Top)
+ annos should contain(MarkAnnotation("~Top|ConcreteHasBlah".mt, "10"))
+ }
}
describe("4: toDefinition") {
it("4.0: should work on modules") {
@@ -311,7 +360,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils {
amark(i.i1.in, "blah")
}
val (_, annos) = getFirrtlAndAnnos(new Top)
- annos should contain(MarkAnnotation("~Top|AddTwoMixedModules/i1:AddOne_2>in".rt, "blah"))
+ annos should contain(MarkAnnotation("~Top|AddTwoMixedModules/i1:AddOne_1>in".rt, "blah"))
}
it("5.3: toAbsoluteTarget on a submodule's data, in an aggregate, within a definition") {
class Top() extends Module {
@@ -319,7 +368,7 @@ class DefinitionSpec extends ChiselFunSpec with Utils {
amark(i.i1.x.head, "blah")
}
val (_, annos) = getFirrtlAndAnnos(new Top)
- annos should contain(MarkAnnotation("~Top|InstantiatesHasVec/i1:HasVec_2>x[0]".rt, "blah"))
+ annos should contain(MarkAnnotation("~Top|InstantiatesHasVec/i1:HasVec_1>x[0]".rt, "blah"))
}
}
describe("6: @instantiable traits should work as expected") {
diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala
index 23b8c9c0..c0f504ff 100644
--- a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala
+++ b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala
@@ -36,6 +36,19 @@ object Examples {
out := innerWire
}
@instantiable
+ class AddOneParameterized(width: Int) extends Module {
+ @public val in = IO(Input(UInt(width.W)))
+ @public val out = IO(Output(UInt(width.W)))
+ out := in + 1.U
+ }
+ class AddOneWithNested(width: Int) extends Module {
+ @public val in = IO(Input(UInt(width.W)))
+ @public val out = IO(Output(UInt(width.W)))
+ val addOneDef = Seq.fill(3)(Definition(new AddOne))
+ out := in + 1.U
+ }
+
+ @instantiable
class AddTwo extends Module {
@public val in = IO(Input(UInt(32.W)))
@public val out = IO(Output(UInt(32.W)))
@@ -58,6 +71,33 @@ object Examples {
out := i1.out
}
@instantiable
+ class AddTwoParameterized(width: Int, makeParameterizedOnes: Int => Seq[Instance[AddOneParameterized]]) extends Module {
+ val in = IO(Input(UInt(width.W)))
+ val out = IO(Output(UInt(width.W)))
+ val addOnes = makeParameterizedOnes(width)
+ addOnes.head.in := in
+ out := addOnes.last.out
+ addOnes.zip(addOnes.tail).foreach{ case (head, tail) => tail.in := head.out}
+ }
+ @instantiable
+ class AddTwoWithNested(width: Int, makeParameterizedOnes: Int => Seq[Instance[AddOneWithNested]]) extends Module {
+ val in = IO(Input(UInt(width.W)))
+ val out = IO(Output(UInt(width.W)))
+ val addOnes = makeParameterizedOnes(width)
+ }
+
+ @instantiable
+ class AddFour extends Module {
+ @public val in = IO(Input(UInt(32.W)))
+ @public val out = IO(Output(UInt(32.W)))
+ @public val definition = Definition(new AddTwoMixedModules)
+ @public val i0 = Instance(definition)
+ @public val i1 = Instance(definition)
+ i0.in := in
+ i1.in := i0.out
+ out := i1.out
+ }
+ @instantiable
class AggregatePortModule extends Module {
@public val io = IO(new Bundle {
val in = Input(UInt(32.W))
@@ -183,4 +223,17 @@ object Examples {
@public val out = IO(Output(UInt(3.W)))
out := RegNext(in)
}
+ @instantiable
+ abstract class HasBlah() extends Module {
+ @public val blah: Int
+ }
+
+ @instantiable
+ class ConcreteHasBlah() extends HasBlah {
+ val blah = 10
+ }
+ @instantiable
+ class HasTypeParams[D <: Data](d: D) extends Module {
+ @public val blah = Wire(d)
+ }
}
diff --git a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala
index 3866bf87..9ceb9b40 100644
--- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala
+++ b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala
@@ -89,7 +89,7 @@ class InstanceSpec extends ChiselFunSpec with Utils {
mark(i0.i1, "i0.i1")
}
val (_, annos) = getFirrtlAndAnnos(new Top)
- annos should contain (MarkAnnotation("~Top|Top/i0:AddTwoMixedModules/i1:AddOne_2".it, "i0.i1"))
+ annos should contain (MarkAnnotation("~Top|Top/i0:AddTwoMixedModules/i1:AddOne_1".it, "i0.i1"))
}
it("1.5: should work on an instantiable container, annotating a wire") {
class Top extends Module {
@@ -144,6 +144,15 @@ class InstanceSpec extends ChiselFunSpec with Utils {
val (_, annos) = getFirrtlAndAnnos(new Top)
annos should contain (MarkAnnotation("~Top|AddOneWithAnnotation>innerWire".rt, "innerWire"))
}
+ it("1.11: should work on things with type parameters"){
+ class Top extends Module {
+ val definition = Definition(new HasTypeParams[UInt](UInt(3.W)))
+ val i0 = Instance(definition)
+ mark(i0.blah, "blah")
+ }
+ val (_, annos) = getFirrtlAndAnnos(new Top)
+ annos should contain (MarkAnnotation("~Top|Top/i0:HasTypeParams>blah".rt, "blah"))
+ }
}
describe("2: Annotations on designs not in the same chisel compilation") {
it("2.0: should work on an innerWire, marked in a different compilation") {
@@ -353,7 +362,7 @@ class InstanceSpec extends ChiselFunSpec with Utils {
amark(i.i1.in, "blah")
}
val (_, annos) = getFirrtlAndAnnos(new Top)
- annos should contain(MarkAnnotation("~Top|Top/i:AddTwoMixedModules/i1:AddOne_2>in".rt, "blah"))
+ annos should contain(MarkAnnotation("~Top|Top/i:AddTwoMixedModules/i1:AddOne_1>in".rt, "blah"))
}
it("5.3: toAbsoluteTarget on a submodule's data, in an aggregate, within an instance") {
class Top() extends Module {
@@ -361,7 +370,7 @@ class InstanceSpec extends ChiselFunSpec with Utils {
amark(i.i1.x.head, "blah")
}
val (_, annos) = getFirrtlAndAnnos(new Top)
- annos should contain(MarkAnnotation("~Top|Top/i:InstantiatesHasVec/i1:HasVec_2>x[0]".rt, "blah"))
+ annos should contain(MarkAnnotation("~Top|Top/i:InstantiatesHasVec/i1:HasVec_1>x[0]".rt, "blah"))
}
it("5.4: toAbsoluteTarget on a submodule's data, in an aggregate, within an instance, ILit") {
class MyBundle extends Bundle { val x = UInt(3.W) }
@@ -379,7 +388,7 @@ class InstanceSpec extends ChiselFunSpec with Utils {
amark(i.i1.x.head.x, "blah")
}
val (_, annos) = getFirrtlAndAnnos(new Top)
- annos should contain(MarkAnnotation("~Top|Top/i:InstantiatesHasVec/i1:HasVec_2>x[0].x".rt, "blah"))
+ annos should contain(MarkAnnotation("~Top|Top/i:InstantiatesHasVec/i1:HasVec_1>x[0].x".rt, "blah"))
}
it("5.5: toAbsoluteTarget on a subinstance") {
class Top() extends Module {
@@ -620,7 +629,7 @@ class InstanceSpec extends ChiselFunSpec with Utils {
}
it("7.3: should work with DataView + implicit conversion") {
- import chiselTests.experimental.SeqToVec._
+ import chisel3.experimental.conversions._
@instantiable
class MyModule extends RawModule {
private val a = IO(Input(UInt(8.W)))
@@ -705,5 +714,142 @@ class InstanceSpec extends ChiselFunSpec with Utils {
}
}
}
+ describe("9: isA[..]") {
+ it("9.0: it should work on simple classes") {
+ class Top extends Module {
+ val d = Definition(new AddOne)
+ require(d.isA[AddOne])
+ }
+ getFirrtlAndAnnos(new Top)
+ }
+ it("9.1: it should not work on inner classes") {
+ class InnerClass extends Module
+ class Top extends Module {
+ val d = Definition(new InnerClass)
+ "require(d.isA[Module])" should compile // ensures that the test below is checking something useful
+ "require(d.isA[InnerClass])" shouldNot compile
+ }
+ getFirrtlAndAnnos(new Top)
+ }
+ it("9.2: it should work on super classes") {
+ class InnerClass extends Module
+ class Top extends Module {
+ val d = Definition(new InnerClass)
+ require(d.isA[Module])
+ }
+ getFirrtlAndAnnos(new Top)
+ }
+ it("9.2: it should work after casts") {
+ class Top extends Module {
+ val d0: Definition[Module] = Definition(new AddOne)
+ require(d0.isA[AddOne])
+ val d1: Definition[Module] = Definition((new AddOne).asInstanceOf[Module])
+ require(d1.isA[AddOne])
+ val i0: Instance[Module] = Instance(d0)
+ require(i0.isA[AddOne])
+ val i1: Instance[Module] = Instance(d1)
+ require(i1.isA[AddOne])
+ val i2: Instance[Module] = Instance(Definition(new AddOne))
+ require(i2.isA[AddOne])
+ }
+ getFirrtlAndAnnos(new Top)
+ }
+ }
+ describe("10: Select APIs") {
+ it("10.0: instancesOf") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules =>
+ val targets = aop.Select.instancesOf[AddOne](m.toDefinition).map { i: Instance[AddOne] => i.toTarget }
+ targets should be (Seq(
+ "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it,
+ "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it,
+ ))
+ })
+ getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect))
+ }
+ it("10.1: instancesIn") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules =>
+ val insts = aop.Select.instancesIn(m.toDefinition)
+ val abs = insts.map { i: Instance[BaseModule] => i.toAbsoluteTarget }
+ val rel = insts.map { i: Instance[BaseModule] => i.toTarget }
+ abs should be (Seq(
+ "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it,
+ "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it,
+ ))
+ rel should be (Seq(
+ "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it,
+ "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it,
+ ))
+ })
+ getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect))
+ }
+ it("10.2: allInstancesOf") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddFour =>
+ val insts = aop.Select.allInstancesOf[AddOne](m.toDefinition)
+ val abs = insts.map { i: Instance[AddOne] => i.in.toAbsoluteTarget }
+ val rel = insts.map { i: Instance[AddOne] => i.in.toTarget }
+ rel should be (Seq(
+ "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt,
+ "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt,
+ "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt,
+ "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt,
+ ))
+ abs should be (Seq(
+ "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt,
+ "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_1>in".rt,
+ "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt,
+ "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt,
+ ))
+ })
+ getFirrtlAndAnnos(new AddFour, Seq(aspect))
+ }
+ it("10.3: definitionsOf") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules =>
+ val targets = aop.Select.definitionsOf[AddOne](m.toDefinition).map { i: Definition[AddOne] => i.in.toTarget }
+ targets should be (Seq(
+ "~AddTwoMixedModules|AddOne>in".rt,
+ "~AddTwoMixedModules|AddOne_1>in".rt,
+ ))
+ })
+ getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect))
+ }
+ it("10.4: definitionsIn") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddTwoMixedModules =>
+ val targets = aop.Select.definitionsIn(m.toDefinition).map { i: Definition[BaseModule] => i.toTarget }
+ targets should be (Seq(
+ "~AddTwoMixedModules|AddOne".mt,
+ "~AddTwoMixedModules|AddOne_1".mt,
+ ))
+ })
+ getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect))
+ }
+ it("10.5: allDefinitionsOf") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddFour =>
+ val targets = aop.Select.allDefinitionsOf[AddOne](m.toDefinition).map { i: Definition[AddOne] => i.in.toTarget }
+ targets should be (Seq(
+ "~AddFour|AddOne>in".rt,
+ "~AddFour|AddOne_1>in".rt,
+ ))
+ })
+ getFirrtlAndAnnos(new AddFour, Seq(aspect))
+ }
+ it("10.6: Select.collectDeep should fail when combined with hierarchy package") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddFour =>
+ aop.Select.collectDeep(m) { case m: AddOne => m.toTarget }
+ })
+ intercept[Exception] { getFirrtlAndAnnos(new AddFour, Seq(aspect)) }
+ }
+ it("10.7: Select.getDeep should fail when combined with hierarchy package") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddFour =>
+ aop.Select.getDeep(m) { m: BaseModule => Nil }
+ })
+ intercept[Exception] { getFirrtlAndAnnos(new AddFour, Seq(aspect)) }
+ }
+ it("10.8: Select.instances should fail when combined with hierarchy package") {
+ val aspect = aop.inspecting.InspectingAspect({ m: AddFour =>
+ aop.Select.instances(m)
+ })
+ intercept[Exception] { getFirrtlAndAnnos(new AddFour, Seq(aspect)) }
+ }
+ }
}
diff --git a/src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala b/src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala
deleted file mode 100644
index 1e080739..00000000
--- a/src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala
+++ /dev/null
@@ -1,154 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package chiselTests.experimental.verification
-
-import chisel3._
-import chisel3.experimental.{ChiselAnnotation, verification => formal}
-import chisel3.stage.ChiselStage
-import chiselTests.ChiselPropSpec
-import firrtl.annotations.{ReferenceTarget, SingleTargetAnnotation}
-
-import java.io.File
-import org.scalatest.matchers.should.Matchers
-
-class SimpleTest extends Module {
- val io = IO(new Bundle{
- val in = Input(UInt(8.W))
- val out = Output(UInt(8.W))
- })
- io.out := io.in
- formal.cover(io.in === 3.U)
- when (io.in === 3.U) {
- formal.assume(io.in =/= 2.U)
- formal.assert(io.out === io.in)
- }
-}
-
-/** Dummy verification annotation.
- * @param target target of component to be annotated
- */
-case class VerifAnnotation(target: ReferenceTarget) extends SingleTargetAnnotation[ReferenceTarget] {
- def duplicate(n: ReferenceTarget): VerifAnnotation = this.copy(target = n)
-}
-
-object VerifAnnotation {
- /** Create annotation for a given verification component.
- * @param c component to be annotated
- */
- def annotate(c: experimental.BaseSim): Unit = {
- chisel3.experimental.annotate(new ChiselAnnotation {
- def toFirrtl: VerifAnnotation = VerifAnnotation(c.toTarget)
- })
- }
-}
-
-class VerificationSpec extends ChiselPropSpec with Matchers {
-
- def assertContains(s: Seq[String], x: String): Unit = {
- val containsLine = s.map(_.contains(x)).reduce(_ || _)
- assert(containsLine, s"\n $x\nwas not found in`\n ${s.mkString("\n ")}``")
- }
-
- property("basic equality check should work") {
- val fir = ChiselStage.emitChirrtl(new SimpleTest)
- val lines = fir.split("\n").map(_.trim)
-
- // reset guard around the verification statement
- assertContains(lines, "when _T_2 : @[VerificationSpec.scala")
- assertContains(lines, "cover(clock, _T, UInt<1>(\"h1\"), \"\")")
-
- assertContains(lines, "when _T_6 : @[VerificationSpec.scala")
- assertContains(lines, "assume(clock, _T_4, UInt<1>(\"h1\"), \"\")")
-
- assertContains(lines, "when _T_9 : @[VerificationSpec.scala")
- assertContains(lines, "assert(clock, _T_7, UInt<1>(\"h1\"), \"\")")
- }
-
- property("annotation of verification constructs should work") {
- /** Circuit that contains and annotates verification nodes. */
- class AnnotationTest extends Module {
- val io = IO(new Bundle{
- val in = Input(UInt(8.W))
- val out = Output(UInt(8.W))
- })
- io.out := io.in
- val cov = formal.cover(io.in === 3.U)
- val assm = formal.assume(io.in =/= 2.U)
- val asst = formal.assert(io.out === io.in)
- VerifAnnotation.annotate(cov)
- VerifAnnotation.annotate(assm)
- VerifAnnotation.annotate(asst)
- }
-
- // compile circuit
- val testDir = new File("test_run_dir", "VerificationAnnotationTests")
- (new ChiselStage).emitSystemVerilog(
- gen = new AnnotationTest,
- args = Array("-td", testDir.getPath)
- )
-
- // read in annotation file
- val annoFile = new File(testDir, "AnnotationTest.anno.json")
- annoFile should exist
- val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList
-
- // check for expected verification annotations
- exactly(3, annoLines) should include ("chiselTests.experimental.verification.VerifAnnotation")
- exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>asst")
- exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>assm")
- exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>cov")
-
- // read in FIRRTL file
- val firFile = new File(testDir, "AnnotationTest.fir")
- firFile should exist
- val firLines = scala.io.Source.fromFile(firFile).getLines.toList
-
- // check that verification components have expected names
- exactly(1, firLines) should include ("cover(clock, _T, UInt<1>(\"h1\"), \"\") : cov")
- exactly(1, firLines) should include ("assume(clock, _T_3, UInt<1>(\"h1\"), \"\") : assm")
- exactly(1, firLines) should include ("assert(clock, _T_6, UInt<1>(\"h1\"), \"\") : asst")
- }
-
- property("annotation of verification constructs with suggested name should work") {
- /** Circuit that annotates a renamed verification nodes. */
- class AnnotationRenameTest extends Module {
- val io = IO(new Bundle{
- val in = Input(UInt(8.W))
- val out = Output(UInt(8.W))
- })
- io.out := io.in
-
- val goodbye = formal.assert(io.in === 1.U)
- goodbye.suggestName("hello")
- VerifAnnotation.annotate(goodbye)
-
- VerifAnnotation.annotate(formal.assume(io.in =/= 2.U).suggestName("howdy"))
- }
-
- // compile circuit
- val testDir = new File("test_run_dir", "VerificationAnnotationRenameTests")
- (new ChiselStage).emitSystemVerilog(
- gen = new AnnotationRenameTest,
- args = Array("-td", testDir.getPath)
- )
-
- // read in annotation file
- val annoFile = new File(testDir, "AnnotationRenameTest.anno.json")
- annoFile should exist
- val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList
-
- // check for expected verification annotations
- exactly(2, annoLines) should include ("chiselTests.experimental.verification.VerifAnnotation")
- exactly(1, annoLines) should include ("~AnnotationRenameTest|AnnotationRenameTest>hello")
- exactly(1, annoLines) should include ("~AnnotationRenameTest|AnnotationRenameTest>howdy")
-
- // read in FIRRTL file
- val firFile = new File(testDir, "AnnotationRenameTest.fir")
- firFile should exist
- val firLines = scala.io.Source.fromFile(firFile).getLines.toList
-
- // check that verification components have expected names
- exactly(1, firLines) should include ("assert(clock, _T, UInt<1>(\"h1\"), \"\") : hello")
- exactly(1, firLines) should include ("assume(clock, _T_3, UInt<1>(\"h1\"), \"\") : howdy")
- }
-}