aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorazidar2016-02-06 09:59:13 -0800
committerazidar2016-02-09 18:57:07 -0800
commit69597a7d57236bc43c964f7714bfa8ed53bf3bee (patch)
treedd9d9870fe4fb2d21690d1757177fd10facfab99
parentbf900917c50a440632dbcaae17bcfe9613d14452 (diff)
Added constprop,v-wrap,v-rename. All set to attempt like->like comparison of rocketchip
-rw-r--r--src/main/scala/firrtl/Compiler.scala13
-rw-r--r--src/main/scala/firrtl/Emitter.scala578
-rw-r--r--src/main/scala/firrtl/PrimOps.scala6
-rw-r--r--src/main/scala/firrtl/Utils.scala20
-rw-r--r--src/main/scala/firrtl/WIR.scala9
-rw-r--r--src/main/scala/firrtl/passes/Passes.scala170
-rw-r--r--src/main/stanza/chirrtl.stanza16
-rw-r--r--src/main/stanza/passes.stanza2
8 files changed, 778 insertions, 36 deletions
diff --git a/src/main/scala/firrtl/Compiler.scala b/src/main/scala/firrtl/Compiler.scala
index 34feab99..d2f9fc0e 100644
--- a/src/main/scala/firrtl/Compiler.scala
+++ b/src/main/scala/firrtl/Compiler.scala
@@ -22,6 +22,7 @@ object VerilogCompiler extends Compiler {
// Copied from Stanza implementation
val passes = Seq(
//CheckHighForm,
+ FromCHIRRTL,
ToWorkingIR,
ResolveKinds,
InferTypes,
@@ -31,14 +32,20 @@ object VerilogCompiler extends Compiler {
ExpandConnects,
RemoveAccesses,
ExpandWhens,
- CheckInitialization,
+ //CheckInitialization,
ConstProp,
- ToWorkingIR,
ResolveKinds,
InferTypes,
ResolveGenders,
InferWidths,
- LowerTypes
+ LowerTypes,
+ ResolveKinds,
+ InferTypes,
+ ResolveGenders,
+ InferWidths,
+ VerilogWrap,
+ SplitExp,
+ VerilogRename
)
def run(c: Circuit, w: Writer)
{
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index 09302fb3..596c1f93 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -11,6 +11,10 @@ import scala.io.Source
import Utils._
import firrtl.passes._
+import WrappedExpression._
+// Datastructures
+import scala.collection.mutable.HashMap
+import scala.collection.mutable.ArrayBuffer
trait Emitter extends LazyLogging {
def run(c: Circuit, w: Writer)
@@ -20,22 +24,562 @@ object FIRRTLEmitter extends Emitter {
def run(c: Circuit, w: Writer) = w.write(c.serialize)
}
+case class VIndent()
+case class VRandom()
object VerilogEmitter extends Emitter {
- // Currently just trap into Stanza
- 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)
- }
+ val tab = " "
+ val ran = VRandom()
+ var w:Option[Writer] = None
+ var mname = ""
+ def wref (n:String,t:Type) = WRef(n,t,ExpKind(),UNKNOWNGENDER)
+ def escape (s:String) : String = {
+ val sx = ArrayBuffer[String]()
+ sx += "\""
+ var percent:Boolean = false
+ for (c <- s) {
+ if (c == '\n') sx += "\\n"
+ else {
+ if((c == 'x') && percent) sx += "h" else sx += c.toString
+ }
+ percent = (c == '%')
+ }
+ sx += "\""
+ sx.reduce(_ + _)
+ }
+ def remove_root (ex:Expression) : Expression = {
+ (ex.as[WSubField].get.exp) match {
+ case (e:WSubField) => remove_root(e)
+ case (e:WRef) => WRef(ex.as[WSubField].get.name,tpe(ex),InstanceKind(),UNKNOWNGENDER)
+ }
+ }
+ def not_empty (s:ArrayBuffer[_]) : Boolean = if (s.size == 0) false else true
+ def rand_string (t:Type) : Seq[Any] = {
+ val wx = ((long_BANG(t) + 31) / 32)
+ Seq("{",wx,"{",ran,"}}")
+ }
+ def emit (x:Any) = emit2(x,0)
+ def emit2 (x:Any, top:Int) : Unit = {
+ def cast (e:Expression) : Any = {
+ (tpe(e)) match {
+ case (t:UIntType) => e
+ case (t:SIntType) => Seq("$signed(",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(lowered_name(e))
+ case (e:WSubAccess) => w.get.write(lowered_name(e.exp) + "[" + lowered_name(e.index) + "]")
+ case (e:WSubIndex) => w.get.write(e.serialize())
+ case (_:UIntValue|_:SIntValue) => v_print(e)
+ }
+ }
+ 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 (t: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)
+ case (i:Long) => w.get.write(i.toInt)
+ case (t:VIndent) => w.get.write(" ")
+ case (r:VRandom) => w.get.write("$random")
+ case (s:Seq[Any]) => {
+ s.foreach((x:Any) => emit2(x.as[Any], top + 1))
+ if (top == 0) w.get.write("\n")
+ }
+ }
+ }
+
+ //;------------- PASS -----------------
+ def v_print (e:Expression) = {
+ e match {
+ case (e:UIntValue) => {
+ val str = e.value.toString
+ val out = str.substring(1,str.length() - 1)
+ w.get.write(long_BANG(tpe(e)).toString + "'" + out)
+ }
+ case (e:SIntValue) => {
+ val str = e.value.toString
+ val out = str.substring(1,str.length() - 1)
+ w.get.write(long_BANG(tpe(e)).toString + "'s" + out)
+ }
+ }
+ }
+ def op_stream (doprim:DoPrim) : Seq[Any] = {
+ def cast_if (e:Expression) : Any = {
+ val signed = doprim.args.find(x => tpe(x).typeof[SIntType])
+ if (signed == None) e
+ else tpe(e) 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 = {
+ (tpe(e)) 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
+
+ doprim.op match {
+ case ADD_OP => Seq(cast_if(a0())," + ", cast_if(a1()))
+ case ADDW_OP => Seq(cast_if(a0())," + ", cast_if(a1()))
+ case SUB_OP => Seq(cast_if(a0())," _ ", cast_if(a1()))
+ case SUBW_OP => Seq(cast_if(a0())," _ ", cast_if(a1()))
+ case MUL_OP => Seq(cast_if(a0())," * ", cast_if(a1()) )
+ case DIV_OP => Seq(cast_if(a0())," / ", cast_if(a1()) )
+ case REM_OP => Seq(cast_if(a0())," % ", cast_if(a1()) )
+ case LESS_OP => Seq(cast_if(a0())," < ", cast_if(a1()))
+ case LESS_EQ_OP => Seq(cast_if(a0())," <= ", cast_if(a1()))
+ case GREATER_OP => Seq(cast_if(a0())," > ", cast_if(a1()))
+ case GREATER_EQ_OP => Seq(cast_if(a0())," >= ", cast_if(a1()))
+ case EQUAL_OP => Seq(cast_if(a0())," == ", cast_if(a1()))
+ case NEQUAL_OP => Seq(cast_if(a0())," != ", cast_if(a1()))
+ case PAD_OP => {
+ val w = long_BANG(tpe(a0()))
+ val diff = (c0() - w)
+ if (w == 0) Seq(a0())
+ else doprim.tpe match {
+ case (t:SIntType) => Seq("{{",diff,"{",a0(),"[",w - 1,"]}}, ",a0()," }")
+ case (t) => Seq("{{",diff,"'d0 }, ",a0()," }")
+ }
+ }
+ case AS_UINT_OP => Seq("$unsigned(",a0(),")")
+ case AS_SINT_OP => Seq("$signed(",a0(),")")
+ case AS_CLOCK_OP => Seq("$unsigned(",a0(),")")
+ case DYN_SHIFT_LEFT_OP => Seq(cast(a0())," << ", a1())
+ case DYN_SHIFT_RIGHT_OP => {
+ (doprim.tpe) match {
+ case (t:SIntType) => Seq(cast(a0())," >>> ",a1())
+ case (t) => Seq(cast(a0())," >> ",a1())
+ }
+ }
+ case SHIFT_LEFT_OP => Seq(cast(a0())," << ",c0())
+ case SHIFT_RIGHT_OP => Seq(a0(),"[", long_BANG(tpe(a0())) - 1,":",c0(),"]")
+ case NEG_OP => Seq("-{",cast(a0()),"}")
+ case CONVERT_OP => {
+ tpe(a0()) match {
+ case (t:UIntType) => Seq("{1'b0,",cast(a0()),"}")
+ case (t:SIntType) => Seq(cast(a0()))
+ }
+ }
+ case NOT_OP => Seq("~",a0())
+ case AND_OP => Seq(cast_as(a0())," & ", cast_as(a1()))
+ case OR_OP => Seq(cast_as(a0())," | ", cast_as(a1()))
+ case XOR_OP => Seq(cast_as(a0())," ^ ", cast_as(a1()))
+ case AND_REDUCE_OP => {
+ val v = ArrayBuffer[Seq[Any]]()
+ for (b <- 0 until long_BANG(doprim.tpe).toInt) {
+ v += Seq(cast(a0()),"[",b,"]")
+ }
+ v.reduce(_ + " & " + _)
+ }
+ case OR_REDUCE_OP => {
+ val v = ArrayBuffer[Seq[Any]]()
+ for (b <- 0 until long_BANG(doprim.tpe).toInt) {
+ v += Seq(cast(a0()),"[",b,"]")
+ }
+ v.reduce(_ + " | " + _)
+ }
+ case XOR_REDUCE_OP => {
+ val v = ArrayBuffer[Seq[Any]]()
+ for (b <- 0 until long_BANG(doprim.tpe).toInt) {
+ v += Seq(cast(a0()),"[",b,"]")
+ }
+ v.reduce(_ + " ^ " + _)
+ }
+ case CONCAT_OP => Seq("{",cast(a0()),",",cast(a1()),"}")
+ case BITS_SELECT_OP => {
+ if (c0() == c1()) Seq(a0(),"[",c0(),"]")
+ else Seq(a0(),"[",c0(),":",c1(),"]")
+ }
+ case HEAD_OP => {
+ val w = long_BANG(tpe(a0()))
+ val high = w - 1
+ val low = w - c0()
+ Seq(a0(),"[",high,":",low,"]")
+ }
+ case TAIL_OP => {
+ val w = long_BANG(tpe(a0()))
+ val low = w - c0() - 1
+ Seq(a0(),"[",low,":",0,"]")
+ }
+ }
+ }
+
+ def emit_verilog (m:InModule) : Module = {
+ mname = m.name
+ val netlist = HashMap[WrappedExpression,Expression]()
+ val simlist = ArrayBuffer[Stmt]()
+ val namehash = sym_hash
+ def build_netlist (s:Stmt) : Stmt = {
+ s match {
+ case (s:Connect) => netlist(s.loc) = s.exp
+ case (s:IsInvalid) => {
+ val n = firrtl_gensym("GEN",namehash)
+ val e = wref(n,tpe(s.exp))
+ netlist(s.exp) = 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) => sMap(build_netlist,s)
+ }
+ s
+ }
+
+ val portdefs = ArrayBuffer[Seq[Any]]()
+ val declares = ArrayBuffer[Seq[Any]]()
+ val instdeclares = ArrayBuffer[Seq[Any]]()
+ val assigns = ArrayBuffer[Seq[Any]]()
+ val at_clock = HashMap[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 assign (e:Expression,value:Expression) =
+ assigns += Seq("assign ",e," = ",value,";")
+ def update_and_reset (r:Expression,clk:Expression,reset:Expression,init:Expression) = {
+ if (!at_clock.contains(clk)) { at_clock(clk) = ArrayBuffer[Seq[Any]]() }
+ def add_update (e:Expression,tabs:String) : Unit = {
+ e match {
+ case (e:Mux) => {
+ at_clock(clk) += Seq(tabs,"if(",e.cond,") begin")
+ add_update(e.tval,tabs + tab)
+ at_clock(clk) += Seq(tabs,"end else begin")
+ add_update(e.fval,tabs + tab)
+ at_clock(clk) += Seq(tabs,"end")
+ }
+ case (e) => {
+ if (e == r) at_clock(clk) += Seq(tabs,";")
+ else at_clock(clk) += Seq(tabs,r," <= ",e,";")
+ }
+ }
+ }
+ val tv = init
+ val fv = netlist(r)
+ add_update(Mux(reset,tv,fv,mux_type_and_widths(tv,fv)),"")
+ }
+ 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 {
+ at_clock(clk) += Seq("if(",en,") begin")
+ at_clock(clk) += Seq(tab,e," <= ",value,";")
+ at_clock(clk) += Seq("end")
+ }
+ }
+ def initialize (e:Expression) = initials += Seq(e," = ",rand_string(tpe(e)),";")
+ def initialize_mem (n:String,i:Int,t:Type) = {
+ initials += Seq("for (initvar = 0; initvar < ",i,"; initvar = initvar+1)")
+ val index = WRef("initvar",UnknownType(),ExpKind(),UNKNOWNGENDER)
+ initials += Seq(tab,WSubAccess(wref(n,t),index,UnknownType(),FEMALE), " = ",rand_string(t),";")
+ }
+ 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),"(",lowered_name(e),")")
+ if (i != es.size - 1) instdeclares += Seq(s,",")
+ else instdeclares += s
+ }}
+ instdeclares += Seq(");")
+ for (e <- es) {
+ declare("wire",lowered_name(e),tpe(e))
+ val ex = WRef(lowered_name(e),tpe(e),kind(e),gender(e))
+ if (gender(e) == FEMALE) assign(ex,netlist(e))
+ }
+ }
+ def simulate (clk:Expression,en:Expression,s:Seq[Any]) = {
+ if (!at_clock.contains(clk)) at_clock(clk) = ArrayBuffer[Seq[Any]]()
+ at_clock(clk) += Seq("`ifndef SYNTHESIS")
+ at_clock(clk) += Seq(tab,"if(",en,") begin")
+ at_clock(clk) += Seq(tab,tab,s)
+ at_clock(clk) += Seq(tab,"end")
+ at_clock(clk) += Seq("`endif")
+ }
+ def stop (ret:Int) : Seq[Any] = {
+ Seq("$fdisplay(32'h80000002,\"",ret,"\");$finish;")
+ }
+ def printf (str:String,args:Seq[Expression]) : Seq[Any] = {
+ val strx = (Seq(escape(str)) ++ args).reduce(_ + "," + _)
+ Seq("$fwrite(32'h80000002,",strx,");")
+ }
+ def delay (e:Expression, n:Int, clk:Expression) : Expression = {
+ var ex = e
+ for (i <- 0 until n) {
+ val name = firrtl_gensym("GEN",namehash)
+ declare("reg",name,tpe(e))
+ val exx = WRef(name,tpe(e),ExpKind(),UNKNOWNGENDER)
+ update(exx,ex,clk,one)
+ ex = exx
+ }
+ ex
+ }
+ def build_ports () = {
+ (m.ports,0 until m.ports.size).zipped.foreach{(p,i) => {
+ var end = ",\n"
+ if (m.ports.size - 1 == i) end = "\n);\n"
+ 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))
+ }
+ }
+ }}
+ if (m.ports.size == 0) w.get.write(");\n")
+ }
+ def build_streams (s:Stmt) : Stmt = {
+ s match {
+ 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.exp).as[WRef].get
+ declare("reg",wref.name,tpe(s.exp))
+ initialize(wref)
+ }
+ case (s:DefPoison) => {
+ val n = s.name
+ val e = wref(n,s.tpe)
+ declare("reg",n,tpe(e))
+ initialize(e)
+ }
+ case (s:DefNode) => {
+ declare("wire",s.name,tpe(s.value))
+ assign(WRef(s.name,tpe(s.value),NodeKind(),MALE),s.value)
+ }
+ case (s:Stop) => simulate(s.clk,s.en,stop(s.ret))
+ case (s:Print) => simulate(s.clk,s.en,printf(s.string,s.args))
+ 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.data_type,s.depth))
+ initialize_mem(s.name,s.depth,s.data_type)
+ for (r <- s.readers ) {
+ val data = mem_exp(r,"data")
+ val addr = mem_exp(r,"addr")
+ val en = mem_exp(r,"en")
+ val clk = mem_exp(r,"clk")
+
+ declare("wire",lowered_name(data),tpe(data))
+ declare("wire",lowered_name(addr),tpe(addr))
+ declare("wire",lowered_name(en),tpe(en))
+ declare("wire",lowered_name(clk),tpe(clk))
+
+ //; Read port
+ assign(addr,netlist(addr)) //;Connects value to m.r.addr
+ assign(en,netlist(en)) //;Connects value to m.r.en
+ assign(clk,netlist(clk)) //;Connects value to m.r.clk
+ val addrx = delay(addr,s.read_latency,clk)
+ val enx = delay(en,s.read_latency,clk)
+ val mem_port = WSubAccess(mem,addrx,UnknownType(),UNKNOWNGENDER)
+ assign(data,mem_port)
+ }
+
+ 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")
+ val clk = mem_exp(w,"clk")
+
+ declare("wire",lowered_name(data),tpe(data))
+ declare("wire",lowered_name(addr),tpe(addr))
+ declare("wire",lowered_name(mask),tpe(mask))
+ declare("wire",lowered_name(en),tpe(en))
+ declare("wire",lowered_name(clk),tpe(clk))
+
+ //; Write port
+ assign(data,netlist(data))
+ assign(addr,netlist(addr))
+ assign(mask,netlist(mask))
+ assign(en,netlist(en))
+ assign(clk,netlist(clk))
+
+ val datax = delay(data,s.write_latency - 1,clk)
+ val addrx = delay(addr,s.write_latency - 1,clk)
+ val maskx = delay(mask,s.write_latency - 1,clk)
+ val enx = delay(en,s.write_latency - 1,clk)
+ val mem_port = WSubAccess(mem,addrx,UnknownType(),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 data = mem_exp(rw,"data")
+ val mask = mem_exp(rw,"mask")
+ val addr = mem_exp(rw,"addr")
+ val en = mem_exp(rw,"en")
+ val clk = mem_exp(rw,"clk")
+
+ declare("wire",lowered_name(wmode),tpe(wmode))
+ declare("wire",lowered_name(rdata),tpe(rdata))
+ declare("wire",lowered_name(data),tpe(data))
+ declare("wire",lowered_name(mask),tpe(mask))
+ declare("wire",lowered_name(addr),tpe(addr))
+ declare("wire",lowered_name(en),tpe(en))
+ declare("wire",lowered_name(clk),tpe(clk))
+
+ //; Assigned to lowered wires of each
+ assign(clk,netlist(clk))
+ assign(addr,netlist(addr))
+ assign(data,netlist(data))
+ assign(addr,netlist(addr))
+ assign(mask,netlist(mask))
+ assign(en,netlist(en))
+ assign(wmode,netlist(wmode))
+
+ //; Delay new signals by latency
+ val raddrx = delay(addr,s.read_latency,clk)
+ val waddrx = delay(addr,s.write_latency - 1,clk)
+ val enx = delay(en,s.write_latency - 1,clk)
+ val rmodx = delay(wmode,s.write_latency - 1,clk)
+ val datax = delay(data,s.write_latency - 1,clk)
+ val maskx = delay(mask,s.write_latency - 1,clk)
+
+ //; Write
+
+ val rmem_port = WSubAccess(mem,raddrx,UnknownType(),UNKNOWNGENDER)
+ assign(rdata,rmem_port)
+ val wmem_port = WSubAccess(mem,waddrx,UnknownType(),UNKNOWNGENDER)
+ update(wmem_port,datax,clk,AND(AND(enx,maskx),wmode))
+ }
+ }
+ case (s:Begin) => sMap(build_streams _,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(");"))
+
+ 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("`ifndef SYNTHESIS"))
+ emit(Seq(" integer initvar;"))
+ emit(Seq(" initial begin"))
+ emit(Seq(" #0.002;"))
+ 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"))
+ }
+
+ build_netlist(m.body)
+ build_ports()
+ build_streams(m.body)
+ emit_streams()
+ m
+ }
+
+ def run(c: Circuit, w: Writer) = {
+ this.w = Some(w)
+ for (m <- c.modules) {
+ m match {
+ case (m:InModule) => emit_verilog(m)
+ case (m:ExModule) => false
+ }
+ }
+ }
+ //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)
+ //}
}
diff --git a/src/main/scala/firrtl/PrimOps.scala b/src/main/scala/firrtl/PrimOps.scala
index 790fa538..f947be35 100644
--- a/src/main/scala/firrtl/PrimOps.scala
+++ b/src/main/scala/firrtl/PrimOps.scala
@@ -40,7 +40,11 @@ object PrimOps extends LazyLogging {
CONCAT_OP -> "cat",
BITS_SELECT_OP -> "bits",
HEAD_OP -> "head",
- TAIL_OP -> "tail"
+ TAIL_OP -> "tail",
+
+ //This are custom, we need to refactor to enable easily extending FIRRTL with custom primops
+ ADDW_OP -> "addw",
+ SUBW_OP -> "subw"
)
lazy val listing: Seq[String] = PrimOps.mapPrimOp2String.map { case (k,v) => v } toSeq
private val mapString2PrimOp = mapPrimOp2String.map(_.swap)
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala
index b9fb49c6..b66b0932 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -125,6 +125,13 @@ object Utils {
}
}
}
+ def lowered_name (e:Expression) : String = {
+ (e) match {
+ case (e:WRef) => e.name
+ case (e:WSubField) => lowered_name(e.exp) + "_" + e.name
+ case (e:WSubIndex) => lowered_name(e.exp) + "_" + e.value
+ }
+ }
def get_flip (t:Type, i:Int, f:Flip) : Flip = {
if (i >= get_size(t)) error("Shouldn't be here")
val x = t match {
@@ -228,6 +235,19 @@ object Utils {
case t => error("No width!")
}
}
+ def long_BANG (t:Type) : Long = {
+ (t) match {
+ case (t:UIntType) => t.width.as[IntWidth].get.width.toLong
+ case (t:SIntType) => t.width.as[IntWidth].get.width.toLong
+ case (t:BundleType) => {
+ var w = 0
+ for (f <- t.fields) { w = w + long_BANG(f.tpe).toInt }
+ w
+ }
+ case (t:VectorType) => t.size * long_BANG(t.tpe)
+ case (t:ClockType) => 1
+ }
+ }
// =================================
def error(str:String) = throw new FIRRTLException(str)
def debug(node: AST)(implicit flags: FlagMap): String = {
diff --git a/src/main/scala/firrtl/WIR.scala b/src/main/scala/firrtl/WIR.scala
index 26e3a131..8ebfa9a6 100644
--- a/src/main/scala/firrtl/WIR.scala
+++ b/src/main/scala/firrtl/WIR.scala
@@ -4,7 +4,6 @@ package firrtl
import scala.collection.Seq
import Utils._
-
trait Kind
case class WireKind() extends Kind
case class PoisonKind() extends Kind
@@ -29,6 +28,14 @@ case class WVoid() extends Expression
case class WInvalid() extends Expression
case class WDefInstance(info:Info,name:String,module:String,tpe:Type) extends Stmt
+case object ADDW_OP extends PrimOp
+case object SUBW_OP extends PrimOp
+
+object WrappedExpression {
+ def apply (e:Expression) = new WrappedExpression(e)
+ def we (e:Expression) = new WrappedExpression(e)
+ def weq (e1:Expression,e2:Expression) = we(e1) == we(e2)
+}
class WrappedExpression (val e1:Expression) {
override def equals (we:Any) = {
we match {
diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala
index d3d7027a..89d27733 100644
--- a/src/main/scala/firrtl/passes/Passes.scala
+++ b/src/main/scala/firrtl/passes/Passes.scala
@@ -906,7 +906,7 @@ object RemoveAccesses extends Pass {
}
}
-object ExpandWhens extends Pass with StanzaPass {
+object ExpandWhens extends Pass {
def name = "Expand Whens"
var mname = ""
// ; ========== Expand When Utilz ==========
@@ -1111,7 +1111,62 @@ object CheckInitialization extends Pass with StanzaPass {
object ConstProp extends Pass with StanzaPass {
def name = "Constant Propogation"
+ var mname = ""
def run (c:Circuit): Circuit = stanzaPass(c, "const-prop")
+ def const_prop_e (e:Expression) : Expression = {
+ eMap(const_prop_e _,e) match {
+ case (e:DoPrim) => {
+ e.op match {
+ case SHIFT_RIGHT_OP => {
+ (e.args(0)) match {
+ case (x:UIntValue) => {
+ val b = x.value >> e.consts(0).toInt
+ UIntValue(b,tpe(e).as[UIntType].get.width)
+ }
+ case (x:SIntValue) => {
+ val b = x.value >> e.consts(0).toInt
+ SIntValue(b,tpe(e).as[SIntType].get.width)
+ }
+ case (x) => e
+ }
+ }
+ case BITS_SELECT_OP => {
+ e.args(0) match {
+ case (x:UIntValue) => {
+ val hi = e.consts(0).toInt
+ val lo = e.consts(1).toInt
+ require(hi >= lo)
+ val b = (x.value >> lo) & ((BigInt(1) << (hi - lo + 1)) - 1)
+ UIntValue(b,tpe(e).as[UIntType].get.width)
+ }
+ case (x) => {
+ if (long_BANG(tpe(e)) == long_BANG(tpe(x))) {
+ if (tpe(x).typeof[UIntType] != None) x
+ else DoPrim(AS_UINT_OP,Seq(x),Seq(),tpe(e))
+ }
+ else e
+ }
+ }
+ }
+ case (_) => e
+ }
+ }
+ case (e) => e
+ }
+ }
+ def const_prop_s (s:Stmt) : Stmt = eMap(const_prop_e _, sMap(const_prop_s _,s))
+ def const_prop (c:Circuit) : Circuit = {
+ val modulesx = c.modules.map{ m => {
+ m match {
+ case (m:ExModule) => m
+ case (m:InModule) => {
+ mname = m.name
+ InModule(m.info,m.name,m.ports,const_prop_s(m.body))
+ }
+ }
+ }}
+ Circuit(c.info,modulesx,c.main)
+ }
}
object LoToVerilog extends Pass with StanzaPass {
@@ -1119,19 +1174,113 @@ object LoToVerilog extends Pass with StanzaPass {
def run (c:Circuit): Circuit = stanzaPass(c, "lo-to-verilog")
}
-object VerilogWrap extends Pass with StanzaPass {
+object FromCHIRRTL extends Pass with StanzaPass {
+ def name = "From CHIRRTL"
+ def run (c:Circuit): Circuit = stanzaPass(c, "from-chirrtl")
+}
+
+object VerilogWrap extends Pass {
def name = "Verilog Wrap"
- def run (c:Circuit): Circuit = stanzaPass(c, "verilog-wrap")
+ var mname = ""
+ def v_wrap_e (e:Expression) : Expression = {
+ eMap(v_wrap_e _,e) match {
+ case (e:DoPrim) => {
+ def a0 () = e.args(0)
+ if (e.op == TAIL_OP) {
+ (a0()) match {
+ case (e0:DoPrim) => {
+ if (e0.op == ADD_OP) DoPrim(ADDW_OP,e0.args,Seq(),tpe(e))
+ else if (e0.op == SUB_OP) DoPrim(SUBW_OP,e0.args,Seq(),tpe(e))
+ else e
+ }
+ case (e0) => e
+ }
+ }
+ else e
+ }
+ case (e) => e
+ }
+ }
+ def v_wrap_s (s:Stmt) : Stmt = eMap(v_wrap_e _,sMap(v_wrap_s _,s))
+ def run (c:Circuit): Circuit = {
+ val modulesx = c.modules.map{ m => {
+ (m) match {
+ case (m:InModule) => {
+ mname = m.name
+ InModule(m.info,m.name,m.ports,v_wrap_s(m.body))
+ }
+ case (m:ExModule) => m
+ }
+ }}
+ Circuit(c.info,modulesx,c.main)
+ }
}
-object SplitExp extends Pass with StanzaPass {
+object SplitExp extends Pass {
def name = "Split Expressions"
- def run (c:Circuit): Circuit = stanzaPass(c, "split-expressions")
+ var mname = ""
+ def split_exp (m:InModule) : InModule = {
+ mname = m.name
+ val v = ArrayBuffer[Stmt]()
+ val sh = sym_hash
+ def split_exp_s (s:Stmt) : Stmt = {
+ def split (e:Expression) : Expression = {
+ val n = firrtl_gensym("GEN",sh)
+ v += DefNode(info(s),n,e)
+ WRef(n,tpe(e),kind(e),gender(e))
+ }
+ def split_exp_e (i:Int)(e:Expression) : Expression = {
+ eMap(split_exp_e(i + 1) _,e) match {
+ case (e:DoPrim) => if (i > 0) split(e) else e
+ case (e) => e
+ }
+ }
+ eMap(split_exp_e(0) _,s) match {
+ case (s:Begin) => sMap(split_exp_s _,s)
+ case (s) => v += s; s
+ }
+ }
+ split_exp_s(m.body)
+ InModule(m.info,m.name,m.ports,Begin(v))
+ }
+
+ def run (c:Circuit): Circuit = {
+ val modulesx = c.modules.map{ m => {
+ (m) match {
+ case (m:InModule) => split_exp(m)
+ case (m:ExModule) => m
+ }
+ }}
+ Circuit(c.info,modulesx,c.main)
+ }
}
-object VerilogRename extends Pass with StanzaPass {
+object VerilogRename extends Pass {
def name = "Verilog Rename"
- def run (c:Circuit): Circuit = stanzaPass(c, "verilog-rename")
+ def run (c:Circuit): Circuit = {
+ def verilog_rename_n (n:String) : String = {
+ if (v_keywords.contains(n)) (n + "$") else n
+ }
+ def verilog_rename_e (e:Expression) : Expression = {
+ (e) match {
+ case (e:WRef) => WRef(verilog_rename_n(e.name),e.tpe,kind(e),gender(e))
+ case (e) => eMap(verilog_rename_e,e)
+ }
+ }
+ def verilog_rename_s (s:Stmt) : Stmt = {
+ stMap(verilog_rename_n _,eMap(verilog_rename_e _,sMap(verilog_rename_s _,s)))
+ }
+ val modulesx = c.modules.map{ m => {
+ val portsx = m.ports.map{ p => {
+ Port(p.info,verilog_rename_n(p.name),p.direction,p.tpe)
+ }}
+ m match {
+ case (m:InModule) => InModule(m.info,m.name,portsx,verilog_rename_s(m.body))
+ case (m:ExModule) => m
+ }
+ }}
+ Circuit(c.info,modulesx,c.main)
+ }
}
object LowerTypes extends Pass {
@@ -1204,13 +1353,6 @@ object LowerTypes extends Pass {
}
}
def merge (a:String,b:String,x:String) : String = a + x + b
- def lowered_name (e:Expression) : String = {
- (e) match {
- case (e:WRef) => e.name
- case (e:WSubField) => lowered_name(e.exp) + "_" + e.name
- case (e:WSubIndex) => lowered_name(e.exp) + "_" + e.value
- }
- }
def root_ref (e:Expression) : WRef = {
(e) match {
case (e:WRef) => e
diff --git a/src/main/stanza/chirrtl.stanza b/src/main/stanza/chirrtl.stanza
index 0a07fcf0..fc770764 100644
--- a/src/main/stanza/chirrtl.stanza
+++ b/src/main/stanza/chirrtl.stanza
@@ -11,6 +11,7 @@ public val chirrtl-passes = to-list $ [
CInferTypes()
CInferMDir()
RemoveCHIRRTL()
+ FromCHIRRTL()
]
; ===============================
@@ -421,3 +422,18 @@ defn remove-chirrtl (c:Circuit) :
(m:ExModule) : m
+;============ FromCHIRRTL ==============
+
+public defstruct FromCHIRRTL <: Pass
+public defmethod pass (b:FromCHIRRTL) -> (Circuit -> Circuit) : from-chirrtl
+public defmethod name (b:FromCHIRRTL) -> String : "From CHIRRTL"
+public defmethod short-name (b:FromCHIRRTL) -> String : "from-chirrtl"
+
+defn from-chirrtl (c:Circuit) -> Circuit :
+ val c1 = c-infer-types(c)
+ ;println(c1)
+ val c2 = infer-mdir(c1)
+ ;println(c2)
+ val c3 = remove-chirrtl(c2)
+ ;println(c3)
+ c3
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza
index 155c1b0a..9d7a1b97 100644
--- a/src/main/stanza/passes.stanza
+++ b/src/main/stanza/passes.stanza
@@ -2895,3 +2895,5 @@ defn lo-to-verilog (with-output:(() -> False) -> False, c:Circuit) :
val c5 = verilog-rename(c4)
;println(c5)
emit-verilog(with-output,c5)
+
+