diff options
| author | Adam Izraelevitz | 2016-09-25 20:35:09 -0700 |
|---|---|---|
| committer | GitHub | 2016-09-25 20:35:09 -0700 |
| commit | e54fb610c6bf0a7fe5c9c0f0e0b3acbb3728cfd0 (patch) | |
| tree | 7c186c96c782f488a9ceea21abb3f60594bf98c7 /src/test | |
| parent | 7c4fa71a062f0c18a3af13c9e8853fdec2818da9 (diff) | |
Spec features added: AnalogType and Attach (#295)
* Spec features added: AnalogType and Attach
AnalogType(width: Width):
- Concrete syntax:
wire x: AnalogType<10>
- New groundtype, very restricted in use cases.
- Can only declare ports and wires with Analog type
- Analog types are never equivalent, thus if x and y have Analog
types: x <= y is never legal.
Attach(info: Info, source: Expression, exprs: Seq[Expression]):
- Concrete syntax:
attach x to (y, z)
- New statement
- Source can be any groundtyped expression (UInt, SInt, Analog, Clock)
- Exprs must have an Analog type reference an instance port
- Source and exprs must have identical widths
Included WDefInstanceConnector to enable emission of Verilog inout
Should be mostly feature complete.
Need to update spec if PR gets accepted.
* Fixed bug where invalidated ports aren't handled
* Bugfix for VerilogPrep
Intermediate wires for invalidated instance ports were not invalidated
* Bugfix: calling create_exp with name/tpe
Returns unknown gender, which was passing through
Caused temporary wire to not be declared
Because Verilog is dumb, undeclared wires are assumed to be 1bit signals
* Addressed donggyukim's style comments
* Reworked pass to only allow analog types in attach
Restrict source to be only wire or port kind
Much simpler implementation, almost identical functionality
Clearer semantics (i think?)
* Fixup bugs from pulling in new changes from master
* comments for type eqs and small style fixes
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/scala/firrtlTests/AttachSpec.scala | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/src/test/scala/firrtlTests/AttachSpec.scala b/src/test/scala/firrtlTests/AttachSpec.scala new file mode 100644 index 00000000..d1e07eae --- /dev/null +++ b/src/test/scala/firrtlTests/AttachSpec.scala @@ -0,0 +1,413 @@ +/* +Copyright (c) 2014 - 2016 The Regents of the University of +California (Regents). All Rights Reserved. Redistribution and use in +source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, +ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF +REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF +ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION +TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. +*/ + +package firrtlTests + +import java.io._ +import org.scalatest._ +import org.scalatest.prop._ +import firrtl._ +import firrtl.Annotations._ +import firrtl.ir.Circuit +import firrtl.passes._ +import firrtl.Parser.IgnoreInfo + +class InoutVerilog extends FirrtlFlatSpec { + def parse (input:String) = Parser.parse(input.split("\n").toIterator, IgnoreInfo) + private def executeTest(input: String, expected: Seq[String], compiler: Compiler) = { + val writer = new StringWriter() + compiler.compile(parse(input), new AnnotationMap(Seq.empty), writer) + val lines = writer.toString().split("\n") map normalized + expected foreach { e => + lines should contain(e) + } + } + "Circuit" should "attach a module input source" 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 to (a.an, b.an) + | module A: + | input an: Analog<3> + | module B: + | input an: Analog<3> """.stripMargin + val check = + """module Attaching( + | inout [2:0] an + |); + | A a ( + | .an(an) + | ); + | B b ( + | .an(an) + | ); + |endmodule + |module A( + | inout [2:0] an + |); + |endmodule + |module B( + | inout [2:0] an + |); + |endmodule + |""".stripMargin.split("\n") map normalized + executeTest(input, check, compiler) + } + + "Circuit" should "attach a module output source" 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.an, b.an) + | module A: + | input an: Analog<3> + | module B: + | input an: Analog<3> """.stripMargin + val check = + """module Attaching( + | inout [2:0] an + |); + | A a ( + | .an(an) + | ); + | B b ( + | .an(an) + | ); + |endmodule + |module A( + | inout [2:0] an + |); + |endmodule + |module B( + | inout [2:0] an + |); + |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) + } + } + + "Circuit" should "attach a wire source" 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 = + """module Attaching( + |); + | wire [2:0] x; + | A a ( + | .an(x) + | ); + |endmodule + |""".stripMargin.split("\n") map normalized + executeTest(input, check, compiler) + } +} + +class AttachAnalogSpec extends FirrtlFlatSpec { + def parse (input:String) = Parser.parse(input.split("\n").toIterator, IgnoreInfo) + private def executeTest(input: String, expected: Seq[String], passes: Seq[Pass]) = { + val c = passes.foldLeft(Parser.parse(input.split("\n").toIterator)) { + (c: Circuit, p: Pass) => p.run(c) + } + val lines = c.serialize.split("\n") map normalized + + expected foreach { e => + lines should contain(e) + } + } + + "Connecting analog types" should "throw an exception" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes) + val input = + """circuit Unit : + | module Unit : + | input y: Analog<1> + | output x: Analog<1> + | x <= y""".stripMargin + intercept[CheckTypes.InvalidConnect] { + passes.foldLeft(parse(input)) { + (c: Circuit, p: Pass) => p.run(c) + } + } + } + + "Declaring register with analog types" should "throw an exception" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes) + val input = + """circuit Unit : + | module Unit : + | input clk: Clock + | reg r: Analog<2>, clk""".stripMargin + intercept[CheckTypes.IllegalAnalogDeclaration] { + passes.foldLeft(parse(input)) { + (c: Circuit, p: Pass) => p.run(c) + } + } + } + + "Declaring memory with analog types" should "throw an exception" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes) + val input = + """circuit Unit : + | module Unit : + | input clk: Clock + | mem m: + | data-type => Analog<2> + | depth => 4 + | read-latency => 0 + | write-latency => 1 + | read-under-write => undefined""".stripMargin + intercept[CheckTypes.IllegalAnalogDeclaration] { + passes.foldLeft(parse(input)) { + (c: Circuit, p: Pass) => p.run(c) + } + } + } + + "Declaring node with analog types" should "throw an exception" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes) + val input = + """circuit Unit : + | module Unit : + | input in: Analog<2> + | node n = in """.stripMargin + intercept[CheckTypes.IllegalAnalogDeclaration] { + passes.foldLeft(parse(input)) { + (c: Circuit, p: Pass) => p.run(c) + } + } + } + + "Attaching a non-analog source" should "not be ok" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes) + val input = + """circuit Unit : + | module Unit : + | 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) + | 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] { + passes.foldLeft(parse(input)) { + (c: Circuit, p: Pass) => p.run(c) + } + } + } + + "Inequal attach widths" should "throw an exception" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input i: Analog<3> + | inst a of A + | attach i to (a.o) + | extmodule A : + | output o: Analog<2> """.stripMargin + intercept[CheckWidths.AttachWidthsNotEqual] { + passes.foldLeft(parse(input)) { + (c: Circuit, p: Pass) => p.run(c) + } + } + } + + //"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) + //} +} |
