aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam Izraelevitz2016-09-07 16:08:55 -0700
committerGitHub2016-09-07 16:08:55 -0700
commit8beaa3be259d2a793e3a99628b2f0d38d98f5b9a (patch)
treed6c137d446a254bae87cd015c94bf86806225042 /src
parent5697d30179a0f2e86dc618092af63e6eb997a534 (diff)
parent13345ce816a51cc19f93a03c4148eecf0dd2c739 (diff)
Merge branch 'master' into cleanup_passes
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/Emitter.scala972
1 files changed, 444 insertions, 528 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index 6c658257..378eac6d 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -29,21 +29,19 @@ package firrtl
import com.typesafe.scalalogging.LazyLogging
import java.nio.file.{Paths, Files}
-import java.io.Writer
-import java.io.Reader
+import java.io.{Reader, Writer}
import scala.sys.process._
import scala.io.Source
import Utils._
-import firrtl.Mappers._
+import firrtl.ir._
import firrtl.passes._
+import firrtl.Mappers._
import firrtl.PrimOps._
-import firrtl.ir._
-import WrappedExpression._
+import firrtl.WrappedExpression._
// Datastructures
-import scala.collection.mutable.LinkedHashMap
-import scala.collection.mutable.ArrayBuffer
+import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
class EmitterException(message: String) extends PassException(message)
@@ -63,243 +61,186 @@ case class VRandom(width: BigInt) extends Expression {
def serialize: String = "RANDOM"
}
class VerilogEmitter extends Emitter {
- val tab = " "
- var w:Option[Writer] = None
- var mname = ""
- def wref (n:String,t:Type) = WRef(n,t,ExpKind(),UNKNOWNGENDER)
- def remove_root (ex:Expression) : Expression = {
- (ex.asInstanceOf[WSubField].exp) match {
- case (e:WSubField) => remove_root(e)
- case (e:WRef) => WRef(ex.asInstanceOf[WSubField].name,ex.tpe,InstanceKind(),UNKNOWNGENDER)
- }
- }
- def not_empty (s:ArrayBuffer[_]) : Boolean = if (s.size == 0) false else true
- def emit (x:Any) = emit2(x,0)
- def emit2 (x:Any, top:Int) : Unit = {
- def cast (e:Expression) : Any = {
- e.tpe match {
- case (t:UIntType) => e
- case (t:SIntType) => Seq("$signed(",e,")")
- case ClockType => e
- }
- }
- (x) match {
- case (e:Expression) => {
- (e) match {
- case (e:DoPrim) => emit2(op_stream(e), top + 1)
- case (e:Mux) => emit2(Seq(e.cond," ? ",cast(e.tval)," : ",cast(e.fval)),top + 1)
- case (e:ValidIf) => emit2(Seq(cast(e.value)),top + 1)
- case (e:WRef) => w.get.write(e.serialize)
- case (e:WSubField) => w.get.write(LowerTypes.loweredName(e))
- case (e:WSubAccess) => w.get.write(LowerTypes.loweredName(e.exp) + "[" + LowerTypes.loweredName(e.index) + "]")
- case (e:WSubIndex) => w.get.write(e.serialize)
- case (e:Literal) => v_print(e)
- case (e:VRandom) => w.get.write(s"{${e.nWords}{$$random}}")
- }
- }
- case (t:Type) => {
- (t) match {
- case (_:UIntType|_:SIntType) =>
- val wx = long_BANG(t) - 1
- if (wx > 0) w.get.write("[" + wx + ":0]") else w.get.write("")
- case ClockType => w.get.write("")
- case (t:VectorType) =>
- emit2(t.tpe, top + 1)
- w.get.write("[" + (t.size - 1) + ":0]")
- case (t) => error("Shouldn't be here"); w.get.write(t.serialize)
- }
- }
- case (p:Direction) => {
- p match {
- case Input => w.get.write("input")
- case Output => w.get.write("output")
- }
- }
- case (s:String) => w.get.write(s)
- case (i:Int) => w.get.write(i.toString)
- case (i:Long) => w.get.write(i.toString)
- case (t:VIndent) => w.get.write(" ")
- case (s:Seq[Any]) => {
- s.foreach((x:Any) => emit2(x, top + 1))
- if (top == 0) w.get.write("\n")
- }
- }
- }
+ val tab = " "
+ def wref(n: String, t: Type) = WRef(n, t, ExpKind(), UNKNOWNGENDER)
+ def remove_root(ex: Expression): Expression = ex match {
+ case ex: WSubField => ex.exp match {
+ case (e: WSubField) => remove_root(e)
+ case (_: WRef) => WRef(ex.name, ex.tpe, InstanceKind(), UNKNOWNGENDER)
+ }
+ case _ => error("Shouldn't be here")
+ }
+ 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 {
+ case (t: UIntType) => e
+ case (t: SIntType) => Seq("$signed(",e,")")
+ case ClockType => e
+ }
+ (x) match {
+ case (e: DoPrim) => emit(op_stream(e), top + 1)
+ case (e: Mux) => emit(Seq(e.cond," ? ",cast(e.tval)," : ",cast(e.fval)),top + 1)
+ case (e: ValidIf) => emit(Seq(cast(e.value)),top + 1)
+ case (e: WRef) => w write e.serialize
+ case (e: WSubField) => w write LowerTypes.loweredName(e)
+ case (e: WSubAccess) => w write (
+ s"${LowerTypes.loweredName(e.exp)}[${LowerTypes.loweredName(e.index)}]")
+ 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 = long_BANG(t) - 1
+ if (wx > 0) w write s"[$wx:0]"
+ case (t: SIntType) =>
+ val wx = long_BANG(t) - 1
+ if (wx > 0) w write s"[$wx:0]"
+ case ClockType =>
+ 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
+ case (t: VIndent) => w write " "
+ case (s: Seq[Any]) =>
+ s foreach (emit(_, top + 1))
+ if (top == 0) w write "\n"
+ case _ => error("Shouldn't be here")
+ }
+ }
//;------------- PASS -----------------
- def v_print (e:Expression) = {
- e match {
- case UIntLiteral(value, IntWidth(width)) => {
- val str = s"$width'h${value.toString(16)}"
- w.get.write(str)
- }
- case SIntLiteral(value, IntWidth(width)) => {
- val unsignedValue = value + (if (value < 0) BigInt(1) << width.toInt else 0)
- val str = s"$width'sh${unsignedValue.toString(16)}"
- w.get.write(str)
- }
- }
+ def v_print(e: Expression)(implicit w: Writer) = e match {
+ case UIntLiteral(value, IntWidth(width)) =>
+ w write s"$width'h${value.toString(16)}"
+ case SIntLiteral(value, IntWidth(width)) =>
+ val unsignedValue = value + (if (value < 0) BigInt(1) << width.toInt else 0)
+ w write s"$width'sh${unsignedValue.toString(16)}"
}
- def op_stream (doprim:DoPrim) : Seq[Any] = {
- def cast_if (e:Expression) : Any = {
- val signed = doprim.args.find(x => x.tpe match {
- case _: SIntType => true
- case _ => false
- })
- if (signed == None) e
- else e.tpe match {
- case (t:SIntType) => Seq("$signed(",e,")")
- case (t:UIntType) => Seq("$signed({1'b0,",e,"})")
- }
- }
- def cast (e:Expression) : Any = {
- (doprim.tpe) match {
- case (t:UIntType) => e
- case (t:SIntType) => Seq("$signed(",e,")")
- }
- }
- def cast_as (e:Expression) : Any = {
- (e.tpe) match {
- case (t:UIntType) => e
- case (t:SIntType) => Seq("$signed(",e,")")
- }
- }
- def a0 () : Expression = doprim.args(0)
- def a1 () : Expression = doprim.args(1)
- def a2 () : Expression = doprim.args(2)
- def c0 () : Int = doprim.consts(0).toInt
- def c1 () : Int = doprim.consts(1).toInt
-
- def checkArgumentLegality(e: Expression) = e match {
- case _: UIntLiteral =>
- case _: SIntLiteral =>
- case _: WRef =>
- case _: WSubField =>
- case _ => throw new EmitterException(s"Can't emit ${e.getClass.getName} as PrimOp argument")
- }
- doprim.args foreach checkArgumentLegality
-
- doprim.op match {
- case Add => Seq(cast_if(a0())," + ", cast_if(a1()))
- case Addw => Seq(cast_if(a0())," + ", cast_if(a1()))
- case Sub => Seq(cast_if(a0())," - ", cast_if(a1()))
- case Subw => Seq(cast_if(a0())," - ", cast_if(a1()))
- case Mul => Seq(cast_if(a0())," * ", cast_if(a1()) )
- case Div => Seq(cast_if(a0())," / ", cast_if(a1()) )
- case Rem => Seq(cast_if(a0())," % ", cast_if(a1()) )
- case Lt => Seq(cast_if(a0())," < ", cast_if(a1()))
- case Leq => Seq(cast_if(a0())," <= ", cast_if(a1()))
- case Gt => Seq(cast_if(a0())," > ", cast_if(a1()))
- case Geq => Seq(cast_if(a0())," >= ", cast_if(a1()))
- case Eq => Seq(cast_if(a0())," == ", cast_if(a1()))
- case Neq => Seq(cast_if(a0())," != ", cast_if(a1()))
- case Pad => {
- val w = long_BANG(a0().tpe)
- val diff = (c0() - w)
- if (w == 0) Seq(a0())
- else doprim.tpe match {
- // Either sign extend or zero extend.
- case (t:SIntType) => {
- // If width == 1, don't extract bit
- if (w == 1) Seq("{", c0(),"{", a0(), "}}")
- else Seq("{{", diff, "{", a0(), "[", w - 1,"]}},", a0(), "}")
- }
- case (t) => Seq("{{", diff, "'d0}, ", a0(), "}")
- }
- }
- case AsUInt => Seq("$unsigned(",a0(),")")
- case AsSInt => Seq("$signed(",a0(),")")
- case AsClock => Seq("$unsigned(",a0(),")")
- case Dshlw => Seq(cast(a0())," << ", a1())
- case Dshl => Seq(cast(a0())," << ", a1())
- case Dshr => {
- (doprim.tpe) match {
- case (t:SIntType) => Seq(cast(a0())," >>> ",a1())
- case (t) => Seq(cast(a0())," >> ",a1())
- }
- }
- case Shlw => Seq(cast(a0())," << ", c0())
- case Shl => Seq(cast(a0())," << ",c0())
- case Shr => {
- if (c0 >= long_BANG(a0.tpe))
- error("Verilog emitter does not support SHIFT_RIGHT >= arg width")
- Seq(a0(),"[", long_BANG(a0().tpe) - 1,":",c0(),"]")
- }
- case Neg => Seq("-{",cast(a0()),"}")
- case Cvt => {
- a0().tpe match {
- case (t:UIntType) => Seq("{1'b0,",cast(a0()),"}")
- case (t:SIntType) => Seq(cast(a0()))
- }
- }
- case Not => Seq("~ ",a0())
- case And => Seq(cast_as(a0())," & ", cast_as(a1()))
- case Or => Seq(cast_as(a0())," | ", cast_as(a1()))
- case Xor => Seq(cast_as(a0())," ^ ", cast_as(a1()))
- case Andr => {
- val v = ArrayBuffer[Seq[Any]]()
- for (b <- 0 until long_BANG(doprim.tpe).toInt) {
- v += Seq(cast(a0()),"[",b,"]")
- }
- v.reduce(_ + " & " + _)
- }
- case Orr => {
- val v = ArrayBuffer[Seq[Any]]()
- for (b <- 0 until long_BANG(doprim.tpe).toInt) {
- v += Seq(cast(a0()),"[",b,"]")
- }
- v.reduce(_ + " | " + _)
- }
- case Xorr => {
- val v = ArrayBuffer[Seq[Any]]()
- for (b <- 0 until long_BANG(doprim.tpe).toInt) {
- v += Seq(cast(a0()),"[",b,"]")
- }
- v.reduce(_ + " ^ " + _)
- }
- case Cat => Seq("{",cast(a0()),",",cast(a1()),"}")
- case Bits => {
- // If selecting zeroth bit and single-bit wire, just emit the wire
- if (c0() == 0 && c1() == 0 && long_BANG(a0().tpe) == 1) Seq(a0())
- else if (c0() == c1()) Seq(a0(),"[",c0(),"]")
- else Seq(a0(),"[",c0(),":",c1(),"]")
- }
- case Head => {
- val w = long_BANG(a0().tpe)
- val high = w - 1
- val low = w - c0()
- Seq(a0(),"[",high,":",low,"]")
+ def op_stream(doprim: DoPrim): Seq[Any] = {
+ def cast_if(e: Expression): Any = {
+ doprim.args find (_.tpe match {
+ case (_: SIntType) => true
+ case (_) => false
+ }) match {
+ case None => e
+ case Some(_) => e.tpe match {
+ case (_: SIntType) => Seq("$signed(", e, ")")
+ case (_: UIntType) => Seq("$signed({1'b0,", e, "})")
}
- case Tail => {
- val w = long_BANG(a0().tpe)
- val low = w - c0() - 1
- Seq(a0(),"[",low,":",0,"]")
+ }
+ }
+ def cast(e: Expression): Any = doprim.tpe match {
+ case (t: UIntType) => e
+ case (t: SIntType) => Seq("$signed(",e,")")
+ }
+ def cast_as(e: Expression): Any = e.tpe match {
+ case (t: UIntType) => e
+ case (t: SIntType) => Seq("$signed(",e,")")
+ }
+ def a0: Expression = doprim.args(0)
+ def a1: Expression = doprim.args(1)
+ def c0: Int = doprim.consts(0).toInt
+ def c1: Int = doprim.consts(1).toInt
+
+ def checkArgumentLegality(e: Expression) = e match {
+ case _: UIntLiteral | _: SIntLiteral | _: WRef | _: WSubField =>
+ case _ => throw new EmitterException(s"Can't emit ${e.getClass.getName} as PrimOp argument")
+ }
+ doprim.args foreach checkArgumentLegality
+ doprim.op match {
+ case Add => Seq(cast_if(a0), " + ", cast_if(a1))
+ case Addw => Seq(cast_if(a0), " + ", cast_if(a1))
+ case Sub => Seq(cast_if(a0), " - ", cast_if(a1))
+ case Subw => Seq(cast_if(a0), " - ", cast_if(a1))
+ case Mul => Seq(cast_if(a0), " * ", cast_if(a1))
+ case Div => Seq(cast_if(a0), " / ", cast_if(a1))
+ case Rem => Seq(cast_if(a0), " % ", cast_if(a1))
+ case Lt => Seq(cast_if(a0), " < ", cast_if(a1))
+ case Leq => Seq(cast_if(a0), " <= ", cast_if(a1))
+ case Gt => Seq(cast_if(a0), " > ", cast_if(a1))
+ case Geq => Seq(cast_if(a0), " >= ", cast_if(a1))
+ case Eq => Seq(cast_if(a0), " == ", cast_if(a1))
+ case Neq => Seq(cast_if(a0), " != ", cast_if(a1))
+ case Pad =>
+ val w = long_BANG(a0.tpe)
+ val diff = (c0 - w)
+ if (w == 0) Seq(a0)
+ else doprim.tpe match {
+ // Either sign extend or zero extend.
+ // If width == 1, don't extract bit
+ case (_: SIntType) if w == 1 => Seq("{", c0, "{", a0, "}}")
+ case (_: SIntType) => Seq("{{", diff, "{", a0, "[", w - 1, "]}},", a0, "}")
+ case (_) => Seq("{{", diff, "'d0}, ", a0, "}")
}
- }
+ case AsUInt => Seq("$unsigned(", a0, ")")
+ case AsSInt => Seq("$signed(", a0, ")")
+ case AsClock => Seq("$unsigned(", a0, ")")
+ case Dshlw => Seq(cast(a0), " << ", a1)
+ case Dshl => Seq(cast(a0), " << ", a1)
+ case Dshr => (doprim.tpe) match {
+ case (_: SIntType) => Seq(cast(a0)," >>> ", a1)
+ case (_) => Seq(cast(a0), " >> ", a1)
+ }
+ case Shlw => Seq(cast(a0), " << ", c0)
+ case Shl => Seq(cast(a0), " << ", c0)
+ case Shr if c0 >= long_BANG(a0.tpe) =>
+ error("Verilog emitter does not support SHIFT_RIGHT >= arg width")
+ case Shr => Seq(a0,"[", long_BANG(a0.tpe) - 1, ":", c0, "]")
+ case Neg => Seq("-{", cast(a0), "}")
+ case Cvt => a0.tpe match {
+ case (_: UIntType) => Seq("{1'b0,", cast(a0), "}")
+ case (_: SIntType) => Seq(cast(a0))
+ }
+ case Not => Seq("~ ", a0)
+ case And => Seq(cast_as(a0), " & ", cast_as(a1))
+ case Or => Seq(cast_as(a0), " | ", cast_as(a1))
+ case Xor => Seq(cast_as(a0), " ^ ", cast_as(a1))
+ case Andr => (0 until long_BANG(doprim.tpe).toInt) map (
+ Seq(cast(a0), "[", _, "]")) reduce (_ + " & " + _)
+ case Orr => (0 until long_BANG(doprim.tpe).toInt) map (
+ Seq(cast(a0), "[", _, "]")) reduce (_ + " | " + _)
+ case Xorr => (0 until long_BANG(doprim.tpe).toInt) map (
+ Seq(cast(a0), "[", _, "]")) reduce (_ + " ^ " + _)
+ case Cat => Seq("{", cast(a0), ",", cast(a1), "}")
+ // If selecting zeroth bit and single-bit wire, just emit the wire
+ case Bits if c0 == 0 && c1 == 0 && long_BANG(a0.tpe) == 1 => Seq(a0)
+ case Bits if c0 == c1 => Seq(a0, "[", c0, "]")
+ case Bits => Seq(a0, "[", c0, ":", c1, "]")
+ case Head =>
+ val w = long_BANG(a0.tpe)
+ val high = w - 1
+ val low = w - c0
+ Seq(a0, "[", high, ":", low, "]")
+ case Tail =>
+ val w = long_BANG(a0.tpe)
+ val low = w - c0 - 1
+ Seq(a0, "[", low, ":", 0, "]")
+ }
}
- def emit_verilog (m:Module) : DefModule = {
- mname = m.name
- val netlist = LinkedHashMap[WrappedExpression,Expression]()
+ def emit_verilog(m: Module)(implicit w: Writer): DefModule = {
+ val netlist = LinkedHashMap[WrappedExpression, Expression]()
val simlist = ArrayBuffer[Statement]()
val namespace = Namespace(m)
- def build_netlist (s:Statement) : Statement = {
- s match {
- case (s:Connect) => netlist(s.loc) = s.expr
- case (s:IsInvalid) => {
- val n = namespace.newTemp
- val e = wref(n,s.expr.tpe)
- netlist(s.expr) = e
- }
- case (s:Conditionally) => simlist += s
- case (s:DefNode) => {
- val e = WRef(s.name,get_type(s),NodeKind(),MALE)
- netlist(e) = s.value
- }
- case (s) => s map (build_netlist)
- }
- s
+ def build_netlist(s: Statement): Statement = s map build_netlist match {
+ case (s: Connect) =>
+ netlist(s.loc) = s.expr
+ s
+ case (s: IsInvalid) =>
+ netlist(s.expr) = wref(namespace.newTemp, s.expr.tpe)
+ s
+ case (s: Conditionally) =>
+ simlist += s
+ s
+ case (s: DefNode) =>
+ val e = WRef(s.name, get_type(s), NodeKind(), MALE)
+ netlist(e) = s.value
+ s
+ case (s) => s
}
val portdefs = ArrayBuffer[Seq[Any]]()
@@ -309,14 +250,16 @@ class VerilogEmitter extends Emitter {
val at_clock = LinkedHashMap[Expression,ArrayBuffer[Seq[Any]]]()
val initials = ArrayBuffer[Seq[Any]]()
val simulates = ArrayBuffer[Seq[Any]]()
- def declare (b:String,n:String,t:Type) = {
- t match {
- case (t:VectorType) => declares += Seq(b," ",t.tpe," ",n," [0:",t.size - 1,"];")
- case (t) => declares += Seq(b," ",t," ",n,";")
- }
+ def declare (b: String, n: String, t: Type) = t match {
+ case (t: VectorType) =>
+ declares += Seq(b, " ", t.tpe, " ", n, " [0:", t.size - 1, "];")
+ case (t) =>
+ declares += Seq(b, " ", t, " ", n,";")
+ }
+ def assign (e: Expression, value: Expression) {
+ assigns += Seq("assign ", e, " = ", value, ";")
}
- def assign (e:Expression,value:Expression) =
- assigns += Seq("assign ",e," = ",value,";")
+
// In simulation, assign garbage under a predicate
def garbageAssign(e: Expression, syn: Expression, garbageCond: Expression) = {
assigns += Seq("`ifndef RANDOMIZE_GARBAGE_ASSIGN")
@@ -369,7 +312,8 @@ class VerilogEmitter extends Emitter {
addUpdate(Mux(reset, tv, fv, mux_type_and_widths(tv, fv)), "")
}
}
- def update (e:Expression,value:Expression,clk:Expression,en:Expression) = {
+
+ def update(e: Expression, value: Expression, clk: Expression, en: Expression) {
if (!at_clock.contains(clk)) at_clock(clk) = ArrayBuffer[Seq[Any]]()
if (weq(en,one)) at_clock(clk) += Seq(e," <= ",value,";")
else {
@@ -378,46 +322,50 @@ class VerilogEmitter extends Emitter {
at_clock(clk) += Seq("end")
}
}
+
// Declares an intermediate wire to hold a large enough random number.
// Then, return the correct number of bits selected from the random value
- def rand_string (t:Type) : Seq[Any] = {
+ def rand_string(t: Type) : Seq[Any] = {
val nx = namespace.newTemp
val rand = VRandom(long_BANG(t))
val tx = SIntType(IntWidth(rand.realWidth))
- declare("reg",nx,tx)
- initials += Seq(wref(nx,tx)," = ",VRandom(long_BANG(t)),";")
- Seq(nx,"[",long_BANG(t) - 1,":0]")
+ declare("reg",nx, tx)
+ initials += Seq(wref(nx, tx), " = ", VRandom(long_BANG(t)), ";")
+ Seq(nx, "[", long_BANG(t) - 1, ":0]")
}
+
def initialize(e: Expression) = {
initials += Seq("`ifdef RANDOMIZE_REG_INIT")
initials += Seq(e, " = ", rand_string(e.tpe), ";")
initials += Seq("`endif")
}
- def initialize_mem(s: DefMemory) = {
- val index = WRef("initvar", s.dataType, ExpKind(), UNKNOWNGENDER)
+
+ def initialize_mem(s: DefMemory) {
+ val index = wref("initvar", s.dataType)
val rstring = rand_string(s.dataType)
initials += Seq("`ifdef RANDOMIZE_MEM_INIT")
initials += Seq("for (initvar = 0; initvar < ", s.depth, "; initvar = initvar+1)")
- initials += Seq(tab, WSubAccess(wref(s.name, s.dataType), index, s.dataType, FEMALE), " = ", rstring,";")
+ initials += Seq(tab, WSubAccess(wref(s.name, s.dataType), index, s.dataType, FEMALE),
+ " = ", rstring,";")
initials += Seq("`endif")
}
- def instantiate (n:String,m:String,es:Seq[Expression]) = {
- instdeclares += Seq(m," ",n," (")
- (es,0 until es.size).zipped.foreach{ (e,i) => {
- val s = Seq(tab,".",remove_root(e),"(",LowerTypes.loweredName(e),")")
- if (i != es.size - 1) instdeclares += Seq(s,",")
- else instdeclares += s
- }}
+
+ def instantiate(n: String,m: String, es: Seq[Expression]) {
+ instdeclares += Seq(m, " ", n, " (")
+ es.zipWithIndex foreach {case (e, i) =>
+ val s = Seq(tab, ".", remove_root(e), "(", LowerTypes.loweredName(e), ")")
+ if (i != es.size - 1) instdeclares += Seq(s, ",")
+ else instdeclares += s
+ }
instdeclares += Seq(");")
- for (e <- es) {
- declare("wire",LowerTypes.loweredName(e),e.tpe)
- val ex = WRef(LowerTypes.loweredName(e),e.tpe,kind(e),gender(e))
- if (gender(e) == FEMALE) {
- assign(ex,netlist(e))
- }
+ es foreach { e =>
+ declare("wire",LowerTypes.loweredName(e), e.tpe)
+ val ex = WRef(LowerTypes.loweredName(e), e.tpe, kind(e), gender(e))
+ if (gender(e) == FEMALE) assign(ex,netlist(e))
}
}
- def simulate(clk: Expression, en: Expression, s: Seq[Any], cond: Option[String]) = {
+
+ def simulate(clk: Expression, en: Expression, s: Seq[Any], cond: Option[String]) {
if (!at_clock.contains(clk)) at_clock(clk) = ArrayBuffer[Seq[Any]]()
at_clock(clk) += Seq("`ifndef SYNTHESIS")
if (cond.nonEmpty) {
@@ -435,261 +383,248 @@ class VerilogEmitter extends Emitter {
}
at_clock(clk) += Seq("`endif")
}
- def stop(ret: Int): Seq[Any] = {
- Seq(if (ret == 0) "$finish;" else "$fatal;")
- }
- def printf (str:StringLit,args:Seq[Expression]) : Seq[Any] = {
- val q = '"'.toString
- val strx = Seq(q + VerilogStringLitHandler.escape(str) + q) ++
- args.flatMap(x => Seq(",",x))
- Seq("$fwrite(32'h80000002,",strx,");")
+
+ def stop(ret: Int): Seq[Any] = Seq(if (ret == 0) "$finish;" else "$fatal;")
+
+ def printf(str: StringLit, args: Seq[Expression]): Seq[Any] = {
+ val q = '"'.toString
+ val strx = s"""$q${VerilogStringLitHandler escape str}$q""" +:
+ (args flatMap (Seq("," , _)))
+ Seq("$fwrite(32'h80000002,", strx, ");")
}
- def delay (e:Expression, n:Int, clk:Expression) : Expression = {
- ((0 until n) foldLeft e){(ex, i) =>
- val name = namespace.newTemp
- declare("reg",name,e.tpe)
- val exx = WRef(name,e.tpe,ExpKind(),UNKNOWNGENDER)
- initialize(exx)
- update(exx,ex,clk,one)
- exx
- }
+
+ def delay(e: Expression, n: Int, clk: Expression): Expression = {
+ ((0 until n) foldLeft e){(ex, i) =>
+ val name = namespace.newTemp
+ declare("reg", name, e.tpe)
+ val exx = wref(name, e.tpe)
+ initialize(exx)
+ update(exx, ex, clk, one)
+ exx
+ }
}
- def build_ports () = {
- (m.ports,0 until m.ports.size).zipped.foreach{(p,i) => {
- p.direction match {
- case Input => portdefs += Seq(p.direction," ",p.tpe," ",p.name)
- case Output => {
- portdefs += Seq(p.direction," ",p.tpe," ",p.name)
- val ex = WRef(p.name,p.tpe,PortKind(),FEMALE)
- assign(ex,netlist(ex))
- }
- }
- }}
+
+ def build_ports: Unit = m.ports.zipWithIndex foreach {case (p, i) =>
+ p.direction match {
+ case Input =>
+ portdefs += Seq(p.direction, " ", p.tpe, " ", p.name)
+ case Output =>
+ portdefs += Seq(p.direction, " ", p.tpe, " ", p.name)
+ val ex = WRef(p.name, p.tpe, PortKind(), FEMALE)
+ assign(ex, netlist(ex))
+ }
}
- def build_streams (s:Statement) : Statement = {
- s match {
- case EmptyStmt => s
- case (s:Connect) => s
- case (s:DefWire) =>
- declare("wire",s.name,s.tpe)
- val e = wref(s.name,s.tpe)
- assign(e,netlist(e))
- case (s:DefRegister) => {
- declare("reg",s.name,s.tpe)
- val e = wref(s.name,s.tpe)
- update_and_reset(e,s.clock,s.reset,s.init)
- initialize(e)
- }
- case (s:IsInvalid) => {
- val wref = netlist(s.expr).asInstanceOf[WRef]
- declare("wire",wref.name,s.expr.tpe)
- invalidAssign(wref)
- }
- case (s:DefNode) => {
- declare("wire",s.name,s.value.tpe)
- assign(WRef(s.name,s.value.tpe,NodeKind(),MALE),s.value)
- }
- case (s:Stop) => {
- val errorString = StringLit(s"${s.ret}\n".getBytes)
- simulate(s.clk, s.en, stop(s.ret), Some("STOP_COND"))
- }
- case (s:Print) => simulate(s.clk, s.en, printf(s.string, s.args), Some("PRINTF_COND"))
- case (s:WDefInstance) => {
- val es = create_exps(WRef(s.name,s.tpe,InstanceKind(),MALE))
- instantiate(s.name,s.module,es)
- }
- case (s:DefMemory) => {
- val mem = WRef(s.name,get_type(s),MemKind(s.readers ++ s.writers ++ s.readwriters),UNKNOWNGENDER)
- def mem_exp (p:String,f:String) = {
- val t1 = field_type(mem.tpe,p)
- val t2 = field_type(t1,f)
- val x = WSubField(mem,p,t1,UNKNOWNGENDER)
- WSubField(x,f,t2,UNKNOWNGENDER)
- }
-
- declare("reg",s.name,VectorType(s.dataType,s.depth))
- initialize_mem(s)
- for (r <- s.readers ) {
- val data = mem_exp(r,"data")
- val addr = mem_exp(r,"addr")
- val en = mem_exp(r,"en")
- //Ports should share an always@posedge, so can't have intermediary wire
- val clk = netlist(mem_exp(r,"clk"))
-
- declare("wire",LowerTypes.loweredName(data),data.tpe)
- declare("wire",LowerTypes.loweredName(addr),addr.tpe)
- declare("wire",LowerTypes.loweredName(en),en.tpe)
-
- //; Read port
- assign(addr,netlist(addr)) //;Connects value to m.r.addr
- assign(en,netlist(en)) //;Connects value to m.r.en
- val addr_pipe = delay(addr,s.readLatency-1,clk)
- val en_pipe = if (weq(en,one)) one else delay(en,s.readLatency-1,clk)
- val addrx = if (s.readLatency > 0) {
- val name = namespace.newTemp
- val ref = WRef(name,addr.tpe,ExpKind(),UNKNOWNGENDER)
- declare("reg",name,addr.tpe)
- initialize(ref)
- update(ref,addr_pipe,clk,en_pipe)
- ref
- } else addr
- val mem_port = WSubAccess(mem,addrx,s.dataType,UNKNOWNGENDER)
- val depthValue = UIntLiteral(s.depth, IntWidth(BigInt(s.depth).bitLength))
- val garbageGuard = DoPrim(Geq, Seq(addrx, depthValue), Seq(), UnknownType)
-
- if ((s.depth & (s.depth - 1)) == 0)
- assign(data, mem_port)
- else
- garbageAssign(data, mem_port, garbageGuard)
- }
-
- for (w <- s.writers ) {
- val data = mem_exp(w,"data")
- val addr = mem_exp(w,"addr")
- val mask = mem_exp(w,"mask")
- val en = mem_exp(w,"en")
- //Ports should share an always@posedge, so can't have intermediary wire
- val clk = netlist(mem_exp(w,"clk"))
-
- declare("wire",LowerTypes.loweredName(data),data.tpe)
- declare("wire",LowerTypes.loweredName(addr),addr.tpe)
- declare("wire",LowerTypes.loweredName(mask),mask.tpe)
- declare("wire",LowerTypes.loweredName(en),en.tpe)
-
- //; Write port
- assign(data,netlist(data))
- assign(addr,netlist(addr))
- assign(mask,netlist(mask))
- assign(en,netlist(en))
-
- val datax = delay(data,s.writeLatency - 1,clk)
- val addrx = delay(addr,s.writeLatency - 1,clk)
- val maskx = delay(mask,s.writeLatency - 1,clk)
- val enx = delay(en,s.writeLatency - 1,clk)
- val mem_port = WSubAccess(mem,addrx,s.dataType,UNKNOWNGENDER)
- update(mem_port,datax,clk,AND(enx,maskx))
- }
-
- for (rw <- s.readwriters) {
- val wmode = mem_exp(rw,"wmode")
- val rdata = mem_exp(rw,"rdata")
- val wdata = mem_exp(rw,"wdata")
- val wmask = mem_exp(rw,"wmask")
- val addr = mem_exp(rw,"addr")
- val en = mem_exp(rw,"en")
- //Ports should share an always@posedge, so can't have intermediary wire
- val clk = netlist(mem_exp(rw,"clk"))
-
- declare("wire",LowerTypes.loweredName(wmode),wmode.tpe)
- declare("wire",LowerTypes.loweredName(rdata),rdata.tpe)
- declare("wire",LowerTypes.loweredName(wdata),wdata.tpe)
- declare("wire",LowerTypes.loweredName(wmask),wmask.tpe)
- declare("wire",LowerTypes.loweredName(addr),addr.tpe)
- declare("wire",LowerTypes.loweredName(en),en.tpe)
-
- //; Assigned to lowered wires of each
- assign(addr,netlist(addr))
- assign(wdata,netlist(wdata))
- assign(addr,netlist(addr))
- assign(wmask,netlist(wmask))
- assign(en,netlist(en))
- assign(wmode,netlist(wmode))
-
- //; Delay new signals by latency
- val raddrx = if (s.readLatency > 0) delay(addr,s.readLatency - 1,clk) else addr
- val waddrx = delay(addr,s.writeLatency - 1,clk)
- val enx = delay(en,s.writeLatency - 1,clk)
- val wmodex = delay(wmode,s.writeLatency - 1,clk)
- val wdatax = delay(wdata,s.writeLatency - 1,clk)
- val wmaskx = delay(wmask,s.writeLatency - 1,clk)
-
- val raddrxx = if (s.readLatency > 0) {
- val name = namespace.newTemp
- val ref = WRef(name,raddrx.tpe,ExpKind(),UNKNOWNGENDER)
- declare("reg",name,raddrx.tpe)
- initialize(ref)
- ref
- } else addr
- val rmem_port = WSubAccess(mem,raddrxx,s.dataType,UNKNOWNGENDER)
- assign(rdata,rmem_port)
- val wmem_port = WSubAccess(mem,waddrx,s.dataType,UNKNOWNGENDER)
-
- def declare_and_assign(exp: Expression) = {
- val name = namespace.newTemp
- val ref = wref(name, exp.tpe)
- declare("wire", name, exp.tpe)
- assign(ref, exp)
- ref
- }
- val ren = declare_and_assign(NOT(wmodex))
- val wen = declare_and_assign(AND(wmodex, wmaskx))
- if (s.readLatency > 0)
- update(raddrxx,raddrx,clk,AND(enx,ren))
- update(wmem_port,wdatax,clk,AND(enx,wen))
- }
+
+ def build_streams(s: Statement): Statement = s map build_streams match {
+ case (s: DefWire) =>
+ declare("wire",s.name,s.tpe)
+ val e = wref(s.name,s.tpe)
+ assign(e,netlist(e))
+ s
+ case (s: DefRegister) =>
+ declare("reg", s.name, s.tpe)
+ val e = wref(s.name, s.tpe)
+ update_and_reset(e, s.clock, s.reset, s.init)
+ initialize(e)
+ s
+ case (s: IsInvalid) =>
+ val wref = netlist(s.expr) match { case e: WRef => e }
+ declare("reg", wref.name, s.expr.tpe)
+ initialize(wref)
+ s
+ case (s: DefNode) =>
+ declare("wire", s.name, s.value.tpe)
+ assign(WRef(s.name, s.value.tpe, NodeKind(), MALE), s.value)
+ s
+ case (s: Stop) =>
+ val errorString = StringLit(s"${s.ret}\n".getBytes)
+ simulate(s.clk, s.en, stop(s.ret), Some("STOP_COND"))
+ s
+ case (s: Print) =>
+ simulate(s.clk, s.en, printf(s.string, s.args), Some("PRINTF_COND"))
+ s
+ case (s: WDefInstance) =>
+ val es = create_exps(WRef(s.name, s.tpe, InstanceKind(), MALE))
+ instantiate(s.name, s.module, es)
+ s
+ case (s: DefMemory) =>
+ val mem = WRef(s.name, get_type(s),
+ MemKind(s.readers ++ s.writers ++ s.readwriters), UNKNOWNGENDER)
+ def mem_exp (p: String, f: String) = {
+ val t1 = field_type(mem.tpe, p)
+ val t2 = field_type(t1, f)
+ val x = WSubField(mem, p, t1, UNKNOWNGENDER)
+ WSubField(x, f, t2, UNKNOWNGENDER)
+ }
+
+ declare("reg", s.name, VectorType(s.dataType, s.depth))
+ initialize_mem(s)
+ for (r <- s.readers) {
+ val data = mem_exp(r, "data")
+ val addr = mem_exp(r, "addr")
+ val en = mem_exp(r, "en")
+ // Ports should share an always@posedge, so can't have intermediary wire
+ val clk = netlist(mem_exp(r, "clk"))
+
+ declare("wire", LowerTypes.loweredName(data), data.tpe)
+ declare("wire", LowerTypes.loweredName(addr), addr.tpe)
+ declare("wire", LowerTypes.loweredName(en), en.tpe)
+
+ //; Read port
+ assign(addr, netlist(addr)) //;Connects value to m.r.addr
+ assign(en, netlist(en)) //;Connects value to m.r.en
+ val addr_pipe = delay(addr,s.readLatency-1,clk)
+ val en_pipe = if (weq(en,one)) one else delay(en,s.readLatency-1,clk)
+ val addrx = if (s.readLatency > 0) {
+ val name = namespace.newTemp
+ val ref = wref(name, addr.tpe)
+ declare("reg", name, addr.tpe)
+ initialize(ref)
+ update(ref,addr_pipe,clk,en_pipe)
+ ref
+ } else addr
+ val mem_port = WSubAccess(mem,addrx,s.dataType,UNKNOWNGENDER)
+ val depthValue = UIntLiteral(s.depth, IntWidth(BigInt(s.depth).bitLength))
+ val garbageGuard = DoPrim(Geq, Seq(addrx, depthValue), Seq(), UnknownType)
+
+ if ((s.depth & (s.depth - 1)) == 0)
+ assign(data, mem_port)
+ else
+ garbageAssign(data, mem_port, garbageGuard)
+ }
+
+ for (w <- s.writers) {
+ val data = mem_exp(w, "data")
+ val addr = mem_exp(w, "addr")
+ val mask = mem_exp(w, "mask")
+ val en = mem_exp(w, "en")
+ //Ports should share an always@posedge, so can't have intermediary wire
+ val clk = netlist(mem_exp(w, "clk"))
+
+ declare("wire", LowerTypes.loweredName(data), data.tpe)
+ declare("wire", LowerTypes.loweredName(addr), addr.tpe)
+ declare("wire", LowerTypes.loweredName(mask), mask.tpe)
+ declare("wire", LowerTypes.loweredName(en), en.tpe)
+
+ //; Write port
+ assign(data,netlist(data))
+ assign(addr,netlist(addr))
+ assign(mask,netlist(mask))
+ assign(en,netlist(en))
+
+ val datax = delay(data, s.writeLatency - 1, clk)
+ val addrx = delay(addr, s.writeLatency - 1, clk)
+ val maskx = delay(mask, s.writeLatency - 1, clk)
+ val enx = delay(en, s.writeLatency - 1, clk)
+ val mem_port = WSubAccess(mem, addrx, s.dataType, UNKNOWNGENDER)
+ update(mem_port, datax, clk, AND(enx, maskx))
+ }
+
+ for (rw <- s.readwriters) {
+ val wmode = mem_exp(rw, "wmode")
+ val rdata = mem_exp(rw, "rdata")
+ val wdata = mem_exp(rw, "wdata")
+ val wmask = mem_exp(rw, "wmask")
+ val addr = mem_exp(rw, "addr")
+ val en = mem_exp(rw, "en")
+ //Ports should share an always@posedge, so can't have intermediary wire
+ val clk = netlist(mem_exp(rw, "clk"))
+
+ declare("wire", LowerTypes.loweredName(wmode), wmode.tpe)
+ declare("wire", LowerTypes.loweredName(rdata), rdata.tpe)
+ declare("wire", LowerTypes.loweredName(wdata), wdata.tpe)
+ declare("wire", LowerTypes.loweredName(wmask), wmask.tpe)
+ declare("wire", LowerTypes.loweredName(addr), addr.tpe)
+ declare("wire", LowerTypes.loweredName(en), en.tpe)
+
+ //; Assigned to lowered wires of each
+ assign(addr, netlist(addr))
+ assign(wdata, netlist(wdata))
+ assign(addr, netlist(addr))
+ assign(wmask, netlist(wmask))
+ assign(en, netlist(en))
+ assign(wmode, netlist(wmode))
+
+ //; Delay new signals by latency
+ val raddrx = if (s.readLatency > 0) delay(addr, s.readLatency - 1, clk) else addr
+ val waddrx = delay(addr,s.writeLatency - 1,clk)
+ val enx = delay(en,s.writeLatency - 1,clk)
+ val wmodex = delay(wmode,s.writeLatency - 1,clk)
+ val wdatax = delay(wdata,s.writeLatency - 1,clk)
+ val wmaskx = delay(wmask,s.writeLatency - 1,clk)
+
+ val raddrxx = if (s.readLatency > 0) {
+ val name = namespace.newTemp
+ val ref = wref(name, raddrx.tpe)
+ declare("reg", name, raddrx.tpe)
+ initialize(ref)
+ ref
+ } else addr
+ val rmem_port = WSubAccess(mem, raddrxx, s.dataType, UNKNOWNGENDER)
+ assign(rdata, rmem_port)
+ val wmem_port = WSubAccess(mem, waddrx, s.dataType, UNKNOWNGENDER)
+
+ def declare_and_assign(exp: Expression) = {
+ val name = namespace.newTemp
+ val ref = wref(name, exp.tpe)
+ declare("wire", name, exp.tpe)
+ assign(ref, exp)
+ ref
}
- case (s:Block) => s map (build_streams)
- }
- s
+ val ren = declare_and_assign(NOT(wmodex))
+ val wen = declare_and_assign(AND(wmodex, wmaskx))
+ if (s.readLatency > 0)
+ update(raddrxx, raddrx, clk, AND(enx, ren))
+ update(wmem_port, wdatax, clk, AND(enx, wen))
+ }
+ s
+ case s => s
}
- def emit_streams () = {
- emit(Seq("module ",m.name,"("))
- if (not_empty(portdefs)) {
- (portdefs,0 until portdefs.size).zipped.foreach{ (x,i) => {
- if (i != portdefs.size - 1) emit(Seq(tab,x,","))
- else emit(Seq(tab,x))
- }}
- }
- emit(Seq(");"))
+ def emit_streams {
+ emit(Seq("module ", m.name, "("))
+ for ((x, i) <- portdefs.zipWithIndex) {
+ if (i != portdefs.size - 1)
+ emit(Seq(tab, x, ","))
+ else
+ emit(Seq(tab, x))
+ }
+ emit(Seq(");"))
- if (not_empty(declares)) {
- for (x <- declares) emit(Seq(tab,x))
- }
- if (not_empty(instdeclares)) {
- for (x <- instdeclares) emit(Seq(tab,x))
- }
- if (not_empty(assigns)) {
- for (x <- assigns) emit(Seq(tab,x))
- }
- if (not_empty(initials)) {
- emit(Seq("`ifdef RANDOMIZE"))
- emit(Seq(" integer initvar;"))
- emit(Seq(" initial begin"))
- // This enables test benches to set the random values at time 0.001,
- // then start the simulation later
- // Verilator does not support delay statements, so they are omitted.
- emit(Seq(" `ifndef verilator"))
- emit(Seq(" #0.002 begin end"))
- emit(Seq(" `endif"))
- for (x <- initials) {
- emit(Seq(tab,x))
- }
- emit(Seq(" end"))
- emit(Seq("`endif"))
- }
-
- for (clk_stream <- at_clock) {
- if (not_empty(clk_stream._2)) {
- emit(Seq(tab,"always @(posedge ",clk_stream._1,") begin"))
- for (x <- clk_stream._2) {
- emit(Seq(tab,tab,x))
- }
- emit(Seq(tab,"end"))
- }
- }
-
- emit(Seq("endmodule"))
+ for (x <- declares) emit(Seq(tab, x))
+ for (x <- instdeclares) emit(Seq(tab, x))
+ for (x <- assigns) emit(Seq(tab, x))
+ if (!initials.isEmpty) {
+ emit(Seq("`ifdef RANDOMIZE"))
+ emit(Seq(" integer initvar;"))
+ emit(Seq(" initial begin"))
+ // This enables test benches to set the random values at time 0.001,
+ // then start the simulation later
+ // Verilator does not support delay statements, so they are omitted.
+ emit(Seq(" `ifndef verilator"))
+ emit(Seq(" #0.002 begin end"))
+ emit(Seq(" `endif"))
+ for (x <- initials) emit(Seq(tab, x))
+ emit(Seq(" end"))
+ emit(Seq("`endif"))
+ }
+
+ for (clk_stream <- at_clock if !clk_stream._2.isEmpty) {
+ emit(Seq(tab, "always @(posedge ", clk_stream._1, ") begin"))
+ for (x <- clk_stream._2) emit(Seq(tab, tab, x))
+ emit(Seq(tab, "end"))
+ }
+ emit(Seq("endmodule"))
}
build_netlist(m.body)
- build_ports()
+ build_ports
build_streams(m.body)
- emit_streams()
+ emit_streams
m
}
- def emit_preamble() {
+ def emit_preamble(implicit w: Writer) {
emit(Seq(
"`ifdef RANDOMIZE_GARBAGE_ASSIGN\n",
"`define RANDOMIZE\n",
@@ -706,29 +641,10 @@ class VerilogEmitter extends Emitter {
}
def run(c: Circuit, w: Writer) = {
- this.w = Some(w)
- emit_preamble()
- for (m <- c.modules) {
- m match {
- case (m:Module) => emit_verilog(m)
- case (m:ExtModule) => false
- }
- }
+ emit_preamble(w)
+ c.modules foreach {
+ case (m: Module) => emit_verilog(m)(w)
+ case (m: ExtModule) =>
+ }
}
- //def run(c: Circuit, w: Writer)
- //{
- // logger.debug(s"Verilog Emitter is not yet implemented in Scala")
- // val toStanza = Files.createTempFile(Paths.get(""), "verilog", ".fir")
- // val fromStanza = Files.createTempFile(Paths.get(""), "verilog", ".fir")
- // Files.write(toStanza, c.serialize.getBytes)
-
- // val cmd = Seq("firrtl-stanza", "-i", toStanza.toString, "-o", fromStanza.toString, "-b", "verilog")
- // logger.debug(cmd.mkString(" "))
- // val ret = cmd.!
- // // Copy from Stanza output to user requested outputFile (we can't get filename from Writer)
- // Source.fromFile(fromStanza.toString) foreach { w.write(_) }
-
- // Files.delete(toStanza)
- // Files.delete(fromStanza)
- //}
}