diff options
| author | Jack Koenig | 2017-02-26 18:34:30 -0800 |
|---|---|---|
| committer | GitHub | 2017-02-26 18:34:30 -0800 |
| commit | 6b030c982c11a330c81daeee7b798f6c147b9a05 (patch) | |
| tree | 565a8b2fdceab1904dcdede7e3cfa1f5ca4b1d6f | |
| parent | 1f9fd2f9b9e9a0117b0dd65524c9dcb767c02778 (diff) | |
Align types and names of ports in emitted Verilog (#463)
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 59 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/VerilogEmitterTests.scala | 43 |
2 files changed, 79 insertions, 23 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index 151ad9e4..9ad97859 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -62,6 +62,13 @@ class VerilogEmitter extends Emitter with PassBased { s".${name}($strx)" case RawStringParam(name, value) => s".$name($value)" } + def stringify(tpe: GroundType): String = tpe match { + case (_: UIntType | _: SIntType | _: AnalogType) => + val wx = bitWidth(tpe) - 1 + if (wx > 0) s"[$wx:0]" else "" + case ClockType => "" + case _ => error("Trying to write unsupported type in the Verilog Emitter") + } def emit(x: Any)(implicit w: Writer) { emit(x, 0) } def emit(x: Any, top: Int)(implicit w: Writer) { def cast(e: Expression): Any = e.tpe match { @@ -80,21 +87,10 @@ class VerilogEmitter extends Emitter with PassBased { case (e: WSubIndex) => w write e.serialize case (e: Literal) => v_print(e) case (e: VRandom) => w write s"{${e.nWords}{$$random}}" - case (t: UIntType) => - val wx = bitWidth(t) - 1 - if (wx > 0) w write s"[$wx:0]" - case (t: SIntType) => - val wx = bitWidth(t) - 1 - if (wx > 0) w write s"[$wx:0]" - case ClockType => - case t: AnalogType => - val wx = bitWidth(t) - 1 - if (wx > 0) w write s"[$wx:0]" - case (t: VectorType) => + case (t: GroundType) => w write stringify(t) + case (t: VectorType) => emit(t.tpe, top + 1) w write s"[${t.size - 1}:0]" - case Input => w write "input" - case Output => w write "output" case (s: String) => w write s case (i: Int) => w write i.toString case (i: Long) => w write i.toString @@ -382,16 +378,33 @@ class VerilogEmitter extends Emitter with PassBased { Seq("$fwrite(32'h80000002,", strx, ");") } - def build_ports(): Unit = portdefs ++= m.ports.zipWithIndex map { - case (p, i) => (p.tpe, p.direction) match { - case (AnalogType(_), _) => - Seq("inout", " ", p.tpe, " ", p.name) - case (_, Input) => - Seq(p.direction, " ", p.tpe, " ", p.name) - case (_, Output) => - val ex = WRef(p.name, p.tpe, PortKind, FEMALE) - assign(ex, netlist(ex)) - Seq(p.direction, " ", p.tpe, " ", p.name) + // Turn ports into Seq[String] and add to portdefs + def build_ports(): Unit = { + def padToMax(strs: Seq[String]): Seq[String] = { + val len = if (strs.nonEmpty) strs.map(_.length).max else 0 + strs map (_.padTo(len, ' ')) + } + // Turn directions into strings (and AnalogType into inout) + val dirs = m.ports map { case Port(_, name, dir, tpe) => + (dir, tpe) match { + case (_, AnalogType(_)) => "inout " // padded to length of output + case (Input, _) => "input " + case (Output, _) => + // Assign to the Port + val ex = WRef(name, tpe, PortKind, FEMALE) + assign(ex, netlist(ex)) + "output" + } + } + // Turn types into strings, all ports must be GroundTypes + val tpes = m.ports map { + case Port(_,_,_, tpe: GroundType) => stringify(tpe) + case port: Port => error("Trying to emit non-GroundType Port $port") + } + + // dirs are already padded + portdefs ++= (dirs, padToMax(tpes), m.ports).zipped.map { + case (dir, tpe, Port(_, name, _,_)) => Seq(dir, " " , tpe, " ", name) } } diff --git a/src/test/scala/firrtlTests/VerilogEmitterTests.scala b/src/test/scala/firrtlTests/VerilogEmitterTests.scala index 41fd6e41..862a9605 100644 --- a/src/test/scala/firrtlTests/VerilogEmitterTests.scala +++ b/src/test/scala/firrtlTests/VerilogEmitterTests.scala @@ -96,3 +96,46 @@ class DoPrimVerilog extends FirrtlFlatSpec { executeTest(input, check, compiler) } } + +class VerilogEmitterSpec extends FirrtlFlatSpec { + "Ports" should "emit with widths aligned and names aligned" in { + val compiler = new VerilogCompiler + val input = + """circuit Test : + | module Test : + | input a : UInt<25000> + | output b : UInt + | input c : UInt<32> + | output d : UInt + | input e : UInt<1> + | input f : Analog<32> + | b <= a + | d <= add(c, e) + |""".stripMargin + val check = Seq( + " input [24999:0] a,", + " output [24999:0] b,", + " input [31:0] c,", + " output [32:0] d,", + " input e,", + " inout [31:0] f" + ) + // We don't use executeTest because we care about the spacing in the result + val writer = new java.io.StringWriter + compiler.compile(CircuitState(parse(input), ChirrtlForm), writer) + val lines = writer.toString.split("\n") + for (c <- check) { + lines should contain (c) + } + } + "The Verilog Emitter" should "support Modules with no ports" in { + val compiler = new VerilogCompiler + val input = + """circuit Test : + | module Test : + | wire x : UInt<32> + | x <= UInt(0) + """.stripMargin + compiler.compile(CircuitState(parse(input), ChirrtlForm), new java.io.StringWriter) + } +} |
