diff options
| author | Adam Izraelevitz | 2016-10-17 15:10:12 -0700 |
|---|---|---|
| committer | GitHub | 2016-10-17 15:10:12 -0700 |
| commit | 7d08b9a1486fef0459481f6e542464a29fbe1db5 (patch) | |
| tree | e8b2289ac5cbecbd59d58cab8bd503287818ec5d /src/test | |
| parent | 2848d87721df110d0425114283cb5fa7e6c2ee03 (diff) | |
Add fixed point type (#322)
* WIP: Adding FixedType to Firrtl proper
Got simple example running through width inference
Checks should be ok
Need to look into FixedLiteral more
* Added simple test for fixed types
* Added asFixedPoint to primops
* Added tail case for FixedType
* Added ConvertFixedToSInt.scala
Added pass to MiddleToLowerFirrtl transform
* Replace AsFixedType with AsSInt in fixed removal
* Bugfix: constant from asFixed not deleted
* Added unit test for bulk connect
* Fixed partial connect bug #241
* Fixed missing case for FixedPoint in legalizeConnect
* Add FixedMathSpec that demonstrates some problems with FixedPointMath
* Fixed test and ConvertToSInt to pass.
Negative binary points not easily supported, needs much more time to
implement.
* Refactored checking neg widths
Make checking for negative binary points easier
* Added tests for inferring many FixedType ops
shl, shr, cat, bits, head, tail, setbp, shiftbp
* Handle bpshl, bpshr, bpset in ConvertFixedToSInt
Changed name from shiftbp -> bpshl, bpshr
Change name from setbp -> bpset
Added more tests
* Added set binary point test that fails
* Added simple test for zero binary point
* gitignore fixes for antlr intermediate dir and intellij dir
* removed unused imports
retool the fixed point with zero binary point test
* simplified example of inability to set binary point to zero
* Temporary fix for zero-width binary point
This fix allows for all widths to be zero, but since this is a feature I
am working on next, I'm not going to bother with a more stringent check.
* change version for dsp tools
* Removed extra temporary file
* Fixed merge bug
* Fixed another merge bug
* Removed commented out/unrelated files
* Removed snake case
Diffstat (limited to 'src/test')
3 files changed, 660 insertions, 0 deletions
diff --git a/src/test/scala/firrtlTests/fixed/FixedPointMathSpec.scala b/src/test/scala/firrtlTests/fixed/FixedPointMathSpec.scala new file mode 100644 index 00000000..85f34606 --- /dev/null +++ b/src/test/scala/firrtlTests/fixed/FixedPointMathSpec.scala @@ -0,0 +1,118 @@ +// See LICENSE for license details. + +package firrtlTests.fixed + +import java.io.StringWriter + +import firrtl.Annotations.AnnotationMap +import firrtl.{LowFirrtlCompiler, Parser} +import firrtl.Parser.IgnoreInfo +import firrtlTests.FirrtlFlatSpec + +class FixedPointMathSpec extends FirrtlFlatSpec { + def parse (input:String) = Parser.parse(input.split("\n").toIterator, IgnoreInfo) + + "Fixed types" should "parse" in { + val SumPattern = """.*output sum.*<(\d+)>.*.*""".r + val ProductPattern = """.*output product.*<(\d+)>.*""".r + val DifferencePattern = """.*output difference.*<(\d+)>.*""".r + + val AssignPattern = """\s*(\w+) <= (\w+)\((.*)\)\s*""".r + + for { + bits1 <- 1 to 4 +// binaryPoint1 <- -4 to 4 + binaryPoint1 <- 1 to 4 + bits2 <- 1 to 4 +// binaryPoint2 <- -4 to 4 + binaryPoint2 <- 1 to 4 + } { + val input = + s"""circuit Unit : + | module Unit : + | input a : Fixed<$bits1><<$binaryPoint1>> + | input b : Fixed<$bits2><<$binaryPoint2>> + | output sum : Fixed + | output product : Fixed + | output difference : Fixed + | sum <= add(a, b) + | product <= mul(a, b) + | difference <= sub(a, b) + | """. + stripMargin + + val lowerer = new LowFirrtlCompiler + + val writer = new StringWriter() + + lowerer.compile(parse(input), new AnnotationMap(Seq.empty), writer) + + val output = writer.toString.split("\n") + + def config = s"($bits1,$binaryPoint1)($bits2,$binaryPoint2)" + + def inferredAddWidth: Int = { + val binaryDifference = binaryPoint1 - binaryPoint2 + val (newW1, newW2) = if(binaryDifference > 0) { + (bits1, bits2 + binaryDifference) + } else { + (bits1 + binaryDifference.abs, bits2) + } + newW1.max(newW2) + 1 + } + + println(s"Test for configuratio $config") + + for(line <- output) { + line match { + case SumPattern(varWidth) => + assert(varWidth.toInt === inferredAddWidth, s"$config sum sint bits wrong for $line") + case ProductPattern(varWidth) => + assert(varWidth.toInt === bits1 + bits2, s"$config product bits wrong for $line") + case DifferencePattern(varWidth) => + assert(varWidth.toInt === inferredAddWidth, s"$config difference bits wrong for $line") + case AssignPattern(varName, operation, args) => + varName match { + case "sum" => + assert(operation === "add", s"var sum should be result of an add in $line") + if (binaryPoint1 > binaryPoint2) { + assert(!args.contains("shl(a"), s"$config first arg should be just a in $line") + assert(args.contains(s"shl(b, ${binaryPoint1 - binaryPoint2})"), + s"$config second arg incorrect in $line") + } else if (binaryPoint1 < binaryPoint2) { + assert(args.contains(s"shl(a, ${(binaryPoint1 - binaryPoint2).abs})"), + s"$config second arg incorrect in $line") + assert(!args.contains("shl(b"), s"$config second arg should be just b in $line") + } else { + assert(!args.contains("shl(a"), s"$config first arg should be just a in $line") + assert(!args.contains("shl(b"), s"$config second arg should be just b in $line") + } + case "product" => + assert(operation === "mul", s"var sum should be result of an add in $line") + assert(!args.contains("shl(a"), s"$config first arg should be just a in $line") + assert(!args.contains("shl(b"), s"$config second arg should be just b in $line") + case "difference" => + assert(operation === "sub", s"var difference should be result of an sub in $line") + if (binaryPoint1 > binaryPoint2) { + assert(!args.contains("shl(a"), s"$config first arg should be just a in $line") + assert(args.contains(s"shl(b, ${binaryPoint1 - binaryPoint2})"), + s"$config second arg incorrect in $line") + } else if (binaryPoint1 < binaryPoint2) { + assert(args.contains(s"shl(a, ${(binaryPoint1 - binaryPoint2).abs})"), + s"$config second arg incorrect in $line") + assert(!args.contains("shl(b"), s"$config second arg should be just b in $line") + } else { + assert(!args.contains("shl(a"), s"$config first arg should be just a in $line") + assert(!args.contains("shl(b"), s"$config second arg should be just b in $line") + } + case _ => + } + case _ => +// println(s"No pattern found for ${line}") + } + } + + println(writer.toString) + } + } +} diff --git a/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala b/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala new file mode 100644 index 00000000..7144f98a --- /dev/null +++ b/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala @@ -0,0 +1,321 @@ +/* +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 +package fixed + +import firrtl._ +import firrtl.ir.Circuit +import firrtl.passes._ +import firrtl.Parser.IgnoreInfo + +class FixedTypeInferenceSpec 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 + + for(l <- lines) { + println(l) + } + expected foreach { e => + lines should contain(e) + } + } + + "Fixed types" should "infer add correctly" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | input b : Fixed<10> + | input c : Fixed<4><<3>> + | output d : Fixed + | d <= add(a, add(b, c))""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | input b : Fixed<10><<0>> + | input c : Fixed<4><<3>> + | output d : Fixed<15><<3>> + | d <= add(a, add(b, c))""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "be correctly shifted left" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed + | d <= shl(a, 2)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed<12><<2>> + | d <= shl(a, 2)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "be correctly shifted right" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed + | d <= shr(a, 2)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed<8><<2>> + | d <= shr(a, 2)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "relatively move binary point left" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed + | d <= bpshl(a, 2)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed<12><<4>> + | d <= bpshl(a, 2)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "relatively move binary point right" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed + | d <= bpshr(a, 2)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed<8><<0>> + | d <= bpshr(a, 2)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "absolutely set binary point correctly" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed + | d <= bpset(a, 3)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed<11><<3>> + | d <= bpset(a, 3)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "cat, head, tail, bits" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | input b : Fixed<7><<3>> + | input c : UInt<2> + | output cat : Fixed + | output head : UInt + | output tail : UInt + | output bits : UInt + | cat <= cat(a, c) + | head <= head(a, 3) + | tail <= tail(a, 3) + | bits <= bits(a, 6, 3)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | input b : Fixed<7><<3>> + | input c : UInt<2> + | output cat : Fixed<12><<4>> + | output head : UInt<3> + | output tail : UInt<7> + | output bits : UInt<4> + | cat <= cat(a, c) + | head <= head(a, 3) + | tail <= tail(a, 3) + | bits <= bits(a, 6, 3)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "be cast to" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths) + val input = + """circuit Unit : + | module Unit : + | input a : SInt<10> + | output d : Fixed + | d <= asFixedPoint(a, 2)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : SInt<10> + | output d : Fixed<10><<2>> + | d <= asFixedPoint(a, 2)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "support binary point of zero" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths, + ConvertFixedToSInt) + val input = + """ + |circuit Unit : + | module Unit : + | input clk : Clock + | input reset : UInt<1> + | input io_in : Fixed<6><<0>> + | output io_out : Fixed<6><<0>> + | + | io_in is invalid + | io_out is invalid + | io_out <= io_in + """.stripMargin + val check = + """ + |circuit Unit : + | module Unit : + | input clk : Clock + | input reset : UInt<1> + | input io_in : SInt<6> + | output io_out : SInt<6> + | + | io_out <= io_in + | + """.stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } +} + +// vim: set ts=4 sw=4 et: diff --git a/src/test/scala/firrtlTests/fixed/RemoveFixedTypeSpec.scala b/src/test/scala/firrtlTests/fixed/RemoveFixedTypeSpec.scala new file mode 100644 index 00000000..d9d6dd27 --- /dev/null +++ b/src/test/scala/firrtlTests/fixed/RemoveFixedTypeSpec.scala @@ -0,0 +1,221 @@ +/* +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 +package fixed + +import firrtl.Annotations.AnnotationMap +import firrtl._ +import firrtl.ir.Circuit +import firrtl.passes._ +import firrtl.Parser.IgnoreInfo + +class RemoveFixedTypeSpec 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 + + for(l <- lines) { + println(l) + } + expected foreach { e => + lines should contain(e) + } + } + + "Fixed types" should "be removed" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths, + ConvertFixedToSInt) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | input b : Fixed<10> + | input c : Fixed<4><<3>> + | output d : Fixed<<5>> + | d <= add(a, add(b, c))""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : SInt<10> + | input b : SInt<10> + | input c : SInt<4> + | output d : SInt<15> + | d <= shl(add(shl(a, 1), add(shl(b, 3), c)), 2)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + "Fixed types" should "be removed, even with a bulk connect" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths, + ConvertFixedToSInt) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | input b : Fixed<10> + | input c : Fixed<4><<3>> + | output d : Fixed<<5>> + | d <- add(a, add(b, c))""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : SInt<10> + | input b : SInt<10> + | input c : SInt<4> + | output d : SInt<15> + | d <- shl(add(shl(a, 1), add(shl(b, 3), c)), 2)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "remove binary point shift correctly" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths, + ConvertFixedToSInt) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed<12><<4>> + | d <= bpshl(a, 2)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : SInt<10> + | output d : SInt<12> + | d <= shl(a, 2)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "remove binary point shift correctly in reverse" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths, + ConvertFixedToSInt) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed<9><<1>> + | d <= bpshr(a, 1)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : SInt<10> + | output d : SInt<9> + | d <= shr(a, 1)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed types" should "remove an absolutely set binary point correctly" in { + val passes = Seq( + ToWorkingIR, + CheckHighForm, + ResolveKinds, + InferTypes, + CheckTypes, + ResolveGenders, + CheckGenders, + InferWidths, + CheckWidths, + ConvertFixedToSInt) + val input = + """circuit Unit : + | module Unit : + | input a : Fixed<10><<2>> + | output d : Fixed + | d <= bpset(a, 3)""".stripMargin + val check = + """circuit Unit : + | module Unit : + | input a : SInt<10> + | output d : SInt<11> + | d <= shl(a, 1)""".stripMargin + executeTest(input, check.split("\n") map normalized, passes) + } + + "Fixed point numbers" should "allow binary point to be set to zero at creation" in { + val input = + """ + |circuit Unit : + | module Unit : + | input clk : Clock + | input reset : UInt<1> + | input io_in : Fixed<6><<0>> + | output io_out : Fixed + | + | io_in is invalid + | io_out is invalid + | io_out <= io_in + """.stripMargin + + class CheckChirrtlTransform extends Transform with SimpleRun { + val passSeq = Seq(passes.CheckChirrtl) + def execute (circuit: Circuit, annotationMap: AnnotationMap): TransformResult = + run(circuit, passSeq) + } + + val chirrtlTransform = new CheckChirrtlTransform + chirrtlTransform.execute(parse(input), new AnnotationMap(Seq.empty)) + } +} + +// vim: set ts=4 sw=4 et: |
