diff options
| author | Jack Koenig | 2017-02-07 16:54:35 -0800 |
|---|---|---|
| committer | Adam Izraelevitz | 2017-02-07 16:54:35 -0800 |
| commit | 2f4ae9b4164cf415600de970b3ac5a1b9760efa5 (patch) | |
| tree | 6e131cd16157f921bb3ae83cb15caa0f53feb51a /src/test | |
| parent | 16238da2b50706e511f22f257402a3c2c009c004 (diff) | |
Rework Attach to work on arbitrary Analog hierarchies (#415)
* Rework Attach to work on arbitrary Analog hierarchies
If there are zero or one Analog sources in an Attach (source meaning
wire or parent module port), then the Attach will be emitted as a simple
point to point connection. In the general case, alias is used for
simulation while forwards and backwards assigns for synthesis. Verilator
does not currently support the general case so an `ifdef Verilator
`error is emitted.
* Add helper functions for creating WRef from Reg and Wire
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/scala/firrtlTests/AttachSpec.scala | 349 |
1 files changed, 150 insertions, 199 deletions
diff --git a/src/test/scala/firrtlTests/AttachSpec.scala b/src/test/scala/firrtlTests/AttachSpec.scala index 2eba9b96..32dc00a0 100644 --- a/src/test/scala/firrtlTests/AttachSpec.scala +++ b/src/test/scala/firrtlTests/AttachSpec.scala @@ -11,7 +11,7 @@ import firrtl.ir.Circuit import firrtl.passes._ import firrtl.Parser.IgnoreInfo -class InoutVerilog extends FirrtlFlatSpec { +class InoutVerilogSpec extends FirrtlFlatSpec { private def executeTest(input: String, expected: Seq[String], compiler: Compiler) = { val writer = new StringWriter() compiler.compile(CircuitState(parse(input), ChirrtlForm), writer) @@ -20,132 +20,175 @@ class InoutVerilog extends FirrtlFlatSpec { lines should contain(e) } } - "Circuit" should "attach a module input source" in { + + behavior of "Analog" + + it should "attach a module input source directly" in { + val compiler = new VerilogCompiler + val input = + """circuit Attaching : + | module Attaching : + | input an: Analog<3> + | inst a of A + | inst b of B + | attach (an, a.an1, b.an2) + | module A: + | input an1: Analog<3> + | module B: + | input an2: Analog<3> """.stripMargin + val check = + """module Attaching( + | inout [2:0] an + |); + | A a ( + | .an1(an) + | ); + | B b ( + | .an2(an) + | ); + |endmodule + |module A( + | inout [2:0] an1 + |); + |endmodule + |module B( + | inout [2:0] an2 + |); + |endmodule + |""".stripMargin.split("\n") map normalized + executeTest(input, check, compiler) + } + + it should "attach two instances" in { + val compiler = new VerilogCompiler + val input = + """circuit Attaching : + | module Attaching : + | inst a of A + | inst b of B + | attach (a.an, b.an) + | module A: + | input an: Analog<3> + | module B: + | input an: Analog<3> """.stripMargin + val check = + """module Attaching( + |); + | wire [2:0] _GEN_0; + | A a ( + | .an(_GEN_0) + | ); + | A b ( + | .an(_GEN_0) + | ); + |endmodule + |module A( + | inout [2:0] an + |); + |endmodule + |""".stripMargin.split("\n") map normalized + executeTest(input, check, compiler) + } + + it should "attach a wire source" in { val compiler = new VerilogCompiler val input = - """circuit Attaching : - | module Attaching : - | input an: Analog<3> + """circuit Attaching : + | module Attaching : + | wire x: Analog | inst a of A - | inst b of B - | attach an to (a.an1, b.an2) - | module A: - | input an1: Analog<3> - | module B: - | input an2: Analog<3> """.stripMargin - val check = + | attach (x, a.an) + | module A: + | input an: Analog<3> """.stripMargin + val check = """module Attaching( - | inout [2:0] an |); + | wire [2:0] x; | A a ( - | .an1(an) - | ); - | B b ( - | .an2(an) + | .an(x) | ); |endmodule - |module A( - | inout [2:0] an1 - |); - |endmodule - |module B( - | inout [2:0] an2 - |); - |endmodule |""".stripMargin.split("\n") map normalized - executeTest(input, check, compiler) - } + executeTest(input, check, compiler) + } - "Circuit" should "attach a module output source" in { + it should "attach multiple sources" in { val compiler = new VerilogCompiler val input = - """circuit Attaching : - | module Attaching : - | output an: Analog<3> - | inst a of A - | inst b of B - | attach an to (a.an1, b.an2) - | module A: - | input an1: Analog<3> - | module B: - | input an2: Analog<3> """.stripMargin - val check = + """circuit Attaching : + | module Attaching : + | input a1 : Analog<3> + | input a2 : Analog<3> + | wire x: Analog<3> + | attach (x, a1, a2)""".stripMargin + val check = """module Attaching( - | inout [2:0] an - |); - | A a ( - | .an1(an) - | ); - | B b ( - | .an2(an) - | ); - |endmodule - |module A( - | inout [2:0] an1 - |); - |endmodule - |module B( - | inout [2:0] an2 + | inout [2:0] a1, + | inout [2:0] a2 |); + | wire [2:0] x; + | `ifdef SYNTHESIS + | assign x = a1; + | assign a1 = x; + | assign x = a2; + | assign a2 = x; + | assign a1 = a2; + | assign a2 = a1; + | `elseif verilator + | `error "Verilator does not support alias and thus cannot arbirarily connect bidirectional wires and ports" + | `else + | alias x = a1 = a2; + | `endif |endmodule |""".stripMargin.split("\n") map normalized - executeTest(input, check, compiler) - } - - "Circuit" should "not attach an instance input source" in { - val compiler = new VerilogCompiler - val input = - """circuit Attaching : - | module Attaching : - | inst a of A - | inst b of B - | attach a.an to (b.an) - | module A: - | input an: Analog<3> - | module B: - | input an: Analog<3> """.stripMargin - intercept[CheckTypes.IllegalAttachSource] { - executeTest(input, Seq.empty, compiler) - } - } - - "Circuit" should "attach an instance output source" in { - val compiler = new VerilogCompiler - val input = - """circuit Attaching : - | module Attaching : - | inst a of A - | inst b of B - | attach b.an to (a.an) - | module A: - | input an: Analog<3> - | module B: - | input an: Analog<3> """.stripMargin - intercept[CheckTypes.IllegalAttachSource] { - executeTest(input, Seq.empty, compiler) - } + executeTest(input, check, compiler) } - "Circuit" should "attach a wire source" in { + it should "preserve attach order" in { val compiler = new VerilogCompiler val input = - """circuit Attaching : - | module Attaching : - | wire x: Analog - | inst a of A - | attach x to (a.an) - | module A: - | input an: Analog<3> """.stripMargin - val check = + """circuit Attaching : + | module Attaching : + | input a : Analog<32> + | input b : Analog<32> + | input c : Analog<32> + | input d : Analog<32> + | attach (a, b) + | attach (c, b) + | attach (a, d)""".stripMargin + val check = """module Attaching( + | inout [31:0] a, + | inout [31:0] b, + | inout [31:0] c, + | inout [31:0] d |); - | wire [2:0] x; - | A a ( - | .an(x) - | ); + | alias a = b = c = d; |endmodule |""".stripMargin.split("\n") map normalized executeTest(input, check, compiler) + + val input2 = + """circuit Attaching : + | module Attaching : + | input a : Analog<32> + | input b : Analog<32> + | input c : Analog<32> + | input d : Analog<32> + | attach (a, b) + | attach (c, d) + | attach (d, a)""".stripMargin + val check2 = + """module Attaching( + | inout [31:0] a, + | inout [31:0] b, + | inout [31:0] c, + | inout [31:0] d + |); + | alias a = b = c = d; + |endmodule + |""".stripMargin.split("\n") map normalized + executeTest(input2, check2, compiler) } } @@ -211,7 +254,7 @@ class AttachAnalogSpec extends FirrtlFlatSpec { """circuit Unit : | module Unit : | input clock: Clock - | mem m: + | mem m: | data-type => Analog<2> | depth => 4 | read-latency => 0 @@ -243,7 +286,7 @@ class AttachAnalogSpec extends FirrtlFlatSpec { } } - "Attaching a non-analog source" should "not be ok" in { + "Attaching a non-analog expression" should "not be ok" in { val passes = Seq( ToWorkingIR, CheckHighForm, @@ -256,80 +299,12 @@ class AttachAnalogSpec extends FirrtlFlatSpec { | input source: UInt<2> | inst a of A | inst b of B - | attach source to (a.o, b.o) - | extmodule A : - | output o: Analog<2> - | extmodule B: - | input o: Analog<2>""".stripMargin - intercept[CheckTypes.IllegalAttachSource] { - passes.foldLeft(parse(input)) { - (c: Circuit, p: Pass) => p.run(c) - } - } - } - - "Attach instance analog male source" should "not be ok." in { - val passes = Seq( - ToWorkingIR, - CheckHighForm, - ResolveKinds, - InferTypes, - CheckTypes) - val input = - """circuit Unit : - | module Unit : - | inst a of A - | inst b of B - | attach a.o to (b.o) + | attach (source, a.o, b.o) | extmodule A : | output o: Analog<2> | extmodule B: | input o: Analog<2>""".stripMargin - intercept[CheckTypes.IllegalAttachSource] { - passes.foldLeft(parse(input)) { - (c: Circuit, p: Pass) => p.run(c) - } - } - } - - "Attach instance analog female source" should "not be ok." in { - val passes = Seq( - ToWorkingIR, - CheckHighForm, - ResolveKinds, - InferTypes, - CheckTypes) - val input = - """circuit Unit : - | module Unit : - | inst a of A - | inst b of B - | attach b.o to (a.o) - | extmodule A : - | output o: Analog<2> - | extmodule B: - | input o: Analog<2>""".stripMargin - intercept[CheckTypes.IllegalAttachSource] { - passes.foldLeft(parse(input)) { - (c: Circuit, p: Pass) => p.run(c) - } - } - } - - "Attach port analog expr" should "throw an exception" in { - val passes = Seq( - ToWorkingIR, - CheckHighForm, - ResolveKinds, - InferTypes, - CheckTypes) - val input = - """circuit Unit : - | module Unit : - | input i: Analog<2> - | input j: Analog<2> - | attach j to (i) """.stripMargin - intercept[CheckTypes.IllegalAttachExp] { + intercept[CheckTypes.OpNotAnalog] { passes.foldLeft(parse(input)) { (c: Circuit, p: Pass) => p.run(c) } @@ -350,7 +325,7 @@ class AttachAnalogSpec extends FirrtlFlatSpec { | module Unit : | input i: Analog<3> | inst a of A - | attach i to (a.o) + | attach (i, a.o) | extmodule A : | output o: Analog<2> """.stripMargin intercept[CheckWidths.AttachWidthsNotEqual] { @@ -359,28 +334,4 @@ class AttachAnalogSpec extends FirrtlFlatSpec { } } } - - //"Simple compound expressions" should "be split" in { - // val passes = Seq( - // ToWorkingIR, - // ResolveKinds, - // InferTypes, - // ResolveGenders, - // InferWidths, - // SplitExpressions - // ) - // val input = - // """circuit Top : - // | module Top : - // | input a : UInt<32> - // | input b : UInt<32> - // | input d : UInt<32> - // | output c : UInt<1> - // | c <= geq(add(a, b),d)""".stripMargin - // val check = Seq( - // "node GEN_0 = add(a, b)", - // "c <= geq(GEN_0, d)" - // ) - // executeTest(input, check, passes) - //} } |
