diff options
| author | azidar | 2015-05-15 16:34:34 -0700 |
|---|---|---|
| committer | azidar | 2015-05-15 16:34:34 -0700 |
| commit | 2702e571040e7a07317b79f9c5cfdbd61b9ab2bf (patch) | |
| tree | 0e5973d175be18851865b712e16871764157889f /src/main/stanza/flo.stanza | |
| parent | 521a4277bfc1d764dc9ee771c604200525e871cb (diff) | |
Updated firrtl for its passes to be a bit more modular, and to enable plugging in other backends. Also updated a lot of tests, but not all of them because its annoying.
Diffstat (limited to 'src/main/stanza/flo.stanza')
| -rw-r--r-- | src/main/stanza/flo.stanza | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza new file mode 100644 index 00000000..d98ed0ce --- /dev/null +++ b/src/main/stanza/flo.stanza @@ -0,0 +1,221 @@ +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 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" ;; todo: signed version + PAD-S-OP : "rsh" ;; todo: signed version + NEG-U-OP : "neg" + NEG-S-OP : "neg" + ;AS-UINT-U-OP : + ;AS-UINT-S-OP : + ;AS-SINT-U-OP : + ;AS-SINT-S-OP : + 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 : + ;CONVERT-S-OP : + 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" + 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) : + 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)) "'" 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)) "'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 |
