aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/Emitter.scala59
-rw-r--r--src/test/scala/firrtlTests/VerilogEmitterTests.scala43
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)
+ }
+}