diff options
| author | Jack Koenig | 2016-09-07 14:18:29 -0700 |
|---|---|---|
| committer | GitHub | 2016-09-07 14:18:29 -0700 |
| commit | 0ed5eb48cdb916b644aaf9e5dbf48f6cfb6c60f4 (patch) | |
| tree | 71829e27aa3c57e682c8231c27027b3efbd2918d /src/test | |
| parent | 16426b3a68d85ce7dd9655b0ce773431eb69fc74 (diff) | |
Add Printable (#270)
Printable is a new type that changes how printing of Chisel types is represented
It uses an ordered collection rather than a format string and specifiers
Features:
- Custom String Interpolator for Scala-like printf
- String-like manipulation of "hardware strings" for custom pretty-printing
- Default pretty-printing for Chisel data types
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/scala/chiselTests/PrintableSpec.scala | 162 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Printf.scala | 9 |
2 files changed, 171 insertions, 0 deletions
diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala new file mode 100644 index 00000000..a2c8c62a --- /dev/null +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -0,0 +1,162 @@ +package chiselTests + +import org.scalatest.{FlatSpec, Matchers} +import scala.collection.mutable + +import chisel3._ +import chisel3.testers.BasicTester + +/* Printable Tests */ +class PrintableSpec extends FlatSpec with Matchers { + private val PrintfRegex = """\s*printf\((.*)\).*""".r + // This regex is brittle, it relies on the first two arguments of the printf + // not containing quotes, problematic if Chisel were to emit UInt<1>("h01") + // instead of the current UInt<1>(1) for the enable signal + private val StringRegex = """([^"]*)"(.*?)"(.*)""".r + private case class Printf(str: String, args: Seq[String]) + private def getPrintfs(firrtl: String): Seq[Printf] = { + def processArgs(str: String): Seq[String] = + str split "," map (_.trim) filter (_.nonEmpty) + def processBody(str: String): (String, Seq[String]) = { + str match { + case StringRegex(_, fmt, args) => + (fmt, processArgs(args)) + case _ => fail(s"Regex to process Printf should work on $str!") + } + } + + firrtl split "\n" collect { + case PrintfRegex(matched) => + val (str, args) = processBody(matched) + Printf(str, args) + } + } + + behavior of "Printable & Custom Interpolator" + + it should "pass exact strings through" in { + class MyModule extends BasicTester { + printf(p"An exact string") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("An exact string", Seq())) => + case e => fail() + } + } + it should "handle Printable and String concatination" in { + class MyModule extends BasicTester { + printf(p"First " + PString("Second ") + "Third") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("First Second Third", Seq())) => + case e => fail() + } + } + it should "call toString on non-Printable objects" in { + class MyModule extends BasicTester { + val myInt = 1234 + printf(p"myInt = $myInt") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("myInt = 1234", Seq())) => + case e => fail() + } + } + it should "generate proper printf for simple Decimal printing" in { + class MyModule extends BasicTester { + val myWire = Wire(init = UInt(1234)) + printf(p"myWire = ${Decimal(myWire)}") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("myWire = %d", Seq("myWire"))) => + case e => fail() + } + } + it should "handle printing literals" in { + class MyModule extends BasicTester { + printf(Decimal(UInt(10, 32))) + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("%d", Seq(lit))) => + assert(lit contains "UInt<32>") + case e => fail() + } + } + it should "correctly escape percent" in { + class MyModule extends BasicTester { + printf(p"%") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("%%", Seq())) => + case e => fail() + } + } + it should "support names of circuit elements and the current module" in { + class MyBundle extends Bundle { + val foo = UInt(width = 32) + override def cloneType = (new MyBundle).asInstanceOf[this.type] + } + class MyModule extends BasicTester { + override def desiredName = "MyModule" + val myWire = Wire(new MyBundle) + printf(p"${Name(myWire.foo)}") + printf(p"${FullName(myWire.foo)}") + printf(p"${FullName(this)}") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("foo", Seq()), + Printf("myWire.foo", Seq()), + Printf("MyModule", Seq())) => + case e => fail() + } + } + it should "print UInts and SInts as Decimal by default" in { + class MyModule extends BasicTester { + val myUInt = Wire(init = UInt(0)) + val mySInt = Wire(init = SInt(-1)) + printf(p"$myUInt & $mySInt") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("%d & %d", Seq("myUInt", "mySInt"))) => + case e => fail() + } + } + it should "print Vecs like Scala Seqs by default" in { + class MyModule extends BasicTester { + val myVec = Wire(Vec(4, UInt(width = 32))) + myVec foreach (_ := UInt(0)) + printf(p"$myVec") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("Vec(%d, %d, %d, %d)", + Seq("myVec[0]", "myVec[1]", "myVec[2]", "myVec[3]"))) => + case e => fail() + } + } + it should "print Bundles like Scala Maps by default" in { + class MyModule extends BasicTester { + val myBun = Wire(new Bundle { + val foo = UInt(width = 32) + val bar = UInt(width = 32) + }) + myBun.foo := UInt(0) + myBun.bar := UInt(0) + printf(p"$myBun") + } + val firrtl = Driver.emit(() => new MyModule) + getPrintfs(firrtl) match { + case Seq(Printf("Bundle(foo -> %d, bar -> %d)", + Seq("myBun.foo", "myBun.bar"))) => + case e => fail() + } + } +} diff --git a/src/test/scala/chiselTests/Printf.scala b/src/test/scala/chiselTests/Printf.scala index c872fde4..28b6132b 100644 --- a/src/test/scala/chiselTests/Printf.scala +++ b/src/test/scala/chiselTests/Printf.scala @@ -4,6 +4,7 @@ package chiselTests import org.scalatest._ import chisel3._ +import chisel3.util._ import chisel3.testers.BasicTester class SinglePrintfTester() extends BasicTester { @@ -24,6 +25,11 @@ class MultiPrintfTester() extends BasicTester { stop() } +class ASCIIPrintableTester extends BasicTester { + printf(PString((0x20 to 0x7e) map (_.toChar) mkString "")) + stop() +} + class PrintfSpec extends ChiselFlatSpec { "A printf with a single argument" should "run" in { assertTesterPasses { new SinglePrintfTester } @@ -34,4 +40,7 @@ class PrintfSpec extends ChiselFlatSpec { "A printf with ASCII characters 1-127" should "run" in { assertTesterPasses { new ASCIIPrintfTester } } + "A printf with Printable ASCII characters 1-127" should "run" in { + assertTesterPasses { new ASCIIPrintableTester } + } } |
