aboutsummaryrefslogtreecommitdiff
path: root/src/main/stanza/flo.stanza
diff options
context:
space:
mode:
authorazidar2015-05-15 16:34:34 -0700
committerazidar2015-05-15 16:34:34 -0700
commit2702e571040e7a07317b79f9c5cfdbd61b9ab2bf (patch)
tree0e5973d175be18851865b712e16871764157889f /src/main/stanza/flo.stanza
parent521a4277bfc1d764dc9ee771c604200525e871cb (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.stanza221
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