diff options
| author | jackbackrack | 2015-05-19 16:02:21 -0700 |
|---|---|---|
| committer | jackbackrack | 2015-05-19 16:02:21 -0700 |
| commit | f4edadb530297f4f3e293c81c0d8414f8279b65b (patch) | |
| tree | 643db928ee1a396a2ecbf8477fd3fa6aee9f3927 /src | |
| parent | eb7d0913bd01cffdc2be944c7001721f737b44bf (diff) | |
| parent | 14bb9cda8352388bcd33ba9ca2700805dc51639f (diff) | |
get flo backend running again with no pads and generic operators
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/stanza/compilers.stanza | 74 | ||||
| -rw-r--r-- | src/main/stanza/errors.stanza | 51 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 80 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-test-main.stanza | 38 | ||||
| -rw-r--r-- | src/main/stanza/flo.stanza | 177 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 79 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 117 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 532 | ||||
| -rw-r--r-- | src/main/stanza/primop.stanza | 437 | ||||
| -rw-r--r-- | src/main/stanza/verilog.stanza | 197 |
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 |
