aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjackbackrack2015-05-19 16:02:21 -0700
committerjackbackrack2015-05-19 16:02:21 -0700
commitf4edadb530297f4f3e293c81c0d8414f8279b65b (patch)
tree643db928ee1a396a2ecbf8477fd3fa6aee9f3927 /src
parenteb7d0913bd01cffdc2be944c7001721f737b44bf (diff)
parent14bb9cda8352388bcd33ba9ca2700805dc51639f (diff)
get flo backend running again with no pads and generic operators
Diffstat (limited to 'src')
-rw-r--r--src/main/stanza/compilers.stanza74
-rw-r--r--src/main/stanza/errors.stanza51
-rw-r--r--src/main/stanza/firrtl-ir.stanza80
-rw-r--r--src/main/stanza/firrtl-test-main.stanza38
-rw-r--r--src/main/stanza/flo.stanza177
-rw-r--r--src/main/stanza/ir-parser.stanza79
-rw-r--r--src/main/stanza/ir-utils.stanza117
-rw-r--r--src/main/stanza/passes.stanza532
-rw-r--r--src/main/stanza/primop.stanza437
-rw-r--r--src/main/stanza/verilog.stanza197
10 files changed, 809 insertions, 973 deletions
diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza
new file mode 100644
index 00000000..e912d3a0
--- /dev/null
+++ b/src/main/stanza/compilers.stanza
@@ -0,0 +1,74 @@
+defpackage firrtl/compiler :
+ import core
+ import verse
+ import firrtl/passes
+ import firrtl/errors
+ import firrtl/flo
+ import firrtl/verilog
+ import firrtl/ir2
+ import firrtl/ir-utils
+
+public defstruct StandardFlo <: Compiler :
+ file: String with: (as-method => true)
+public defmethod passes (c:StandardFlo) -> List<Pass> :
+ to-list $ [
+ CheckHighForm()
+ TempElimination()
+ ToWorkingIR()
+ MakeExplicitReset()
+ ResolveKinds()
+ CheckKinds()
+ InferTypes()
+ CheckTypes()
+ ResolveGenders()
+ CheckGenders()
+ ExpandAccessors()
+ LowerToGround()
+ ExpandIndexedConnects()
+ ExpandWhens()
+ InferWidths()
+ Inline()
+ SplitExp()
+ ToRealIR()
+ Flo(file(c))
+ ]
+
+public defstruct StandardVerilog <: Compiler :
+ file: String with: (as-method => true)
+public defmethod passes (c:StandardVerilog) -> List<Pass> :
+ to-list $ [
+ CheckHighForm()
+ TempElimination()
+ ToWorkingIR()
+ MakeExplicitReset()
+ ResolveKinds()
+ CheckKinds()
+ InferTypes()
+ CheckTypes()
+ ResolveGenders()
+ CheckGenders()
+ ExpandAccessors()
+ LowerToGround()
+ ExpandIndexedConnects()
+ ExpandWhens()
+ InferWidths()
+ Inline()
+ SplitExp()
+ ToRealIR()
+ Verilog(file(c))
+ ]
+
+;============= DRIVER ======================================
+public defn run-passes (c:Circuit,comp:Compiler) :
+ run-passes(c,passes(comp))
+public defn run-passes (c:Circuit,ls:List<Pass>) :
+ var c*:Circuit = c
+ println("Compiling!")
+ if PRINT-CIRCUITS : println("Original Circuit")
+ if PRINT-CIRCUITS : print(c)
+ for p in ls do :
+ if PRINT-CIRCUITS : println(name(p))
+ c* = pass(p)(c*)
+ if PRINT-CIRCUITS : print(c*)
+ if PRINT-CIRCUITS : println-all(["Finished " name(p) "\n"])
+ println("Done!")
diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza
index 93250b6f..8c5532b0 100644
--- a/src/main/stanza/errors.stanza
+++ b/src/main/stanza/errors.stanza
@@ -15,12 +15,6 @@ defpackage firrtl/errors :
; * Only modules in circuit (no statements or expressions) <- parser
; * Module must be a reference in inst declaration
-;AFTER GENDER INFERENCE
-; o Nodes always male
-; o Accessors only have one gender, unless rdwr
-; o output/input only one gender
-; o correctly check for the base bundle
-
;AFTER WIDTH INFERENCE
; o No names
; o No Unknowns
@@ -50,6 +44,11 @@ defpackage firrtl/errors :
; * all references are declared
; * UInt only has positive ints
+public defstruct CheckHighForm <: Pass
+public defmethod pass (b:CheckHighForm) -> (Circuit -> Circuit) : check-high-form
+public defmethod name (b:CheckHighForm) -> String : "High Form Check"
+public defmethod short-name (b:CheckHighForm) -> String : "high-form-check"
+
;----------------- Errors ------------------------
defn NotUnique (info:FileInfo, name:Symbol) :
PassException $ string-join $
@@ -141,7 +140,7 @@ public defn check-high-form (c:Circuit) -> Circuit :
defn check-valid-loc (info:FileInfo,e:Expression) -> False :
match(e) :
- (e:UIntValue|SIntValue|DoPrim|ReadPort|Register|Pad) :
+ (e:UIntValue|SIntValue|DoPrim|ReadPort|Register) :
add(errors,InvalidLOC(info))
(e) : false
@@ -182,10 +181,13 @@ public defn check-high-form (c:Circuit) -> Circuit :
(s:DefInstance) :
if not contains?(name(module(s) as Ref),map(name,modules(c))) :
add(errors, ModuleNotDefined(info(s),name(module(s) as Ref)))
+ check-name(info(s),name(s))
add(names,name(s))
(s:DefNode) :
+ check-name(info(s),name(s))
add(names,name(s))
(s:DefAccessor) :
+ check-name(info(s),name(s))
add(names,name(s))
(s:Connect) :
check-valid-loc(info(s),loc(s))
@@ -226,6 +228,11 @@ public defn check-high-form (c:Circuit) -> Circuit :
; o onreset can only handle a register
; o Cannot use a mem in anything except an accessor, Readport, or Writeport
+public defstruct CheckKinds <: Pass
+public defmethod pass (b:CheckKinds) -> (Circuit -> Circuit) : check-kinds
+public defmethod name (b:CheckKinds) -> String : "Check Kinds"
+public defmethod short-name (b:CheckKinds) -> String : "check-kinds"
+
;----------------- Errors ---------------------
defn NotMem (info:FileInfo, name:Symbol) :
PassException $ string-join $
@@ -277,8 +284,8 @@ public defn check-kinds (c:Circuit) -> Circuit :
check-is-mem(info,mem(e))
check-not-mem(info,index(e))
check-not-mem(info,enable(e))
- (e:Pad) :
- check-not-mem(info,value(e))
+ ;(e:Pad) :
+ ;check-not-mem(info,value(e))
(e) : do(check-not-mem{info,_},e)
defn check-kinds-s (s:Stmt) -> False :
do(check-kinds-e{info(s),_:Expression},s)
@@ -311,6 +318,11 @@ public defn check-kinds (c:Circuit) -> Circuit :
; o := has same types
; o 2nd arg in dshr/l must be UInt, in general do primops
+public defstruct CheckTypes <: Pass
+public defmethod pass (b:CheckTypes) -> (Circuit -> Circuit) : check-types
+public defmethod name (b:CheckTypes) -> String : "Check Types"
+public defmethod short-name (b:CheckTypes) -> String : "check-types"
+
;----------------- Errors ---------------------
defn SubfieldNotInBundle (info:FileInfo, name:Symbol) :
PassException $ string-join $
@@ -336,9 +348,9 @@ defn EnableNotUInt (info:FileInfo) :
PassException $ string-join $
[info ": Enable is not of UIntType."]
-defn PadNotGround (info:FileInfo) :
- PassException $ string-join $
- [info ": Illegal Pad on non-ground type."]
+;defn PadNotGround (info:FileInfo) :
+ ;PassException $ string-join $
+ ;[info ": Illegal Pad on non-ground type."]
defn InvalidConnect (info:FileInfo) :
PassException $ string-join $
@@ -391,9 +403,9 @@ public defn check-types (c:Circuit) -> Circuit :
if type(enable(e)) != u() : add(errors,EnableNotUInt(info))
(e:Register) :
if type(enable(e)) != u() : add(errors,EnableNotUInt(info))
- (e:Pad) :
- val t = type(value(e))
- if not (t == u() or t == s()) : add(errors,PadNotGround(info))
+ ;(e:Pad) :
+ ;val t = type(value(e))
+ ;if not (t == u() or t == s()) : add(errors,PadNotGround(info))
(e:UIntValue|SIntValue) : false
e
defn check-types-s (s:Stmt) -> Stmt :
@@ -421,6 +433,11 @@ public defn check-types (c:Circuit) -> Circuit :
; o output/input only one gender
; o correctly check for the base bundle
+public defstruct CheckGenders <: Pass
+public defmethod pass (b:CheckGenders) -> (Circuit -> Circuit) : check-genders
+public defmethod name (b:CheckGenders) -> String : "Check Genders"
+public defmethod short-name (b:CheckGenders) -> String : "check-genders"
+
;----------------- Errors ---------------------
defn WrongGender (info:FileInfo,expr:Symbol,wrong:Symbol,right:Symbol) :
PassException $ string-join $
@@ -452,7 +469,7 @@ public defn check-genders (c:Circuit) -> Circuit :
val f = {_ as Field} $ for f in fields(type(exp(e)) as BundleType) find : name(f) == name(e)
get-gender(exp(e),genders) * flip(f)
(e:WIndex) : get-gender(exp(e),genders)
- (e:Pad) : MALE
+ ;(e:Pad) : MALE
(e:DoPrim) : MALE
(e:UIntValue) : MALE
(e:SIntValue) : MALE
@@ -466,7 +483,7 @@ public defn check-genders (c:Circuit) -> Circuit :
(e:WRef) : false
(e:WSubfield) : false
(e:WIndex) : false
- (e:Pad) : check-gender(info,genders,value(e),MALE)
+ ;(e:Pad) : check-gender(info,genders,value(e),MALE)
(e:DoPrim) :
for e in args(e) do :
check-gender(info,genders,e,MALE)
diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza
index 02145678..39538498 100644
--- a/src/main/stanza/firrtl-ir.stanza
+++ b/src/main/stanza/firrtl-ir.stanza
@@ -20,106 +20,30 @@ public defstruct IntWidth <: Width :
public definterface PrimOp
public val ADD-OP = new PrimOp
-public val ADD-UU-OP = new PrimOp
-public val ADD-US-OP = new PrimOp
-public val ADD-SU-OP = new PrimOp
-public val ADD-SS-OP = new PrimOp
public val SUB-OP = new PrimOp
-public val SUB-UU-OP = new PrimOp
-public val SUB-US-OP = new PrimOp
-public val SUB-SU-OP = new PrimOp
-public val SUB-SS-OP = new PrimOp
public val MUL-OP = new PrimOp
-public val MUL-UU-OP = new PrimOp
-public val MUL-US-OP = new PrimOp
-public val MUL-SU-OP = new PrimOp
-public val MUL-SS-OP = new PrimOp
public val DIV-OP = new PrimOp
-public val DIV-UU-OP = new PrimOp
-public val DIV-US-OP = new PrimOp
-public val DIV-SU-OP = new PrimOp
-public val DIV-SS-OP = new PrimOp
public val MOD-OP = new PrimOp
-public val MOD-UU-OP = new PrimOp
-public val MOD-US-OP = new PrimOp
-public val MOD-SU-OP = new PrimOp
-public val MOD-SS-OP = new PrimOp
public val QUO-OP = new PrimOp
-public val QUO-UU-OP = new PrimOp
-public val QUO-US-OP = new PrimOp
-public val QUO-SU-OP = new PrimOp
-public val QUO-SS-OP = new PrimOp
public val REM-OP = new PrimOp
-public val REM-UU-OP = new PrimOp
-public val REM-US-OP = new PrimOp
-public val REM-SU-OP = new PrimOp
-public val REM-SS-OP = new PrimOp
public val ADD-WRAP-OP = new PrimOp
-public val ADD-WRAP-UU-OP = new PrimOp
-public val ADD-WRAP-US-OP = new PrimOp
-public val ADD-WRAP-SU-OP = new PrimOp
-public val ADD-WRAP-SS-OP = new PrimOp
public val SUB-WRAP-OP = new PrimOp
-public val SUB-WRAP-UU-OP = new PrimOp
-public val SUB-WRAP-US-OP = new PrimOp
-public val SUB-WRAP-SU-OP = new PrimOp
-public val SUB-WRAP-SS-OP = new PrimOp
public val LESS-OP = new PrimOp
-public val LESS-UU-OP = new PrimOp
-public val LESS-US-OP = new PrimOp
-public val LESS-SU-OP = new PrimOp
-public val LESS-SS-OP = new PrimOp
public val LESS-EQ-OP = new PrimOp
-public val LESS-EQ-UU-OP = new PrimOp
-public val LESS-EQ-US-OP = new PrimOp
-public val LESS-EQ-SU-OP = new PrimOp
-public val LESS-EQ-SS-OP = new PrimOp
public val GREATER-OP = new PrimOp
-public val GREATER-UU-OP = new PrimOp
-public val GREATER-US-OP = new PrimOp
-public val GREATER-SU-OP = new PrimOp
-public val GREATER-SS-OP = new PrimOp
public val GREATER-EQ-OP = new PrimOp
-public val GREATER-EQ-UU-OP = new PrimOp
-public val GREATER-EQ-US-OP = new PrimOp
-public val GREATER-EQ-SU-OP = new PrimOp
-public val GREATER-EQ-SS-OP = new PrimOp
public val NEQUAL-OP = new PrimOp
-public val NEQUAL-UU-OP = new PrimOp
-public val NEQUAL-SS-OP = new PrimOp
public val EQUAL-OP = new PrimOp
-public val EQUAL-UU-OP = new PrimOp
-public val EQUAL-SS-OP = new PrimOp
public val MUX-OP = new PrimOp
-public val MUX-UU-OP = new PrimOp
-public val MUX-SS-OP = new PrimOp
public val PAD-OP = new PrimOp
-public val PAD-U-OP = new PrimOp
-public val PAD-S-OP = new PrimOp
public val AS-UINT-OP = new PrimOp
-public val AS-UINT-U-OP = new PrimOp
-public val AS-UINT-S-OP = new PrimOp
public val AS-SINT-OP = new PrimOp
-public val AS-SINT-U-OP = new PrimOp
-public val AS-SINT-S-OP = new PrimOp
public val DYN-SHIFT-LEFT-OP = new PrimOp
-public val DYN-SHIFT-LEFT-U-OP = new PrimOp
-public val DYN-SHIFT-LEFT-S-OP = new PrimOp
public val DYN-SHIFT-RIGHT-OP = new PrimOp
-public val DYN-SHIFT-RIGHT-U-OP = new PrimOp
-public val DYN-SHIFT-RIGHT-S-OP = new PrimOp
public val SHIFT-LEFT-OP = new PrimOp
-public val SHIFT-LEFT-U-OP = new PrimOp
-public val SHIFT-LEFT-S-OP = new PrimOp
public val SHIFT-RIGHT-OP = new PrimOp
-public val SHIFT-RIGHT-U-OP = new PrimOp
-public val SHIFT-RIGHT-S-OP = new PrimOp
public val NEG-OP = new PrimOp
-public val NEG-U-OP = new PrimOp
-public val NEG-S-OP = new PrimOp
public val CONVERT-OP = new PrimOp
-public val CONVERT-U-OP = new PrimOp
-public val CONVERT-S-OP = new PrimOp
public val BIT-NOT-OP = new PrimOp
public val BIT-AND-OP = new PrimOp
public val BIT-OR-OP = new PrimOp
@@ -170,10 +94,6 @@ public defstruct Register <: Expression :
type: Type with: (as-method => true)
value: Expression
enable: Expression
-public defstruct Pad <: Expression :
- value: Expression
- width: Width
- type: Type with: (as-method => true)
public definterface Stmt
public defmulti info (s:Stmt) -> FileInfo
diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza
index 0f977ebe..5a7e593d 100644
--- a/src/main/stanza/firrtl-test-main.stanza
+++ b/src/main/stanza/firrtl-test-main.stanza
@@ -9,6 +9,9 @@
#include("passes.stanza")
#include("primop.stanza")
#include("errors.stanza")
+#include("compilers.stanza")
+#include("flo.stanza")
+#include("verilog.stanza")
defpackage firrtl-main :
import core
@@ -18,6 +21,7 @@ defpackage firrtl-main :
import stz/lexer
import stz/parser
import firrtl/ir-utils
+ import firrtl/compiler
defn set-printvars! (p:List<Char>) :
if contains(p,'t') : PRINT-TYPES = true
@@ -29,24 +33,46 @@ defn set-printvars! (p:List<Char>) :
if contains(p,'d') : PRINT-DEBUG = true
if contains(p,'i') : PRINT-INFO = true
-;firrtl -i gcd.fir -o gcd.flo -x qabcefghipjklmno -p c
+defn get-passes (pass-names:List<String>) -> List<Pass> :
+ for n in pass-names map :
+ val p = for p in standard-passes find :
+ n == short-name(p)
+ if p == false :
+ error(to-string $ ["Unrecognized pass flag: " n])
+ p as Pass
+
defn main () :
val args = commandline-arguments()
var input = false
var output = false
- var passes = "qabcefghipjklmno"
+ var compiler = false
+ val pass-names = Vector<String>()
var printvars = ""
for (s in args, i in 0 to false) do :
if s == "-i" : input = args[i + 1]
if s == "-o" : output = args[i + 1]
- if s == "-x" : passes = args[i + 1]
+ if s == "-x" : add(pass-names,args[i + 1])
+ if s == "-X" : compiler = args[i + 1]
if s == "-p" : printvars = args[i + 1]
- if input == false : error("No input file provided. Use -i flag")
- if output == false : error("No output file provided. Use -o flag")
+
+ if input == false :
+ error("No input file provided. Use -i flag.")
+ if output == false :
+ error("No output file provided. Use -o flag.")
+ if compiler == false and length(pass-names) == 0 :
+ error("Must specify a compiler. Use -X flag.")
+
val lexed = lex-file(input as String)
val c = parse-firrtl(lexed)
set-printvars!(to-list(printvars))
- run-passes(c,to-list(passes),output as String)
+
+ if compiler == false :
+ run-passes(c,get-passes(to-list(pass-names)))
+ else :
+ switch {_ == compiler} :
+ "flo" : run-passes(c,StandardFlo(output as String))
+ "verilog" : run-passes(c,StandardVerilog(output as String))
+ else : error("Invalid compiler flag")
main()
diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza
new file mode 100644
index 00000000..4bab7025
--- /dev/null
+++ b/src/main/stanza/flo.stanza
@@ -0,0 +1,177 @@
+defpackage firrtl/flo :
+ import core
+ import verse
+ import firrtl/ir-utils
+ import firrtl/ir2
+
+public defstruct Flo <: Pass :
+ file : String
+public defmethod pass (b:Flo) -> (Circuit -> Circuit) : emit-flo{file(b),_}
+public defmethod name (b:Flo) -> String : "To Flo"
+
+;============= FLO PRINTER ======================================
+; Emit
+
+defn is-sint? (arg:Expression) -> True|False : type(arg) typeof SIntType
+
+defn flo-op-name (op:PrimOp, args:List<Expression>) -> String :
+ switch {op == _ } :
+ ADD-OP : "add"
+ ADD-WRAP-OP : "add"
+ SUB-OP : "sub"
+ SUB-WRAP-OP : "sub"
+ MUL-OP : "mul" ;; todo: signed version
+ DIV-OP : "div" ;; todo: signed version
+ MOD-OP : "mod" ;; todo: signed version
+ QUO-OP : "div" ;; todo: signed version
+ REM-OP : "mod" ;; todo: signed version
+ LESS-OP : "lt" ;; todo: signed version
+ LESS-EQ-OP : "lte" ;; todo: swap args
+ GREATER-OP : "lt" ;; todo: swap args
+ GREATER-EQ-OP : "lte" ;; todo: signed version
+ NEQUAL-OP : "neq"
+ EQUAL-OP : "eq"
+ MUX-OP : "mux"
+ PAD-OP : if is-sint?(args[0]): "arsh" else: "rsh"
+ NEG-OP : "neg"
+ AS-UINT-OP : "mov"
+ SHIFT-LEFT-OP : "lsh"
+ SHIFT-RIGHT-OP : if is-sint?(args[0]): "arsh" else: "rsh"
+ DYN-SHIFT-LEFT-OP : "lsh"
+ DYN-SHIFT-RIGHT-OP : if is-sint?(args[0]): "arsh" else: "rsh"
+ CONVERT-OP : if is-sint?(args[0]): "arsh" else: "rsh"
+ BIT-AND-OP : "and"
+ BIT-NOT-OP : "not"
+ BIT-OR-OP : "or"
+ BIT-XOR-OP : "xor"
+ CONCAT-OP : "cat"
+ BIT-SELECT-OP : "rsh"
+ BITS-SELECT-OP : "rsh"
+ BIT-XOR-REDUCE-OP : "xorr"
+ else :
+ error $ string-join $ ["Unable to print Primop: " op]
+
+defn sane-width (wd:Width) -> Int :
+ match(wd) :
+ (w:IntWidth) : max(1, width(w))
+ (w) : error(string-join(["Unknown width: " w]))
+
+defn prim-width (type:Type) -> Int :
+ match(type) :
+ (t:UIntType) : sane-width(width(t))
+ (t:SIntType) : sane-width(width(t))
+ (t) : error("Bad prim width type")
+
+defn sizeof (in: Int) -> Int :
+ max(1, ceil-log2(in + 1))
+
+defn emit-all (es:Streamable, top:Symbol) :
+ for e in es do :
+ match(e) :
+ (ex:Expression) : emit!(ex,top)
+ (ex:String) : print(ex)
+ (ex:Symbol) : print(ex)
+ ;; (ex:Int) : print-all([ex "'" sizeof(ex)])
+ (ex:Int) : print(ex)
+ (ex) : print(ex)
+
+defn emit! (e:Expression,top:Symbol) :
+ defn greater-op? (op: PrimOp) -> True|False :
+ contains?([GREATER-OP], op)
+ defn greater-eq-op? (op: PrimOp) -> True|False :
+ contains?([GREATER-EQ-OP], op)
+ defn less-eq-op? (op: PrimOp) -> True|False :
+ contains?([LESS-EQ-OP], op)
+ defn less-op? (op: PrimOp) -> True|False :
+ contains?([LESS-OP], op)
+ defn cmp-op? (op: PrimOp) -> True|False :
+ greater-op?(op) or greater-eq-op?(op) or less-op?(op) or less-eq-op?(op) or
+ contains?([EQUAL-OP NEQUAL-OP] op)
+ match(e) :
+ (e:Ref) : emit-all([top "::" name(e)], top)
+ (e:UIntValue) : emit-all([value(e) "'" sane-width(width(e))], top)
+ (e:SIntValue) : emit-all([value(e) "'" sane-width(width(e))], top)
+ (e:Subfield) : emit-all([exp(e) "/" name(e)], top)
+ (e:Index) : emit-all([exp(e) "/" value(e)], top)
+ ;(e:Pad) :
+ ;emit-all(["rsh'" prim-width(type(e)) " " value(e) " 0"], top)
+ (e:Register) :
+ emit-all(["reg'" prim-width(type(e)) " " enable(e) " " value(e)], top)
+ (e:ReadPort) :
+ emit-all(["rd'" prim-width(type(e)) " " "1" " " mem(e) " " index(e)], top) ;; enable(e)
+ (e:DoPrim) :
+ if cmp-op?(op(e)) :
+ emit-all([flo-op-name(op(e), args(e)) "'" prim-width(type(args(e)[0]))], top)
+ if greater-op?(op(e)) or greater-eq-op?(op(e)) :
+ emit-all([" " args(e)[1] " " args(e)[0]], top)
+ else :
+ emit-all([" " args(e)[0] " " args(e)[1]], top)
+ else if op(e) == BIT-SELECT-OP :
+ emit-all([flo-op-name(op(e), args(e)) "'1 " args(e)[0] " " consts(e)[0]], top)
+ else if op(e) == BITS-SELECT-OP :
+ val w = consts(e)[0] - consts(e)[1] + 1
+ emit-all([flo-op-name(op(e), args(e)) "'" w " " args(e)[0] " " consts(e)[1]], top)
+ ;; else if op(e) == CONCAT-OP :
+ ;; val w = consts(e)[0] - consts(e)[1] + 1
+ ;; emit-all([flo-op-name(op(e), args(e)) "'" w " " args(e)[0] " " consts(e)[1]], top)
+ else :
+ emit-all([flo-op-name(op(e), args(e)) "'" prim-width(type(e))], top)
+ ;if (op(e) == PAD-U-OP) or (op(e) == PAD-S-OP) :
+ ;emit-all([" " args(e)[0] " " consts(e)[0]], top)
+ ;else :
+ for arg in args(e) do :
+ print(" ")
+ emit!(arg, top)
+ for const in consts(e) do :
+ print-all([" " const "'" sizeof(const)])
+ (e) : error("SHOULDN'T EMIT THIS") ;; print-all(["EMIT(" e ")"])
+ ;(e) : emit-all(["mov'" prim-width(type(e)) " " e], top) ;TODO, not sure which one is right
+
+defn maybe-mov (e:Expression) -> String :
+ val need-mov? = match(e) :
+ (e:Ref) : true
+ (e:UIntValue) : true
+ (e:SIntValue) : true
+ (e:Subfield) : true
+ (e:Index) : true
+ (e) : false
+ if need-mov?: "mov " else: ""
+
+defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol) :
+ match(s) :
+ (s:DefWire) : ""
+ (s:DefInstance) : error("Shouldn't be here")
+ (s:DefMemory) :
+ val vtype = type(s) as VectorType
+ emit-all([top "::" name(s) " = mem'" prim-width(type(vtype)) " " size(vtype) "\n"], top)
+ (s:DefNode) :
+ if value(s) typeof WritePort :
+ val e = value(s) as WritePort
+ val n = firrtl-gensym(`F)
+ emit-all([top "::" n " = wr'" prim-width(type(e)) " " enable(e) " " mem(e) " " index(e) " " top "::" name(s) "\n"], top)
+ else :
+ emit-all([top "::" name(s) " = " maybe-mov(value(s)) value(s) "\n"], top)
+ (s:Begin) : do(emit-s{_, v, top}, body(s))
+ (s:Connect) :
+ val n = name(loc(s) as Ref)
+ if contains?(v,n) :
+ emit-all([top "::" n " = out'" prim-width(type(loc(s))) " " exp(s) "\n"], top)
+ else :
+ emit-all([top "::" n " = " maybe-mov(exp(s)) exp(s) "\n"], top)
+ (s) : s
+
+defn emit-module (m:Module) :
+ val v = Vector<Symbol>()
+ for port in ports(m) do :
+ if name(port) ==`reset :
+ emit-all([name(m) "::" name(port) " = rst'1\n"], name(m))
+ else : switch {_ == direction(port)} :
+ INPUT : print-all([name(m) "::" name(port) " = " "in'" prim-width(type(port)) "\n"])
+ OUTPUT : add(v,name(port))
+ emit-s(body(m), to-list(v), name(m))
+
+public defn emit-flo (file:String, c:Circuit) :
+ with-output-file{file, _} $ fn () :
+ emit-module(modules(c)[0])
+ false
+ c
diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza
index 15cc497a..0833543f 100644
--- a/src/main/stanza/ir-parser.stanza
+++ b/src/main/stanza/ir-parser.stanza
@@ -32,106 +32,30 @@ defn atom? (x) : unwrap-token(x) not-typeof List
defn primop (x:Symbol) : get?(OPERATORS, x, false)
val OPERATORS = HashTable<Symbol, PrimOp>(symbol-hash)
OPERATORS[`add] = ADD-OP
-OPERATORS[`add-uu] = ADD-UU-OP
-OPERATORS[`add-us] = ADD-US-OP
-OPERATORS[`add-su] = ADD-SU-OP
-OPERATORS[`add-ss] = ADD-SS-OP
OPERATORS[`sub] = SUB-OP
-OPERATORS[`sub-uu] = SUB-UU-OP
-OPERATORS[`sub-us] = SUB-US-OP
-OPERATORS[`sub-su] = SUB-SU-OP
-OPERATORS[`sub-ss] = SUB-SS-OP
OPERATORS[`mul] = MUL-OP
-OPERATORS[`mul-uu] = MUL-UU-OP
-OPERATORS[`mul-us] = MUL-US-OP
-OPERATORS[`mul-su] = MUL-SU-OP
-OPERATORS[`mul-ss] = MUL-SS-OP
OPERATORS[`div] = DIV-OP
-OPERATORS[`div-uu] = DIV-UU-OP
-OPERATORS[`div-us] = DIV-US-OP
-OPERATORS[`div-su] = DIV-SU-OP
-OPERATORS[`div-ss] = DIV-SS-OP
OPERATORS[`mod] = MOD-OP
-OPERATORS[`mod-uu] = MOD-UU-OP
-OPERATORS[`mod-us] = MOD-US-OP
-OPERATORS[`mod-su] = MOD-SU-OP
-OPERATORS[`mod-ss] = MOD-SS-OP
OPERATORS[`quo] = QUO-OP
-OPERATORS[`quo-uu] = QUO-UU-OP
-OPERATORS[`quo-us] = QUO-US-OP
-OPERATORS[`quo-su] = QUO-SU-OP
-OPERATORS[`quo-ss] = QUO-SS-OP
OPERATORS[`rem] = REM-OP
-OPERATORS[`rem-uu] = REM-UU-OP
-OPERATORS[`rem-us] = REM-US-OP
-OPERATORS[`rem-su] = REM-SU-OP
-OPERATORS[`rem-ss] = REM-SS-OP
OPERATORS[`add-wrap] = ADD-WRAP-OP
-OPERATORS[`add-wrap-uu] = ADD-WRAP-UU-OP
-OPERATORS[`add-wrap-us] = ADD-WRAP-US-OP
-OPERATORS[`add-wrap-su] = ADD-WRAP-SU-OP
-OPERATORS[`add-wrap-ss] = ADD-WRAP-SS-OP
OPERATORS[`sub-wrap] = SUB-WRAP-OP
-OPERATORS[`sub-wrap-uu] = SUB-WRAP-UU-OP
-OPERATORS[`sub-wrap-us] = SUB-WRAP-US-OP
-OPERATORS[`sub-wrap-su] = SUB-WRAP-SU-OP
-OPERATORS[`sub-wrap-ss] = SUB-WRAP-SS-OP
OPERATORS[`lt] = LESS-OP
-OPERATORS[`lt-uu] = LESS-UU-OP
-OPERATORS[`lt-us] = LESS-US-OP
-OPERATORS[`lt-su] = LESS-SU-OP
-OPERATORS[`lt-ss] = LESS-SS-OP
OPERATORS[`leq] = LESS-EQ-OP
-OPERATORS[`leq-uu] = LESS-EQ-UU-OP
-OPERATORS[`leq-us] = LESS-EQ-US-OP
-OPERATORS[`leq-su] = LESS-EQ-SU-OP
-OPERATORS[`leq-ss] = LESS-EQ-SS-OP
OPERATORS[`gt] = GREATER-OP
-OPERATORS[`gt-uu] = GREATER-UU-OP
-OPERATORS[`gt-us] = GREATER-US-OP
-OPERATORS[`gt-su] = GREATER-SU-OP
-OPERATORS[`gt-ss] = GREATER-SS-OP
OPERATORS[`geq] = GREATER-EQ-OP
-OPERATORS[`geq-uu] = GREATER-EQ-UU-OP
-OPERATORS[`geq-us] = GREATER-EQ-US-OP
-OPERATORS[`geq-su] = GREATER-EQ-SU-OP
-OPERATORS[`geq-ss] = GREATER-EQ-SS-OP
OPERATORS[`eq] = EQUAL-OP
-OPERATORS[`eq-uu] = EQUAL-UU-OP
-OPERATORS[`eq-ss] = EQUAL-SS-OP
OPERATORS[`neq] = NEQUAL-OP
-OPERATORS[`neq-uu] = NEQUAL-UU-OP
-OPERATORS[`neq-ss] = NEQUAL-SS-OP
OPERATORS[`mux] = MUX-OP
-OPERATORS[`mux-uu] = MUX-UU-OP
-OPERATORS[`mux-ss] = MUX-SS-OP
OPERATORS[`pad] = PAD-OP
-OPERATORS[`pad-u] = PAD-U-OP
-OPERATORS[`pad-s] = PAD-S-OP
OPERATORS[`neg] = NEG-OP
-OPERATORS[`neg-u] = NEG-U-OP
-OPERATORS[`neg-s] = NEG-S-OP
OPERATORS[`as-UInt] = AS-UINT-OP
-OPERATORS[`as-UInt-u] = AS-UINT-U-OP
-OPERATORS[`as-UInt-s] = AS-UINT-S-OP
OPERATORS[`as-SInt] = AS-SINT-OP
-OPERATORS[`as-SInt-u] = AS-SINT-U-OP
-OPERATORS[`as-SInt-s] = AS-SINT-S-OP
OPERATORS[`dshl] = DYN-SHIFT-LEFT-OP
-OPERATORS[`dshl-u] = DYN-SHIFT-LEFT-U-OP
-OPERATORS[`dshl-s] = DYN-SHIFT-LEFT-S-OP
OPERATORS[`dshr] = DYN-SHIFT-RIGHT-OP
-OPERATORS[`dshr-u] = DYN-SHIFT-RIGHT-U-OP
-OPERATORS[`dshr-s] = DYN-SHIFT-RIGHT-S-OP
OPERATORS[`shl] = SHIFT-LEFT-OP
-OPERATORS[`shl-u] = SHIFT-LEFT-U-OP
-OPERATORS[`shl-s] = SHIFT-LEFT-S-OP
OPERATORS[`shr] = SHIFT-RIGHT-OP
-OPERATORS[`shr-u] = SHIFT-RIGHT-U-OP
-OPERATORS[`shr-s] = SHIFT-RIGHT-S-OP
OPERATORS[`convert] = CONVERT-OP
-OPERATORS[`convert-u] = CONVERT-U-OP
-OPERATORS[`convert-s] = CONVERT-S-OP
OPERATORS[`bit-and-reduce] = BIT-AND-REDUCE-OP
OPERATORS[`bit-or-reduce] = BIT-OR-REDUCE-OP
OPERATORS[`bit-xor-reduce] = BIT-XOR-REDUCE-OP
@@ -309,9 +233,6 @@ defsyntax firrtl :
expterm = (Register(?v:#exp, ?e:#exp)) : Register(UnknownType(), v, e)
expterm != (Register) : FPE(form, "Invalid syntax for Register expression.")
- expterm = (Pad(?e:#exp, ?w:#width$)) : Pad(e,w,UnknownType())
- expterm != (Pad) : FPE(form, "Invalid syntax for Pad expression.")
-
expterm = (?op:#sym(?es:#exp ... ?ints:#int ... ?rest ...)) :
if not empty?(rest) :
FPE(rest, "Illegal operands to primitive operator.")
diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza
index 190ad09a..d2afca05 100644
--- a/src/main/stanza/ir-utils.stanza
+++ b/src/main/stanza/ir-utils.stanza
@@ -7,6 +7,43 @@ defpackage firrtl/ir-utils :
public defmulti print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|Module|Circuit) -> False
+;============== GENSYM STUFF ======================
+
+val sym-hash = HashTable<Symbol,Int>(symbol-hash)
+public defn firrtl-gensym (s:Symbol) -> Symbol :
+ val cur = get?(sym-hash,s,0)
+ val nxt = cur + 1
+ sym-hash[s] = nxt
+ symbol-join([s cur])
+
+public defn firrtl-gensym () -> Symbol :
+ firrtl-gensym(`gen)
+
+;============== Exceptions =====================
+
+public definterface PassException <: Exception
+public defn PassException (s:String) :
+ new PassException :
+ defmethod print (o:OutputStream, this) :
+ print(o, s)
+
+public defn PassExceptions (xs:Streamable<PassException>) :
+ PassException(string-join(xs, "\n"))
+
+;============== Pass/Compiler Structs ============
+
+public definterface Compiler
+public defmulti passes (c:Compiler) -> List<Pass>
+public defmulti file (c:Compiler) -> String
+
+public definterface Pass
+public defmulti pass (p:Pass) -> (Circuit -> Circuit)
+public defmulti name (p:Pass) -> String
+public defmulti short-name (p:Pass) -> String
+public defmethod print (o:OutputStream, p:Pass) :
+ print(o,name(p))
+
+
;============== PRINTERS ===================================
defmethod print (o:OutputStream, d:Flip) :
@@ -31,106 +68,30 @@ defmethod print (o:OutputStream, op:PrimOp) :
print{o, _} $
switch {op == _} :
ADD-OP : "add"
- ADD-UU-OP : "add-uu"
- ADD-US-OP : "add-us"
- ADD-SU-OP : "add-su"
- ADD-SS-OP : "add-ss"
SUB-OP : "sub"
- SUB-UU-OP : "sub-uu"
- SUB-US-OP : "sub-us"
- SUB-SU-OP : "sub-su"
- SUB-SS-OP : "sub-ss"
MUL-OP : "mul"
- MUL-UU-OP : "mul-uu"
- MUL-US-OP : "mul-us"
- MUL-SU-OP : "mul-su"
- MUL-SS-OP : "mul-ss"
DIV-OP : "div"
- DIV-UU-OP : "div-uu"
- DIV-US-OP : "div-us"
- DIV-SU-OP : "div-su"
- DIV-SS-OP : "div-ss"
MOD-OP : "mod"
- MOD-UU-OP : "mod-uu"
- MOD-US-OP : "mod-us"
- MOD-SU-OP : "mod-su"
- MOD-SS-OP : "mod-ss"
QUO-OP : "quo"
- QUO-UU-OP : "quo-uu"
- QUO-US-OP : "quo-us"
- QUO-SU-OP : "quo-su"
- QUO-SS-OP : "quo-ss"
REM-OP : "rem"
- REM-UU-OP : "rem-uu"
- REM-US-OP : "rem-us"
- REM-SU-OP : "rem-su"
- REM-SS-OP : "rem-ss"
ADD-WRAP-OP : "add-wrap"
- ADD-WRAP-UU-OP : "add-wrap-uu"
- ADD-WRAP-US-OP : "add-wrap-us"
- ADD-WRAP-SU-OP : "add-wrap-su"
- ADD-WRAP-SS-OP : "add-wrap-ss"
SUB-WRAP-OP : "sub-wrap"
- SUB-WRAP-UU-OP : "sub-wrap-uu"
- SUB-WRAP-US-OP : "sub-wrap-us"
- SUB-WRAP-SU-OP : "sub-wrap-su"
- SUB-WRAP-SS-OP : "sub-wrap-ss"
LESS-OP : "lt"
- LESS-UU-OP : "lt-uu"
- LESS-US-OP : "lt-us"
- LESS-SU-OP : "lt-su"
- LESS-SS-OP : "lt-ss"
LESS-EQ-OP : "leq"
- LESS-EQ-UU-OP : "leq-uu"
- LESS-EQ-US-OP : "leq-us"
- LESS-EQ-SU-OP : "leq-su"
- LESS-EQ-SS-OP : "leq-ss"
GREATER-OP : "gt"
- GREATER-UU-OP : "gt-uu"
- GREATER-US-OP : "gt-us"
- GREATER-SU-OP : "gt-su"
- GREATER-SS-OP : "gt-ss"
GREATER-EQ-OP : "geq"
- GREATER-EQ-UU-OP : "geq-uu"
- GREATER-EQ-US-OP : "geq-us"
- GREATER-EQ-SU-OP : "geq-su"
- GREATER-EQ-SS-OP : "geq-ss"
EQUAL-OP : "eq"
- EQUAL-UU-OP : "eq-uu"
- EQUAL-SS-OP : "eq-ss"
NEQUAL-OP : "neq"
- NEQUAL-UU-OP : "neq-uu"
- NEQUAL-SS-OP : "neq-ss"
MUX-OP : "mux"
- MUX-UU-OP : "mux-uu"
- MUX-SS-OP : "mux-ss"
PAD-OP : "pad"
- PAD-U-OP : "pad-u"
- PAD-S-OP : "pad-s"
AS-UINT-OP : "as-UInt"
- AS-UINT-U-OP : "as-UInt-u"
- AS-UINT-S-OP : "as-UInt-s"
AS-SINT-OP : "as-SInt"
- AS-SINT-U-OP : "as-SInt-u"
- AS-SINT-S-OP : "as-SInt-s"
DYN-SHIFT-LEFT-OP : "dshl"
- DYN-SHIFT-LEFT-U-OP : "dshl-u"
- DYN-SHIFT-LEFT-S-OP : "dshl-s"
DYN-SHIFT-RIGHT-OP : "dshr"
- DYN-SHIFT-RIGHT-U-OP : "dshr-u"
- DYN-SHIFT-RIGHT-S-OP : "dshr-s"
SHIFT-LEFT-OP : "shl"
- SHIFT-LEFT-U-OP : "shl-u"
- SHIFT-LEFT-S-OP : "shl-s"
SHIFT-RIGHT-OP : "shr"
- SHIFT-RIGHT-U-OP : "shr-u"
- SHIFT-RIGHT-S-OP : "shr-s"
CONVERT-OP : "convert"
- CONVERT-U-OP : "convert-u"
- CONVERT-S-OP : "convert-s"
NEG-OP : "neg"
- NEG-U-OP : "neg-u"
- NEG-S-OP : "neg-s"
BIT-NOT-OP : "bit-not"
BIT-AND-OP : "bit-and"
BIT-OR-OP : "bit-or"
@@ -156,7 +117,6 @@ defmethod print (o:OutputStream, e:Expression) :
(e:ReadPort) : print-all(o, ["ReadPort(" mem(e) ", " index(e) ", " enable(e) ")"])
(e:WritePort) : print-all(o, ["WritePort(" mem(e) ", " index(e) ", " enable(e) ")"])
(e:Register) : print-all(o, ["Register(" value(e) ", " enable(e) ")"])
- (e:Pad) : print-all(o, ["Pad(" value(e) ", " width(e) ")"])
print-debug(o,e)
defmethod print (o:OutputStream, c:Stmt) :
@@ -261,7 +221,6 @@ defmethod map (f: Expression -> Expression, e:Expression) -> Expression :
(e:ReadPort) : ReadPort(f(mem(e)), f(index(e)), type(e), f(enable(e)))
(e:WritePort) : WritePort(f(mem(e)), f(index(e)), type(e), f(enable(e)))
(e:Register) : Register(type(e),f(value(e)),f(enable(e)))
- (e:Pad) : Pad(f(value(e)),width(e),type(e))
(e) : e
public defmulti map<?T> (f: Expression -> Expression, c:?T&Stmt) -> T
@@ -287,7 +246,6 @@ defmethod map (f: Width -> Width, c:Expression) -> Expression :
match(c) :
(c:UIntValue) : UIntValue(value(c),f(width(c)))
(c:SIntValue) : SIntValue(value(c),f(width(c)))
- (c:Pad) : Pad(value(c),f(width(c)),type(c))
(c) : c
public defmulti map<?T> (f: Width -> Width, c:?T&Type) -> T
@@ -307,7 +265,6 @@ defmethod map (f: Type -> Type, c:Expression) -> Expression :
(c:ReadPort) : ReadPort(mem(c),index(c),f(type(c)),enable(c))
(c:WritePort) : WritePort(mem(c),index(c),f(type(c)),enable(c))
(c:Register) : Register(f(type(c)),value(c),enable(c))
- (c:Pad) : Pad(value(c),width(c),f(type(c)))
(c) : c
public defmulti map<?T> (f: Type -> Type, c:?T&Stmt) -> T
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza
index ee96708c..4421e79b 100644
--- a/src/main/stanza/passes.stanza
+++ b/src/main/stanza/passes.stanza
@@ -7,16 +7,26 @@ defpackage firrtl/passes :
import firrtl-main
import firrtl/errors
-;============== Exceptions =====================
-public definterface PassException <: Exception
-public defn PassException (s:String) :
- new PassException :
- defmethod print (o:OutputStream, this) :
- print(o, s)
-
-public defn PassExceptions (xs:Streamable<PassException>) :
- PassException(string-join(xs, "\n"))
-
+;============== Pass List ================
+public val standard-passes = to-list $ [
+ CheckHighForm()
+ TempElimination()
+ ToWorkingIR()
+ MakeExplicitReset()
+ ResolveKinds()
+ CheckKinds()
+ InferTypes()
+ CheckTypes()
+ ResolveGenders()
+ CheckGenders()
+ ExpandAccessors()
+ LowerToGround()
+ ExpandIndexedConnects()
+ ExpandWhens()
+ InferWidths()
+ Inline()
+ SplitExp()
+ ToRealIR() ]
;=============== WORKING IR ================================
public definterface Kind
public defstruct WireKind <: Kind
@@ -149,18 +159,6 @@ defmethod info (stmt:EmptyStmt) -> FileInfo : FileInfo()
defmethod type (exp:UIntValue) -> Type : UIntType(width(exp))
defmethod type (exp:SIntValue) -> Type : SIntType(width(exp))
-;============== GENSYM STUFF ======================
-
-val sym-hash = HashTable<Symbol,Int>(symbol-hash)
-defn firrtl-gensym (s:Symbol) -> Symbol :
- val cur = get?(sym-hash,s,0)
- val nxt = cur + 1
- sym-hash[s] = nxt
- symbol-join([s cur])
-
-defn firrtl-gensym () -> Symbol :
- firrtl-gensym(`gen)
-
;============== DEBUG STUFF =============================
public var PRINT-TYPES : True|False = false
public var PRINT-KINDS : True|False = false
@@ -198,12 +196,12 @@ defn hasGender (e:?) :
e typeof WRef|WSubfield|WIndex|WDefAccessor
defn hasWidth (e:?) :
- e typeof UIntType|SIntType|UIntValue|SIntValue|Pad
+ e typeof UIntType|SIntType|UIntValue|SIntValue
defn hasType (e:?) :
e typeof Ref|Subfield|Index|DoPrim|WritePort|ReadPort|WRef|WSubfield
|WIndex|DefWire|DefRegister|DefMemory|Register
- |VectorType|Port|Field|Pad
+ |VectorType|Port|Field
defn hasKind (e:?) :
e typeof WRef
@@ -246,15 +244,15 @@ defmethod print (o:OutputStream, e:WIndex) :
print-debug(o,e as ?)
defmethod print (o:OutputStream, s:WDefAccessor) :
- print-all(o,["accessor " name(s) " = " source(s) "[" index(s) "] @[" info(s) "]"])
+ print-all(o,["accessor " name(s) " = " source(s) "[" index(s) "]"])
print-debug(o,s)
defmethod print (o:OutputStream, c:ConnectToIndexed) :
- print-all(o, [locs(c) "[" index(c) "] := " exp(c) " @[" info(c) "]"])
+ print-all(o, [locs(c) "[" index(c) "] := " exp(c)])
print-debug(o,c as ?)
defmethod print (o:OutputStream, c:ConnectFromIndexed) :
- print-all(o, [loc(c) " := " exps(c) "[" index(c) "] @[" info(c) "]"])
+ print-all(o, [loc(c) " := " exps(c) "[" index(c) "]" ])
print-debug(o,c as ?)
defmethod map (f: Expression -> Expression, e: WSubfield) :
@@ -279,6 +277,10 @@ defmethod map (f: Type -> Type, e: WIndex) :
;================= Temporary Variable Elimination ========================
; Returns a new Circuit where temporary variables are removed and returns
; the resulting nested expression
+public defstruct TempElimination <: Pass
+public defmethod pass (b:TempElimination) -> (Circuit -> Circuit) : temp-elimination
+public defmethod name (b:TempElimination) -> String : "Temp Elimination"
+public defmethod short-name (b:TempElimination) -> String : "temp-elim"
defn temp-elimination (c:Circuit) :
val h = HashTable<Symbol,Expression>(symbol-hash)
@@ -308,6 +310,10 @@ defn temp-elimination (c:Circuit) :
; Returns a new Circuit with Refs, Subfields, Indexes and DefAccessors
; replaced with IR-internal nodes that contain additional
; information (kind, gender)
+public defstruct ToWorkingIR <: Pass
+public defmethod pass (b:ToWorkingIR) -> (Circuit -> Circuit) : to-working-ir
+public defmethod name (b:ToWorkingIR) -> String : "Working IR"
+public defmethod short-name (b:ToWorkingIR) -> String : "to-working-ir"
defn to-working-ir (c:Circuit) :
defn to-exp (e:Expression) :
@@ -334,6 +340,10 @@ defn to-working-ir (c:Circuit) :
; If reset is not explicitly passed to instantiations, then this
; pass autmatically connects the parent module's reset to the
; instantiation's reset
+public defstruct MakeExplicitReset <: Pass
+public defmethod pass (b:MakeExplicitReset) -> (Circuit -> Circuit) : make-explicit-reset
+public defmethod name (b:MakeExplicitReset) -> String : "Make Explicit Reset"
+public defmethod short-name (b:MakeExplicitReset) -> String : "make-explicit-reset"
defn make-explicit-reset (c:Circuit) :
defn find-explicit (c:Circuit) -> List<Symbol> :
@@ -374,6 +384,10 @@ defn make-explicit-reset (c:Circuit) :
; objects referenced. This information is stored in the kind
; field in WRef. This pass walks the graph and returns a new
; Circuit where all WRef kinds are resolved
+public defstruct ResolveKinds <: Pass
+public defmethod pass (b:ResolveKinds) -> (Circuit -> Circuit) : resolve-kinds
+public defmethod name (b:ResolveKinds) -> String : "Resolve Kinds"
+public defmethod short-name (b:ResolveKinds) -> String : "resolve-kinds"
defn resolve-kinds (c:Circuit) :
defn resolve (body:Stmt, kinds:HashTable<Symbol,Kind>) :
@@ -428,6 +442,10 @@ defn resolve-kinds (c:Circuit) :
; resolving the subexpressions in its elements.
; Type errors are not checked in this pass, as this is
; postponed for a later/earlier pass.
+public defstruct InferTypes <: Pass
+public defmethod pass (b:InferTypes) -> (Circuit -> Circuit) : infer-types
+public defmethod name (b:InferTypes) -> String : "Infer Types"
+public defmethod short-name (b:InferTypes) -> String : "infer-types"
defn type (m:Module) -> Type :
BundleType(for p in ports(m) map : to-field(p))
@@ -464,7 +482,6 @@ defn infer-exp-types (e:Expression, l:List<KeyValue<Symbol,Type>>) -> Expression
(e:ReadPort) : ReadPort(mem(e),index(e),get-vector-subtype(type(mem(e))),enable(e))
(e:WritePort) : WritePort(mem(e),index(e),get-vector-subtype(type(mem(e))),enable(e))
(e:Register) : Register(type(value(e)),value(e),enable(e))
- (e:Pad) : Pad(value(e),width(e),type(value(e)))
(e:UIntValue|SIntValue) : e
defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue<Symbol,Type>>] :
@@ -517,6 +534,10 @@ defn infer-types (c:Circuit) -> Circuit :
; elements are single-gender (e.g. accessors, ports).
; Because accessor gender is not known during declaration,
; this pass requires iterating until a fixed point is reached.
+public defstruct ResolveGenders <: Pass
+public defmethod pass (b:ResolveGenders) -> (Circuit -> Circuit) : resolve-genders
+public defmethod name (b:ResolveGenders) -> String : "Resolve Genders"
+public defmethod short-name (b:ResolveGenders) -> String : "resolve-genders"
; Notes
; Is there a case where an incorrect gender would cause a weird result in resolving an accessor gender, such that a following gender check is wrong/right which it shouldn't be?
@@ -637,6 +658,10 @@ defn resolve-genders (c:Circuit) :
; of the accessor, it is transformed into ConnectToIndexed (male) or
; ConnectFromIndexed (female)
; Eg:
+public defstruct ExpandAccessors <: Pass
+public defmethod pass (b:ExpandAccessors) -> (Circuit -> Circuit) : expand-accessors
+public defmethod name (b:ExpandAccessors) -> String : "Expand Accessors"
+public defmethod short-name (b:ExpandAccessors) -> String : "expand-accessors"
defn expand-vector (e:Expression) -> List<Expression> :
val t = type(e) as VectorType
@@ -679,6 +704,10 @@ defn expand-accessors (c:Circuit) :
; This pass involves filling a table mapping the name of elevated types
; to the lowered ground expression names and genders. This allows
; references to be resolved.
+public defstruct LowerToGround <: Pass
+public defmethod pass (b:LowerToGround) -> (Circuit -> Circuit) : lower-to-ground
+public defmethod name (b:LowerToGround) -> String : "Lower To Ground"
+public defmethod short-name (b:LowerToGround) -> String : "lower-to-ground"
defstruct EF :
exp : Expression
@@ -715,7 +744,7 @@ defn index-of-elem (t:BundleType, s:Symbol) -> Int :
defn generate-entry (n:Symbol,t:Type) -> List<NTF> :
- defn uniquify (n*:Symbol) -> Symbol : symbol-join([n "$" n*])
+ defn uniquify (n*:Symbol) -> Symbol : symbol-join([n "_" n*])
match(t) :
(t:BundleType) :
for f in fields(t) map-append :
@@ -760,9 +789,9 @@ defn expand-expr (e:Expression) -> List<EF> :
val exps = expand-expr(exp(e))
val len = num-elems(type(e))
headn(tailn(exps,len * value(e)),len)
- (e:Pad) :
- val v = exp(head(expand-expr(value(e))))
- list(EF(Pad(v,width(e),type(e)),DEFAULT))
+ ;(e:Pad) :
+ ;val v = exp(head(expand-expr(value(e))))
+ ;list(EF(Pad(v,width(e),type(e)),DEFAULT))
(e:DoPrim) :
val args = for x in args(e) map : exp(head(expand-expr(x)))
list(EF(DoPrim(op(e),args,consts(e),type(e)),DEFAULT))
@@ -894,15 +923,19 @@ defn lower-to-ground (c:Circuit) -> Circuit :
; This pass converts ConnectToIndexed and ConnectFromIndexed
; into a series of when statements. TODO what about initial
; values?
+public defstruct ExpandIndexedConnects <: Pass
+public defmethod pass (b:ExpandIndexedConnects) -> (Circuit -> Circuit) : expand-connect-indexed
+public defmethod name (b:ExpandIndexedConnects) -> String : "Expand Indexed Connects"
+public defmethod short-name (b:ExpandIndexedConnects) -> String : "expand-indexed-connects"
defn expand-connect-indexed-stmt (s: Stmt) -> Stmt :
defn equality (e1:Expression,e2:Expression) -> Expression :
- DoPrim(EQUAL-UU-OP,list(e1,e2),List(),UIntType(UnknownWidth()))
+ DoPrim(EQUAL-OP,list(e1,e2),List(),UIntType(UnknownWidth()))
defn get-name (e:Expression) -> Symbol :
match(e) :
- (e:WRef) : symbol-join([name(e) `#])
- (e:WSubfield) : symbol-join([get-name(exp(e)) `. name(e) `#])
- (e:WIndex) : symbol-join([get-name(exp(e)) `. to-symbol(value(e)) `#])
+ (e:WRef) : symbol-join([name(e) `__])
+ (e:WSubfield) : symbol-join([get-name(exp(e)) `. name(e) `__])
+ (e:WIndex) : symbol-join([get-name(exp(e)) `. to-symbol(value(e)) `__])
(e) : `T
match(s) :
(s:ConnectToIndexed) : Begin $
@@ -910,15 +943,15 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt :
else :
val ref = WRef(firrtl-gensym(get-name(exp(s))),type(index(s)),NodeKind(),UNKNOWN-GENDER)
append(
- list(Connect(info(s),head(locs(s)),exp(s)),DefNode(info(s),name(ref),index(s)))
+ list(DefNode(info(s),name(ref),index(s)))
to-list $
- for (i in 1 to false, l in tail(locs(s))) stream : Conditionally(
+ for (i in 0 to false, l in locs(s)) stream : Conditionally(
info(s),
equality(ref,UIntValue(i,UnknownWidth())),
Connect(info(s),l,exp(s)),
EmptyStmt()
)
- )
+ )
(s:ConnectFromIndexed) : Begin $
if length(exps(s)) == 0 : list(EmptyStmt())
else :
@@ -963,6 +996,10 @@ defn expand-connect-indexed (c: Circuit) -> Circuit :
; The ReadPort enable is calcuated by scanning all entries in
; the table for when this is referenced (a read). All conditions
; are accumulated and OR'ed together.
+public defstruct ExpandWhens <: Pass
+public defmethod pass (b:ExpandWhens) -> (Circuit -> Circuit) : expand-whens
+public defmethod name (b:ExpandWhens) -> String : "Expand Whens"
+public defmethod short-name (b:ExpandWhens) -> String : "expand-whens"
; ======== Expression Computation Library ===========
@@ -980,7 +1017,7 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False :
(e1:WRef,e2:WRef) : name(e1) == name(e2)
;(e1:DoPrim,e2:DoPrim) : TODO
(e1:WSubfield,e2:WSubfield) : name(e1) == name(e2)
- (e1:Pad,e2:Pad) : width(e1) == width(e2) and value(e1) == value(e2)
+ ;(e1:Pad,e2:Pad) : width(e1) == width(e2) and value(e1) == value(e2)
(e1:DoPrim,e2:DoPrim) :
var are-equal? = op(e1) == op(e2)
for (x in args(e1),y in args(e2)) do :
@@ -1009,7 +1046,7 @@ defn OR (e1:Expression,e2:Expression) -> Expression :
defn NOT (e1:Expression) -> Expression :
if e1 == one : zero
else if e1 == zero : one
- else : DoPrim(EQUAL-UU-OP,list(e1,zero),list(),UIntType(IntWidth(1)))
+ else : DoPrim(EQUAL-OP,list(e1,zero),list(),UIntType(IntWidth(1)))
defn children (e:Expression) -> List<Expression> :
val es = Vector<Expression>()
@@ -1106,7 +1143,7 @@ defn remove-nul (sv:SymbolicValue) -> SymbolicValue :
defn to-exp (sv:SymbolicValue) -> Expression|False :
match(remove-nul(sv)) :
(sv:SVMux) :
- DoPrim(MUX-UU-OP,
+ DoPrim(MUX-OP,
list(pred(sv),to-exp(conseq(sv)) as Expression,to-exp(alt(sv)) as Expression),
list(),
UIntType(IntWidth(1)))
@@ -1132,7 +1169,6 @@ defn reduce-or (l:List<Expression>) -> Expression :
; kinds: Used to know the kind of reference, so we know whether we should error if it isn't initialized. We also know how we should declare the refernce.
; enables:Calculated off of assigns.
-
defn expand-whens (ports:List<Port>, table:HashTable<Symbol,SymbolicValue>,cons:Vector<Stmt>) -> False :
for p in ports do :
if direction(p) == OUTPUT :
@@ -1156,24 +1192,29 @@ defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stm
else : Connect(info(s),ref,to-exp(table[name(s)]) as Expression)
}()
(s:DefRegister) :
- add(decs,DefWire(info(s),name(s),type(s)))
+ ;add(decs,DefWire(info(s),name(s),type(s)))
+ ;add{cons,_} $ {
+ ; val ref = WRef(name(s),type(s),RegKind(),FEMALE)
+ ; val e = to-exp(table[name(s)])
+ ; match(e) :
+ ; (e:False) : EmptyStmt()
+ ; (e:Expression) : Connect(info(s),ref,Register(type(s),e, to-exp(optimize $ get-write-enable(table[name(s)])) as Expression))
+ ;}()
+ val e = to-exp(table[name(s)])
add{cons,_} $ {
- val ref = WRef(name(s),type(s),RegKind(),FEMALE)
- val e = to-exp(table[name(s)])
match(e) :
(e:False) : EmptyStmt()
- (e:Expression) : Connect(info(s),ref,Register(type(s),e, to-exp(optimize $ get-write-enable(table[name(s)])) as Expression))
+ (e:Expression) : DefNode(info(s),name(s),Register(type(s),e,to-exp(optimize $ get-write-enable(table[name(s)])) as Expression))
}()
(s:WDefAccessor) :
val t = type(type(source(s)) as VectorType)
val n = name(s)
- add(decs,DefWire(info(s),n,t))
add{cons,_} $ {
switch {_ == gender(s)} :
MALE :
- val ref = WRef(n,t,ReadAccessorKind(),FEMALE)
- Begin $ list $ Connect(info(s),ref,ReadPort(source(s),index(s),t,get-read-enable(n,table)))
+ Begin $ list $ DefNode(info(s),n,ReadPort(source(s),index(s),t,get-read-enable(n,table)))
FEMALE :
+ add(decs,DefWire(info(s),n,t))
val ref = WRef(n,t,WriteAccessorKind(),FEMALE)
val e = to-exp(table[n])
val s* = match(e) :
@@ -1350,6 +1391,10 @@ defn expand-whens (c:Circuit) -> Circuit :
; Finally, you replace all width variables with the solved
; widths.
; Low FIRRTL Pass.
+public defstruct InferWidths <: Pass
+public defmethod pass (b:InferWidths) -> (Circuit -> Circuit) : infer-widths
+public defmethod name (b:InferWidths) -> String : "Infer Widths"
+public defmethod short-name (b:InferWidths) -> String : "infer-widths"
public defstruct VarWidth <: Width :
name: Symbol
@@ -1412,10 +1457,8 @@ defn apply (a:Int|False,b:Int|False, f: (Int,Int) -> Int) -> Int|False :
if a typeof Int and b typeof Int : f(a as Int, b as Int)
else : false
-; TODO: I should make MaxWidth take a variable list of arguments, which would make it easier to write the simplify function. It looks like there isn't a bug in the algorithm, but simplification reallllly speeds it up.
-
-defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Int> :
+defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Width> :
defn contains? (n:Symbol,h:HashTable<Symbol,?>) -> True|False : key?(h,n)
defn make-unique (ls:List<WGeq>) -> HashTable<Symbol,Width> :
val h = HashTable<Symbol,Width>(symbol-hash)
@@ -1492,34 +1535,6 @@ defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Int> :
w
look(w)
has?
- defn evaluate (h:HashTable<Symbol,Width>) -> HashTable<Symbol,Int> :
- defn apply (a:Int|False,f:(Int) -> Int) -> Int|False :
- if a typeof Int : f(a as Int)
- else : false
- defn apply (a:Int|False,b:Int|False, f: (Int,Int) -> Int) -> Int|False :
- if a typeof Int and b typeof Int : f(a as Int, b as Int)
- else : false
- defn apply-l (l:List<Int|False>,f:(Int,Int) -> Int) -> Int|False :
- if length(l) == 0 : 0
- else : apply(head(l),apply-l(tail(l),f),f)
- defn max (a:Int,b:Int) -> Int :
- if a >= b : a
- else : b
- defn solve (w:Width) -> Int|False :
- match(w) :
- (w:VarWidth) : false
- (w:MaxWidth) : apply-l(map(solve,args(w)),max)
- (w:PlusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ + _})
- (w:MinusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ - _})
- (w:ExpWidth) : apply(2,solve(arg1(w)),{pow(_,_) - 1})
- (w:IntWidth) : width(w)
- (w) : error("Shouldn't be here")
-
- val i = HashTable<Symbol,Int>(symbol-hash)
- for x in h do :
- val s = solve(value(x))
- if s typeof Int : i[key(x)] = s as Int
- i
; Forward solve
; Returns a solved list where each constraint undergoes:
@@ -1572,11 +1587,7 @@ defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Int> :
for x in b do : println-debug(x)
println-debug("=========================")
- ; Evaluate
- val e = evaluate(b)
- println-debug("Evaluated Constraints")
- for x in e do : println-debug(x)
- e
+ b
public defn width! (t:Type) -> Width :
match(t) :
@@ -1611,15 +1622,15 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod
(e:WSubfield) : WSubfield(exp(e),name(e),bundle-field-type(type(exp(e)),name(e)),gender(e))
(e:WIndex) : error("Shouldn't be here")
(e:DoPrim) : DoPrim(op(e),args(e),consts(e),primop-gen-constraints(e,v))
- (e:Pad) :
- val value-w = width!(value(e))
- val pad-w = remove-unknowns-w(width(e))
- add(v,WGeq(pad-w, value-w))
- val pad-t = match(type(e)) :
- (t:UIntType) : UIntType(pad-w)
- (t:SIntType) : SIntType(pad-w)
- (t) : error("Shouldn't be here")
- Pad(value(e),pad-w,pad-t)
+ ;(e:Pad) :
+ ; val value-w = width!(value(e))
+ ; val pad-w = remove-unknowns-w(width(e))
+ ; add(v,WGeq(pad-w, value-w))
+ ; val pad-t = match(type(e)) :
+ ; (t:UIntType) : UIntType(pad-w)
+ ; (t:SIntType) : SIntType(pad-w)
+ ; (t) : error("Shouldn't be here")
+ ; Pad(value(e),pad-w,pad-t)
(e:ReadPort) : ReadPort(mem(e),index(e),type(type(mem(e)) as VectorType),enable(e))
(e:WritePort) : WritePort(mem(e),index(e),type(type(mem(e)) as VectorType),enable(e))
(e:Register) : Register(type(value(e)),value(e),enable(e))
@@ -1658,21 +1669,47 @@ defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTabl
build-environment(body(m))
h
-defn replace-var-widths (c:Circuit,h:HashTable<Symbol,Int>) -> Circuit :
- defn replace-var-widths-w (w:Width) -> Width :
+defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit :
+ defn evaluate (w:Width) -> Width :
+ defn apply (a:Int|False,f:(Int) -> Int) -> Int|False :
+ if a typeof Int : f(a as Int)
+ else : false
+ defn apply (a:Int|False,b:Int|False, f: (Int,Int) -> Int) -> Int|False :
+ if a typeof Int and b typeof Int : f(a as Int, b as Int)
+ else : false
+ defn apply-l (l:List<Int|False>,f:(Int,Int) -> Int) -> Int|False :
+ if length(l) == 0 : 0
+ else : apply(head(l),apply-l(tail(l),f),f)
+ defn max (a:Int,b:Int) -> Int :
+ if a >= b : a
+ else : b
+ defn solve (w:Width) -> Int|False :
+ match(w) :
+ (w:VarWidth) :
+ val w* = h[name(w)]
+ if w* typeof VarWidth : false
+ else : solve(w*)
+ (w:MaxWidth) : apply-l(map(solve,args(w)),max)
+ (w:PlusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ + _})
+ (w:MinusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ - _})
+ (w:ExpWidth) : apply(2,solve(arg1(w)),{pow(_,_) - 1})
+ (w:IntWidth) : width(w)
+ (w) : error("Shouldn't be here")
+
+ val s = solve(w)
+ if s typeof Int : IntWidth(s as Int)
+ else : w
+
+ defn reduce-var-widths-w (w:Width) -> Width :
println-all-debug(["REPLACE: " w])
- val w* = match(w) :
- (w:VarWidth) :
- if key?(h,name(w)) : IntWidth(h[name(w)])
- else: w
- (w) : w
+ val w* = evaluate(w)
println-all-debug(["WITH: " w*])
w*
val modules* = for m in modules(c) map :
- Module{info(m),name(m),_,mapr(replace-var-widths-w,body(m))} $
+ Module{info(m),name(m),_,mapr(reduce-var-widths-w,body(m))} $
for p in ports(m) map :
- Port(info(p),name(p),direction(p),mapr(replace-var-widths-w,type(p)))
+ Port(info(p),name(p),direction(p),mapr(reduce-var-widths-w,type(p)))
Circuit(info(c),modules*,main(c))
@@ -1710,12 +1747,16 @@ defn infer-widths (c:Circuit) -> Circuit :
println-debug("======== SOLVED CONSTRAINTS ========")
for x in h do : println-debug(x)
println-debug("====================================")
- replace-var-widths(Circuit(info(c),modules*,main(c)),h)
+ reduce-var-widths(Circuit(info(c),modules*,main(c)),h)
;================= Inline Instances ========================
; Inlines instances. Assumes module with same name as the
; Circuit is the top level module
+public defstruct Inline <: Pass
+public defmethod pass (b:Inline) -> (Circuit -> Circuit) : inline-instances
+public defmethod name (b:Inline) -> String : "Inline Instances"
+public defmethod short-name (b:Inline) -> String : "inline-instances"
defn inline-instances (c:Circuit) :
val h = HashTable<Symbol,Module>(symbol-hash)
@@ -1741,17 +1782,17 @@ defn inline-instances (c:Circuit) :
(e:WSubfield) :
match(kind(exp(e) as WRef)) :
(k:InstanceKind) :
- WRef(symbol-join([name(exp(e) as WRef) "$" name(e)]),type(e),k,gender(e))
+ WRef(symbol-join([name(exp(e) as WRef) "_" name(e)]),type(e),k,gender(e))
(k:MemKind) : e
(e) : e
- defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n "$" ref])
+ defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n "_" ref])
defn rename-e (e:Expression,n:Symbol) -> Expression :
match(map(rename-e{_,n},e)) :
(e:WRef) : WRef(rename(name(e),n),type(e),kind(e),gender(e))
(e:WSubfield) :
match(kind(exp(e) as WRef)) :
(k:InstanceKind) :
- WRef(symbol-join([name(exp(e) as WRef) "$" name(e)]),type(e),k,gender(e))
+ WRef(symbol-join([name(exp(e) as WRef) "_" name(e)]),type(e),k,gender(e))
(k:MemKind) : e
(e) : e
defn rename-s (s:Stmt,n:Symbol) -> Stmt :
@@ -1769,6 +1810,10 @@ defn inline-instances (c:Circuit) :
;================= Split Expressions ========================
; Intended to only work on low firrtl
+public defstruct SplitExp <: Pass
+public defmethod pass (b:SplitExp) -> (Circuit -> Circuit) : split-exp
+public defmethod name (b:SplitExp) -> String : "Split Expressions"
+public defmethod short-name (b:SplitExp) -> String : "split-expressions"
defn split-exp (c:Circuit) :
defn split-exp-s (s:Stmt,v:Vector<Stmt>) -> False :
@@ -1786,11 +1831,10 @@ defn split-exp (c:Circuit) :
false
defn split-exp-e (e:Expression,v:Vector<Stmt>,n:Symbol|False,info:FileInfo) -> Expression :
match(map(split-exp-e{_,v,n,info},e)):
- (e:Subfield|DoPrim|Pad|ReadPort|Register|WritePort) :
+ (e:Subfield|DoPrim|ReadPort|Register|WritePort) :
val n* =
if n typeof False : firrtl-gensym(`T)
- else : firrtl-gensym(symbol-join([n as Symbol `#]))
- ;to-symbol $ string-join $ [n as Symbol firrtl-gensym(`#)]
+ else : firrtl-gensym(symbol-join([n as Symbol `__]))
add(v,DefNode(info,n*,e))
WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER)
(e) : e
@@ -1803,6 +1847,10 @@ defn split-exp (c:Circuit) :
;================= Bring to Real IR ========================
; Returns a new Circuit with only real IR nodes.
+public defstruct ToRealIR <: Pass
+public defmethod pass (b:ToRealIR) -> (Circuit -> Circuit) : to-real-ir
+public defmethod name (b:ToRealIR) -> String : "Real IR"
+public defmethod short-name (b:ToRealIR) -> String : "real-ir"
defn to-real-ir (c:Circuit) :
defn to-exp (e:Expression) :
@@ -1823,265 +1871,3 @@ defn to-real-ir (c:Circuit) :
for m in modules(c) map :
Module(info(m),name(m), ports(m), to-stmt(body(m)))
-;============= FLO PRINTER ======================================
-; Emit
-
-defn flo-op-name (op:PrimOp) -> String :
- switch {op == _ } :
- ;NEG-OP : "neg"
- ;NEG-OP : "neg"
- ;NEG-OP : "neg"
- ;NEG-OP : "neg"
- ADD-UU-OP : "add"
- ADD-US-OP : "add"
- ADD-SU-OP : "add"
- ADD-SS-OP : "add"
- ADD-WRAP-UU-OP : "add"
- ADD-WRAP-US-OP : "add"
- ADD-WRAP-SU-OP : "add"
- ADD-WRAP-SS-OP : "add"
- SUB-UU-OP : "sub"
- SUB-US-OP : "sub"
- SUB-SU-OP : "sub"
- SUB-SS-OP : "sub"
- SUB-WRAP-UU-OP : "sub"
- SUB-WRAP-US-OP : "sub"
- SUB-WRAP-SU-OP : "sub"
- SUB-WRAP-SS-OP : "sub"
- MUL-UU-OP : "mul" ;; todo: signed version
- MUL-US-OP : "mul" ;; todo: signed version
- MUL-SU-OP : "mul" ;; todo: signed version
- MUL-SS-OP : "mul" ;; todo: signed version
- DIV-UU-OP : "div" ;; todo: signed version
- DIV-US-OP : "div" ;; todo: signed version
- DIV-SU-OP : "div" ;; todo: signed version
- DIV-SS-OP : "div" ;; todo: signed version
- MOD-UU-OP : "mod" ;; todo: signed version
- MOD-US-OP : "mod" ;; todo: signed version
- MOD-SU-OP : "mod" ;; todo: signed version
- MOD-SS-OP : "mod" ;; todo: signed version
- LESS-UU-OP : "lt" ;; todo: signed version
- LESS-US-OP : "lt" ;; todo: signed version
- LESS-SU-OP : "lt" ;; todo: signed version
- LESS-SS-OP : "lt" ;; todo: signed version
- LESS-EQ-UU-OP : "lte" ;; todo: swap args
- LESS-EQ-US-OP : "lte" ;; todo: swap args
- LESS-EQ-SU-OP : "lte" ;; todo: swap args
- LESS-EQ-SS-OP : "lte" ;; todo: swap args
- GREATER-UU-OP : "lt" ;; todo: swap args
- GREATER-US-OP : "lt" ;; todo: swap args
- GREATER-SU-OP : "lt" ;; todo: swap args
- GREATER-SS-OP : "lt" ;; todo: swap args
- GREATER-EQ-UU-OP : "lte" ;; todo: signed version
- GREATER-EQ-US-OP : "lte" ;; todo: signed version
- GREATER-EQ-SU-OP : "lte" ;; todo: signed version
- GREATER-EQ-SS-OP : "lte" ;; todo: signed version
- NEQUAL-UU-OP : "neq"
- NEQUAL-SS-OP : "neq"
- EQUAL-UU-OP : "eq"
- EQUAL-SS-OP : "eq"
- MUX-UU-OP : "mux"
- MUX-SS-OP : "mux"
- PAD-U-OP : "rsh"
- PAD-S-OP : "arsh"
- NEG-U-OP : "neg"
- NEG-S-OP : "neg"
- AS-UINT-U-OP : "mov"
- AS-UINT-S-OP : "mov"
- AS-SINT-U-OP : "mov"
- AS-SINT-S-OP : "mov"
- SHIFT-LEFT-U-OP : "lsh"
- SHIFT-LEFT-S-OP : "lsh"
- SHIFT-RIGHT-U-OP : "rsh"
- SHIFT-RIGHT-S-OP : "arsh"
- DYN-SHIFT-LEFT-U-OP : "lsh"
- DYN-SHIFT-LEFT-S-OP : "lsh"
- DYN-SHIFT-RIGHT-U-OP : "rsh"
- DYN-SHIFT-RIGHT-S-OP : "arsh"
- CONVERT-U-OP : "arsh"
- CONVERT-S-OP : "mov"
- BIT-AND-OP : "and"
- BIT-NOT-OP : "not"
- BIT-OR-OP : "or"
- BIT-XOR-OP : "xor"
- BIT-XOR-REDUCE-OP : "xorr"
- BIT-AND-REDUCE-OP : "andr"
- BIT-OR-REDUCE-OP : "orr"
- CONCAT-OP : "cat"
- BIT-SELECT-OP : "rsh"
- BITS-SELECT-OP : "rsh"
- else : error $ string-join $ ["Unable to print Primop: " op]
-
-defn sane-width (wd:Width) -> Int :
- match(wd) :
- (w:IntWidth) : max(1, width(w))
- (w) : error(string-join(["Unknown width: " w]))
-
-defn prim-width (type:Type) -> Int :
- match(type) :
- (t:UIntType) : sane-width(width(t))
- (t:SIntType) : sane-width(width(t))
- (t) : error("Bad prim width type")
-
-defn sizeof (in: Int) -> Int :
- max(1, ceil-log2(in + 1))
-
-defn emit-all (es:Streamable, top:Symbol) :
- for e in es do :
- match(e) :
- (ex:Expression) : emit!(ex,top)
- (ex:String) : print(ex)
- (ex:Symbol) : print(ex)
- ;; (ex:Int) : print-all([ex "'" sizeof(ex)])
- (ex:Int) : print(ex)
- (ex) : print(ex)
-
-defn emit! (e:Expression,top:Symbol) :
- defn greater-op? (op: PrimOp) -> True|False :
- contains?([GREATER-OP, GREATER-UU-OP, GREATER-US-OP, GREATER-SU-OP, GREATER-SS-OP], op)
- defn greater-eq-op? (op: PrimOp) -> True|False :
- contains?([GREATER-EQ-OP, GREATER-EQ-UU-OP, GREATER-EQ-US-OP, GREATER-EQ-SU-OP, GREATER-EQ-SS-OP], op)
- defn less-eq-op? (op: PrimOp) -> True|False :
- contains?([LESS-EQ-OP, LESS-EQ-UU-OP, LESS-EQ-US-OP, LESS-EQ-SS-OP, LESS-EQ-SS-OP], op)
- defn less-op? (op: PrimOp) -> True|False :
- contains?([LESS-OP, LESS-UU-OP, LESS-US-OP, LESS-SS-OP, LESS-SS-OP], op)
- defn cmp-op? (op: PrimOp) -> True|False :
- greater-op?(op) or greater-eq-op?(op) or less-op?(op) or less-eq-op?(op) or
- contains?([EQUAL-OP, EQUAL-UU-OP, EQUAL-SS-OP, NEQUAL-OP, NEQUAL-UU-OP, NEQUAL-SS-OP], op)
- match(e) :
- (e:Ref) : emit-all([top "::" name(e)], top)
- (e:UIntValue) : emit-all([value(e) "'" sane-width(width(e))], top)
- (e:SIntValue) : emit-all([value(e) "'" sane-width(width(e))], top)
- (e:Subfield) : emit-all([exp(e) "/" name(e)], top)
- (e:Index) : emit-all([exp(e) "/" value(e)], top)
- (e:Pad) :
- val op-name = match(type(e)) :
- (t:SIntType) : "arsh"
- (u) : "rsh"
- emit-all([op-name "'" prim-width(type(e)) " " value(e) " 0"], top)
- (e:Register) :
- emit-all(["reg'" prim-width(type(e)) " " enable(e) " " value(e)], top)
- (e:ReadPort) :
- emit-all(["rd'" prim-width(type(e)) " " "1" " " mem(e) " " index(e)], top) ;; enable(e)
- (e:DoPrim) :
- if cmp-op?(op(e)) :
- emit-all([flo-op-name(op(e)) "'" prim-width(type(args(e)[0]))], top)
- if greater-op?(op(e)) or greater-eq-op?(op(e)) :
- emit-all([" " args(e)[1] " " args(e)[0]], top)
- else :
- emit-all([" " args(e)[0] " " args(e)[1]], top)
- else if op(e) == CONVERT-U-OP :
- emit-all(["arsh'" prim-width(type(e)) " " args(e)[0] " 0"], top)
- else if op(e) == BIT-SELECT-OP :
- emit-all([flo-op-name(op(e)) "'1 " args(e)[0] " " consts(e)[0]], top)
- else if op(e) == BITS-SELECT-OP :
- val w = consts(e)[0] - consts(e)[1] + 1
- emit-all([flo-op-name(op(e)) "'" w " " args(e)[0] " " consts(e)[1]], top)
- ;; else if op(e) == CONCAT-OP :
- ;; val w = consts(e)[0] - consts(e)[1] + 1
- ;; emit-all([flo-op-name(op(e)) "'" w " " args(e)[0] " " consts(e)[1]], top)
- else :
- emit-all([flo-op-name(op(e)) "'" prim-width(type(e))], top)
- if (op(e) == PAD-U-OP) or (op(e) == PAD-S-OP) :
- emit-all([" " args(e)[0] " " consts(e)[0]], top)
- else :
- for arg in args(e) do :
- print(" ")
- emit!(arg, top)
- for const in consts(e) do :
- print-all([" " const "'" sizeof(const)])
- (e) : error("SHOULDN'T EMIT THIS") ;; print-all(["EMIT(" e ")"])
- ;(e) : emit-all(["mov'" prim-width(type(e)) " " e], top) ;TODO, not sure which one is right
-
-defn maybe-mov (e:Expression) -> String :
- val need-mov? = match(e) :
- (e:Ref) : true
- (e:UIntValue) : true
- (e:SIntValue) : true
- (e:Subfield) : true
- (e:Index) : true
- (e) : false
- if need-mov?: "mov " else: ""
-
-defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol) :
- match(s) :
- (s:DefWire) : ""
- (s:DefInstance) : error("Shouldn't be here")
- (s:DefMemory) :
- val vtype = type(s) as VectorType
- emit-all([top "::" name(s) " = mem'" prim-width(type(vtype)) " " size(vtype) "\n"], top)
- (s:DefNode) :
- if value(s) typeof WritePort :
- val e = value(s) as WritePort
- val n = firrtl-gensym(`F)
- emit-all([top "::" n " = wr'" prim-width(type(e)) " " enable(e) " " mem(e) " " index(e) " " top "::" name(s) "\n"], top)
- else :
- emit-all([top "::" name(s) " = " maybe-mov(value(s)) value(s) "\n"], top)
- (s:Begin) : do(emit-s{_, v, top}, body(s))
- (s:Connect) :
- val n = name(loc(s) as Ref)
- if contains?(v,n) :
- emit-all([top "::" n " = out'" prim-width(type(loc(s))) " " exp(s) "\n"], top)
- else :
- emit-all([top "::" n " = " maybe-mov(exp(s)) exp(s) "\n"], top)
- (s) : s
-
-defn emit-module (m:Module) :
- val v = Vector<Symbol>()
- for port in ports(m) do :
- if name(port) ==`reset :
- emit-all([name(m) "::" name(port) " = rst'1\n"], name(m))
- else : switch {_ == direction(port)} :
- INPUT : print-all([name(m) "::" name(port) " = " "in'" prim-width(type(port)) "\n"])
- OUTPUT : add(v,name(port))
- emit-s(body(m), to-list(v), name(m))
-
-public defn emit-flo (file:String, c:Circuit) :
- with-output-file{file, _} $ fn () :
- emit-module(modules(c)[0])
- false
- c
-
-;============= DRIVER ======================================
-public defn run-passes (c: Circuit, p: List<Char>,file:String) :
- var c*:Circuit = c
- println("Compiling!")
- if PRINT-CIRCUITS : println("Original Circuit")
- if PRINT-CIRCUITS : print(c)
- defn do-stage (name:String, f: Circuit -> Circuit) :
- if PRINT-CIRCUITS : println(name)
- c* = f(c*)
- if PRINT-CIRCUITS : print(c*)
- if PRINT-CIRCUITS : println-all(["Finished " name "\n"])
-
- if contains(p,'X') or contains(p,'A') : do-stage("High Form Check", check-high-form)
- if contains(p,'X') or contains(p,'a') : do-stage("Temp Elimination", temp-elimination)
- if contains(p,'X') or contains(p,'b') : do-stage("Working IR", to-working-ir)
-
- if contains(p,'X') or contains(p,'c') : do-stage("Make Explicit Reset", make-explicit-reset)
-
- if contains(p,'X') or contains(p,'d') : do-stage("Resolve Kinds", resolve-kinds)
- if contains(p,'X') or contains(p,'D') : do-stage("Check Kinds", check-kinds)
-
- if contains(p,'X') or contains(p,'e') : do-stage("Infer Types", infer-types)
- if contains(p,'X') or contains(p,'E') : do-stage("Check Types", check-types)
-
- if contains(p,'X') or contains(p,'f') : do-stage("Resolve Genders", resolve-genders)
- if contains(p,'X') or contains(p,'F') : do-stage("Check Genders", check-genders)
-
- if contains(p,'X') or contains(p,'g') : do-stage("Expand Accessors", expand-accessors) ;mem kind
- if contains(p,'X') or contains(p,'h') : do-stage("Lower To Ground", lower-to-ground) ;inst kind
- if contains(p,'X') or contains(p,'i') : do-stage("Expand Indexed Connects", expand-connect-indexed)
-
-; make sure no bundle types
- if contains(p,'X') or contains(p,'k') : do-stage("Expand Whens", expand-whens) ; requires types, lowering
-
- if contains(p,'X') or contains(p,'l') : do-stage("Infer Widths", infer-widths) ; requires lowering, expand whens
-
- if contains(p,'X') or contains(p,'m') : do-stage("Inline Instances", inline-instances) ;inst kind
-
- if contains(p,'X') or contains(p,'n') : do-stage("Split Expressions", split-exp)
-
- if contains(p,'X') or contains(p,'o') : do-stage("Real IR", to-real-ir)
- if contains(p,'X') or contains(p,'F') : do-stage("To Flo", emit-flo{file,_})
- println("Done!")
diff --git a/src/main/stanza/primop.stanza b/src/main/stanza/primop.stanza
index a06c9b3f..023723b8 100644
--- a/src/main/stanza/primop.stanza
+++ b/src/main/stanza/primop.stanza
@@ -23,348 +23,109 @@ public defn lower-and-type-primop (e:DoPrim) -> DoPrim :
;println-all(["Inferencing primop type: " e])
switch {op(e) == _} :
- ADD-OP :
- DoPrim{_,args(e),consts(e),u-and(args(e)[0],args(e)[1])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : ADD-UU-OP
- (t1:UIntType, t2:SIntType) : ADD-US-OP
- (t1:SIntType, t2:UIntType) : ADD-SU-OP
- (t1:SIntType, t2:SIntType) : ADD-SS-OP
- ADD-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- ADD-US-OP : DoPrim(op(e),args(e),consts(e),s())
- ADD-SU-OP : DoPrim(op(e),args(e),consts(e),s())
- ADD-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- SUB-OP :
- DoPrim{_,args(e),consts(e),s()} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : SUB-UU-OP
- (t1:UIntType, t2:SIntType) : SUB-US-OP
- (t1:SIntType, t2:UIntType) : SUB-SU-OP
- (t1:SIntType, t2:SIntType) : SUB-SS-OP
- SUB-UU-OP : DoPrim(op(e),args(e),consts(e),s())
- SUB-US-OP : DoPrim(op(e),args(e),consts(e),s())
- SUB-SU-OP : DoPrim(op(e),args(e),consts(e),s())
- SUB-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- MUL-OP :
- DoPrim{_,args(e),consts(e),u-and(args(e)[0],args(e)[1])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : MUL-UU-OP
- (t1:UIntType, t2:SIntType) : MUL-US-OP
- (t1:SIntType, t2:UIntType) : MUL-SU-OP
- (t1:SIntType, t2:SIntType) : MUL-SS-OP
- MUL-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- MUL-US-OP : DoPrim(op(e),args(e),consts(e),s())
- MUL-SU-OP : DoPrim(op(e),args(e),consts(e),s())
- MUL-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- DIV-OP :
- DoPrim{_,args(e),consts(e),u-and(args(e)[0],args(e)[1])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : DIV-UU-OP
- (t1:UIntType, t2:SIntType) : DIV-US-OP
- (t1:SIntType, t2:UIntType) : DIV-SU-OP
- (t1:SIntType, t2:SIntType) : DIV-SS-OP
- DIV-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- DIV-US-OP : DoPrim(op(e),args(e),consts(e),s())
- DIV-SU-OP : DoPrim(op(e),args(e),consts(e),s())
- DIV-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- MOD-OP :
- DoPrim{_,args(e),consts(e),of-type(args(e)[0])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : MOD-UU-OP
- (t1:UIntType, t2:SIntType) : MOD-US-OP
- (t1:SIntType, t2:UIntType) : MOD-SU-OP
- (t1:SIntType, t2:SIntType) : MOD-SS-OP
- MOD-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- MOD-US-OP : DoPrim(op(e),args(e),consts(e),u())
- MOD-SU-OP : DoPrim(op(e),args(e),consts(e),s())
- MOD-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- QUO-OP :
- DoPrim{_,args(e),consts(e),u-and(args(e)[0],args(e)[1])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : QUO-UU-OP
- (t1:UIntType, t2:SIntType) : QUO-US-OP
- (t1:SIntType, t2:UIntType) : QUO-SU-OP
- (t1:SIntType, t2:SIntType) : QUO-SS-OP
- QUO-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- QUO-US-OP : DoPrim(op(e),args(e),consts(e),s())
- QUO-SU-OP : DoPrim(op(e),args(e),consts(e),s())
- QUO-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- REM-OP :
- DoPrim{_,args(e),consts(e),of-type(args(e)[1])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : REM-UU-OP
- (t1:UIntType, t2:SIntType) : REM-US-OP
- (t1:SIntType, t2:UIntType) : REM-SU-OP
- (t1:SIntType, t2:SIntType) : REM-SS-OP
- REM-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- REM-US-OP : DoPrim(op(e),args(e),consts(e),s())
- REM-SU-OP : DoPrim(op(e),args(e),consts(e),u())
- REM-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- ADD-WRAP-OP :
- DoPrim{_,args(e),consts(e),u-and(args(e)[0],args(e)[1])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : ADD-WRAP-UU-OP
- (t1:UIntType, t2:SIntType) : ADD-WRAP-US-OP
- (t1:SIntType, t2:UIntType) : ADD-WRAP-SU-OP
- (t1:SIntType, t2:SIntType) : ADD-WRAP-SS-OP
- ADD-WRAP-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- ADD-WRAP-US-OP : DoPrim(op(e),args(e),consts(e),s())
- ADD-WRAP-SU-OP : DoPrim(op(e),args(e),consts(e),s())
- ADD-WRAP-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- SUB-WRAP-OP :
- DoPrim{_,args(e),consts(e),u-and(args(e)[0],args(e)[1])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : SUB-WRAP-UU-OP
- (t1:UIntType, t2:SIntType) : SUB-WRAP-US-OP
- (t1:SIntType, t2:UIntType) : SUB-WRAP-SU-OP
- (t1:SIntType, t2:SIntType) : SUB-WRAP-SS-OP
- SUB-WRAP-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- SUB-WRAP-US-OP : DoPrim(op(e),args(e),consts(e),s())
- SUB-WRAP-SU-OP : DoPrim(op(e),args(e),consts(e),s())
- SUB-WRAP-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- LESS-OP :
- DoPrim{_,args(e),consts(e),u()} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : LESS-UU-OP
- (t1:UIntType, t2:SIntType) : LESS-US-OP
- (t1:SIntType, t2:UIntType) : LESS-SU-OP
- (t1:SIntType, t2:SIntType) : LESS-SS-OP
- LESS-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- LESS-US-OP : DoPrim(op(e),args(e),consts(e),u())
- LESS-SU-OP : DoPrim(op(e),args(e),consts(e),u())
- LESS-SS-OP : DoPrim(op(e),args(e),consts(e),u())
- LESS-EQ-OP :
- DoPrim{_,args(e),consts(e),u()} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : LESS-EQ-UU-OP
- (t1:UIntType, t2:SIntType) : LESS-EQ-US-OP
- (t1:SIntType, t2:UIntType) : LESS-EQ-SU-OP
- (t1:SIntType, t2:SIntType) : LESS-EQ-SS-OP
- LESS-EQ-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- LESS-EQ-US-OP : DoPrim(op(e),args(e),consts(e),u())
- LESS-EQ-SU-OP : DoPrim(op(e),args(e),consts(e),u())
- LESS-EQ-SS-OP : DoPrim(op(e),args(e),consts(e),u())
- GREATER-OP :
- DoPrim{_,args(e),consts(e),u()} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : GREATER-UU-OP
- (t1:UIntType, t2:SIntType) : GREATER-US-OP
- (t1:SIntType, t2:UIntType) : GREATER-SU-OP
- (t1:SIntType, t2:SIntType) : GREATER-SS-OP
- GREATER-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- GREATER-US-OP : DoPrim(op(e),args(e),consts(e),u())
- GREATER-SU-OP : DoPrim(op(e),args(e),consts(e),u())
- GREATER-SS-OP : DoPrim(op(e),args(e),consts(e),u())
- GREATER-EQ-OP :
- DoPrim{_,args(e),consts(e),u()} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : GREATER-EQ-UU-OP
- (t1:UIntType, t2:SIntType) : GREATER-EQ-US-OP
- (t1:SIntType, t2:UIntType) : GREATER-EQ-SU-OP
- (t1:SIntType, t2:SIntType) : GREATER-EQ-SS-OP
- GREATER-EQ-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- GREATER-EQ-US-OP : DoPrim(op(e),args(e),consts(e),u())
- GREATER-EQ-SU-OP : DoPrim(op(e),args(e),consts(e),u())
- GREATER-EQ-SS-OP : DoPrim(op(e),args(e),consts(e),u())
- EQUAL-OP :
- DoPrim{_,args(e),consts(e),u()} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : EQUAL-UU-OP
- (t1:SIntType, t2:SIntType) : EQUAL-SS-OP
- EQUAL-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- EQUAL-SS-OP : DoPrim(op(e),args(e),consts(e),u())
- NEQUAL-OP :
- DoPrim{_,args(e),consts(e),u()} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType, t2:UIntType) : NEQUAL-UU-OP
- (t1:SIntType, t2:SIntType) : NEQUAL-SS-OP
- NEQUAL-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- NEQUAL-SS-OP : DoPrim(op(e),args(e),consts(e),u())
- MUX-OP :
- DoPrim{_,args(e),consts(e),of-type(args(e)[1])} $
- match(type(args(e)[1]),type(args(e)[2])) :
- (t1:UIntType, t2:UIntType) : MUX-UU-OP
- (t1:SIntType, t2:SIntType) : MUX-SS-OP
- (t1,t2) : error(to-string(args(e)))
- MUX-UU-OP : DoPrim(op(e),args(e),consts(e),u())
- MUX-SS-OP : DoPrim(op(e),args(e),consts(e),s())
- PAD-OP :
- DoPrim{_,args(e),consts(e),of-type(args(e)[0])} $
- match(type(args(e)[0])) :
- (t1:UIntType) : PAD-U-OP
- (t1:SIntType) : PAD-S-OP
- PAD-U-OP : DoPrim(op(e),args(e),consts(e),u())
- PAD-S-OP : DoPrim(op(e),args(e),consts(e),s())
- AS-UINT-OP :
- DoPrim{_,args(e),consts(e),u()} $
- match(type(args(e)[0])) :
- (t1:UIntType) : AS-UINT-U-OP
- (t1:SIntType) : AS-UINT-S-OP
- AS-UINT-U-OP : DoPrim(op(e),args(e),consts(e),u())
- AS-UINT-S-OP : DoPrim(op(e),args(e),consts(e),u())
- AS-SINT-OP :
- DoPrim{_,args(e),consts(e),s()} $
- match(type(args(e)[0])) :
- (t1:UIntType) : AS-SINT-U-OP
- (t1:SIntType) : AS-SINT-S-OP
- AS-SINT-U-OP : DoPrim(op(e),args(e),consts(e),s())
- AS-SINT-S-OP : DoPrim(op(e),args(e),consts(e),s())
- DYN-SHIFT-LEFT-OP :
- DoPrim{_,args(e),consts(e),of-type(args(e)[0])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType,t2:UIntType) : DYN-SHIFT-LEFT-U-OP
- (t1:SIntType,t2:UIntType) : DYN-SHIFT-LEFT-S-OP
- DYN-SHIFT-LEFT-U-OP : DoPrim(op(e),args(e),consts(e),u())
- DYN-SHIFT-LEFT-S-OP : DoPrim(op(e),args(e),consts(e),s())
- DYN-SHIFT-RIGHT-OP :
- DoPrim{_,args(e),consts(e),of-type(args(e)[0])} $
- match(type(args(e)[0]),type(args(e)[1])) :
- (t1:UIntType,t2:UIntType) : DYN-SHIFT-RIGHT-U-OP
- (t1:SIntType,t2:UIntType) : DYN-SHIFT-RIGHT-S-OP
- DYN-SHIFT-RIGHT-U-OP : DoPrim(op(e),args(e),consts(e),u())
- DYN-SHIFT-RIGHT-S-OP : DoPrim(op(e),args(e),consts(e),s())
- SHIFT-LEFT-OP :
- DoPrim{_,args(e),consts(e),of-type(args(e)[0])} $
- match(type(args(e)[0])) :
- (t1:UIntType) : SHIFT-LEFT-U-OP
- (t1:SIntType) : SHIFT-LEFT-S-OP
- SHIFT-LEFT-U-OP : DoPrim(op(e),args(e),consts(e),u())
- SHIFT-LEFT-S-OP : DoPrim(op(e),args(e),consts(e),s())
- SHIFT-RIGHT-OP :
- DoPrim{_,args(e),consts(e),of-type(args(e)[0])} $
- match(type(args(e)[0])) :
- (t1:UIntType) : SHIFT-RIGHT-U-OP
- (t1:SIntType) : SHIFT-RIGHT-S-OP
- SHIFT-RIGHT-U-OP : DoPrim(op(e),args(e),consts(e),u())
- SHIFT-RIGHT-S-OP : DoPrim(op(e),args(e),consts(e),s())
- CONVERT-OP :
- DoPrim{_,args(e),consts(e),s()} $
- match(type(args(e)[0])) :
- (t1:UIntType) : CONVERT-U-OP
- (t1:SIntType) : CONVERT-S-OP
- CONVERT-U-OP : DoPrim(op(e),args(e),consts(e),s())
- CONVERT-S-OP : DoPrim(op(e),args(e),consts(e),s())
- NEG-OP :
- DoPrim{_,args(e),consts(e),u()} $
- match(type(args(e)[0])) :
- (t1:UIntType) : NEG-U-OP
- (t1:SIntType) : NEG-S-OP
- NEG-U-OP : DoPrim(op(e),args(e),consts(e),u())
- NEG-S-OP : DoPrim(op(e),args(e),consts(e),u())
- BIT-NOT-OP : DoPrim(op(e),args(e),consts(e),u())
- BIT-AND-OP : DoPrim(op(e),args(e),consts(e),u())
- BIT-OR-OP : DoPrim(op(e),args(e),consts(e),u())
- BIT-XOR-OP : DoPrim(op(e),args(e),consts(e),u())
- CONCAT-OP : DoPrim(op(e),args(e),consts(e),u())
- BIT-SELECT-OP : DoPrim(op(e),args(e),consts(e),u())
- BITS-SELECT-OP : DoPrim(op(e),args(e),consts(e),u())
- BIT-AND-REDUCE-OP: DoPrim(op(e),args(e),consts(e),u())
- BIT-OR-REDUCE-OP : DoPrim(op(e),args(e),consts(e),u())
- BIT-XOR-REDUCE-OP: DoPrim(op(e),args(e),consts(e),u())
+ ADD-OP : DoPrim(ADD-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
+ SUB-OP : DoPrim(SUB-OP,args(e),consts(e),s())
+ MUL-OP : DoPrim(MUL-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
+ DIV-OP : DoPrim(DIV-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
+ MOD-OP : DoPrim(MOD-OP,args(e),consts(e),of-type(args(e)[0]))
+ QUO-OP : DoPrim(QUO-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
+ REM-OP : DoPrim(REM-OP,args(e),consts(e),of-type(args(e)[1]))
+ ADD-WRAP-OP : DoPrim(ADD-WRAP-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
+ SUB-WRAP-OP : DoPrim(SUB-WRAP-OP,args(e),consts(e),u-and(args(e)[0],args(e)[1]))
+ LESS-OP : DoPrim(LESS-OP,args(e),consts(e),u())
+ LESS-EQ-OP : DoPrim(LESS-EQ-OP,args(e),consts(e),u())
+ GREATER-OP : DoPrim(GREATER-OP,args(e),consts(e),u())
+ GREATER-EQ-OP : DoPrim(GREATER-EQ-OP,args(e),consts(e),u())
+ EQUAL-OP : DoPrim(EQUAL-OP,args(e),consts(e),u())
+ NEQUAL-OP : DoPrim(NEQUAL-OP,args(e),consts(e),u())
+ MUX-OP : DoPrim(MUX-OP,args(e),consts(e),of-type(args(e)[1]))
+ PAD-OP : DoPrim(PAD-OP,args(e),consts(e),of-type(args(e)[0]))
+ AS-UINT-OP : DoPrim(AS-UINT-OP,args(e),consts(e),u())
+ AS-SINT-OP : DoPrim(AS-SINT-OP,args(e),consts(e),s())
+ DYN-SHIFT-LEFT-OP : DoPrim(DYN-SHIFT-LEFT-OP,args(e),consts(e),of-type(args(e)[0]))
+ DYN-SHIFT-RIGHT-OP : DoPrim(DYN-SHIFT-RIGHT-OP,args(e),consts(e),of-type(args(e)[0]))
+ SHIFT-LEFT-OP : DoPrim(SHIFT-LEFT-OP,args(e),consts(e),of-type(args(e)[0]))
+ SHIFT-RIGHT-OP : DoPrim(SHIFT-RIGHT-OP,args(e),consts(e),of-type(args(e)[0]))
+ CONVERT-OP : DoPrim(CONVERT-OP,args(e),consts(e),s())
+ NEG-OP : DoPrim(NEG-OP,args(e),consts(e),u())
+ BIT-NOT-OP : DoPrim(op(e),args(e),consts(e),u())
+ BIT-AND-OP : DoPrim(op(e),args(e),consts(e),u())
+ BIT-OR-OP : DoPrim(op(e),args(e),consts(e),u())
+ BIT-XOR-OP : DoPrim(op(e),args(e),consts(e),u())
+ CONCAT-OP : DoPrim(op(e),args(e),consts(e),u())
+ BIT-SELECT-OP : DoPrim(op(e),args(e),consts(e),u())
+ BITS-SELECT-OP : DoPrim(op(e),args(e),consts(e),u())
+ BIT-AND-REDUCE-OP : DoPrim(op(e),args(e),consts(e),u())
+ BIT-OR-REDUCE-OP : DoPrim(op(e),args(e),consts(e),u())
+ BIT-XOR-REDUCE-OP : DoPrim(op(e),args(e),consts(e),u())
public defn primop-gen-constraints (e:DoPrim,v:Vector<WGeq>) -> Type :
- defn all-equal (ls:List<Width>) -> Width :
- if length(ls) == 1 : (ls[0])
- else :
- val m = MaxWidth(ls)
- for (l in ls) do :
- add(v,WGeq(l,m))
- m
+ defn get-max (i0:Int,i1:Int) -> Width : get-max(list(i0,i1))
+ defn get-max (ls:List<Int>) -> Width :
+ MaxWidth $ for i in ls map : width!(args(e)[i])
+ defn all-max () -> Width :
+ MaxWidth $ for x in args(e) map : width!(x)
+
println-all-debug(["Looking at " op(e) " with inputs " args(e)])
- val all-args-not-equal = to-list([MUX-UU-OP,MUX-SS-OP,CONCAT-OP,BIT-AND-OP,BIT-NOT-OP,BIT-OR-OP,BIT-XOR-OP,BIT-AND-REDUCE-OP,BIT-OR-REDUCE-OP,BIT-XOR-REDUCE-OP,AS-UINT-U-OP,AS-UINT-S-OP,AS-SINT-U-OP,AS-SINT-S-OP,DYN-SHIFT-LEFT-U-OP,DYN-SHIFT-LEFT-S-OP,DYN-SHIFT-RIGHT-U-OP,DYN-SHIFT-RIGHT-S-OP])
-
- val w-var = VarWidth(gensym(`w))
- val w* =
- if not contains?(all-args-not-equal,op(e)) :
- val max-args-w = all-equal(map(width!,args(e)))
- switch {op(e) == _} :
- ADD-UU-OP : PlusWidth(max-args-w,IntWidth(1))
- ADD-US-OP : PlusWidth(max-args-w,IntWidth(1))
- ADD-SU-OP : PlusWidth(max-args-w,IntWidth(1))
- ADD-SS-OP : PlusWidth(max-args-w,IntWidth(1))
- SUB-UU-OP : PlusWidth(max-args-w,IntWidth(1))
- SUB-US-OP : PlusWidth(max-args-w,IntWidth(1))
- SUB-SU-OP : PlusWidth(max-args-w,IntWidth(1))
- SUB-SS-OP : PlusWidth(max-args-w,IntWidth(1))
- MUL-UU-OP : PlusWidth(max-args-w,max-args-w)
- MUL-US-OP : PlusWidth(max-args-w,max-args-w)
- MUL-SU-OP : PlusWidth(max-args-w,max-args-w)
- MUL-SS-OP : PlusWidth(max-args-w,max-args-w)
- DIV-UU-OP : max-args-w
- DIV-US-OP : PlusWidth(max-args-w,IntWidth(1))
- DIV-SU-OP : max-args-w
- DIV-SS-OP : PlusWidth(max-args-w,IntWidth(1))
- ADD-WRAP-UU-OP : max-args-w
- ADD-WRAP-US-OP : max-args-w
- ADD-WRAP-SU-OP : max-args-w
- ADD-WRAP-SS-OP : max-args-w
- SUB-WRAP-UU-OP : max-args-w
- SUB-WRAP-US-OP : max-args-w
- SUB-WRAP-SU-OP : max-args-w
- SUB-WRAP-SS-OP : max-args-w
- LESS-UU-OP : IntWidth(1)
- LESS-US-OP : IntWidth(1)
- LESS-SU-OP : IntWidth(1)
- LESS-SS-OP : IntWidth(1)
- LESS-EQ-UU-OP : IntWidth(1)
- LESS-EQ-US-OP : IntWidth(1)
- LESS-EQ-SU-OP : IntWidth(1)
- LESS-EQ-SS-OP : IntWidth(1)
- GREATER-UU-OP : IntWidth(1)
- GREATER-US-OP : IntWidth(1)
- GREATER-SU-OP : IntWidth(1)
- GREATER-SS-OP : IntWidth(1)
- GREATER-EQ-UU-OP : IntWidth(1)
- GREATER-EQ-US-OP : IntWidth(1)
- GREATER-EQ-SU-OP : IntWidth(1)
- GREATER-EQ-SS-OP : IntWidth(1)
- EQUAL-UU-OP : IntWidth(1)
- EQUAL-SS-OP : IntWidth(1)
- NEQUAL-UU-OP : IntWidth(1)
- NEQUAL-SS-OP : IntWidth(1)
- PAD-U-OP : IntWidth(consts(e)[0])
- PAD-S-OP : IntWidth(consts(e)[0])
- NEG-U-OP : PlusWidth(max-args-w,IntWidth(1))
- NEG-S-OP : PlusWidth(max-args-w,IntWidth(1))
- SHIFT-LEFT-U-OP : PlusWidth(max-args-w,IntWidth(consts(e)[0]))
- SHIFT-LEFT-S-OP : PlusWidth(max-args-w,IntWidth(consts(e)[0]))
- SHIFT-RIGHT-U-OP : MinusWidth(max-args-w,IntWidth(consts(e)[0]))
- SHIFT-RIGHT-S-OP : MinusWidth(max-args-w,IntWidth(consts(e)[0]))
- CONVERT-U-OP : PlusWidth(max-args-w,IntWidth(1))
- CONVERT-S-OP : max-args-w
- BIT-SELECT-OP : IntWidth(1)
- BITS-SELECT-OP : IntWidth(consts(e)[0] - consts(e)[1])
- else :
- switch {op(e) == _} :
- MUX-UU-OP :
- add(v,WGeq(width!(args(e)[0]),IntWidth(1)))
- all-equal(List(w-var,tail(map(width!,args(e)))))
- MUX-SS-OP :
- add(v,WGeq(width!(args(e)[0]),IntWidth(1)))
- all-equal(List(w-var,tail(map(width!,args(e)))))
- CONCAT-OP :
- PlusWidth(width!(args(e)[0]),width!(args(e)[1]))
- BIT-NOT-OP : all-equal(List(w-var,map(width!,args(e))))
- BIT-AND-OP : all-equal(List(w-var,map(width!,args(e))))
- BIT-OR-OP : all-equal(List(w-var,map(width!,args(e))))
- BIT-XOR-OP : all-equal(List(w-var,map(width!,args(e))))
- BIT-AND-REDUCE-OP : all-equal(List(w-var,map(width!,args(e))))
- BIT-OR-REDUCE-OP : all-equal(List(w-var,map(width!,args(e))))
- BIT-XOR-REDUCE-OP : all-equal(List(w-var,map(width!,args(e))))
- AS-UINT-U-OP : all-equal(List(w-var,map(width!,args(e))))
- AS-UINT-S-OP : all-equal(List(w-var,map(width!,args(e))))
- AS-SINT-U-OP : all-equal(List(w-var,map(width!,args(e))))
- AS-SINT-S-OP : all-equal(List(w-var,map(width!,args(e))))
- DYN-SHIFT-LEFT-U-OP :
- PlusWidth(width!(args(e)[0]),ExpWidth(width!(args(e)[1])))
- DYN-SHIFT-LEFT-S-OP :
- PlusWidth(width!(args(e)[0]),ExpWidth(width!(args(e)[1])))
- DYN-SHIFT-RIGHT-U-OP : width!(args(e)[0])
- DYN-SHIFT-RIGHT-S-OP : width!(args(e)[0])
+ val w* = switch {op(e) == _} :
+ ADD-OP : PlusWidth(get-max(0,1),IntWidth(1))
+ SUB-OP : PlusWidth(get-max(0,1),IntWidth(1))
+ MUL-OP : PlusWidth(get-max(0,1),get-max(0,1))
+ DIV-OP :
+ match(type(args(e)[0]),type(args(e)[1])) :
+ (t0:UIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
+ (t0:SIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
+ (t0,t1) : width!(args(e)[0])
+ MOD-OP :
+ match(type(args(e)[0]),type(args(e)[1])) :
+ (t0:SIntType,t1:UIntType) : PlusWidth(width!(args(e)[1]),IntWidth(1))
+ (t0,t1) : width!(args(e)[1])
+ QUO-OP :
+ match(type(args(e)[0]),type(args(e)[1])) :
+ (t0:UIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
+ (t0:SIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
+ (t0,t1) : width!(args(e)[0])
+ REM-OP :
+ match(type(args(e)[0]),type(args(e)[1])) :
+ (t0:SIntType,t1:UIntType) : PlusWidth(width!(args(e)[1]),IntWidth(1))
+ (t0,t1) : width!(args(e)[1])
+ ADD-WRAP-OP : get-max(0,1)
+ SUB-WRAP-OP : get-max(0,1)
+ LESS-OP : IntWidth(1)
+ LESS-EQ-OP : IntWidth(1)
+ GREATER-OP : IntWidth(1)
+ GREATER-EQ-OP : IntWidth(1)
+ EQUAL-OP : IntWidth(1)
+ NEQUAL-OP : IntWidth(1)
+ MUX-OP :
+ add(v,WGeq(IntWidth(1),width!(args(e)[0])))
+ add(v,WGeq(width!(args(e)[0]),IntWidth(1)))
+ get-max(1,2)
+ PAD-OP : IntWidth(consts(e)[0])
+ AS-UINT-OP : width!(args(e)[0])
+ AS-SINT-OP : width!(args(e)[0])
+ SHIFT-LEFT-OP : PlusWidth(width!(args(e)[0]),IntWidth(consts(e)[0]))
+ SHIFT-RIGHT-OP : MinusWidth(width!(args(e)[0]),IntWidth(consts(e)[0]))
+ DYN-SHIFT-LEFT-OP : PlusWidth(width!(args(e)[0]),ExpWidth(width!(args(e)[1])))
+ DYN-SHIFT-RIGHT-OP : width!(args(e)[0])
+ CONVERT-OP :
+ match(type(args(e)[0])) :
+ (t0:UIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1))
+ (t0:SIntType) : width!(args(e)[0])
+ NEG-OP : PlusWidth(width!(args(e)[0]),IntWidth(1))
+ BIT-NOT-OP : width!(args(e)[0])
+ BIT-AND-OP : get-max(0,1)
+ BIT-OR-OP : get-max(0,1)
+ BIT-XOR-OP : get-max(0,1)
+ BIT-AND-REDUCE-OP : all-max()
+ BIT-OR-REDUCE-OP : all-max()
+ BIT-XOR-REDUCE-OP : all-max()
+ CONCAT-OP : PlusWidth(width!(args(e)[0]),width!(args(e)[1]))
+ BIT-SELECT-OP : IntWidth(1)
+ BITS-SELECT-OP : IntWidth(consts(e)[0] - consts(e)[1])
- add(v,WGeq(w-var,w*))
match(type(e)) :
- (t:UIntType) : UIntType(w-var)
- (t:SIntType) : SIntType(w-var)
+ (t:UIntType) : UIntType(w*)
+ (t:SIntType) : SIntType(w*)
(t) : error("Shouldn't be here")
diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza
new file mode 100644
index 00000000..20433f0f
--- /dev/null
+++ b/src/main/stanza/verilog.stanza
@@ -0,0 +1,197 @@
+defpackage firrtl/verilog :
+ import core
+ import verse
+ import firrtl/ir-utils
+ import firrtl/ir2
+
+public defstruct Verilog <: Pass :
+ file : String
+public defmethod pass (b:Verilog) -> (Circuit -> Circuit) : emit-verilog{file(b),_}
+public defmethod name (b:Verilog) -> String : "To Verilog"
+public defmethod short-name (b:Verilog) -> String : "To Verilog"
+
+;============ Utilz =============
+defn width! (w:Width) -> Int :
+ match(w) :
+ (w:IntWidth) : width(w)
+ (w) : error("Non-supported width type.")
+
+defn width! (t:Type) -> Int :
+ match(t) :
+ (t:UIntType) : width!(width(t))
+ (t:SIntType) : width!(width(t))
+ (t) : error("Non-supported type.")
+
+defn emit (w:Width) -> String :
+ match(w) :
+ (w:IntWidth) : string-join $ ["[" width(w) ":0]"] ;TODO check if need to special case 0 or 1 width wires
+ (w) : error("Non-supported width type.")
+
+defn get-width (t:Type) -> String :
+ match(t) :
+ (t:UIntType) : emit(width(t))
+ (t:SIntType) : emit(width(t))
+ (t) : error("Non-supported type.")
+
+
+;============ Verilog Backend =============
+
+defn emit (e:Expression) -> String :
+ match(e) :
+ (e:Ref) : to-string $ name(e)
+ (e:UIntValue) : string-join $ [width!(type(e)) "'d" value(e)]
+ (e:SIntValue) : string-join $ [width!(type(e)) "'sd" value(e)]
+ (e:Subfield) : error("Non-supported expression")
+ (e:Index) : error("Non-supported expression")
+ (e:Register) : error("Non-supported expression")
+ (e:ReadPort) : error("Non-supported expression")
+ (e:WritePort) : error("Non-supported expression")
+ (e:DoPrim) : string-join $ switch {_ == op(e)} :
+ ADD-OP : [emit(args(e)[0]) " + " emit(args(e)[1])]
+ SUB-OP : [emit(args(e)[0]) " - " emit(args(e)[1])]
+ MUL-OP : [emit(args(e)[0]) " * " emit(args(e)[1])]
+ DIV-OP : [emit(args(e)[0]) " / " emit(args(e)[1])]
+ MOD-OP : [emit(args(e)[0]) " % " emit(args(e)[1])]
+ QUO-OP : [emit(args(e)[0]) " / " emit(args(e)[1])]
+ REM-OP : [emit(args(e)[0]) " % " emit(args(e)[1])]
+ ADD-WRAP-OP : [emit(args(e)[0]) " + " emit(args(e)[1])]
+ SUB-WRAP-OP : [emit(args(e)[0]) " - " emit(args(e)[1])]
+ LESS-OP : [emit(args(e)[0]) " < " emit(args(e)[1])]
+ LESS-EQ-OP : [emit(args(e)[0]) " <= " emit(args(e)[1])]
+ GREATER-OP : [emit(args(e)[0]) " > " emit(args(e)[1])]
+ GREATER-EQ-OP : [emit(args(e)[0]) " >= " emit(args(e)[1])]
+ NEQUAL-OP : [emit(args(e)[0]) " != " emit(args(e)[1])]
+ EQUAL-OP : [emit(args(e)[0]) " == " emit(args(e)[1])]
+ MUX-OP : [emit(args(e)[0]) " ? " emit(args(e)[1]) " : " emit(args(e)[2])]
+ PAD-OP :
+ val x = args(e)[0]
+ val w = width!(type(x))
+ val diff = consts(e)[0] - w
+ ["{" diff "{" x "[" w - 1 "]}," emit(x)]
+ AS-UINT-OP :
+ ["$unsigned(" emit(args(e)[0]) " "]
+ AS-SINT-OP :
+ ["$signed(" emit(args(e)[0]) " "]
+ DYN-SHIFT-LEFT-OP : [emit(args(e)[0]) " << " emit(args(e)[1])]
+ DYN-SHIFT-RIGHT-OP : [emit(args(e)[0]) " >> " emit(args(e)[1])]
+ SHIFT-LEFT-OP : [emit(args(e)[0]) " << " emit(args(e)[1])]
+ SHIFT-RIGHT-OP : [emit(args(e)[0]) " >> " emit(args(e)[1])]
+ NEG-OP : ["-{" emit(args(e)[0]) "}"]
+ CONVERT-OP :
+ match(type(args(e)[0])) :
+ (t:UIntType) : ["{1'b0," emit(args(e)[0]) "}"]
+ (t:SIntType) : [emit(args(e)[0])]
+ BIT-NOT-OP : ["!" emit(args(e)[0])]
+ BIT-AND-OP : [emit(args(e)[0]) " & " emit(args(e)[1])]
+ BIT-OR-OP : [emit(args(e)[0]) " | " emit(args(e)[1])]
+ BIT-XOR-OP : [emit(args(e)[0]) " ^ " emit(args(e)[1])]
+ CONCAT-OP : ["{" emit(args(e)[0]) "," emit(args(e)[1]) "}"]
+ BIT-SELECT-OP : [emit(args(e)[0]) "[" consts(e)[0] "]"]
+ BITS-SELECT-OP : [emit(args(e)[0]) "[" consts(e)[1] ":" consts(e)[0] "]"]
+ BIT-AND-REDUCE-OP :
+ var v = emit(args(e)[0])
+ for x in tail(args(e)) do :
+ v = concat(v, [" & " emit(x)])
+ v
+ BIT-OR-REDUCE-OP :
+ var v = emit(args(e)[0])
+ for x in tail(args(e)) do :
+ v = concat(v, [" | " emit(x)])
+ v
+ BIT-XOR-REDUCE-OP :
+ var v = emit(args(e)[0])
+ for x in tail(args(e)) do :
+ v = concat(v, [" ^ " emit(x)])
+ v
+
+defn emit-module (m:Module) :
+ val wires = Vector<Streamable>()
+ val regs = Vector<Streamable>()
+ val inits = Vector<Streamable>()
+ val assigns = Vector<Streamable>()
+ val updates = Vector<Streamable>()
+
+ defn emit-s (s:Stmt) :
+ match(s) :
+ (s:DefWire) : add(wires,["wire " get-width(type(s)) " " name(s) ";"])
+ (s:DefInstance) : false ; TODO fix this
+ (s:DefMemory) :
+ val vtype = type(s) as VectorType
+ val innerwidth =
+ add(regs,["reg " get-width(type(vtype)) " " name(s) " [0:" size(vtype) "];"])
+ add(inits,["for (initvar = 0; initvar < " size(vtype) "; initvar = initvar+1)"])
+ add(inits,[name(s) " = {" width!(type(vtype)) "{$random}};"])
+ (s:DefNode) :
+ if value(s) typeof Register :
+ val reg = value(s) as Register
+ add(regs,["reg " get-width(type(reg)) " " name(s) ";"])
+ add(inits,[name(s) " = {" width!(type(reg)) "{$random}};"])
+ add(updates,["if(" emit(enable(reg)) ") begin"])
+ add(updates,[" " name(s) " <= " emit(value(reg)) ";"])
+ add(updates,["end"])
+ else if value(s) typeof ReadPort :
+ val rp = value(s) as ReadPort
+ add(assigns,["assign " name(s) " = " emit(mem(rp)) "[" emit(index(rp)) "];"])
+ else :
+ add(wires,["wire " get-width(type(value(s))) " " name(s) ";"])
+ add(assigns,["assign " name(s) " = " emit(value(s)) ";"])
+ (s:Begin) : do(emit-s, body(s))
+ (s:Connect) :
+ if loc(s) typeof WritePort :
+ val wp = loc(s) as WritePort
+ add(updates,["if(" emit(enable(wp)) ") begin"])
+ add(updates,[" " emit(mem(wp)) "[" emit(index(wp)) "] <= " emit(exp(s)) ";"])
+ add(updates,["end"])
+ else :
+ add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"])
+ (s) : s
+
+ emit-s(body(m))
+
+ ;==== Actually printing module =====
+ val port-indent = " "
+ print-all(["module " name(m) "(input clk, input reset,\n"])
+ for (p in ports(m),i in 1 to false) do :
+ if name(p) !=`reset :
+ var end = ",\n"
+ if length(ports(m)) - 1 == i :
+ end = "\n);\n"
+ switch {_ == direction(p)} :
+ INPUT : print-all([port-indent "input " get-width(type(p)) " " name(p) end])
+ OUTPUT : print-all([port-indent "output " get-width(type(p)) " " name(p) end])
+
+ for w in wires do :
+ print(" ")
+ println-all(w)
+ for r in regs do :
+ print(" ")
+ println-all(r)
+
+ println("`ifndef SYNTHESIS")
+ println(" integer initvar;")
+ println(" initial begin")
+ println(" #0.002;")
+ for i in inits do :
+ print-all(" ")
+ println-all(i)
+ println(" end")
+ println("`endif")
+
+ for a in assigns do :
+ print(" ")
+ println-all(a)
+
+ println(" always @(posedge clk) begin")
+ for u in updates do :
+ print(" ")
+ println-all(u)
+ println(" end")
+
+ println("endmodule")
+
+
+public defn emit-verilog (file:String, c:Circuit) :
+ with-output-file{file, _} $ fn () :
+ for m in modules(c) do :
+ emit-module(m)
+ c