From 6e9740efd138523dca3de5a871104f91d884c476 Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Wed, 22 Sep 2021 02:56:13 +0800 Subject: implement trace API. (#2077) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>--- .../scala/chiselTests/experimental/TraceSpec.scala | 309 +++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 src/test/scala/chiselTests/experimental/TraceSpec.scala (limited to 'src/test') 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 + |#include + | + |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 contextp{new VerilatedContext}; + | contextp->commandArgs(argc, argv); + | const std::unique_ptr 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"))) + } +} -- cgit v1.2.3 From d1d38bd096fce8b92468720fbedc835ecda40e6b Mon Sep 17 00:00:00 2001 From: Kevin Laeufer Date: Thu, 23 Sep 2021 11:12:26 -0700 Subject: make all verification statements publically available (#2089) --- src/test/scala/chiselTests/PrintableSpec.scala | 8 +- src/test/scala/chiselTests/VerificationSpec.scala | 153 ++++++++++++++++++++ src/test/scala/chiselTests/aop/SelectSpec.scala | 7 +- .../verification/VerificationSpec.scala | 154 --------------------- 4 files changed, 160 insertions(+), 162 deletions(-) create mode 100644 src/test/scala/chiselTests/VerificationSpec.scala delete mode 100644 src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala (limited to 'src/test') diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala index 25b54966..95103352 100644 --- a/src/test/scala/chiselTests/PrintableSpec.scala +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -3,7 +3,7 @@ package chiselTests import chisel3._ -import chisel3.experimental.{BaseSim, ChiselAnnotation} +import chisel3.experimental.ChiselAnnotation import chisel3.stage.ChiselStage import chisel3.testers.BasicTester import firrtl.annotations.{ReferenceTarget, SingleTargetAnnotation} @@ -23,7 +23,7 @@ object PrintfAnnotation { /** Create annotation for a given [[printf]]. * @param c component to be annotated */ - def annotate(c: BaseSim): Unit = { + def annotate(c: VerificationStatement): Unit = { chisel3.experimental.annotate(new ChiselAnnotation { def toFirrtl: PrintfAnnotation = PrintfAnnotation(c.toTarget) }) @@ -246,7 +246,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { // check for expected annotations exactly(3, annoLines) should include ("chiselTests.PrintfAnnotation") exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>farewell") - exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>SIM") + exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>printf") exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>howdy") // read in FIRRTL file @@ -256,7 +256,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { // check that verification components have expected names exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "hello AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : howdy""") - exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "goodbye AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : SIM""") + exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "goodbye AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : printf""") exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "adieu AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : farewell""") } } diff --git a/src/test/scala/chiselTests/VerificationSpec.scala b/src/test/scala/chiselTests/VerificationSpec.scala new file mode 100644 index 00000000..2d7144df --- /dev/null +++ b/src/test/scala/chiselTests/VerificationSpec.scala @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chiselTests + +import chisel3._ +import chisel3.experimental.{ChiselAnnotation, verification => formal} +import chisel3.stage.ChiselStage +import firrtl.annotations.{ReferenceTarget, SingleTargetAnnotation} +import org.scalatest.matchers.should.Matchers + +import java.io.File + +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 + cover(io.in === 3.U) + when (io.in === 3.U) { + assume(io.in =/= 2.U) + 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: VerificationStatement): 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_10 : @[VerificationSpec.scala") + assertContains(lines, "assert(clock, _T_8, 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 = cover(io.in === 3.U) + val assm = chisel3.assume(io.in =/= 2.U) + val asst = chisel3.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.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_7, 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 = chisel3.assert(io.in === 1.U) + goodbye.suggestName("hello") + VerifAnnotation.annotate(goodbye) + + VerifAnnotation.annotate(chisel3.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.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_4, UInt<1>(\"h1\"), \"\") : howdy") + } +} diff --git a/src/test/scala/chiselTests/aop/SelectSpec.scala b/src/test/scala/chiselTests/aop/SelectSpec.scala index e09e78c8..2b47c6b8 100644 --- a/src/test/scala/chiselTests/aop/SelectSpec.scala +++ b/src/test/scala/chiselTests/aop/SelectSpec.scala @@ -133,11 +133,10 @@ class SelectSpec extends ChiselFlatSpec { { dut: SelectTester => Seq(Select.Stop( Seq( - When(Select.ops("eq")(dut).dropRight(1).last.asInstanceOf[Bool]), - When(dut.nreset), - WhenNot(dut.overflow) + When(Select.ops("eq")(dut)(1).asInstanceOf[Bool]), + When(dut.overflow) ), - 1, + 0, dut.clock )) } 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") - } -} -- cgit v1.2.3 From ce15ad50a5c175db06c3bba5e3bf46b6c5466c47 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Tue, 5 Oct 2021 10:27:18 -0700 Subject: Remove all Bundle cloneTypes and chiselRuntimeDeprecate its use (#2052) * Remove all manual cloneTypes and make it chisel runtime deprecated to add one * runtime deprecate cloneType with runtime reflection * [Backport this commit] Bundle: add check that override def cloneType still works (will be made an error later) * Plugin: make it an error to override cloneType and add a test for that * Docs: can't compile the cloneType anymore * BundleSpec: comment out failing test I cannot get to fail or ignore Co-authored-by: Jack Koenig --- src/test/scala/chiselTests/AutoClonetypeSpec.scala | 1 - src/test/scala/chiselTests/BundleSpec.scala | 17 ++++++++++++----- .../chiselTests/CompatibilityInteroperabilitySpec.scala | 5 ----- src/test/scala/chiselTests/CompatibilitySpec.scala | 2 -- src/test/scala/chiselTests/CompileOptionsTest.scala | 2 -- src/test/scala/chiselTests/ComplexAssign.scala | 5 +---- src/test/scala/chiselTests/PrintableSpec.scala | 1 - src/test/scala/chiselTests/RecordSpec.scala | 1 - 8 files changed, 13 insertions(+), 21 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/AutoClonetypeSpec.scala b/src/test/scala/chiselTests/AutoClonetypeSpec.scala index fcbc4785..3f33fda8 100644 --- a/src/test/scala/chiselTests/AutoClonetypeSpec.scala +++ b/src/test/scala/chiselTests/AutoClonetypeSpec.scala @@ -327,7 +327,6 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { it should "support Bundles that implement their own cloneType" in { class MyBundle(i: Int) extends Bundle { val foo = UInt(i.W) - override def cloneType = new MyBundle(i).asInstanceOf[this.type] } elaborate { new MultiIOModule { val in = IO(Input(new MyBundle(8))) diff --git a/src/test/scala/chiselTests/BundleSpec.scala b/src/test/scala/chiselTests/BundleSpec.scala index 1d392f5c..51dedfb1 100644 --- a/src/test/scala/chiselTests/BundleSpec.scala +++ b/src/test/scala/chiselTests/BundleSpec.scala @@ -10,25 +10,20 @@ trait BundleSpecUtils { class BundleFooBar extends Bundle { val foo = UInt(16.W) val bar = UInt(16.W) - override def cloneType: this.type = (new BundleFooBar).asInstanceOf[this.type] } class BundleBarFoo extends Bundle { val bar = UInt(16.W) val foo = UInt(16.W) - override def cloneType: this.type = (new BundleBarFoo).asInstanceOf[this.type] } class BundleFoo extends Bundle { val foo = UInt(16.W) - override def cloneType: this.type = (new BundleFoo).asInstanceOf[this.type] } class BundleBar extends Bundle { val bar = UInt(16.W) - override def cloneType: this.type = (new BundleBar).asInstanceOf[this.type] } class BadSeqBundle extends Bundle { val bar = Seq(UInt(16.W), UInt(8.W), UInt(4.W)) - override def cloneType: this.type = (new BadSeqBundle).asInstanceOf[this.type] } class MyModule(output: Bundle, input: Bundle) extends Module { @@ -162,4 +157,16 @@ class BundleSpec extends ChiselFlatSpec with BundleSpecUtils with Utils { } } } + + // This tests the interaction of override def cloneType and the plugin. + // We are commenting it for now because although this code fails to compile + // as expected when just copied here, the test version is not seeing the failure. + // """ + // class BundleBaz(w: Int) extends Bundle { + // val baz = UInt(w.W) + // // This is a compiler error when using the plugin, which we test below. + // override def cloneType = (new BundleBaz(w)).asInstanceOf[this.type] + // } + // """ shouldNot compile + } diff --git a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala index 1795cc1f..4b03dfa5 100644 --- a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala @@ -12,8 +12,6 @@ object CompatibilityComponents { class ChiselBundle extends Bundle { val a = UInt(width = 32) val b = UInt(width = 32).flip - - override def cloneType: this.type = (new ChiselBundle).asInstanceOf[this.type] } class ChiselRecord extends Record { val elements = ListMap("a" -> UInt(width = 32), "b" -> UInt(width = 32).flip) @@ -48,8 +46,6 @@ object Chisel3Components { class Chisel3Bundle extends Bundle { val a = Output(UInt(32.W)) val b = Input(UInt(32.W)) - - override def cloneType: this.type = (new Chisel3Bundle).asInstanceOf[this.type] } class Chisel3Record extends Record { @@ -341,7 +337,6 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec { val foo = maybeFlip(new Bundle { val bar = UInt(INPUT, width = 8) }) - override def cloneType = (new MyBundle(extraFlip)).asInstanceOf[this.type] } } import chisel3._ diff --git a/src/test/scala/chiselTests/CompatibilitySpec.scala b/src/test/scala/chiselTests/CompatibilitySpec.scala index 2d4ad517..bf8cd3fc 100644 --- a/src/test/scala/chiselTests/CompatibilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilitySpec.scala @@ -195,11 +195,9 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck class SmallBundle extends Bundle { val f1 = UInt(width = 4) val f2 = UInt(width = 5) - override def cloneType: this.type = (new SmallBundle).asInstanceOf[this.type] } class BigBundle extends SmallBundle { val f3 = UInt(width = 6) - override def cloneType: this.type = (new BigBundle).asInstanceOf[this.type] } "A Module with missing bundle fields when compiled with the Chisel compatibility package" should "not throw an exception" in { diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 9c88c1e0..1ecf97f0 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -14,11 +14,9 @@ class CompileOptionsSpec extends ChiselFlatSpec with Utils { class SmallBundle extends Bundle { val f1 = UInt(4.W) val f2 = UInt(5.W) - override def cloneType: this.type = (new SmallBundle).asInstanceOf[this.type] } class BigBundle extends SmallBundle { val f3 = UInt(6.W) - override def cloneType: this.type = (new BigBundle).asInstanceOf[this.type] } "A Module with missing bundle fields when compiled with implicit Strict.CompileOption " should "throw an exception" in { diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 36fb59c2..222b6373 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -7,10 +7,7 @@ import chisel3.testers.BasicTester import chisel3.util._ import org.scalacheck.Shrink -class Complex[T <: Data](val re: T, val im: T) extends Bundle { - override def cloneType: this.type = - new Complex(re.cloneType, im.cloneType).asInstanceOf[this.type] -} +class Complex[T <: Data](val re: T, val im: T) extends Bundle class ComplexAssign(w: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala index 95103352..c7e819ec 100644 --- a/src/test/scala/chiselTests/PrintableSpec.scala +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -139,7 +139,6 @@ class PrintableSpec extends AnyFlatSpec with Matchers { } class MyBundle extends Bundle { val foo = UInt(32.W) - override def cloneType: this.type = (new MyBundle).asInstanceOf[this.type] } class MyModule extends BasicTester { override def desiredName: String = "MyModule" diff --git a/src/test/scala/chiselTests/RecordSpec.scala b/src/test/scala/chiselTests/RecordSpec.scala index c21d455c..f0edca8b 100644 --- a/src/test/scala/chiselTests/RecordSpec.scala +++ b/src/test/scala/chiselTests/RecordSpec.scala @@ -12,7 +12,6 @@ trait RecordSpecUtils { class MyBundle extends Bundle { val foo = UInt(32.W) val bar = UInt(32.W) - override def cloneType: this.type = (new MyBundle).asInstanceOf[this.type] } // Useful for constructing types from CustomBundle // This is a def because each call to this needs to return a new instance -- cgit v1.2.3 From 110705eeace4f9165dc6377e55c86a599f37a465 Mon Sep 17 00:00:00 2001 From: Jared Barocsi Date: Tue, 5 Oct 2021 12:33:23 -0700 Subject: Deprecate auto-application of empty argument lists to parameterless functions (#2124) * Migrate nullary funcs to parameterless versions * Make deprecation message and dummy arguments clear and consistent Co-authored-by: Megan Wachs --- src/test/scala/chiselTests/SIntOps.scala | 2 +- src/test/scala/chiselTests/StrongEnum.scala | 4 +-- src/test/scala/chiselTests/VecLiteralSpec.scala | 48 ++++++++++++------------- 3 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/SIntOps.scala b/src/test/scala/chiselTests/SIntOps.scala index f2e238e9..222d0ba7 100644 --- a/src/test/scala/chiselTests/SIntOps.scala +++ b/src/test/scala/chiselTests/SIntOps.scala @@ -44,7 +44,7 @@ class SIntOps extends Module { io.noteqout := (a =/= b) io.lesseqout := a <= b io.greateqout := a >= b - // io.negout := -a(15, 0).toSInt + io.negout := -a(15, 0).asSInt io.negout := (0.S -% a) } diff --git a/src/test/scala/chiselTests/StrongEnum.scala b/src/test/scala/chiselTests/StrongEnum.scala index d7dea571..404c3f66 100644 --- a/src/test/scala/chiselTests/StrongEnum.scala +++ b/src/test/scala/chiselTests/StrongEnum.scala @@ -257,8 +257,8 @@ class IsLitTester extends BasicTester { for (e <- EnumExample.all) { val wire = WireDefault(e) - assert(e.isLit()) - assert(!wire.isLit()) + assert(e.isLit) + assert(!wire.isLit) } stop() } diff --git a/src/test/scala/chiselTests/VecLiteralSpec.scala b/src/test/scala/chiselTests/VecLiteralSpec.scala index d91cd2f4..74d8c005 100644 --- a/src/test/scala/chiselTests/VecLiteralSpec.scala +++ b/src/test/scala/chiselTests/VecLiteralSpec.scala @@ -142,17 +142,17 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { "lowest of vec literal contains least significant bits and " in { val y = Vec(4, UInt(8.W)).Lit(0 -> 0xAB.U(8.W), 1 -> 0xCD.U(8.W), 2 -> 0xEF.U(8.W), 3 -> 0xFF.U(8.W)) - y.litValue() should be(BigInt("FFEFCDAB", 16)) + y.litValue should be(BigInt("FFEFCDAB", 16)) } "the order lits are specified does not matter" in { val y = Vec(4, UInt(8.W)).Lit(3 -> 0xFF.U(8.W), 2 -> 0xEF.U(8.W), 1 -> 0xCD.U(8.W), 0 -> 0xAB.U(8.W)) - y.litValue() should be(BigInt("FFEFCDAB", 16)) + y.litValue should be(BigInt("FFEFCDAB", 16)) } "regardless of the literals widths, packing should be done based on the width of the Vec's gen" in { val z = Vec(4, UInt(8.W)).Lit(0 -> 0x2.U, 1 -> 0x2.U, 2 -> 0x2.U, 3 -> 0x3.U) - z.litValue() should be(BigInt("03020202", 16)) + z.litValue should be(BigInt("03020202", 16)) } "packing sparse vec lits should not pack, litOption returns None" in { @@ -221,7 +221,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { chisel3.assert(outsideVecLit(2) === 0xBB.U) chisel3.assert(outsideVecLit(3) === 0xAA.U) - chisel3.assert(outsideVecLit.litValue().U === outsideVecLit.asUInt()) + chisel3.assert(outsideVecLit.litValue.U === outsideVecLit.asUInt()) val insideVecLit = Vec(4, UInt(16.W)).Lit(0 -> 0xDD.U, 1 -> 0xCC.U, 2 -> 0xBB.U, 3 -> 0xAA.U) chisel3.assert(insideVecLit(0) === 0xDD.U) @@ -277,15 +277,15 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { 1 -> Vec(3, UInt(4.W)).Lit(0 -> 4.U, 1 -> 5.U, 2 -> 6.U) ) - outerVec.litValue() should be (BigInt("654321", 16)) - outerVec(0).litValue() should be (BigInt("321", 16)) - outerVec(1).litValue() should be (BigInt("654", 16)) - outerVec(0)(0).litValue() should be (BigInt(1)) - outerVec(0)(1).litValue() should be (BigInt(2)) - outerVec(0)(2).litValue() should be (BigInt(3)) - outerVec(1)(0).litValue() should be (BigInt(4)) - outerVec(1)(1).litValue() should be (BigInt(5)) - outerVec(1)(2).litValue() should be (BigInt(6)) + outerVec.litValue should be (BigInt("654321", 16)) + outerVec(0).litValue should be (BigInt("321", 16)) + outerVec(1).litValue should be (BigInt("654", 16)) + outerVec(0)(0).litValue should be (BigInt(1)) + outerVec(0)(1).litValue should be (BigInt(2)) + outerVec(0)(2).litValue should be (BigInt(3)) + outerVec(1)(0).litValue should be (BigInt(4)) + outerVec(1)(1).litValue should be (BigInt(5)) + outerVec(1)(2).litValue should be (BigInt(6)) } "contained vecs should work" in { @@ -473,19 +473,19 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { 0 -> (new SubBundle).Lit(_.foo -> 0xab.U, _.bar -> 0xc.U), 1 -> (new SubBundle).Lit(_.foo -> 0xde.U, _.bar -> 0xf.U) ) - vec.litValue().toString(16) should be("defabc") + vec.litValue.toString(16) should be("defabc") } "vec literals can have bundle children assembled incrementally" in { val bundle1 = (new SubBundle).Lit(_.foo -> 0xab.U, _.bar -> 0xc.U) val bundle2 = (new SubBundle).Lit(_.foo -> 0xde.U, _.bar -> 0xf.U) - bundle1.litValue().toString(16) should be("abc") - bundle2.litValue().toString(16) should be("def") + bundle1.litValue.toString(16) should be("abc") + bundle2.litValue.toString(16) should be("def") val vec = Vec(2, new SubBundle).Lit(0 -> bundle1, 1 -> bundle2) - vec.litValue().toString(16) should be("defabc") + vec.litValue.toString(16) should be("defabc") } "bundles can contain vec lits" in { @@ -495,7 +495,7 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { val foo = Vec(3, UInt(4.W)) val bar = Vec(2, UInt(4.W)) }).Lit(_.foo -> vec1, _.bar -> vec2) - bundle.litValue().toString(16) should be("cbaed") + bundle.litValue.toString(16) should be("cbaed") } "bundles can contain vec lits in-line" in { @@ -506,21 +506,21 @@ class VecLiteralSpec extends ChiselFreeSpec with Utils { _.foo -> Vec(3, UInt(4.W)).Lit(0 -> 0xa.U, 1 -> 0xb.U, 2 -> 0xc.U), _.bar -> Vec(2, UInt(4.W)).Lit(0 -> 0xd.U, 1 -> 0xe.U) ) - bundle.litValue().toString(16) should be("cbaed") + bundle.litValue.toString(16) should be("cbaed") } "Vec.Lit is a trivial Vec literal factory" in { val vec = Vec.Lit(0xa.U, 0xb.U) - vec(0).litValue() should be(0xa) - vec(1).litValue() should be(0xb) + vec(0).litValue should be(0xa) + vec(1).litValue should be(0xb) } "Vec.Lit bases it's element width on the widest literal supplied" in { val vec = Vec.Lit(0xa.U, 0xbbbb.U) - vec(0).litValue() should be(0xa) - vec(1).litValue() should be(0xbbbb) + vec(0).litValue should be(0xa) + vec(1).litValue should be(0xbbbb) vec.length should be(2) vec.getWidth should be(16 * 2) - vec.litValue() should be(BigInt("bbbb000a", 16)) + vec.litValue should be(BigInt("bbbb000a", 16)) } } -- cgit v1.2.3 From c2985aa6ef95a45d6ce9663a17f835eaba0cb9c5 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Tue, 5 Oct 2021 13:20:28 -0700 Subject: Fix naming of unwrapped val io in Chisel.Modules (#2150) The removal of virtual method io accidentally made the naming of io in compatibility mode Bundles sensitive to the prefix at the time of the first access of the field. It also made .suggestName able to override the name. This commit fixes that issue by forcing the name of the io Data to be "io" no matter what.--- src/test/scala/chiselTests/CompatibilitySpec.scala | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/CompatibilitySpec.scala b/src/test/scala/chiselTests/CompatibilitySpec.scala index bf8cd3fc..ccf287a6 100644 --- a/src/test/scala/chiselTests/CompatibilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilitySpec.scala @@ -564,4 +564,32 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck verilog should include ("assign io_out_0 = io_in_0;") } + it should "ignore .suggestName on field io" in { + class MyModule extends Module { + val io = new Bundle { + val foo = UInt(width = 8).asInput + val bar = UInt(width = 8).asOutput + } + io.suggestName("potato") + io.bar := io.foo + } + val verilog = ChiselStage.emitVerilog(new MyModule) + verilog should include ("input [7:0] io_foo") + verilog should include ("output [7:0] io_bar") + } + + it should "properly name field io" in { + class MyModule extends Module { + val io = new Bundle { + val foo = UInt(width = 8).asInput + val bar = UInt(width = 8).asOutput + } + val wire = Wire(init = io.foo) + io.bar := wire + } + val verilog = ChiselStage.emitVerilog(new MyModule) + verilog should include ("input [7:0] io_foo") + verilog should include ("output [7:0] io_bar") + } + } -- cgit v1.2.3 From bdba21b032e592b21d117a8d68f166ba3834c205 Mon Sep 17 00:00:00 2001 From: Kamyar Mohajerani Date: Tue, 5 Oct 2021 18:12:57 -0400 Subject: Circular-shift (rotate) operations for UInt (#1140) * change static shift behavior to mod width when width is known * add dynamic shift * basic tests that actually do something * MatchedRotateLeftAndRight based on the idea from @chick * BasicRotate rotate "b001" and compare with known values * Fix check for KnownWidth(0|1) as suggested by @aswaterman * Add dontTouch to UIntOps.io (other tests were also optimized out) Co-authored-by: Chick Markley Co-authored-by: Andrew Waterman --- src/test/scala/chiselTests/UIntOps.scala | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/UIntOps.scala b/src/test/scala/chiselTests/UIntOps.scala index 62d00de2..bc6454b8 100644 --- a/src/test/scala/chiselTests/UIntOps.scala +++ b/src/test/scala/chiselTests/UIntOps.scala @@ -6,6 +6,7 @@ import chisel3._ import org.scalatest._ import chisel3.stage.ChiselStage import chisel3.testers.BasicTester +import chisel3.util._ import org.scalacheck.Shrink import org.scalatest.matchers.should.Matchers @@ -22,6 +23,8 @@ class UIntOps extends Module { val modout = Output(UInt(32.W)) val lshiftout = Output(UInt(32.W)) val rshiftout = Output(UInt(32.W)) + val lrotateout = Output(UInt(32.W)) + val rrotateout = Output(UInt(32.W)) val lessout = Output(Bool()) val greatout = Output(Bool()) val eqout = Output(Bool()) @@ -30,6 +33,8 @@ class UIntOps extends Module { val greateqout = Output(Bool()) }) + dontTouch(io) + val a = io.a val b = io.b @@ -42,6 +47,8 @@ class UIntOps extends Module { io.modout := a % b io.lshiftout := (a << b(3, 0))(31, 0) io.rshiftout := a >> b + io.lrotateout := a.rotateLeft(5) + io.rrotateout := a.rotateRight(5) io.lessout := a < b io.greatout := a > b io.eqout := a === b @@ -67,6 +74,14 @@ class UIntOpsTester(a: Long, b: Long) extends BasicTester { assert(dut.io.modout === (a % (b max 1)).U(32.W)) assert(dut.io.lshiftout === (a << (b % 16)).U(32.W)) assert(dut.io.rshiftout === (a >> b).U(32.W)) + assert( + dut.io.lrotateout === s"h${Integer.rotateLeft(a.toInt, 5).toHexString}" + .U(32.W) + ) + assert( + dut.io.rrotateout === s"h${Integer.rotateRight(a.toInt, 5).toHexString}" + .U(32.W) + ) assert(dut.io.lessout === (a < b).B) assert(dut.io.greatout === (a > b).B) assert(dut.io.eqout === (a == b).B) @@ -98,6 +113,65 @@ class NegativeShift(t: => Bits) extends Module { Reg(t) >> -1 } +class BasicRotate extends BasicTester { + val shiftAmount = random.LFSR(4) + val ctr = RegInit(0.U(4.W)) + + + val rotL = 1.U(3.W).rotateLeft(shiftAmount) + val rotR = 1.U(3.W).rotateRight(shiftAmount) + + printf("Shift amount: %d rotateLeft:%b rotateRight:%b\n", shiftAmount, rotL, rotR) + + switch(shiftAmount % 3.U) { + is(0.U, 3.U) { + assert(rotL === "b001".U) + assert(rotR === "b001".U) + } + is(1.U) { + assert(rotL === "b010".U) + assert(rotR === "b100".U) + } + is(2.U) { + assert(rotL === "b100".U) + assert(rotR === "b010".U) + } + } + + ctr := ctr + 1.U + + when (ctr === 15.U){ + stop() + } +} + +/** rotating a w-bit word left by n should be equivalent to rotating it by w - n + * to the left + */ +class MatchedRotateLeftAndRight(w: Int = 13) extends BasicTester { + val initValue = BigInt(w, scala.util.Random) + println(s"Initial value: ${initValue.toString(2)}") + + val maxWidthBits = log2Ceil(w + 1) + val shiftAmount1 = RegInit(0.U(w.W)) + val shiftAmount2 = RegInit(w.U(w.W)) + shiftAmount1 := shiftAmount1 + 1.U + shiftAmount2 := shiftAmount2 - 1.U + + val value = RegInit(initValue.U(w.W)) + + val out1 = value.rotateLeft(shiftAmount1) + val out2 = value.rotateRight(shiftAmount2) + + printf("rotateLeft by %d: %b\n", shiftAmount1, out1) + + assert(out1 === out2) + when(shiftAmount1 === w.U) { + assert(out1 === initValue.U) + stop() + } +} + class UIntLitExtractTester extends BasicTester { assert("b101010".U(2) === false.B) assert("b101010".U(3) === true.B) @@ -140,6 +214,16 @@ class UIntOpsSpec extends ChiselPropSpec with Matchers with Utils { } } + property("rotateLeft and rotateRight should work for dynamic shift values") { + assertTesterPasses(new BasicRotate) + } + + property( + "rotateLeft and rotateRight should be consistent for dynamic shift values" + ) { + assertTesterPasses(new MatchedRotateLeftAndRight) + } + property("Bit extraction on literals should work for all non-negative indices") { assertTesterPasses(new UIntLitExtractTester) } -- cgit v1.2.3 From baaa2adcbfcf4fb508d8e5e71345afd1d7e5a352 Mon Sep 17 00:00:00 2001 From: Chick Markley Date: Thu, 7 Oct 2021 14:31:16 -0700 Subject: Fixed bug with unary minus on FixedPoint and Interval (#2154) In `Bits.scala`, `FixedPoint` and `Interval` did not defeine the `do_unary_-` methods (the `do_`) was missing The recent PR #2124 combined with the above fact made DspTools break. This fix is necessary to get that repo to build.--- src/test/scala/chiselTests/FixedPointSpec.scala | 3 +++ src/test/scala/chiselTests/IntervalSpec.scala | 7 +++++++ 2 files changed, 10 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/FixedPointSpec.scala b/src/test/scala/chiselTests/FixedPointSpec.scala index a1acdb17..2530bb13 100644 --- a/src/test/scala/chiselTests/FixedPointSpec.scala +++ b/src/test/scala/chiselTests/FixedPointSpec.scala @@ -60,6 +60,9 @@ class FixedPointFromBitsTester extends BasicTester { val negativefp = (-3.5).F(4.BP) val positivefp = 3.5.F(4.BP) + assert(- positivefp === negativefp) + assert(positivefp === -negativefp) + assert(uint2fp === uint_result) assert(sint2fp === sint_result) assert(fp2fp === fp_result) diff --git a/src/test/scala/chiselTests/IntervalSpec.scala b/src/test/scala/chiselTests/IntervalSpec.scala index abc619e5..a33cedc1 100644 --- a/src/test/scala/chiselTests/IntervalSpec.scala +++ b/src/test/scala/chiselTests/IntervalSpec.scala @@ -406,6 +406,13 @@ class IntervalChainedSubTester extends BasicTester { assert(intervalResult1 === 5.I) assert(intervalResult2 === 5.I) + val negativeInterval = (-3.5).I(4.BP) + val positiveInterval = 3.5.I(4.BP) + + assert(negativeInterval =/= positiveInterval) + assert(-negativeInterval === positiveInterval) + assert(negativeInterval === -positiveInterval) + stop() } -- cgit v1.2.3 From 7930544e9c8047f27285420204d25f78c753ea57 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Fri, 8 Oct 2021 09:07:04 -0700 Subject: Add nullary .fire to Valid and deprecate dummy version (#2156) Also replace all uses of .fire() with .fire--- src/test/scala/chiselTests/QueueFlushSpec.scala | 20 ++++++++--------- src/test/scala/chiselTests/QueueSpec.scala | 30 ++++++++++++------------- 2 files changed, 25 insertions(+), 25 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/QueueFlushSpec.scala b/src/test/scala/chiselTests/QueueFlushSpec.scala index 11a411a8..9e0c6bb4 100644 --- a/src/test/scala/chiselTests/QueueFlushSpec.scala +++ b/src/test/scala/chiselTests/QueueFlushSpec.scala @@ -40,11 +40,11 @@ abstract class FlushQueueTesterBase(elements: Seq[Int], queueDepth: Int, bitWidt q.io.deq.ready := LFSR(16)(tap) q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire()) { + when(q.io.enq.fire) { inCnt.inc() currQCnt := currQCnt + 1.U //counts how many items have been enqueued } - when(q.io.deq.fire()) { + when(q.io.deq.fire) { assert(flushRegister === false.B) //check queue isn't flushed (can't dequeue an empty queue) } when(flushRegister) { //Internal signal maybe_full is a register so some signals update on the next cycle @@ -70,18 +70,18 @@ class QueueGetsFlushedTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, flush := LFSR(16)((tap + 3) % 16) //testing a flush when flush is called randomly val halfCnt = (queueDepth + 1)/2 - when(q.io.deq.fire()) { + when(q.io.deq.fire) { //ensure that what comes out is what comes in assert(currQCnt <= queueDepth.U) assert(elems(outCnt) === q.io.deq.bits) outCnt := outCnt + 1.U when (currQCnt > 0.U) { - currQCnt := Mux(q.io.enq.fire(), currQCnt, (currQCnt - 1.U)) + currQCnt := Mux(q.io.enq.fire, currQCnt, (currQCnt - 1.U)) } } when(flush) { assert(currQCnt === 0.U || q.io.deq.valid) - outCnt := outCnt + Mux(q.io.enq.fire(), (currQCnt + 1.U), currQCnt) + outCnt := outCnt + Mux(q.io.enq.fire, (currQCnt + 1.U), currQCnt) currQCnt := 0.U //resets the number of items currently inside queue } } @@ -102,7 +102,7 @@ class EmptyFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidth: I flush := (cycleCounter.value === 0.U && inCnt.value === 0.U) //flushed only before anything is enqueued q.io.enq.valid := (inCnt.value < elements.length.U) && !flush - when(q.io.deq.fire()) { + when(q.io.deq.fire) { assert(elems(outCnt) === q.io.deq.bits) outCnt := outCnt + 1.U } @@ -124,7 +124,7 @@ class EnqueueEmptyFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitW flush := (cycleCounter.value === 0.U && inCnt.value === 0.U) //flushed only before anything is enqueued cycleCounter.inc() //counts every cycle - when(q.io.deq.fire()) { + when(q.io.deq.fire) { //flush and enqueue were both active on the first cycle, //so that element is flushed immediately which makes outCnt off by one assert(elems(outCounter.value + 1.U) === q.io.deq.bits) //ensure that what comes out is what comes in @@ -145,7 +145,7 @@ class FullQueueFlushEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWidt //testing a flush when queue is full flush := (currQCnt === queueDepth.U) - when(q.io.deq.fire()) { + when(q.io.deq.fire) { //ensure that what comes out is what comes in assert(currQCnt <= queueDepth.U) assert(elems(outCnt) === q.io.deq.bits) @@ -177,7 +177,7 @@ class DequeueFullQueueEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWi q.io.enq.valid := !flushRegister q.io.deq.ready := flush - when(q.io.deq.fire()) { + when(q.io.deq.fire) { //ensure that what comes out is what comes in assert(currQCnt <= queueDepth.U) assert(elems(outCnt) === q.io.deq.bits) @@ -191,7 +191,7 @@ class DequeueFullQueueEdgecaseTester (elements: Seq[Int], queueDepth: Int, bitWi } when(flushRegister) { //check that queue gets flushed when queue is full - assert(q.io.deq.fire() === false.B) + assert(q.io.deq.fire === false.B) } } diff --git a/src/test/scala/chiselTests/QueueSpec.scala b/src/test/scala/chiselTests/QueueSpec.scala index 51b899cb..9eb6c20c 100644 --- a/src/test/scala/chiselTests/QueueSpec.scala +++ b/src/test/scala/chiselTests/QueueSpec.scala @@ -21,10 +21,10 @@ class ThingsPassThroughTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int q.io.deq.ready := LFSR(16)(tap) q.io.flush.foreach { _ := false.B } //Flush behavior is tested in QueueFlushSpec q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire()) { + when(q.io.enq.fire) { inCnt.inc() } - when(q.io.deq.fire()) { + when(q.io.deq.fire) { //ensure that what comes out is what comes in assert(elems(outCnt.value) === q.io.deq.bits) outCnt.inc() @@ -51,10 +51,10 @@ class QueueReasonableReadyValid(elements: Seq[Int], queueDepth: Int, bitWidth: I assert(q.io.deq.valid || q.io.count === 0.U) q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire()) { + when(q.io.enq.fire) { inCnt.inc() } - when(q.io.deq.fire()) { + when(q.io.deq.fire) { outCnt.inc() } when(outCnt.value === elements.length.U) { @@ -74,11 +74,11 @@ class CountIsCorrectTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, t q.io.deq.ready := LFSR(16)(tap) q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire()) { + when(q.io.enq.fire) { inCnt.inc() assert(q.io.count === (inCnt.value - outCnt.value)) } - when(q.io.deq.fire()) { + when(q.io.deq.fire) { outCnt.inc() assert(q.io.count === (inCnt.value - outCnt.value)) } @@ -103,10 +103,10 @@ class QueueSinglePipeTester(elements: Seq[Int], bitWidth: Int, tap: Int, useSync assert(q.io.enq.ready || (q.io.count === 1.U && !q.io.deq.ready)) q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire()) { + when(q.io.enq.fire) { inCnt.inc() } - when(q.io.deq.fire()) { + when(q.io.deq.fire) { outCnt.inc() } @@ -129,10 +129,10 @@ class QueuePipeTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: I assert(q.io.enq.ready || (q.io.count === queueDepth.U && !q.io.deq.ready)) q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire()) { + when(q.io.enq.fire) { inCnt.inc() } - when(q.io.deq.fire()) { + when(q.io.deq.fire) { outCnt.inc() } @@ -155,13 +155,13 @@ class QueueFlowTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap: I q.io.deq.ready := LFSR(16)(tap) //Queue should be empty or valid - assert(q.io.deq.valid || (q.io.count === 0.U && !q.io.enq.fire())) + assert(q.io.deq.valid || (q.io.count === 0.U && !q.io.enq.fire)) q.io.enq.bits := elems(inCnt.value) - when(q.io.enq.fire()) { + when(q.io.enq.fire) { inCnt.inc() } - when(q.io.deq.fire()) { + when(q.io.deq.fire) { outCnt.inc() } when(outCnt.value === elements.length.U) { @@ -183,10 +183,10 @@ class QueueFactoryTester(elements: Seq[Int], queueDepth: Int, bitWidth: Int, tap deq.ready := LFSR(16)(tap) enq.bits := elems(inCnt.value) - when(enq.fire()) { + when(enq.fire) { inCnt.inc() } - when(deq.fire()) { + when(deq.fire) { //ensure that what comes out is what comes in assert(elems(outCnt.value) === deq.bits) outCnt.inc() -- cgit v1.2.3 From 8ed9940ed943d0b7f4248d26c598a95c62340f26 Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Wed, 13 Oct 2021 12:01:52 -0700 Subject: Support @public on unimplemented vals (#2182) --- .../chiselTests/experimental/hierarchy/DefinitionSpec.scala | 11 +++++++++++ .../scala/chiselTests/experimental/hierarchy/Examples.scala | 9 +++++++++ 2 files changed, 20 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala index 19261c36..4eb77c8a 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala @@ -258,6 +258,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") { diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala index 23b8c9c0..94c0e551 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala @@ -183,4 +183,13 @@ 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 + } } -- cgit v1.2.3 From 2534931cbc8d5c730f766c9f16d40936ae710c22 Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Mon, 25 Oct 2021 14:20:22 -0700 Subject: Add type parameter support for @instantiable (#2206) --- src/test/scala/chiselTests/experimental/hierarchy/Examples.scala | 4 ++++ .../scala/chiselTests/experimental/hierarchy/InstanceSpec.scala | 9 +++++++++ 2 files changed, 13 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala index 94c0e551..7c9396cf 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala @@ -192,4 +192,8 @@ object Examples { 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..6c227866 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala @@ -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") { -- cgit v1.2.3 From d9722cd96159cd8957cd335d79dbb495260e590d Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Mon, 25 Oct 2021 15:12:53 -0700 Subject: Add Hierarchy trait (#2204) --- .../chiselTests/experimental/hierarchy/Annotations.scala | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src/test') 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)) } -- cgit v1.2.3 From 2a68cc0636580db1a5fa98e87727bb3ec870e0bc Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Wed, 27 Oct 2021 15:51:21 -0700 Subject: Add java reflection to hierarchy (#2209) * Add Hierarchy trait * Add Hierarchy trait * Add Hierarchy scaladoc * Add license * Add isA and tests * Add back isA * Make calculate via lazy val * Apply suggestions from code review Co-authored-by: Megan Wachs * Add shouldNot compile * Update src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala Co-authored-by: Jack Koenig * Made protected vals private Co-authored-by: Megan Wachs Co-authored-by: Jack Koenig Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>--- .../experimental/hierarchy/InstanceSpec.scala | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala index 6c227866..0795e76c 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala @@ -714,5 +714,46 @@ 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) + } + } } -- cgit v1.2.3 From ef8a9c2148f01e058d2986c9d64f0c35f640790c Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Wed, 27 Oct 2021 16:52:56 -0700 Subject: Add Select APIs for Hierarchy package (#2210) * Add Hierarchy trait * Add Hierarchy trait * Add Hierarchy scaladoc * Add license * Add isA and tests * Add back isA * Add new Select APIs for hierarchy package * Update scaladoc * Write outlines for tests * Add tests and fixes to new Select functions * Make calculate via lazy val * Apply suggestions from code review Co-authored-by: Megan Wachs * Apply suggestions from code review Co-authored-by: Megan Wachs * Clean up scaladoc * Add shouldNot compile * Apply suggestions from code review Co-authored-by: Megan Wachs * Bugfix all funcs should analyze root too * Add mdoc, bugfix toDefinition * Make func private, add scaladoc * Update src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala Co-authored-by: Jack Koenig * Made protected vals private * Apply suggestions from code review Co-authored-by: Jack Koenig * Address code review comments * Added additional null check Co-authored-by: Megan Wachs Co-authored-by: Jack Koenig --- .../experimental/hierarchy/Examples.scala | 12 +++ .../experimental/hierarchy/InstanceSpec.scala | 96 ++++++++++++++++++++++ 2 files changed, 108 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala index 7c9396cf..d8ae7322 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala @@ -57,6 +57,18 @@ object Examples { i1.in := i0.out out := i1.out } + + @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 { diff --git a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala index 0795e76c..83084468 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala @@ -755,5 +755,101 @@ class InstanceSpec extends ChiselFunSpec with Utils { 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_2".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_2".it, + )) + rel should be (Seq( + "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, + "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_2".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_2>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_2>in".rt, + )) + abs should be (Seq( + "~AddFour|AddFour/i0:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i0:AddTwoMixedModules/i1:AddOne_2>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i0:AddOne>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_2>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_2>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_2".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_2>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)) } + } + } } -- cgit v1.2.3 From 00b6a9a9ef398320fc6ffe451b0a757f69aae7bd Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Sun, 14 Nov 2021 04:30:13 +0800 Subject: add tests. --- src/test/scala/chiselTests/CompatibilitySpec.scala | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/CompatibilitySpec.scala b/src/test/scala/chiselTests/CompatibilitySpec.scala index ccf287a6..7ac67b7c 100644 --- a/src/test/scala/chiselTests/CompatibilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilitySpec.scala @@ -536,6 +536,9 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck info("toUInt works") s.toUInt shouldBe a [UInt] + + info("toBools works") + s.toBools shouldBe a [Seq[Bool]] } ChiselStage.elaborate(new Foo) -- cgit v1.2.3 From f26f8554879f638b4c4743becbc6da13da174e63 Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Wed, 24 Nov 2021 03:11:25 +0800 Subject: fix for chipsalliance/firrtl#2421 (#2256) --- src/test/scala/chiselTests/IntervalSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/IntervalSpec.scala b/src/test/scala/chiselTests/IntervalSpec.scala index a33cedc1..c223260d 100644 --- a/src/test/scala/chiselTests/IntervalSpec.scala +++ b/src/test/scala/chiselTests/IntervalSpec.scala @@ -15,7 +15,7 @@ import firrtl.passes.CheckTypes.InvalidConnect import firrtl.passes.CheckWidths.{DisjointSqueeze, InvalidRange} import firrtl.passes.{PassExceptions, WrapWithRemainder} import firrtl.stage.{CompilerAnnotation, FirrtlCircuitAnnotation} -import firrtl.{FIRRTLException, HighFirrtlCompiler, LowFirrtlCompiler, MiddleFirrtlCompiler, MinimumVerilogCompiler, NoneCompiler, SystemVerilogCompiler, VerilogCompiler} +import firrtl.{HighFirrtlCompiler, LowFirrtlCompiler, MiddleFirrtlCompiler, MinimumVerilogCompiler, NoneCompiler, SystemVerilogCompiler, VerilogCompiler} import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers -- cgit v1.2.3 From 563f6157a861d0f524a84d15fc8c2647c8cfb6ba Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Mon, 29 Nov 2021 11:39:00 -0800 Subject: Deprecate chisel3.BackendCompilationUtilities (#2257) Also remove as many deprecated APIs as possible by inlining implementations of old deprecated/removed code from firrtl--- src/test/scala/chiselTests/Harness.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/Harness.scala b/src/test/scala/chiselTests/Harness.scala index 23379498..51576566 100644 --- a/src/test/scala/chiselTests/Harness.scala +++ b/src/test/scala/chiselTests/Harness.scala @@ -4,10 +4,7 @@ package chiselTests import java.io.File -import firrtl.util.BackendCompilationUtilities - -class HarnessSpec extends ChiselPropSpec - with BackendCompilationUtilities { +class HarnessSpec extends ChiselPropSpec { def makeTrivialVerilog: (File => File) = makeHarness((prefix: String) => s""" module ${prefix}; -- cgit v1.2.3 From ef1a14e29e8d634cd8e52490b2a3fc368218c41c Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Tue, 30 Nov 2021 17:05:14 -0800 Subject: Remove unused imports for API removed from firrtl (#2269) This fixes CI which fails with current firrtl 1.5-SNAPSHOT.--- src/test/scala/chiselTests/BlackBoxImpl.scala | 1 - src/test/scala/chiselTests/InlineSpec.scala | 1 - src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala | 1 - src/test/scala/chiselTests/TransitNameSpec.scala | 1 - 4 files changed, 4 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/BlackBoxImpl.scala b/src/test/scala/chiselTests/BlackBoxImpl.scala index a9a6fa29..2fa3d8a6 100644 --- a/src/test/scala/chiselTests/BlackBoxImpl.scala +++ b/src/test/scala/chiselTests/BlackBoxImpl.scala @@ -7,7 +7,6 @@ import java.io.File import chisel3._ import chisel3.util.{HasBlackBoxInline, HasBlackBoxResource, HasBlackBoxPath} import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} -import firrtl.FirrtlExecutionSuccess import firrtl.transforms.BlackBoxNotFoundException import org.scalacheck.Test.Failed import org.scalatest.Succeeded diff --git a/src/test/scala/chiselTests/InlineSpec.scala b/src/test/scala/chiselTests/InlineSpec.scala index 397eac2e..59a1e984 100644 --- a/src/test/scala/chiselTests/InlineSpec.scala +++ b/src/test/scala/chiselTests/InlineSpec.scala @@ -5,7 +5,6 @@ package chiselTests import chisel3._ import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import chisel3.util.experimental.{InlineInstance, FlattenInstance} -import firrtl.FirrtlExecutionSuccess import firrtl.passes.InlineAnnotation import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlStage} import firrtl.transforms.FlattenAnnotation diff --git a/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala b/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala index 8a998496..74e587bc 100644 --- a/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala +++ b/src/test/scala/chiselTests/LoadMemoryFromFileSpec.scala @@ -8,7 +8,6 @@ import chisel3._ import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import chisel3.util.experimental.{loadMemoryFromFile,loadMemoryFromFileInline} import chisel3.util.log2Ceil -import firrtl.FirrtlExecutionSuccess import firrtl.annotations.MemoryLoadFileType import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers diff --git a/src/test/scala/chiselTests/TransitNameSpec.scala b/src/test/scala/chiselTests/TransitNameSpec.scala index b21818d6..656c6731 100644 --- a/src/test/scala/chiselTests/TransitNameSpec.scala +++ b/src/test/scala/chiselTests/TransitNameSpec.scala @@ -6,7 +6,6 @@ import chisel3._ import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage} import chisel3.util.TransitName -import firrtl.FirrtlExecutionSuccess import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers -- cgit v1.2.3 From a476329ef7b051aa480903cacd7d62ee46980c84 Mon Sep 17 00:00:00 2001 From: Aditya Naik Date: Tue, 30 Nov 2021 17:45:59 -0800 Subject: Bugfix - definition name index skipping with D/I (#2249) * Bugfix - definition name index skipping with D/I * Add tests to DefinitionSpec * Add failing test * Fix failing test * Update core/src/main/scala/chisel3/internal/Builder.scala Co-authored-by: Jack Koenig * whitespace * revert package private val Co-authored-by: Jack Koenig Co-authored-by: Jack Koenig --- .../experimental/hierarchy/DefinitionSpec.scala | 44 ++++++++++++++++++++-- .../experimental/hierarchy/Examples.scala | 28 ++++++++++++++ .../experimental/hierarchy/InstanceSpec.scala | 28 +++++++------- 3 files changed, 83 insertions(+), 17 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala index 4eb77c8a..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 @@ -322,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 { @@ -330,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 d8ae7322..c0f504ff 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala @@ -35,6 +35,19 @@ object Examples { innerWire := in + 1.U 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))) @@ -57,6 +70,21 @@ object Examples { i1.in := i0.out 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 { diff --git a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala index 83084468..929e3875 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 { @@ -362,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 { @@ -370,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) } @@ -388,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 { @@ -761,7 +761,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { 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_2".it, + "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it, )) }) getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) @@ -773,11 +773,11 @@ class InstanceSpec extends ChiselFunSpec with Utils { val rel = insts.map { i: Instance[BaseModule] => i.toTarget } abs should be (Seq( "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, - "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_2".it, + "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it, )) rel should be (Seq( "~AddTwoMixedModules|AddTwoMixedModules/i0:AddOne".it, - "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_2".it, + "~AddTwoMixedModules|AddTwoMixedModules/i1:AddOne_1".it, )) }) getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) @@ -789,15 +789,15 @@ class InstanceSpec extends ChiselFunSpec with Utils { 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_2>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_2>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_2>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_2>in".rt, + "~AddFour|AddFour/i1:AddTwoMixedModules/i1:AddOne_1>in".rt, )) }) getFirrtlAndAnnos(new AddFour, Seq(aspect)) @@ -807,7 +807,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { 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_2>in".rt, + "~AddTwoMixedModules|AddOne_1>in".rt, )) }) getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) @@ -817,7 +817,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { val targets = aop.Select.definitionsIn(m.toDefinition).map { i: Definition[BaseModule] => i.toTarget } targets should be (Seq( "~AddTwoMixedModules|AddOne".mt, - "~AddTwoMixedModules|AddOne_2".mt, + "~AddTwoMixedModules|AddOne_1".mt, )) }) getFirrtlAndAnnos(new AddTwoMixedModules, Seq(aspect)) @@ -827,7 +827,7 @@ class InstanceSpec extends ChiselFunSpec with Utils { 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_2>in".rt, + "~AddFour|AddOne_1>in".rt, )) }) getFirrtlAndAnnos(new AddFour, Seq(aspect)) -- cgit v1.2.3 From 392ea3c9b5b04e374eeb1bf3b0d87ac9fbf45513 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 1 Dec 2021 14:49:34 -0800 Subject: Require the chisel3 compiler plugin (#2271) As the chisel3 compiler plugin is now required, we can delete unused code for reflective autoclonetype as well as the noPluginTests.--- src/test/scala/chisel3/testers/TestUtils.scala | 9 - src/test/scala/chiselTests/AutoClonetypeSpec.scala | 198 ++++++++++----------- .../scala/chiselTests/AutoNestedCloneSpec.scala | 65 ++++--- 3 files changed, 121 insertions(+), 151 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chisel3/testers/TestUtils.scala b/src/test/scala/chisel3/testers/TestUtils.scala index c72c779a..338f9cd4 100644 --- a/src/test/scala/chisel3/testers/TestUtils.scala +++ b/src/test/scala/chisel3/testers/TestUtils.scala @@ -12,13 +12,4 @@ object TestUtils { // Useful because TesterDriver.Backend is chisel3 package private def containsBackend(annos: AnnotationSeq): Boolean = annos.collectFirst { case b: Backend => b }.isDefined - - // Allows us to check that the compiler plugin cloneType is actually working - val usingPlugin: Boolean = (new Bundle { def check = _usingPlugin }).check - def elaborateNoReflectiveAutoCloneType(f: => RawModule): Circuit = { - ChiselStage.elaborate { - chisel3.internal.Builder.allowReflectiveAutoCloneType = !usingPlugin - f - } - } } diff --git a/src/test/scala/chiselTests/AutoClonetypeSpec.scala b/src/test/scala/chiselTests/AutoClonetypeSpec.scala index 3f33fda8..ef58f1ed 100644 --- a/src/test/scala/chiselTests/AutoClonetypeSpec.scala +++ b/src/test/scala/chiselTests/AutoClonetypeSpec.scala @@ -5,6 +5,7 @@ package chiselTests import chisel3._ import chisel3.testers.TestUtils import chisel3.util.QueueIO +import chisel3.stage.ChiselStage.elaborate class BundleWithIntArg(val i: Int) extends Bundle { val out = UInt(i.W) @@ -71,14 +72,11 @@ class InheritingBundle extends QueueIO(UInt(8.W), 8) { val error = Output(Bool()) } -// TODO all `.suggestNames` are due to https://github.com/chipsalliance/chisel3/issues/1802 class AutoClonetypeSpec extends ChiselFlatSpec with Utils { - val usingPlugin: Boolean = TestUtils.usingPlugin - val elaborate = TestUtils.elaborateNoReflectiveAutoCloneType _ "Bundles with Scala args" should "not need clonetype" in { elaborate { new Module { - val io = IO(new Bundle{}).suggestName("io") + val io = IO(new Bundle{}) val myWire = Wire(new BundleWithIntArg(8)) assert(myWire.i == 8) @@ -87,7 +85,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { "Bundles with Scala implicit args" should "not need clonetype" in { elaborate { new Module { - val io = IO(new Bundle{}).suggestName("io") + val io = IO(new Bundle{}) implicit val implicitInt: Int = 4 val myWire = Wire(new BundleWithImplicit()) @@ -98,7 +96,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { "Bundles with Scala explicit and impicit args" should "not need clonetype" in { elaborate { new Module { - val io = IO(new Bundle{}).suggestName("io") + val io = IO(new Bundle{}) implicit val implicitInt: Int = 4 val myWire = Wire(new BundleWithArgAndImplicit(8)) @@ -110,7 +108,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { "Subtyped Bundles" should "not need clonetype" in { elaborate { new Module { - val io = IO(new Bundle{}).suggestName("io") + val io = IO(new Bundle{}) val myWire = Wire(new SubBundle(8, 4)) @@ -118,7 +116,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { assert(myWire.i2 == 4) } } elaborate { new Module { - val io = IO(new Bundle{}).suggestName("io") + val io = IO(new Bundle{}) val myWire = Wire(new SubBundleVal(8, 4)) @@ -131,23 +129,12 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { new BundleWithIntArg(8).cloneType } - def checkSubBundleInvalid() = { + "Subtyped Bundles that don't clone well" should "be now be supported!" in { elaborate { new Module { - val io = IO(new Bundle{}).suggestName("io") + val io = IO(new Bundle{}) val myWire = Wire(new SubBundleInvalid(8, 4)) } } } - if (usingPlugin) { - "Subtyped Bundles that don't clone well" should "be now be supported!" in { - checkSubBundleInvalid() - } - } else { - "Subtyped Bundles that don't clone well" should "be caught" in { - a [ChiselException] should be thrownBy extractCause[ChiselException] { - checkSubBundleInvalid() - } - } - } "Inner bundles with Scala args" should "not need clonetype" in { elaborate { new ModuleWithInner } @@ -155,7 +142,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { "Bundles with arguments as fields" should "not need clonetype" in { elaborate { new Module { - val io = IO(Output(new BundleWithArgumentField(UInt(8.W), UInt(8.W)))).suggestName("io") + val io = IO(Output(new BundleWithArgumentField(UInt(8.W), UInt(8.W)))) io.x := 1.U io.y := 1.U } } @@ -163,28 +150,28 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { it should "also work when giving directions to the fields" in { elaborate { new Module { - val io = IO(new BundleWithArgumentField(Input(UInt(8.W)), Output(UInt(8.W)))).suggestName("io") + val io = IO(new BundleWithArgumentField(Input(UInt(8.W)), Output(UInt(8.W)))) io.y := io.x } } } "Bundles inside companion objects" should "not need clonetype" in { elaborate { new Module { - val io = IO(Output(new CompanionObjectWithBundle.Inner)).suggestName("io") + val io = IO(Output(new CompanionObjectWithBundle.Inner)) io.data := 1.U } } } "Parameterized bundles inside companion objects" should "not need clonetype" in { elaborate { new Module { - val io = IO(Output(new CompanionObjectWithBundle.ParameterizedInner(8))).suggestName("io") + val io = IO(Output(new CompanionObjectWithBundle.ParameterizedInner(8))) io.data := 1.U } } } "Nested directioned anonymous Bundles" should "not need clonetype" in { elaborate { new Module { - val io = IO(new NestedAnonymousBundle).suggestName("io") + val io = IO(new NestedAnonymousBundle) val a = WireDefault(io) io.a.a := 1.U } } @@ -197,7 +184,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { val a = Output(UInt(8.W)) } } - val io = IO((new InnerClassThing).createBundle).suggestName("io") + val io = IO((new InnerClassThing).createBundle) val a = WireDefault(io) } } } @@ -208,7 +195,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { val bundleFieldType = UInt(8.W) val io = IO(Output(new Bundle { val a = bundleFieldType - })).suggestName("io") + })) io.a := 0.U } } } @@ -221,7 +208,7 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { } elaborate { new Module { - val io = IO(Output(new BadBundle(UInt(8.W), 1))).suggestName("io") + val io = IO(Output(new BadBundle(UInt(8.W), 1))) io.a := 0.U } } } @@ -265,100 +252,97 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { behavior of "Compiler Plugin Autoclonetype" - // New tests from the plugin - if (usingPlugin) { - it should "NOT break code that extends chisel3.util Bundles if they use the plugin" in { - class MyModule extends MultiIOModule { - val io = IO(new InheritingBundle) - io.deq <> io.enq - io.count := 0.U - io.error := true.B - } - elaborate(new MyModule) + it should "NOT break code that extends chisel3.util Bundles if they use the plugin" in { + class MyModule extends MultiIOModule { + val io = IO(new InheritingBundle) + io.deq <> io.enq + io.count := 0.U + io.error := true.B } + elaborate(new MyModule) + } - it should "support Bundles with non-val parameters" in { - class MyBundle(i: Int) extends Bundle { - val foo = UInt(i.W) - } - elaborate { new MultiIOModule { - val in = IO(Input(new MyBundle(8))) - val out = IO(Output(new MyBundle(8))) - out := in - }} + it should "support Bundles with non-val parameters" in { + class MyBundle(i: Int) extends Bundle { + val foo = UInt(i.W) } + elaborate { new MultiIOModule { + val in = IO(Input(new MyBundle(8))) + val out = IO(Output(new MyBundle(8))) + out := in + }} + } - it should "support type-parameterized Bundles" in { - class MyBundle[T <: Data](gen: T) extends Bundle { - val foo = gen - } - elaborate { new MultiIOModule { - val in = IO(Input(new MyBundle(UInt(8.W)))) - val out = IO(Output(new MyBundle(UInt(8.W)))) - out := in - }} + it should "support type-parameterized Bundles" in { + class MyBundle[T <: Data](gen: T) extends Bundle { + val foo = gen } + elaborate { new MultiIOModule { + val in = IO(Input(new MyBundle(UInt(8.W)))) + val out = IO(Output(new MyBundle(UInt(8.W)))) + out := in + }} + } - it should "support Bundles with non-val implicit parameters" in { - class MyBundle(implicit i: Int) extends Bundle { - val foo = UInt(i.W) - } - elaborate { new MultiIOModule { - implicit val x = 8 - val in = IO(Input(new MyBundle)) - val out = IO(Output(new MyBundle)) - out := in - }} + it should "support Bundles with non-val implicit parameters" in { + class MyBundle(implicit i: Int) extends Bundle { + val foo = UInt(i.W) } + elaborate { new MultiIOModule { + implicit val x = 8 + val in = IO(Input(new MyBundle)) + val out = IO(Output(new MyBundle)) + out := in + }} + } - it should "support Bundles with multiple parameter lists" in { - class MyBundle(i: Int)(j: Int, jj: Int)(k: UInt) extends Bundle { - val foo = UInt((i + j + jj + k.getWidth).W) - } - elaborate { - new MultiIOModule { - val in = IO(Input(new MyBundle(8)(8, 8)(UInt(8.W)))) - val out = IO(Output(new MyBundle(8)(8, 8)(UInt(8.W)))) - out := in - } + it should "support Bundles with multiple parameter lists" in { + class MyBundle(i: Int)(j: Int, jj: Int)(k: UInt) extends Bundle { + val foo = UInt((i + j + jj + k.getWidth).W) + } + elaborate { + new MultiIOModule { + val in = IO(Input(new MyBundle(8)(8, 8)(UInt(8.W)))) + val out = IO(Output(new MyBundle(8)(8, 8)(UInt(8.W)))) + out := in } } + } - it should "support Bundles that implement their own cloneType" in { - class MyBundle(i: Int) extends Bundle { - val foo = UInt(i.W) - } - elaborate { new MultiIOModule { - val in = IO(Input(new MyBundle(8))) - val out = IO(Output(new MyBundle(8))) - out := in - }} + it should "support Bundles that implement their own cloneType" in { + class MyBundle(i: Int) extends Bundle { + val foo = UInt(i.W) } + elaborate { new MultiIOModule { + val in = IO(Input(new MyBundle(8))) + val out = IO(Output(new MyBundle(8))) + out := in + }} + } - it should "support Bundles that capture type parameters from their parent scope" in { - class MyModule[T <: Data](gen: T) extends MultiIOModule { - class MyBundle(n: Int) extends Bundle { - val foo = Vec(n, gen) - } - val in = IO(Input(new MyBundle(4))) - val out = IO(Output(new MyBundle(4))) - out := in + it should "support Bundles that capture type parameters from their parent scope" in { + class MyModule[T <: Data](gen: T) extends MultiIOModule { + class MyBundle(n: Int) extends Bundle { + val foo = Vec(n, gen) } - elaborate(new MyModule(UInt(8.W))) + val in = IO(Input(new MyBundle(4))) + val out = IO(Output(new MyBundle(4))) + out := in } + elaborate(new MyModule(UInt(8.W))) + } - it should "work for higher-kinded types" in { - class DataGen[T <: Data](gen: T) { - def newType: T = gen.cloneType - } - class MyBundle[A <: Data, B <: DataGen[A]](gen: B) extends Bundle { - val foo = gen.newType - } - class MyModule extends MultiIOModule { - val io = IO(Output(new MyBundle[UInt, DataGen[UInt]](new DataGen(UInt(3.W))))) - io.foo := 0.U - } - elaborate(new MyModule) + it should "work for higher-kinded types" in { + class DataGen[T <: Data](gen: T) { + def newType: T = gen.cloneType + } + class MyBundle[A <: Data, B <: DataGen[A]](gen: B) extends Bundle { + val foo = gen.newType + } + class MyModule extends MultiIOModule { + val io = IO(Output(new MyBundle[UInt, DataGen[UInt]](new DataGen(UInt(3.W))))) + io.foo := 0.U } + elaborate(new MyModule) } } diff --git a/src/test/scala/chiselTests/AutoNestedCloneSpec.scala b/src/test/scala/chiselTests/AutoNestedCloneSpec.scala index 401766e2..258d0823 100644 --- a/src/test/scala/chiselTests/AutoNestedCloneSpec.scala +++ b/src/test/scala/chiselTests/AutoNestedCloneSpec.scala @@ -3,6 +3,7 @@ package chiselTests import chisel3._ import chisel3.testers.TestUtils +import chisel3.stage.ChiselStage.elaborate import org.scalatest.matchers.should.Matchers class BundleWithAnonymousInner(val w: Int) extends Bundle { @@ -11,10 +12,7 @@ class BundleWithAnonymousInner(val w: Int) extends Bundle { } } -// TODO all `.suggestNames` are due to https://github.com/chipsalliance/chisel3/issues/1802 class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { - val usingPlugin: Boolean = TestUtils.usingPlugin - val elaborate = TestUtils.elaborateNoReflectiveAutoCloneType _ behavior of "autoCloneType of inner Bundle in Chisel3" @@ -27,7 +25,7 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { } def getIO: InnerIOType = new InnerIOType } - val io = IO(new Bundle {}).suggestName("io") + val io = IO(new Bundle {}) val myWire = Wire((new Middle(w)).getIO) } new Outer(2) @@ -37,7 +35,7 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { it should "clone an anonymous inner bundle successfully" in { elaborate { class TestTop(val w: Int) extends Module { - val io = IO(new Bundle {}).suggestName("io") + val io = IO(new Bundle {}) val myWire = Wire(new Bundle{ val a = UInt(w.W) }) } new TestTop(2) @@ -50,13 +48,13 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { val io = IO(new Bundle{ val in = Input(UInt(w.W)) val out = Output(UInt(w.W)) - }).suggestName("io") + }) } class Outer(val w: Int) extends Module { val io = IO(new Bundle{ val in = Input(UInt(w.W)) val out = Output(UInt(w.W)) - }).suggestName("io") + }) val i = Module(new Inner(w)) val iw = Wire(chiselTypeOf(i.io)) iw <> io @@ -69,7 +67,7 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { it should "clone an anonymous, bound, inner bundle of another bundle successfully" in { elaborate { class TestModule(w: Int) extends Module { - val io = IO(new BundleWithAnonymousInner(w) ).suggestName("io") + val io = IO(new BundleWithAnonymousInner(w)) val w0 = WireDefault(io) val w1 = WireDefault(io.inner) } @@ -85,7 +83,7 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { } val io = IO(new Bundle { val inner = Input(bun) - }).suggestName("io") + }) val w0 = WireDefault(io) val w1 = WireDefault(io.inner) } @@ -100,42 +98,39 @@ class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils { val inner = Input(new Bundle { val x = UInt(8.W) }) - }).suggestName("io") + }) } new TestModule() } } - if (usingPlugin) { - // This works with the plugin, but is a null pointer exception when using reflective autoclonetype - it should "support an anonymous doubly-nested inner bundle" in { - elaborate { - class Outer(val w: Int) extends Module { - class Middle(val w: Int) { - def getIO: Bundle = new Bundle { - val in = Input(UInt(w.W)) - } + it should "support an anonymous doubly-nested inner bundle" in { + elaborate { + class Outer(val w: Int) extends Module { + class Middle(val w: Int) { + def getIO: Bundle = new Bundle { + val in = Input(UInt(w.W)) } - val io = IO(new Bundle {}).suggestName("io") - val myWire = Wire((new Middle(w)).getIO) } - new Outer(2) + val io = IO(new Bundle {}) + val myWire = Wire((new Middle(w)).getIO) } + new Outer(2) } + } - it should "support anonymous Inner bundles that capture type parameters from outer Bundles" in { - elaborate(new MultiIOModule { - class MyBundle[T <: Data](n: Int, gen: T) extends Bundle { - val foo = new Bundle { - val x = Input(Vec(n, gen)) - } - val bar = Output(Option(new { def mkBundle = new Bundle { val x = Vec(n, gen) }}).get.mkBundle) + it should "support anonymous Inner bundles that capture type parameters from outer Bundles" in { + elaborate(new MultiIOModule { + class MyBundle[T <: Data](n: Int, gen: T) extends Bundle { + val foo = new Bundle { + val x = Input(Vec(n, gen)) } - val io = IO(new MyBundle(4, UInt(8.W))) - val myWire = WireInit(io.foo) - val myWire2 = WireInit(io.bar) - io.bar.x := io.foo.x - }) - } + val bar = Output(Option(new { def mkBundle = new Bundle { val x = Vec(n, gen) }}).get.mkBundle) + } + val io = IO(new MyBundle(4, UInt(8.W))) + val myWire = WireInit(io.foo) + val myWire2 = WireInit(io.bar) + io.bar.x := io.foo.x + }) } } -- cgit v1.2.3 From 9dfee489b15642745174d191181ebf6f570db3ca Mon Sep 17 00:00:00 2001 From: Aditya Naik Date: Wed, 1 Dec 2021 16:09:34 -0800 Subject: Refactor Data.toString (#2197) Provides a more intuitive implementation of toString for Data. Utilizes the fact that the compiler plugin provides names earlier than Chisel had in the past so we can accurately guess the name of signals even in the currently elaborating module. Co-authored-by: Megan Wachs Co-authored-by: Jack Koenig --- src/test/scala/chiselTests/DataPrint.scala | 56 +++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 12 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/DataPrint.scala b/src/test/scala/chiselTests/DataPrint.scala index b5f96c4d..7fb790a8 100644 --- a/src/test/scala/chiselTests/DataPrint.scala +++ b/src/test/scala/chiselTests/DataPrint.scala @@ -20,6 +20,14 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { val b = Bool() } + class PartialBundleTest extends Bundle { + val a = UInt(8.W) + val b = Bool() + val c = SInt(8.W) + val e = FixedPoint(5.W, 3.BP) + val f = EnumTest.Type() + } + "Data types" should "have a meaningful string representation" in { ChiselStage.elaborate { new RawModule { UInt().toString should be ("UInt") @@ -31,18 +39,20 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { Vec(3, UInt(2.W)).toString should be ("UInt<2>[3]") EnumTest.Type().toString should be ("EnumTest") (new BundleTest).toString should be ("BundleTest") - } } + new Bundle { val a = UInt(8.W) }.toString should be ("AnonymousBundle") + new Bundle { val a = UInt(8.W) }.a.toString should be ("UInt<8>") + }} } class BoundDataModule extends Module { // not in the test to avoid anon naming suffixes - Wire(UInt()).toString should be("UInt(Wire in BoundDataModule)") - Reg(SInt()).toString should be("SInt(Reg in BoundDataModule)") + Wire(UInt()).toString should be("BoundDataModule.?: Wire[UInt]") + Reg(SInt()).toString should be("BoundDataModule.?: Reg[SInt]") val io = IO(Output(Bool())) // needs a name so elaboration doesn't fail - io.toString should be("Bool(IO in unelaborated BoundDataModule)") + io.toString should be("BoundDataModule.io: IO[Bool]") val m = Mem(4, UInt(2.W)) - m(2).toString should be("UInt<2>(MemPort in BoundDataModule)") - (2.U + 2.U).toString should be("UInt<2>(OpResult in BoundDataModule)") - Wire(Vec(3, UInt(2.W))).toString should be ("UInt<2>[3](Wire in BoundDataModule)") + m(2).toString should be("BoundDataModule.?: MemPort[UInt<2>]") + (2.U + 2.U).toString should be("BoundDataModule.?: OpResult[UInt<2>]") + Wire(Vec(3, UInt(2.W))).toString should be ("BoundDataModule.?: Wire[UInt<2>[3]]") class InnerModule extends Module { val io = IO(Output(new Bundle { @@ -50,8 +60,31 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { })) } val inner = Module(new InnerModule) - inner.clock.toString should be ("Clock(IO clock in InnerModule)") - inner.io.a.toString should be ("UInt<4>(IO io_a in InnerModule)") + inner.clock.toString should be ("InnerModule.clock: IO[Clock]") + inner.io.a.toString should be ("InnerModule.io.a: IO[UInt<4>]") + + class FooTypeTest extends Bundle { + val foo = Vec(2, UInt(8.W)) + val fizz = UInt(8.W) + } + val tpe = new FooTypeTest + val fooio: FooTypeTest = IO(Input(tpe)) + fooio.foo(0).toString should be ("BoundDataModule.fooio.foo[0]: IO[UInt<8>]") + + class NestedBundle extends Bundle { + val nestedFoo = UInt(8.W) + val nestedFooVec = Vec(2, UInt(8.W)) + } + class NestedType extends Bundle { + val foo = new NestedBundle + } + + val nestedTpe = new NestedType + val nestedio = IO(Input(nestedTpe)) + (nestedio.foo.nestedFoo.toString should be + ("BoundDataModule.nestedio.foo.nestedFoo: IO[UInt<8>]")) + (nestedio.foo.nestedFooVec(0).toString should be + ("BoundDataModule.nestedio.foo.nestedFooVec[0]: IO[UInt<8>]")) } "Bound data types" should "have a meaningful string representation" in { @@ -67,13 +100,12 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { true.B.toString should be ("Bool(true)") 2.25.F(6.W, 2.BP).toString should be ("FixedPoint<6><<2>>(2.25)") -2.25.F(6.W, 2.BP).toString should be ("FixedPoint<6><<2>>(-2.25)") + Vec(3, UInt(4.W)).toString should be ("UInt<4>[3]") EnumTest.sNone.toString should be ("EnumTest(0=sNone)") EnumTest.sTwo.toString should be ("EnumTest(2=sTwo)") EnumTest(1.U).toString should be ("EnumTest(1=sOne)") (new BundleTest).Lit(_.a -> 2.U, _.b -> false.B).toString should be ("BundleTest(a=UInt<8>(2), b=Bool(false))") - new Bundle { - val a = UInt(8.W) - }.toString should be ("AnonymousBundle") + (new PartialBundleTest).Lit().toString should be ("PartialBundleTest(a=UInt<8>(DontCare), b=Bool(DontCare), c=SInt<8>(DontCare), e=FixedPoint<5><<3>>(DontCare), f=EnumTest(DontCare))") DontCare.toString should be ("DontCare()") } } } -- cgit v1.2.3 From 08271081e4af2025fc6c6af97511fd110ef65e5c Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 8 Dec 2021 14:21:44 -0800 Subject: Implement DataViews for Seq and Tuple (#2277) * DataProducts for Seq and Tuple2-10 in DataProduct companion object * DataViews for Seq and Tuple 2-10 in DataView companion object * HWTuple2-10 Bundles in chisel3.experimental * Implicit conversions from Seq to Vec and Tuple to HWTuple in chisel3.experimental.conversions--- .../scala/chiselTests/experimental/DataView.scala | 102 +------------ .../experimental/DataViewTargetSpec.scala | 3 +- .../scala/chiselTests/experimental/Tuple.scala | 163 +++++++++++++++++++++ .../experimental/hierarchy/InstanceSpec.scala | 2 +- 4 files changed, 171 insertions(+), 99 deletions(-) create mode 100644 src/test/scala/chiselTests/experimental/Tuple.scala (limited to 'src/test') diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala index d1620e88..399b0cbc 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))) @@ -398,10 +314,6 @@ class DataViewSpec extends ChiselFlatSpec { } it should "error if you try to dynamically index a Vec view" in { - import SeqDataProduct._ - import SeqToVec._ - import Tuple2DataProduct._ - import HWTuple._ class MyModule extends Module { val inA, inB = IO(Input(UInt(8.W))) @@ -434,7 +346,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 +444,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/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/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala index 929e3875..9ceb9b40 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala @@ -629,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))) -- cgit v1.2.3 From 849d4a0b7f6f7ea056c5280b9d319dadf5225022 Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Thu, 9 Dec 2021 10:25:11 +0800 Subject: catch None.get in BitPat.apply(x: UInt): BitPat (#2276) Co-authored-by: Jack Koenig --- src/test/scala/chiselTests/util/BitPatSpec.scala | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/util/BitPatSpec.scala b/src/test/scala/chiselTests/util/BitPatSpec.scala index 0c83493f..e14b4496 100644 --- a/src/test/scala/chiselTests/util/BitPatSpec.scala +++ b/src/test/scala/chiselTests/util/BitPatSpec.scala @@ -28,6 +28,14 @@ class BitPatSpec extends AnyFlatSpec with Matchers { (BitPat.Y(4) ## BitPat.dontCare(3) ## BitPat.N(2)).toString should be (s"BitPat(1111???00)") } + it should "throw when BitPat apply to a Hardware" in { + intercept[java.lang.IllegalArgumentException]{ + chisel3.stage.ChiselStage.emitChirrtl(new chisel3.Module { + BitPat(chisel3.Reg(chisel3.Bool())) + }) + } + } + it should "index and return new BitPat" in { val b = BitPat("b1001???") b(0) should be(BitPat.dontCare(1)) -- cgit v1.2.3 From 3f21bbb52363c3105f6a0ff961fa7a411dd0c7ab Mon Sep 17 00:00:00 2001 From: Aditya Naik Date: Thu, 9 Dec 2021 11:19:27 -0800 Subject: Better MonoConnect error messages (#2248) Co-authored-by: Megan Wachs --- src/test/scala/chiselTests/ConnectSpec.scala | 35 ++++++++++++++++++++++ src/test/scala/chiselTests/InvalidateAPISpec.scala | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/ConnectSpec.scala b/src/test/scala/chiselTests/ConnectSpec.scala index 367864e6..f9ef5946 100644 --- a/src/test/scala/chiselTests/ConnectSpec.scala +++ b/src/test/scala/chiselTests/ConnectSpec.scala @@ -2,6 +2,8 @@ package chiselTests +import org.scalatest._ + import chisel3._ import chisel3.experimental.{Analog, FixedPoint} import chisel3.stage.ChiselStage @@ -126,4 +128,37 @@ class ConnectSpec extends ChiselPropSpec with Utils { property("Pipe internal connections should succeed") { ChiselStage.elaborate( new PipeInternalWires) } + + property("Connect error messages should have meaningful information") { + class InnerExample extends Module { + val myReg = RegInit(0.U(8.W)) + } + + class OuterAssignExample extends Module { + val inner = Module(new InnerExample()) + inner.myReg := false.B // ERROR + } + + val assignError = the [ChiselException] thrownBy {ChiselStage.elaborate { new OuterAssignExample}} + val expectedAssignError = """.*@: myReg in InnerExample cannot be written from module OuterAssignExample.""" + assignError.getMessage should fullyMatch regex expectedAssignError + + class OuterReadExample extends Module { + val myReg = RegInit(0.U(8.W)) + val inner = Module(new InnerExample()) + myReg := inner.myReg // ERROR + } + + val readError = the [ChiselException] thrownBy {ChiselStage.elaborate { new OuterReadExample }} + val expectedReadError = """.*@: myReg in InnerExample cannot be read from module OuterReadExample.""" + readError.getMessage should fullyMatch regex expectedReadError + + val typeMismatchError = the [ChiselException] thrownBy {ChiselStage.elaborate { new RawModule { + val myUInt = Wire(UInt(4.W)) + val mySInt = Wire(SInt(4.W)) + myUInt := mySInt + }}} + val expectedTypeMismatchError = """.*@: Sink \(UInt<4>\) and Source \(SInt<4>\) have different types.""" + typeMismatchError.getMessage should fullyMatch regex expectedTypeMismatchError + } } diff --git a/src/test/scala/chiselTests/InvalidateAPISpec.scala b/src/test/scala/chiselTests/InvalidateAPISpec.scala index b7db33cc..52ad02b4 100644 --- a/src/test/scala/chiselTests/InvalidateAPISpec.scala +++ b/src/test/scala/chiselTests/InvalidateAPISpec.scala @@ -105,7 +105,7 @@ class InvalidateAPISpec extends ChiselPropSpec with Matchers with BackendCompila ChiselStage.elaborate(new ModuleWithDontCareSink) } } - exception.getMessage should include("DontCare cannot be a connection sink (LHS)") + exception.getMessage should include("DontCare cannot be a connection sink") } property("a DontCare cannot be a connection sink (LHS) for <>") { -- cgit v1.2.3 From 630d05bdca90ec1c80eaaa7834e755f51095463d Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Fri, 10 Dec 2021 15:56:56 -0800 Subject: Add support for dynamic indexing on Vec identity views (#2298) --- .../scala/chiselTests/experimental/DataView.scala | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala index 399b0cbc..7c5d170b 100644 --- a/src/test/scala/chiselTests/experimental/DataView.scala +++ b/src/test/scala/chiselTests/experimental/DataView.scala @@ -313,8 +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 { + 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))) @@ -323,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 -- cgit v1.2.3 From 55cb58877aca898f1ccae5edf29aeede9d1b71ba Mon Sep 17 00:00:00 2001 From: Øyvind Harboe Date: Sat, 11 Dec 2021 04:39:27 +0100 Subject: reduceTree() now operates on Seq (#2292) preserves input/output information of the type being reduced. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>--- src/test/scala/chiselTests/Vec.scala | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index 97aea909..24ba0bf8 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -313,6 +313,36 @@ class ModuleIODynamicIndexTester(n: Int) extends BasicTester { when (done) { stop() } } +class ReduceTreeTester() extends BasicTester { + class FooIO[T <: Data](n: Int, private val gen: T) extends Bundle { + val in = Flipped(Vec(n, new DecoupledIO(gen))) + val out = new DecoupledIO(gen) + } + + class Foo[T <: Data](n: Int, private val gen: T) extends Module { + val io = IO(new FooIO(n, gen)) + + def foo(a: DecoupledIO[T], b: DecoupledIO[T]) = { + a.ready := true.B + b.ready := true.B + val out = Wire(new DecoupledIO(gen)) + + out.valid := true.B + + val regSel = RegInit(false.B) + out.bits := Mux(regSel, a.bits, b.bits) + out.ready := a.ready + out + } + + io.out <> io.in.reduceTree(foo) + } + + val dut = Module(new Foo(5, UInt(5.W))) + dut.io := DontCare + stop() +} + class VecSpec extends ChiselPropSpec with Utils { // Disable shrinking on error. implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) @@ -456,4 +486,8 @@ class VecSpec extends ChiselPropSpec with Utils { }} } } + + property("reduceTree should preserve input/output type") { + assertTesterPasses { new ReduceTreeTester() } + } } -- cgit v1.2.3 From 36506c527ff0f51636beee4160f0ce1f6ad2f90a Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Wed, 15 Dec 2021 15:53:52 +0800 Subject: Refactor TruthTable to use Seq (#2217) This makes the resulting Verilog from decoding a TruthTable deterministic.--- .../util/experimental/TruthTableSpec.scala | 31 ++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala b/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala index 743a3cd8..255effaf 100644 --- a/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala +++ b/src/test/scala/chiselTests/util/experimental/TruthTableSpec.scala @@ -2,8 +2,9 @@ package chiselTests.util.experimental +import chisel3._ import chisel3.util.BitPat -import chisel3.util.experimental.decode.TruthTable +import chisel3.util.experimental.decode.{TruthTable, decoder} import org.scalatest.flatspec.AnyFlatSpec class TruthTableSpec extends AnyFlatSpec { @@ -34,16 +35,16 @@ class TruthTableSpec extends AnyFlatSpec { assert(table.toString contains " 0") } "TruthTable" should "deserialize" in { - assert(TruthTable(str) == table) + assert(TruthTable.fromString(str) == table) } "TruthTable" should "merge same key" in { assert( - TruthTable( + TruthTable.fromString( """001100->??1 |001100->1?? |??? |""".stripMargin - ) == TruthTable( + ) == TruthTable.fromString( """001100->1?1 |??? |""".stripMargin @@ -52,7 +53,7 @@ class TruthTableSpec extends AnyFlatSpec { } "TruthTable" should "crash when merging 0 and 1" in { intercept[IllegalArgumentException] { - TruthTable( + TruthTable.fromString( """0->0 |0->1 |??? @@ -60,4 +61,24 @@ class TruthTableSpec extends AnyFlatSpec { ) } } + "TruthTable" should "be reproducible" in { + class Foo extends Module { + + val io = IO(new Bundle{ + val in = Input(UInt(4.W)) + val out = Output(UInt(16.W)) + }) + + + val table = TruthTable( + (0 until 16).map{ + i => BitPat(i.U(4.W)) -> BitPat((1< m.a, "b" -> m.b)) }) } + + property("DataMirror.modulePorts should replace deprecated .getPorts") { + class MyModule extends Module { + val io = IO(new Bundle { + val in = Input(UInt(8.W)) + val out = Output(Vec(2, UInt(8.W))) + }) + val extra = IO(Input(UInt(8.W))) + val delay = RegNext(io.in) + io.out(0) := delay + io.out(1) := delay + extra + } + var mod: MyModule = null + ChiselStage.elaborate { + mod = new MyModule + mod + } + // Note that this is just top-level ports, Aggregates are not flattened + DataMirror.modulePorts(mod) should contain theSameElementsInOrderAs Seq( + "clock" -> mod.clock, + "reset" -> mod.reset, + "io" -> mod.io, + "extra" -> mod.extra + ) + // Delete this when the deprecated API is deleted + // Note this also uses deprecated Port + import chisel3.internal.firrtl.Port + import SpecifiedDirection.{Input => IN, Unspecified} + mod.getPorts should contain theSameElementsInOrderAs Seq( + Port(mod.clock, IN), + Port(mod.reset, IN), + Port(mod.io, Unspecified), + Port(mod.extra, IN) + ): @nowarn // delete when Port and getPorts become private + } + + property("DataMirror.fullModulePorts should return all ports including children of Aggregates") { + class MyModule extends Module { + val io = IO(new Bundle { + val in = Input(UInt(8.W)) + val out = Output(Vec(2, UInt(8.W))) + }) + val extra = IO(Input(UInt(8.W))) + val delay = RegNext(io.in) + io.out(0) := delay + io.out(1) := delay + extra + } + var mod: MyModule = null + ChiselStage.elaborate { + mod = new MyModule + mod + } + val expected = Seq( + "clock" -> mod.clock, + "reset" -> mod.reset, + "io" -> mod.io, + "io_out" -> mod.io.out, + "io_out_0" -> mod.io.out(0), + "io_out_1" -> mod.io.out(1), + "io_in" -> mod.io.in, + "extra" -> mod.extra + ) + DataMirror.fullModulePorts(mod) should contain theSameElementsInOrderAs expected + } + property("A desiredName parameterized by a submodule should work") { ChiselStage.elaborate(new ModuleWrapper(new ModuleWire)).name should be ("ModuleWireWrapper") } -- cgit v1.2.3 From 214115a4cdbf0714d3d1716035f5eb0dd98cba45 Mon Sep 17 00:00:00 2001 From: Jiuyang Liu Date: Thu, 16 Dec 2021 09:47:05 +0800 Subject: BitSet API (#2211) BitSet is a new experimental parent type for BitPat. It enables more complex operations on BitPats. Co-authored-by: Ocean Shen --- src/test/scala/chiselTests/util/BitPatSpec.scala | 2 +- src/test/scala/chiselTests/util/BitSetSpec.scala | 119 +++++++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/chiselTests/util/BitSetSpec.scala (limited to 'src/test') diff --git a/src/test/scala/chiselTests/util/BitPatSpec.scala b/src/test/scala/chiselTests/util/BitPatSpec.scala index e14b4496..549e8bca 100644 --- a/src/test/scala/chiselTests/util/BitPatSpec.scala +++ b/src/test/scala/chiselTests/util/BitPatSpec.scala @@ -24,7 +24,7 @@ class BitPatSpec extends AnyFlatSpec with Matchers { intercept[IllegalArgumentException]{BitPat("b")} } - it should "contact BitPat via ##" in { + it should "concat BitPat via ##" in { (BitPat.Y(4) ## BitPat.dontCare(3) ## BitPat.N(2)).toString should be (s"BitPat(1111???00)") } diff --git a/src/test/scala/chiselTests/util/BitSetSpec.scala b/src/test/scala/chiselTests/util/BitSetSpec.scala new file mode 100644 index 00000000..8120cc97 --- /dev/null +++ b/src/test/scala/chiselTests/util/BitSetSpec.scala @@ -0,0 +1,119 @@ +package chiselTests.util + +import chisel3.util.experimental.BitSet +import chisel3.util.BitPat +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +class BitSetSpec extends AnyFlatSpec with Matchers { + behavior of classOf[BitSet].toString + + it should "reject unequal width when constructing a BitSet" in { + intercept[IllegalArgumentException] { + BitSet.fromString( + """b0010 + |b00010 + |""".stripMargin) + } + } + + it should "return empty subtraction result correctly" in { + val aBitPat = BitPat("b10?") + val bBitPat = BitPat("b1??") + + aBitPat.subtract(bBitPat).isEmpty should be (true) + } + + it should "return nonempty subtraction result correctly" in { + val aBitPat = BitPat("b10?") + val bBitPat = BitPat("b1??") + val cBitPat = BitPat("b11?") + val dBitPat = BitPat("b100") + + val diffBitPat = bBitPat.subtract(aBitPat) + bBitPat.cover(diffBitPat) should be (true) + diffBitPat.equals(cBitPat) should be (true) + + val largerdiffBitPat = bBitPat.subtract(dBitPat) + aBitPat.cover(dBitPat) should be (true) + largerdiffBitPat.cover(diffBitPat) should be (true) + } + + it should "be able to handle complex subtract between BitSet" in { + val aBitSet = BitSet.fromString( + """b?01?0 + |b11111 + |b00000 + |""".stripMargin) + val bBitSet = BitSet.fromString( + """b?1111 + |b?0000 + |""".stripMargin + ) + val expected = BitPat("b?01?0") + + expected.equals(aBitSet.subtract(bBitSet)) should be (true) + } + + it should "be generated from BitPat union" in { + val aBitSet = BitSet.fromString( + """b001?0 + |b000??""".stripMargin) + val aBitPat = BitPat("b000??") + val bBitPat = BitPat("b001?0") + val cBitPat = BitPat("b00000") + aBitPat.cover(cBitPat) should be (true) + aBitSet.cover(bBitPat) should be (true) + + aBitSet.equals(aBitPat.union(bBitPat)) should be (true) + } + + it should "be generated from BitPat subtraction" in { + val aBitSet = BitSet.fromString( + """b001?0 + |b000??""".stripMargin) + val aBitPat = BitPat("b00???") + val bBitPat = BitPat("b001?1") + + aBitSet.equals(aBitPat.subtract(bBitPat)) should be (true) + } + + it should "union two BitSet together" in { + val aBitSet = BitSet.fromString( + """b001?0 + |b001?1 + |""".stripMargin) + val bBitSet = BitSet.fromString( + """b000?? + |b01??? + |""".stripMargin + ) + val cBitPat = BitPat("b0????") + cBitPat.equals(aBitSet.union(bBitSet)) should be (true) + } + + it should "be decoded" in { + import chisel3._ + import chisel3.util.experimental.decode.decoder + // [0 - 256] part into: [0 - 31], [32 - 47, 64 - 127], [192 - 255] + // "0011????" "10??????" is empty to error + chisel3.stage.ChiselStage.emitSystemVerilog(new Module { + val in = IO(Input(UInt(8.W))) + val out = IO(Output(UInt(4.W))) + out := decoder.bitset(in, Seq( + BitSet.fromString( + "b000?????" + ), + BitSet.fromString( + """b0010???? + |b01?????? + |""".stripMargin + ), + BitSet.fromString( + "b11??????" + ) + ), true) + }) + } + +} -- cgit v1.2.3 From 109b4d8629beb62f7516ca14295258b4131f5849 Mon Sep 17 00:00:00 2001 From: Chick Markley Date: Fri, 17 Dec 2021 10:13:54 -0800 Subject: Improve exception message for aliased bundle fields (#2304) - Shows groups of field names that share a common id (i.e. aliased) - Show, as much as possible, them in the order that fields appear in bundle - Updated BundleSpec's relevant tests Co-authored-by: Megan Wachs Co-authored-by: Jack Koenig --- src/test/scala/chiselTests/BundleSpec.scala | 16 ++++++++++------ src/test/scala/chiselTests/RecordSpec.scala | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/BundleSpec.scala b/src/test/scala/chiselTests/BundleSpec.scala index 51dedfb1..d9f82e6d 100644 --- a/src/test/scala/chiselTests/BundleSpec.scala +++ b/src/test/scala/chiselTests/BundleSpec.scala @@ -111,17 +111,21 @@ class BundleSpec extends ChiselFlatSpec with BundleSpecUtils with Utils { } } - "Bundles" should "not have aliased fields" in { + "Bundles" should "with aliased fields, should show a helpful error message" in { + class AliasedBundle extends Bundle { + val a = UInt(8.W) + val b = a + val c = SInt(8.W) + val d = c + } + (the[ChiselException] thrownBy extractCause[ChiselException] { ChiselStage.elaborate { new Module { - val io = IO(Output(new Bundle { - val a = UInt(8.W) - val b = a - })) + val io = IO(Output(new AliasedBundle)) io.a := 0.U io.b := 1.U } } - }).getMessage should include("aliased fields") + }).getMessage should include("contains aliased fields named (a,b),(c,d)") } "Bundles" should "not have bound hardware" in { diff --git a/src/test/scala/chiselTests/RecordSpec.scala b/src/test/scala/chiselTests/RecordSpec.scala index f0edca8b..e6986efb 100644 --- a/src/test/scala/chiselTests/RecordSpec.scala +++ b/src/test/scala/chiselTests/RecordSpec.scala @@ -8,6 +8,8 @@ import chisel3.testers.BasicTester import chisel3.util.{Counter, Queue} import chisel3.experimental.DataMirror +import scala.collection.immutable.SeqMap + trait RecordSpecUtils { class MyBundle extends Bundle { val foo = UInt(32.W) @@ -64,6 +66,11 @@ trait RecordSpecUtils { } } + class AliasedRecord extends Module { + val field = UInt(32.W) + val io = IO(new CustomBundle("in" -> Input(field), "out" -> Output(field))) + } + class RecordIOModule extends Module { val io = IO(new CustomBundle("in" -> Input(UInt(32.W)), "out" -> Output(UInt(32.W)))) io("out") := io("in") @@ -103,6 +110,23 @@ class RecordSpec extends ChiselFlatSpec with RecordSpecUtils with Utils { ChiselStage.elaborate { new MyModule(new MyBundle, fooBarType) } } + they should "not allow aliased fields" in { + class AliasedFieldRecord extends Record { + val foo = UInt(8.W) + val elements = SeqMap("foo" -> foo, "bar" -> foo) + override def cloneType: AliasedFieldRecord.this.type = this + } + + val e = intercept[AliasedAggregateFieldException] { + ChiselStage.elaborate { + new Module { + val io = IO(new AliasedFieldRecord) + } + } + } + e.getMessage should include ("contains aliased fields named (bar,foo)") + } + they should "follow UInt serialization/deserialization API" in { assertTesterPasses { new RecordSerializationTest } } -- cgit v1.2.3