From 3655ae091249a72bd424073cfb4a382a5ab170c6 Mon Sep 17 00:00:00 2001 From: Paul Rigge Date: Tue, 18 Dec 2018 15:47:20 -0800 Subject: Give better error when mport references non-existant memory. (#975) * Give better error when mport references non-existent memory * Closes #796--- src/test/scala/firrtlTests/ChirrtlMemSpec.scala | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/ChirrtlMemSpec.scala b/src/test/scala/firrtlTests/ChirrtlMemSpec.scala index 74d39286..a4473fe7 100644 --- a/src/test/scala/firrtlTests/ChirrtlMemSpec.scala +++ b/src/test/scala/firrtlTests/ChirrtlMemSpec.scala @@ -108,6 +108,23 @@ circuit foo : parse(res.getEmittedCircuit.value) } + "An mport that refers to an undefined memory" should "have a helpful error message" in { + val input = + """circuit testTestModule : + | module testTestModule : + | input clock : Clock + | input reset : UInt<1> + | output io : {flip in : UInt<10>, out : UInt<10>} + | + | node _T_10 = bits(io.in, 1, 0) + | read mport _T_11 = m[_T_10], clock + | io.out <= _T_11""".stripMargin + + intercept[PassException]{ + (new LowFirrtlCompiler).compile(CircuitState(parse(input), ChirrtlForm), Seq()).circuit + }.getMessage should startWith ("Undefined memory m referenced by mport _T_11") + } + ignore should "Memories should not have validif on port clocks when declared in a when" in { val input = """;buildInfoPackage: chisel3, version: 3.0-SNAPSHOT, scalaVersion: 2.11.11, sbtVersion: 0.13.16, builtAtString: 2017-10-06 20:55:20.367, builtAtMillis: 1507323320367 -- cgit v1.2.3 From 3433f8f8a82c3b129456e9512dd2cf442a6042f6 Mon Sep 17 00:00:00 2001 From: Albert Magyar Date: Fri, 21 Dec 2018 10:41:35 -0800 Subject: Enhance CheckCombLoops to support annotated ExtModule paths (#962) --- .../scala/firrtlTests/CheckCombLoopsSpec.scala | 86 ++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/CheckCombLoopsSpec.scala b/src/test/scala/firrtlTests/CheckCombLoopsSpec.scala index 8fc7dda9..98472f14 100644 --- a/src/test/scala/firrtlTests/CheckCombLoopsSpec.scala +++ b/src/test/scala/firrtlTests/CheckCombLoopsSpec.scala @@ -165,6 +165,92 @@ class CheckCombLoopsSpec extends SimpleTransformSpec { } } + "Combinational loop through an annotated ExtModule" should "throw an exception" in { + val input = """circuit hasloops : + | extmodule blackbox : + | input in : UInt<1> + | output out : UInt<1> + | module hasloops : + | input clk : Clock + | input a : UInt<1> + | input b : UInt<1> + | output c : UInt<1> + | output d : UInt<1> + | wire y : UInt<1> + | wire z : UInt<1> + | c <= b + | inst inner of blackbox + | inner.in <= y + | z <= inner.out + | y <= z + | d <= z + |""".stripMargin + + val mt = ModuleTarget("hasloops", "blackbox") + val annos = AnnotationSeq(Seq(ExtModulePathAnnotation(mt.ref("in"), mt.ref("out")))) + val writer = new java.io.StringWriter + intercept[CheckCombLoops.CombLoopException] { + compile(CircuitState(parse(input), ChirrtlForm, annos), writer) + } + } + + "Loop-free circuit with ExtModulePathAnnotations" should "not throw an exception" in { + val input = """circuit hasnoloops : + | extmodule blackbox : + | input in1 : UInt<1> + | input in2 : UInt<1> + | output out1 : UInt<1> + | output out2 : UInt<1> + | module hasnoloops : + | input clk : Clock + | input a : UInt<1> + | output b : UInt<1> + | wire x : UInt<1> + | inst inner of blackbox + | inner.in1 <= a + | x <= inner.out1 + | inner.in2 <= x + | b <= inner.out2 + |""".stripMargin + + val mt = ModuleTarget("hasnoloops", "blackbox") + val annos = AnnotationSeq(Seq( + ExtModulePathAnnotation(mt.ref("in1"), mt.ref("out1")), + ExtModulePathAnnotation(mt.ref("in2"), mt.ref("out2")))) + val writer = new java.io.StringWriter + compile(CircuitState(parse(input), ChirrtlForm, annos), writer) + } + + "Combinational loop through an output RHS reference" should "throw an exception" in { + val input = """circuit hasloops : + | module thru : + | input in : UInt<1> + | output tmp : UInt<1> + | output out : UInt<1> + | tmp <= in + | out <= tmp + | module hasloops : + | input clk : Clock + | input a : UInt<1> + | input b : UInt<1> + | output c : UInt<1> + | output d : UInt<1> + | wire y : UInt<1> + | wire z : UInt<1> + | c <= b + | inst inner of thru + | inner.in <= y + | z <= inner.out + | y <= z + | d <= z + |""".stripMargin + + val writer = new java.io.StringWriter + intercept[CheckCombLoops.CombLoopException] { + compile(CircuitState(parse(input), ChirrtlForm), writer) + } + } + "Multiple simple loops in one SCC" should "throw an exception" in { val input = """circuit hasloops : | module hasloops : -- cgit v1.2.3 From 370d5b499f9c02c50fbd62f3291a53fbe8aea9b3 Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Tue, 25 Dec 2018 11:00:42 -0500 Subject: Performance fix of Uniquify for deep bundles (#980) --- src/test/scala/firrtlTests/UniquifySpec.scala | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/UniquifySpec.scala b/src/test/scala/firrtlTests/UniquifySpec.scala index 43d1e733..bf0586f3 100644 --- a/src/test/scala/firrtlTests/UniquifySpec.scala +++ b/src/test/scala/firrtlTests/UniquifySpec.scala @@ -283,4 +283,23 @@ class UniquifySpec extends FirrtlFlatSpec { executeTest(input, expected) } + + it should "quickly rename deep bundles" in { + def mkType(i: Int): String = { + if(i == 0) "UInt<8>" else s"{x: ${mkType(i - 1)}}" + } + + val depth = 500 + + val input = + s"""circuit Test: + | module Test : + | input in: ${mkType(depth)} + | output out: ${mkType(depth)} + | out <= in + |""".stripMargin + + val (ms, _) = Utils.time(compileToVerilog(input)) + (ms < 8000) shouldBe true + } } -- cgit v1.2.3 From 8bc25bbc0ff998565afd153a44bf8f11316ba0f0 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 2 Jan 2019 17:37:18 -0800 Subject: Make GroupComponents run ResolveKinds This fixes an issue where expressions created by GroupComponents would be improperly lowered because they were not marked as references to instance ports. --- .../transforms/GroupComponentsSpec.scala | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/transforms/GroupComponentsSpec.scala b/src/test/scala/firrtlTests/transforms/GroupComponentsSpec.scala index 3a32ec71..f51d44ae 100644 --- a/src/test/scala/firrtlTests/transforms/GroupComponentsSpec.scala +++ b/src/test/scala/firrtlTests/transforms/GroupComponentsSpec.scala @@ -3,6 +3,10 @@ package transforms import firrtl.annotations.{CircuitName, ComponentName, ModuleName} import firrtl.transforms.{GroupAnnotation, GroupComponents} +import firrtl._ +import firrtl.ir._ + +import FirrtlCheckers._ class GroupComponentsSpec extends LowTransformSpec { def transform = new GroupComponents() @@ -288,3 +292,35 @@ class GroupComponentsSpec extends LowTransformSpec { execute(input, check, groups) } } + +class GroupComponentsIntegrationSpec extends FirrtlFlatSpec { + def topComp(name: String): ComponentName = ComponentName(name, ModuleName("Top", CircuitName("Top"))) + "Grouping" should "properly set kinds" in { + val input = + """circuit Top : + | module Top : + | input clk: Clock + | input data: UInt<16> + | output out: UInt<16> + | reg r: UInt<16>, clk + | r <= data + | out <= r + """.stripMargin + val groups = Seq( + GroupAnnotation(Seq(topComp("r")), "MyModule", "inst", Some("_OUT"), Some("_IN")) + ) + val result = (new VerilogCompiler).compileAndEmit( + CircuitState(parse(input), ChirrtlForm, groups), + Seq(new GroupComponents) + ) + result should containTree { + case Connect(_, WSubField(WRef("inst",_, InstanceKind,_), "data_IN", _,_), WRef("data",_,_,_)) => true + } + result should containTree { + case Connect(_, WSubField(WRef("inst",_, InstanceKind,_), "clk_IN", _,_), WRef("clk",_,_,_)) => true + } + result should containTree { + case Connect(_, WRef("out",_,_,_), WSubField(WRef("inst",_, InstanceKind,_), "r_OUT", _,_)) => true + } + } +} -- cgit v1.2.3 From 1931649a050619a711c066f669d93d436bd03296 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Fri, 4 Jan 2019 13:39:04 -0800 Subject: Fix GroupComponents to work with unused components Previously, components that did not affect the output would cause exceptions because they were missing from the label2group Map. This commit treats them as "reachable" by the ports so they are included in the default "ungrouped" group. --- .../transforms/GroupComponentsSpec.scala | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/transforms/GroupComponentsSpec.scala b/src/test/scala/firrtlTests/transforms/GroupComponentsSpec.scala index f51d44ae..c54e02e3 100644 --- a/src/test/scala/firrtlTests/transforms/GroupComponentsSpec.scala +++ b/src/test/scala/firrtlTests/transforms/GroupComponentsSpec.scala @@ -46,6 +46,43 @@ class GroupComponentsSpec extends LowTransformSpec { """.stripMargin execute(input, check, groups) } + "Grouping" should "work even when there are unused nodes" in { + val input = + s"""circuit $top : + | module $top : + | input in: UInt<16> + | output out: UInt<16> + | node n = UInt<16>("h0") + | wire w : UInt<16> + | wire a : UInt<16> + | wire b : UInt<16> + | a <= UInt<16>("h0") + | b <= a + | w <= in + | out <= w + """.stripMargin + val groups = Seq( + GroupAnnotation(Seq(topComp("w")), "Child", "inst", Some("_OUT"), Some("_IN")) + ) + val check = + s"""circuit Top : + | module $top : + | input in: UInt<16> + | output out: UInt<16> + | inst inst of Child + | node n = UInt<16>("h0") + | inst.in_IN <= in + | node a = UInt<16>("h0") + | node b = a + | out <= inst.w_OUT + | module Child : + | input in_IN : UInt<16> + | output w_OUT : UInt<16> + | node w = in_IN + | w_OUT <= w + """.stripMargin + execute(input, check, groups) + } "The two sets of instances" should "be grouped" in { val input = -- cgit v1.2.3 From 5f0e893c9213464507418a532ee61347a5da26c8 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Tue, 8 Jan 2019 07:26:20 -0800 Subject: Avoid enforcing time constrains during coverage tests. (#989) This fixes issue #988 I tried one alternative to this fix: record the time to do a *no rename* run (`depth = 0`) and check that the time to do the *deep rename* (`depth = 500`) was a reasonable multiple of the *no rename* test. Unfortunately, the discrepancies were all over the map, sometime as much three orders of magnitude difference. I decided the current fix was the simplest - don't enforce timing checks if we're doing coverage testing, although determining the latter is brittle.--- src/test/scala/firrtlTests/UniquifySpec.scala | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/UniquifySpec.scala b/src/test/scala/firrtlTests/UniquifySpec.scala index bf0586f3..561f0a84 100644 --- a/src/test/scala/firrtlTests/UniquifySpec.scala +++ b/src/test/scala/firrtlTests/UniquifySpec.scala @@ -12,6 +12,7 @@ import firrtl._ import firrtl.annotations._ import firrtl.annotations.TargetToken._ import firrtl.transforms.DontTouchAnnotation +import firrtl.util.TestOptions class UniquifySpec extends FirrtlFlatSpec { @@ -285,6 +286,12 @@ class UniquifySpec extends FirrtlFlatSpec { } it should "quickly rename deep bundles" in { + // We use a fixed time to determine if this test passed or failed. + // This test would pass under normal conditions, but would fail during coverage tests. + // Since executions times vary significantly under coverage testing, we check a global + // to see if timing measurements are accurate enough to enforce the timing checks. + val maxMs = 8000.0 + def mkType(i: Int): String = { if(i == 0) "UInt<8>" else s"{x: ${mkType(i - 1)}}" } @@ -299,7 +306,9 @@ class UniquifySpec extends FirrtlFlatSpec { | out <= in |""".stripMargin - val (ms, _) = Utils.time(compileToVerilog(input)) - (ms < 8000) shouldBe true + val (renameMs, _) = Utils.time(compileToVerilog(input)) + + if (TestOptions.accurateTiming) + renameMs shouldBe < (maxMs) } } -- cgit v1.2.3 From f5a42ce22193a038008a1c4f80618e38f72b40f1 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Sun, 13 Jan 2019 21:05:17 -0800 Subject: Keep constant propagating expressions until done optimizing --- .../scala/firrtlTests/ConstantPropagationTests.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/ConstantPropagationTests.scala b/src/test/scala/firrtlTests/ConstantPropagationTests.scala index 603ddc25..a6df1a3b 100644 --- a/src/test/scala/firrtlTests/ConstantPropagationTests.scala +++ b/src/test/scala/firrtlTests/ConstantPropagationTests.scala @@ -734,6 +734,24 @@ class ConstantPropagationSingleModule extends ConstantPropagationSpec { """.stripMargin (parse(exec(input))) should be(parse(check)) } + + // Optimizing this mux gives: z <= pad(UInt<2>(0), 4) + // Thus this checks that we then optimize that pad + "ConstProp" should "optimize nested Expressions" in { + val input = + """circuit Top : + | module Top : + | output z : UInt<4> + | z <= mux(UInt(1), UInt<2>(0), UInt<4>(0)) + """.stripMargin + val check = + """circuit Top : + | module Top : + | output z : UInt<4> + | z <= UInt<4>("h0") + """.stripMargin + (parse(exec(input))) should be(parse(check)) + } } // More sophisticated tests of the full compiler -- cgit v1.2.3 From f961bfca704c9095309e110ff3a546a40b1a2dc5 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Sun, 13 Jan 2019 16:11:22 -0800 Subject: Constant Propagate dshl and dshr with constant amounts Fixes #990 h/t @pentin-as and @abejgonzalez --- .../firrtlTests/ConstantPropagationTests.scala | 71 ++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/ConstantPropagationTests.scala b/src/test/scala/firrtlTests/ConstantPropagationTests.scala index a6df1a3b..8a69fcaa 100644 --- a/src/test/scala/firrtlTests/ConstantPropagationTests.scala +++ b/src/test/scala/firrtlTests/ConstantPropagationTests.scala @@ -1122,6 +1122,77 @@ class ConstantPropagationIntegrationSpec extends LowTransformSpec { | z <= _T_61""".stripMargin execute(input, check, Seq.empty) } + + behavior of "ConstProp" + + it should "optimize shl of constants" in { + val input = + """circuit Top : + | module Top : + | output z : UInt<7> + | z <= shl(UInt(5), 4) + """.stripMargin + val check = + """circuit Top : + | module Top : + | output z : UInt<7> + | z <= UInt<7>("h50") + """.stripMargin + execute(input, check, Seq.empty) + } + + it should "optimize shr of constants" in { + val input = + """circuit Top : + | module Top : + | output z : UInt<1> + | z <= shr(UInt(5), 2) + """.stripMargin + val check = + """circuit Top : + | module Top : + | output z : UInt<1> + | z <= UInt<1>("h1") + """.stripMargin + execute(input, check, Seq.empty) + } + + // Due to #866, we need dshl optimized away or it'll become a dshlw and error in parsing + // Include cat to verify width is correct + it should "optimize dshl of constant" in { + val input = + """circuit Top : + | module Top : + | output z : UInt<8> + | node n = dshl(UInt<1>(0), UInt<2>(0)) + | z <= cat(UInt<4>("hf"), n) + """.stripMargin + val check = + """circuit Top : + | module Top : + | output z : UInt<8> + | z <= UInt<8>("hf0") + """.stripMargin + execute(input, check, Seq.empty) + } + + // Include cat and constants to verify width is correct + it should "optimize dshr of constant" in { + val input = + """circuit Top : + | module Top : + | output z : UInt<8> + | node n = dshr(UInt<4>(0), UInt<2>(2)) + | z <= cat(UInt<4>("hf"), n) + """.stripMargin + val check = + """circuit Top : + | module Top : + | output z : UInt<8> + | z <= UInt<8>("hf0") + """.stripMargin + execute(input, check, Seq.empty) + } } -- cgit v1.2.3