diff options
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 4 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 1 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 65 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 1669 |
4 files changed, 732 insertions, 1007 deletions
diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index 402409c0..d9105430 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -81,6 +81,9 @@ 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 @@ -105,6 +108,7 @@ public val SHIFT-RIGHT-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 public val BIT-XOR-OP = new PrimOp diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 491fc22c..d6d33467 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -184,6 +184,7 @@ defsyntax firrtl : operators[`convert] = CONVERT-OP operators[`convert-u] = CONVERT-U-OP operators[`convert-s] = CONVERT-S-OP + operators[`bit-not] = BIT-NOT-OP operators[`bit-and] = BIT-AND-OP operators[`bit-or] = BIT-OR-OP operators[`bit-xor] = BIT-XOR-OP diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 80cd39a7..ae8fdbe9 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -289,31 +289,48 @@ defmethod map (f: Type -> Type, c:Stmt) -> Stmt : (c:DefMemory) : DefRegister(name(c),f(type(c))) (c) : c +public defmulti mapr<?T> (f: Width -> Width, t:?T&Type) -> T +defmethod mapr (f: Width -> Width, t:Type) -> Type : + defn apply-t (t:Type) -> Type : + map{f,_} $ map(apply-t,t) + apply-t(t) + +public defmulti mapr<?T> (f: Width -> Width, s:?T&Stmt) -> T +defmethod mapr (f: Width -> Width, s:Stmt) -> Stmt : + defn apply-t (t:Type) -> Type : mapr(f,t) + defn apply-e (e:Expression) -> Expression : + map{f,_} $ map{apply-t,_} $ map(apply-e,e) + defn apply-s (s:Stmt) -> Stmt : + map{apply-t,_} $ map{apply-e,_} $ map(apply-s,s) + apply-s(s) + + ;================= HELPER FUNCTIONS USING MAP =================== -; These don't work properly.. -;public defmulti do (f:Expression -> ?, e:Expression) -> False -;defmethod do (f:Expression -> ?, e:Expression) -> False : -; for x in e map : -; f(x) -; x -; false -; -;public defmulti do (f:Expression -> ?, s:Stmt) -> False -;defmethod do (f:Expression -> ?, s:Stmt) -> False : -; defn f* (x:Expression) : -; f(x) -; x -; map(f*,s) -; false -; -;public defmulti do (f:Stmt -> ?, s:Stmt) -> False -;defmethod do (f:Stmt -> ?, s:Stmt) -> False : -; defn f* (x:Stmt) : -; f(x) -; x -; map(f*,s) -; false -; +public defmulti do (f:Expression -> ?, e:Expression) -> False +defmethod do (f:Expression -> ?, e:Expression) -> False : + defn f* (x:Expression) : + f(x) + x + map(f*,e) + false + +public defmulti do (f:Expression -> ?, s:Stmt) -> False +defmethod do (f:Expression -> ?, s:Stmt) -> False : + defn f* (x:Expression) : + f(x) + x + map(f*,s) + false + +public defmulti do (f:Stmt -> ?, s:Stmt) -> False +defmethod do (f:Stmt -> ?, s:Stmt) -> False : + defn f* (x:Stmt) : + f(x) + x + map(f*,s) + false + +; Not well defined - usually use dor on fields of a recursive type ;public defmulti dor (f:Expression -> ?, e:Expression) -> False ;defmethod dor (f:Expression -> ?, e:Expression) -> False : ; f(e) diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index f5bd655a..aa940ceb 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -189,7 +189,6 @@ defn any-debug? (e:Expression|Stmt|Type|Port|Field) : (hasGender(e) and PRINT-GENDERS) or (hasType(e) and PRINT-TYPES) or (hasWidth(e) and PRINT-WIDTHS) or - (hasType(e) and PRINT-WIDTHS) or (hasKind(e) and PRINT-KINDS) defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field) : @@ -492,6 +491,7 @@ defn get-primop-rettype (e:DoPrim) -> Type : CONVERT-OP : s() CONVERT-U-OP : s() CONVERT-S-OP : s() + BIT-NOT-OP : u() BIT-AND-OP : u() BIT-OR-OP : u() BIT-XOR-OP : u() @@ -985,7 +985,7 @@ defn expand-connect-indexed (c: Circuit) -> Circuit : ; times. defn initialize-registers (c:Circuit) : - defn to-wire-name (y:Symbol) : to-symbol("~$init" % [y]) + defn to-wire-name (y:Symbol) : symbol-join([ y "$init"]) defn add-when (s:Stmt,h:HashTable<Symbol,Type>) -> Stmt : var inits = List<Stmt>() for kv in h do : @@ -1266,11 +1266,12 @@ defn expand-whens (assign:HashTable<Symbol,SymbolicValue>, add(decs,Connect(ref,reg)) (k:InstanceKind) : val s = stmts[n] as DefInstance - val x = split(to-string(n),'.') + val x = to-symbol(split(to-string(n),'.')[0]) val f = to-symbol(split(to-string(n),'.')[1]) - val ref = WSubfield(module(s),f,bundle-field-type(type(module(s)),f),FEMALE) + val ref = WRef(x,type(module(s)),k,FEMALE) + val sref = WSubfield(ref,f,bundle-field-type(type(module(s)),f),FEMALE) if has-nul?(assign[n]) : println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error - else : add(decs,Connect(ref,to-exp(assign[n]))) + else : add(decs,Connect(sref,to-exp(assign[n]))) (k) : val s = stmts[n] as DefWire val ref = WRef(n,type(s),k,FEMALE) @@ -1433,13 +1434,20 @@ defstruct MinusWidth <: Width : arg1 : Width arg2 : Width defstruct MaxWidth <: Width : - arg1 : Width - arg2 : Width + args : List<Width> + +public defmulti map<?T> (f: Width -> Width, w:?T&Width) -> T +defmethod map (f: Width -> Width, w:Width) -> Width : + match(w) : + (w:MaxWidth) : MaxWidth(map(f,args(w))) + (w:PlusWidth) : PlusWidth(f(arg1(w)),f(arg2(w))) + (w:MinusWidth) : MinusWidth(f(arg1(w)),f(arg2(w))) + (w) : w defmethod print (o:OutputStream, w:VarWidth) : print(o,name(w)) defmethod print (o:OutputStream, w:MaxWidth) : - print-all(o,["max(" arg1(w) "," arg2(w) ")"]) + print-all(o,["max" args(w)]) defmethod print (o:OutputStream, w:PlusWidth) : print-all(o,[ arg1(w) " + " arg2(w)]) defmethod print (o:OutputStream, w:MinusWidth) : @@ -1449,1007 +1457,701 @@ definterface Constraint defstruct WGeq <: Constraint : loc : Width exp : Width -defstruct WEq <: Constraint : - loc : Width - exp : Width defmethod print (o:OutputStream, c:WGeq) : print-all(o,[ loc(c) " >= " exp(c)]) -defmethod print (o:OutputStream, c:WEq) : - print-all(o,[ loc(c) " = " exp(c)]) +defmethod equal? (w1:Width,w2:Width) -> True|False : + match(w1,w2) : + (w1:VarWidth,w2:VarWidth) : name(w1) == name(w2) + (w1:MaxWidth,w2:MaxWidth) : + label<True|False> ret : + if not length(args(w1)) == length(args(w2)) : ret(false) + else : + for w in args(w1) do : + if not contains?(args(w2),w) : ret(false) + ret(true) + (w1:IntWidth,w2:IntWidth) : width(w1) == width(w2) + (w1,w2) : 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 + +; 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 remove-var-widths (c:Circuit) -> Circuit : - -;defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Int> : +defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Int> : + 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) + for g in ls do : + match(loc(g)) : + (w:VarWidth) : + val n = name(w) + if contains?(n,h) : h[n] = MaxWidth(list(exp(g),h[n])) + else : h[n] = exp(g) + (w) : w + h + defn simplify (w:Width) -> Width : + match(map(simplify,w)) : + (w:MaxWidth) : + val v = Vector<Width>() + for w* in args(w) do : + match(w*) : + (w:MaxWidth) : + for x in args(w) do : add(v,x) + (w) : add(v,w) + MaxWidth(unique(v)) + (w) : w + defn substitute (w:Width,h:HashTable<Symbol,Width>) -> Width : + ;println-all(["Substituting for [" w "]"]) + val w* = simplify(w) + ;println-all(["After Simplify: [" w "]"]) + match(map(substitute{_,h},simplify(w))) : + (w:VarWidth) : + ;println("matched varwidth!") + if contains?(name(w),h) : + ;println("Contained!") + ;println-all(["Width: " w]) + ;println-all(["Accessed: " h[name(w)]]) + val t = simplify(substitute(h[name(w)],h)) + ;val t = h[name(w)] + ;println-all(["Width after sub: " t]) + h[name(w)] = t + t + else : w + (w): + ;println-all(["not varwidth!" w]) + w + defn b-sub (w:Width,h:HashTable<Symbol,Width>) -> Width: + match(map(b-sub{_,h},w)) : + (w:VarWidth) : + if key?(h,name(w)) : h[name(w)] + else : w + (w) : w + defn remove-cycle (n:Symbol,w:Width) -> Width : + ;println-all(["Removing cycle for " n " inside " w]) + val w* = match(map(remove-cycle{n,_},w)) : + (w:MaxWidth) : MaxWidth(to-list(filter({_ != VarWidth(n)},args(w)))) + (w) : w + ;println-all(["After removing cycle for " n ", returning " w*]) + w* + defn self-rec? (n:Symbol,w:Width) -> True|False : + var has? = false + defn look (w:Width) -> Width : + match(map(look,w)) : + (w:VarWidth) : if name(w) == n : has? = true + (w) : w + w + look(w) + has? + defn evaluate (h:HashTable<Symbol,Width>) -> HashTable<Symbol,Int> : + 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: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: + ; 1) Continuous Solving (using triangular solving) + ; 2) Remove Cycles + ; 3) Move to solved if not self-recursive + val u = make-unique(l) + println("======== UNIQUE CONSTRAINTS ========") + for x in u do : println(x) + println("====================================") + + val f = HashTable<Symbol,Width>(symbol-hash) + val o = Vector<Symbol>() + for x in u do : + ;println("==== SOLUTIONS TABLE ====") + ;for x in f do : println(x) + ;println("=========================") + + val [n e] = [key(x) value(x)] + + val e-sub = substitute(e,f) + ;println(["Solving " n " => " e]) + ;println(["After Substitute: " n " => " e-sub]) + ;println("==== SOLUTIONS TABLE (Post Substitute) ====") + ;for x in f do : println(x) + ;println("=========================") + val e* = remove-cycle{n,_} $ e-sub + ;println(["After Remove Cycle: " n " => " e*]) + if not self-rec?(n,e*) : + ;println-all(["Not rec!: " n " => " e*]) + ;println-all(["Adding [" n "=>" e* "] to Solutions Table"]) + add(o,n) + f[n] = e* + + ;println("Forward Solved Constraints") + ;for x in f do : println(x) + + ; Backwards Solve + val b = HashTable<Symbol,Width>(symbol-hash) + for i in (length(o) - 1) through 0 by -1 do : + val n = o[i] + ;println-all(["SOLVE BACK: [" n " => " f[n] "]"]) + ;println("==== SOLUTIONS TABLE ====") + ;for x in b do : println(x) + ;println("=========================") + val e* = simplify(b-sub(f[n],b)) + ;println-all(["BACK RETURN: [" n " => " e* "]"]) + b[n] = e* + ;println("==== SOLUTIONS TABLE (Post backsolve) ====") + ;for x in b do : println(x) + ;println("=========================") + + ; Evaluate + val e = evaluate(b) + ;println("Evaluated Constraints") + ;for x in e do : println(x) + e defn width! (t:Type) -> Width : match(t) : (t:UIntType) : width(t) (t:SIntType) : width(t) (t) : error("No width!") -defn prim-width (e:DoPrim,v:Vector<WGeq>) -> Width : - defn e-width (e:Expression) -> Width : width!(type(e)) - defn wpc (l:List<Expression>,c:List<Int>) : PlusWidth(e-width(l[0]),IntWidth(c[0])) - defn wmc (l:List<Expression>,c:List<Int>) : MinusWidth(e-width(l[0]),IntWidth(c[0])) - defn maxw (l:List<Expression>) : MaxWidth(e-width(l[0]),e-width(l[1])) - defn mp1 (l:List<Expression>) : PlusWidth(MaxWidth(e-width(l[0]),e-width(l[1])),IntWidth(1)) - defn sum (l:List<Expression>) : PlusWidth(e-width(l[0]),e-width(l[1])) - switch {op(e) == _} : - ADD-UU-OP : mp1(args(e)) - ADD-US-OP : mp1(args(e)) - ADD-SU-OP : mp1(args(e)) - ADD-SS-OP : mp1(args(e)) - SUB-UU-OP : mp1(args(e)) - SUB-US-OP : mp1(args(e)) - SUB-SU-OP : mp1(args(e)) - SUB-SS-OP : mp1(args(e)) - MUL-UU-OP : sum(args(e)) - MUL-US-OP : sum(args(e)) - MUL-SU-OP : sum(args(e)) - MUL-SS-OP : sum(args(e)) - ;(p:DIV-UU-OP) : - ;(p:DIV-US-OP) : - ;(p:DIV-SU-OP) : - ;(p:DIV-SS-OP) : - ;(p:MOD-UU-OP) : - ;(p:MOD-US-OP) : - ;(p:MOD-SU-OP) : - ;(p:MOD-SS-OP) : - ;(p:QUO-UU-OP) : - ;(p:QUO-US-OP) : - ;(p:QUO-SU-OP) : - ;(p:QUO-SS-OP) : - ;(p:REM-UU-OP) : - ;(p:REM-US-OP) : - ;(p:REM-SU-OP) : - ;(p:REM-SS-OP) : - ADD-WRAP-UU-OP : maxw(args(e)) - ADD-WRAP-US-OP : maxw(args(e)) - ADD-WRAP-SU-OP : maxw(args(e)) - ADD-WRAP-SS-OP : maxw(args(e)) - SUB-WRAP-UU-OP : maxw(args(e)) - SUB-WRAP-US-OP : maxw(args(e)) - SUB-WRAP-SU-OP : maxw(args(e)) - SUB-WRAP-SS-OP : maxw(args(e)) - 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) - MUX-UU-OP : maxw(args(e)) - MUX-SS-OP : maxw(args(e)) - PAD-U-OP : IntWidth(consts(e)[0]) - PAD-S-OP : IntWidth(consts(e)[0]) - AS-UINT-U-OP : e-width(args(e)[0]) - AS-UINT-S-OP : e-width(args(e)[0]) - AS-SINT-U-OP : e-width(args(e)[0]) - AS-SINT-S-OP : e-width(args(e)[0]) - SHIFT-LEFT-U-OP : wpc(args(e),consts(e)) - SHIFT-LEFT-S-OP : wpc(args(e),consts(e)) - SHIFT-RIGHT-U-OP : wmc(args(e),consts(e)) - SHIFT-RIGHT-S-OP : wmc(args(e),consts(e)) - CONVERT-U-OP : PlusWidth(e-width(args(e)[0]),IntWidth(1)) - CONVERT-S-OP : e-width(args(e)[0]) - BIT-AND-OP : maxw(args(e)) - BIT-OR-OP : maxw(args(e)) - BIT-XOR-OP : maxw(args(e)) - CONCAT-OP : sum(args(e)) - BIT-SELECT-OP : IntWidth(1) - BITS-SELECT-OP : IntWidth(consts(e)[0] - consts(e)[1]) - -defn gen-constraints (c:Circuit, m:Module) -> List<WGeq> : - val v = Vector<WGeq>() - val h = HashTable<Symbol,Type>(symbol-hash) - - defn get-width (e:Expression) -> Width : - match(e) : - (e:WRef) : - val [wdec wref] = match(kind(e)) : - (k:InstanceKind) : error("Shouldn't be here") - (k:MemKind) : - [width! $ type $ (h[name(e)] as VectorType), - width! $ type $ (type(e) as VectorType)] - (k) : - [width! $ h[name(e)], - width! $ type(e)] - add(v,WGeq(wdec,wref)) - add(v,WGeq(wref,wdec)) - wdec - (e:WSubfield) : ;assumes only subfields are instances - val wdec = width! $ bundle-field-type(h[name(exp(e) as WRef)],name(e)) - val wref = width! $ bundle-field-type(type(exp(e)),name(e)) - add(v,WGeq(wdec,wref)) - add(v,WGeq(wref,wdec)) - wdec - (e:WIndex) : error("Shouldn't be here") - (e:UIntValue) : width(e) - (e:SIntValue) : width(e) - (e:DoPrim) : prim-width(e,v) - (e:ReadPort|WritePort) : - add(v,WGeq(get-width(enable(e)),IntWidth(1))) - add(v,WGeq(IntWidth(1),get-width(enable(e)))) - get-width(mem(e)) - (e:Register) : - add(v,WGeq(get-width(enable(e)),IntWidth(1))) - add(v,WGeq(IntWidth(1),get-width(enable(e)))) - val w = width!(type(e)) - add(v,WGeq(get-width(value(e)),w)) - add(v,WGeq(w,get-width(value(e)))) - w - defn gen-constraints (s:Stmt) -> Stmt : - match(map(gen-constraints,s)) : - (s:DefWire) : h[name(s)] = type(s) - (s:DefInstance) : h[name(s)] = h[name(module(s) as WRef)] - (s:DefMemory) : h[name(s)] = type(s) - (s:DefNode) : h[name(s)] = type(value(s)) +defn width! (e:Expression) -> Width : width!(type(e)) + +defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Module: + defn prim-type (e:DoPrim,v:Vector<WGeq>) -> Type : + defn add-c (w:Width) -> Type: + val w* = VarWidth(gensym(`w)) + add(v,WGeq(w*,w)) + add(v,WGeq(w,w*)) + match(type(e)) : + (t:UIntType) : UIntType(w*) + (t:SIntType) : SIntType(w*) + (t) : error("Shouldn't be here") + defn wpc (l:List<Expression>,c:List<Int>) : + add-c(PlusWidth(width!(l[0]),IntWidth(c[0]))) + defn wmc (l:List<Expression>,c:List<Int>) : + add-c(MinusWidth(width!(l[0]),IntWidth(c[0]))) + defn maxw (l:List<Expression>) : + add-c(MaxWidth(list(width!(l[0]),width!(l[1])))) + defn cons (ls:List<Expression>) : + val l = width!(ls[0]) + val r = width!(ls[1]) + add(v,WGeq(l,r)) + add(v,WGeq(r,l)) + add-c(l) + add-c(r) + defn mp1 (l:List<Expression>) : + add-c(PlusWidth(MaxWidth(list(width!(l[0]),width!(l[1]))),IntWidth(1))) + defn sum (l:List<Expression>) : + add-c(PlusWidth(width!(l[0]),width!(l[1]))) + + println-all(["Looking at " op(e) " with inputs " args(e)]) + switch {op(e) == _} : + ADD-UU-OP : mp1(args(e)) + ADD-US-OP : mp1(args(e)) + ADD-SU-OP : mp1(args(e)) + ADD-SS-OP : mp1(args(e)) + SUB-UU-OP : mp1(args(e)) + SUB-US-OP : mp1(args(e)) + SUB-SU-OP : mp1(args(e)) + SUB-SS-OP : mp1(args(e)) + MUL-UU-OP : sum(args(e)) + MUL-US-OP : sum(args(e)) + MUL-SU-OP : sum(args(e)) + MUL-SS-OP : sum(args(e)) + ;(p:DIV-UU-OP) : + ;(p:DIV-US-OP) : + ;(p:DIV-SU-OP) : + ;(p:DIV-SS-OP) : + ;(p:MOD-UU-OP) : + ;(p:MOD-US-OP) : + ;(p:MOD-SU-OP) : + ;(p:MOD-SS-OP) : + ;(p:QUO-UU-OP) : + ;(p:QUO-US-OP) : + ;(p:QUO-SU-OP) : + ;(p:QUO-SS-OP) : + ;(p:REM-UU-OP) : + ;(p:REM-US-OP) : + ;(p:REM-SU-OP) : + ;(p:REM-SS-OP) : + ADD-WRAP-UU-OP : maxw(args(e)) + ADD-WRAP-US-OP : maxw(args(e)) + ADD-WRAP-SU-OP : maxw(args(e)) + ADD-WRAP-SS-OP : maxw(args(e)) + SUB-WRAP-UU-OP : maxw(args(e)) + SUB-WRAP-US-OP : maxw(args(e)) + SUB-WRAP-SU-OP : maxw(args(e)) + SUB-WRAP-SS-OP : maxw(args(e)) + LESS-UU-OP : add-c(IntWidth(1)) + LESS-US-OP : add-c(IntWidth(1)) + LESS-SU-OP : add-c(IntWidth(1)) + LESS-SS-OP : add-c(IntWidth(1)) + LESS-EQ-UU-OP : add-c(IntWidth(1)) + LESS-EQ-US-OP : add-c(IntWidth(1)) + LESS-EQ-SU-OP : add-c(IntWidth(1)) + LESS-EQ-SS-OP : add-c(IntWidth(1)) + GREATER-UU-OP : add-c(IntWidth(1)) + GREATER-US-OP : add-c(IntWidth(1)) + GREATER-SU-OP : add-c(IntWidth(1)) + GREATER-SS-OP : add-c(IntWidth(1)) + GREATER-EQ-UU-OP : add-c(IntWidth(1)) + GREATER-EQ-US-OP : add-c(IntWidth(1)) + GREATER-EQ-SU-OP : add-c(IntWidth(1)) + GREATER-EQ-SS-OP : add-c(IntWidth(1)) + EQUAL-UU-OP : add-c(IntWidth(1)) + EQUAL-SS-OP : add-c(IntWidth(1)) + MUX-UU-OP : cons(args(e)) + MUX-SS-OP : cons(args(e)) + PAD-U-OP : add-c(IntWidth(consts(e)[0])) + PAD-S-OP : add-c(IntWidth(consts(e)[0])) + AS-UINT-U-OP : add-c(width!(args(e)[0])) + AS-UINT-S-OP : add-c(width!(args(e)[0])) + AS-SINT-U-OP : add-c(width!(args(e)[0])) + AS-SINT-S-OP : add-c(width!(args(e)[0])) + SHIFT-LEFT-U-OP : wpc(args(e),consts(e)) + SHIFT-LEFT-S-OP : wpc(args(e),consts(e)) + SHIFT-RIGHT-U-OP : wmc(args(e),consts(e)) + SHIFT-RIGHT-S-OP : wmc(args(e),consts(e)) + CONVERT-U-OP : add-c(PlusWidth(width!(args(e)[0]),IntWidth(1))) + CONVERT-S-OP : add-c(width!(args(e)[0])) + BIT-NOT-OP : maxw(args(e)) + BIT-AND-OP : maxw(args(e)) + BIT-OR-OP : maxw(args(e)) + BIT-XOR-OP : maxw(args(e)) + CONCAT-OP : sum(args(e)) + BIT-SELECT-OP : add-c(IntWidth(1)) + BITS-SELECT-OP : add-c(IntWidth(consts(e)[0] - consts(e)[1])) + + defn gen-constraints-s (s:Stmt) -> Stmt : + match(map(gen-constraints-s,s)) : + (s:DefWire) : DefWire(name(s),h[name(s)]) + (s:DefInstance) : DefInstance(name(s),gen-constraints(module(s))) + (s:DefMemory) : DefMemory(name(s),h[name(s)] as VectorType) + (s:DefNode) : DefNode(name(s),gen-constraints(value(s))) (s:Connect) : - add(v,WGeq(get-width(loc(s)),get-width(exp(s)))) - add(v,WGeq(get-width(exp(s)),get-width(loc(s)))) - (s) : "" - s + val l = gen-constraints(loc(s)) + val e = gen-constraints(exp(s)) + add(v,WGeq(width!(type(l)),width!(type(e)))) + add(v,WGeq(width!(type(e)),width!(type(l)))) + Connect(l,e) + (s) : s + + defn gen-constraints (e:Expression) -> Expression : + match(map(gen-constraints,e)) : + (e:WRef) : WRef(name(e),h[name(e)],kind(e),gender(e)) + (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),prim-type(e,v)) + (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)) + (e:UIntValue) : + match(width(e)) : + (w:UnknownWidth) : + val w* = VarWidth(gensym(`w)) + add(v,WGeq(w*,IntWidth(ceil-log2(value(e))))) + UIntValue(value(e),w*) + (w) : e + (e:SIntValue) : + match(width(e)) : + (w:UnknownWidth) : + val w* = VarWidth(gensym(`w)) + add(v,WGeq(w*,IntWidth(1 + ceil-log2(abs(value(e)))))) + SIntValue(value(e),w*) + (w) : e + (e) : e - for m in modules(c) do : - h[name(m)] = BundleType(map(to-field,ports(m))) - for p in ports(m) do : - h[name(p)] = type(p) - gen-constraints(body(m)) - to-list(v) + val ports* = + for p in ports(m) map : Port(name(p),direction(p),h[name(p)]) + Module(name(m),ports*,gen-constraints-s(body(m))) -defn remove-unknown-widths (c:Circuit) -> Circuit : - defn remove-unknown-widths-wid (w:Width) -> Width : - match(w) : - (w:UnknownWidth) : VarWidth(gensym(`w)) +defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTable<Symbol,Type> : + defn build-environment (s:Stmt) -> False : + match(s) : + (s:DefWire) : h[name(s)] = remove-unknowns(type(s)) + (s:DefInstance) : h[name(s)] = h[name(module(s) as WRef)] + (s:DefMemory) : h[name(s)] = remove-unknowns(type(s)) + (s:DefNode) : h[name(s)] = remove-unknowns(type(value(s))) + (s) : false + do(build-environment,s) + for p in ports(m) do : + h[name(p)] = bundle-field-type(h[name(m)],name(p)) + build-environment(body(m)) + h + +defn replace-var-widths (c:Circuit,h:HashTable<Symbol,Int>) -> Circuit : + defn replace-var-widths-w (w:Width) -> Width : + println-all(["REPLACE: " w]) + val w* = match(w) : + (w:VarWidth) : + if key?(h,name(w)) : IntWidth(h[name(w)]) + else: w (w) : w - defn remove-unknown-widths-type (t:Type) -> Type : - map{remove-unknown-widths-wid,_} $ - map(remove-unknown-widths-type,t) - defn remove-unknown-widths-exp (e:Expression) -> Expression : - map{remove-unknown-widths-wid,_} $ - map{remove-unknown-widths-type,_} $ - map(remove-unknown-widths-exp,e) - defn remove-unknown-widths-stmt (s:Stmt) -> Stmt : - map{remove-unknown-widths-type,_} $ - map{remove-unknown-widths-exp,_} $ - map(remove-unknown-widths-stmt,s) + println-all(["WITH: " w*]) + w* + val modules* = for m in modules(c) map : - Module{name(m),_,body(m)} $ + Module{name(m),_,mapr(replace-var-widths-w,body(m))} $ for p in ports(m) map : - Port(name(p),direction(p),remove-unknown-widths-type(type(p))) - - val modules** = for m in modules* map : - Module(name(m),ports(m),remove-unknown-widths-stmt(body(m))) - Circuit(modules**,main(c)) - -defn infer-widths (c:Circuit) -> Circuit : - val c* = remove-unknown-widths(c) - for m in modules(c*) do : - val l = gen-constraints(c*,m) - for x in l do : println(x) - c* - ;val h = solve-constraints(l) - ;replace-var-widths(c*,h) - - - - - - - - - + Port(name(p),direction(p),mapr(replace-var-widths-w,type(p))) + Circuit(modules*,main(c)) - - - - - - - - - - - - - - - - -;;==================== WIDTH INFERENCE ====================== -;defstruct WidthVar <: Width : -; name: Symbol -; -;defmethod print (o:OutputStream, w:WidthVar) : -; print(o, name(w)) -; -;defn width! (t:Type) : -; match(t) : -; (t:UIntType) : width(t) -; (t:SIntType) : width(t) -; (t) : error("No width field.") -; -;defn put-width (t:Type, w:Width) : -; match(t) : -; (t:UIntType) : UIntType(w) -; (t:SIntType) : SIntType(w) -; (t) : t -; -;defn put-width (e:Expression, w:Width) : -; val type* = put-width(type(e), w) -; put-type(e, type*) -; -;defn add-width-vars (t:Type) : -; defn width? (w:Width) : +;defn remove-unknown-widths (c:Circuit) -> Circuit : +; defn remove-unknown-widths-w (w:Width) -> Width : ; match(w) : -; (w:UnknownWidth) : WidthVar(gensym()) +; (w:UnknownWidth) : VarWidth(gensym(`w)) ; (w) : w -; match(t) : -; (t:UIntType) : UIntType(width?(width(t))) -; (t:SIntType) : SIntType(width?(width(t))) -; (t) : map(add-width-vars, t) -; -;defn uint-width (i:Int) : -; var v:Int = i -; var n:Int = 0 -; while v != 0 : -; v = v >> 1 -; n = n + 1 -; IntWidth(n) -; -;defn sint-width (i:Int) : -; if i > 0 : -; val w = uint-width(i) -; IntWidth(width(w) + 1) -; else : -; val w = uint-width(neg(i) - 1) -; IntWidth(width(w) + 1) -; -;defn to-exp (w:Width) : -; match(w) : -; (w:IntWidth) : ELit(width(w)) -; (w:WidthVar) : EVar(name(w)) -; (w) : error $ string-join $ [ -; "Cannot convert " w " to exp."] -; -;defn primop-width (op:PrimOp, ws:List<Width>, ints:List<Int>) -> Exp : -; defn wmax (w1:Width, w2:Width) : -; EMax(to-exp(w1), to-exp(w2)) -; defn wplus (w1:Width, w2:Width) : -; EPlus(to-exp(w1), to-exp(w2)) -; defn wplus (w1:Width, w2:Int) : -; EPlus(to-exp(w1), ELit(w2)) -; defn wminus (w1:Width, w2:Width) : -; EMinus(to-exp(w1), to-exp(w2)) -; defn wminus (w1:Width, w2:Int) : -; EMinus(to-exp(w1), ELit(w2)) -; defn wmax-inc (w1:Width, w2:Width) : -; EPlus(wmax(w1, w2), ELit(1)) -; -; switch {op == _} : -; ADD-OP : wmax-inc(ws[0], ws[1]) -; ADD-WRAP-OP : wmax(ws[0], ws[1]) -; SUB-OP : wmax-inc(ws[0], ws[1]) -; SUB-WRAP-OP : wmax(ws[0], ws[1]) -; MUL-OP : wplus(ws[0], ws[1]) -; DIV-OP : wminus(ws[0], ws[1]) -; MOD-OP : to-exp(ws[1]) -; SHIFT-LEFT-OP : wplus(ws[0], ints[0]) -; SHIFT-RIGHT-OP : wminus(ws[0], ints[0]) -; PAD-OP : ELit(ints[0]) -; BIT-AND-OP : wmax(ws[0], ws[1]) -; BIT-OR-OP : wmax(ws[0], ws[1]) -; BIT-XOR-OP : wmax(ws[0], ws[1]) -; CONCAT-OP : wplus(ws[0], ints[0]) -; BIT-SELECT-OP : ELit(1) -; BITS-SELECT-OP : ELit(ints[0]) -; MUX-OP : wmax(ws[1], ws[2]) -; LESS-OP : ELit(1) -; LESS-EQ-OP : ELit(1) -; GREATER-OP : ELit(1) -; GREATER-EQ-OP : ELit(1) -; EQUAL-OP : ELit(1) -; -;defn put-type (el:Element, t:Type) -> Element : -; match(el) : -; (el:Register) : Register(t, value(el), enable(el)) -; (el:Memory) : Memory(t, writers(el)) -; (el:Node) : Node(t, value(el)) -; (el:Instance) : Instance(t, module(el), ports(el)) -; -;defn generate-constraints (c:Circuit) -> [Circuit, Vector<WConstraint>] : -; ;Constraints -; val cs = Vector<WConstraint>() -; defn new-constraint (Constraint: (Symbol, Exp) -> WConstraint, wvar:Width, width:Width) : -; match(wvar) : -; (wvar:WidthVar) : -; add(cs, Constraint(name(wvar), to-exp(width))) -; (wvar) : -; false -; -; defn to-width (e:Exp) : -; match(e) : -; (e:ELit) : -; IntWidth(width(e)) -; (e:EVar) : -; WidthVar(name(e)) -; (e) : -; val x = gensym() -; add(cs, WidthEqual(x, e)) -; WidthVar(x) -; -; ;Module types -; val mod-types = HashTable<Symbol,Type>(symbol-hash) -; -; defn add-port-vars (m:Module) -> Module : -; val ports* = +; val modules* = for m in modules(c) map : +; Module{name(m),_,body(m)} $ ; for p in ports(m) map : -; val type* = add-width-vars(type(p)) -; Port(name(p), gender(p), type*) -; mod-types[name(m)] = BundleType(ports*) -; Module(name(m), ports*, body(m)) -; -; ;Add Width Variables -; defn add-module-vars (m:Module) -> Module : -; val types = HashTable<Symbol,Type>(symbol-hash) -; for p in ports(m) do : -; types[name(p)] = type(p) -; -; defn infer-exp-width (e:Expression) -> Expression : -; match(map(infer-exp-width, e)) : -; (e:WRef) : -; match(kind(e)) : -; (k:ModuleKind) : put-type(e, mod-types[name(e)]) -; (k) : put-type(e, types[name(e)]) -; (e:WSubfield) : -; val t = bundle-field-type(type(exp(e)), name(e)) -; put-width(e, width!(t)) -; (e:UIntValue) : -; match(width(e)) : -; (w:UnknownWidth) : UIntValue(value(e), uint-width(value(e))) -; (w) : e -; (e:SIntValue) : -; match(width(e)) : -; (w:UnknownWidth) : SIntValue(value(e), sint-width(value(e))) -; (w) : e -; (e:DoPrim) : -; val widths = map(width!{type(_)}, args(e)) -; val w = to-width(primop-width(op(e), widths, consts(e))) -; put-width(e, w) -; (e:ReadPort) : -; val elem-type = type(type(mem(e)) as VectorType) -; put-width(e, width!(elem-type)) -; -; defn infer-comm-width (c:Stmt) : -; match(c) : -; (c:LetRec) : -; ;Add width vars to elements -; var entries*: List<KeyValue<Symbol,Element>> = -; for entry in entries(c) map : -; val el-name = key(entry) -; key(entry) => -; match(value(entry)) : -; (el:Register|Node) : -; put-type(el, add-width-vars(type(el))) -; (el:Memory) : -; el -; (el:Instance) : -; val mod-type = type(infer-exp-width(module(el))) as BundleType -; val type = BundleType $ to-list $ -; for p in ports(mod-type) filter : -; gender(p) == OUTPUT -; put-type(el, type) -; -; ;Add vars to environment -; for entry in entries* do : -; types[key(entry)] = type(value(entry)) -; -; ;Infer types for elements -; entries* = -; for entry in entries* map : -; key(entry) => map(infer-exp-width, value(entry)) -; -; ;Generate constraints -; for entry in entries* do : -; val el-name = key(entry) -; match(value(entry)) : -; (el:Register) : -; new-constraint(WidthEqual, reg-width, val-width) where : -; val reg-width = width!(types[el-name]) -; val val-width = width!(type(value(el))) -; (el:Node) : -; new-constraint(WidthEqual, node-width, val-width) where : -; val node-width = width!(types[el-name]) -; val val-width = width!(type(value(el))) -; (el:Instance) : -; val mod-type = type(module(el)) as BundleType -; for entry in ports(el) do : -; new-constraint(WidthGreater, port-width, val-width) where : -; val port-name = key(entry) -; val port-width = width!(bundle-field-type(mod-type, port-name)) -; val val-width = width!(type(value(entry))) -; (el) : false -; -; ;Analyze body -; LetRec(entries*, infer-comm-width(body(c))) -; -; (c:Connect) : -; val loc* = infer-exp-width(loc(c)) -; val exp* = infer-exp-width(exp(c)) -; new-constraint(WidthGreater, loc-width, exp-width) where : -; val loc-width = width!(type(loc*)) -; val exp-width = width!(type(exp*)) -; Connect(loc*, exp*) -; -; (c:Begin) : -; map(infer-comm-width, c) -; -; Module(name(m), ports(m), body*) where : -; val body* = infer-comm-width(body(m)) -; -; val c* = -; Circuit(modules*, main(c)) where : -; val ms = map(add-port-vars, modules(c)) -; val modules* = map(add-module-vars, ms) -; [c*, cs] -; +; Port(name(p),direction(p),mapr(remove-unknown-widths-w,type(p))) ; -;;================== FILL WIDTHS ============================ -;defn fill-widths (c:Circuit, solved:Streamable<WidthEqual>) : -; ;Populate table -; val table = HashTable<Symbol, Width>(symbol-hash) -; for eq in solved do : -; table[name(eq)] = IntWidth(width(value(eq) as ELit)) -; -; defn width? (w:Width) : -; match(w) : -; (w:WidthVar) : get?(table, name(w), UnknownWidth()) -; (w) : w -; -; defn fill-type (t:Type) : -; match(t) : -; (t:UIntType) : UIntType(width?(width(t))) -; (t:SIntType) : SIntType(width?(width(t))) -; (t) : map(fill-type, t) -; -; defn fill-exp (e:Expression) -> Expression : -; val e* = map(fill-exp, e) -; val type* = fill-type(type(e)) -; put-type(e*, type*) -; -; defn fill-element (e:Element) : -; val e* = map(fill-exp, e) -; val type* = fill-type(type(e)) -; put-type(e*, type*) -; -; defn fill-comm (c:Stmt) : -; match(c) : -; (c:LetRec) : -; val entries* = -; for e in entries(c) map : -; key(e) => fill-element(value(e)) -; LetRec(entries*, fill-comm(body(c))) -; (c) : -; map{fill-comm, _} $ -; map(fill-exp, c) -; -; defn fill-port (p:Port) : -; Port(name(p), gender(p), fill-type(type(p))) -; -; defn fill-mod (m:Module) : -; Module(name(m), ports*, body*) where : -; val ports* = map(fill-port, ports(m)) -; val body* = fill-comm(body(m)) -; -; Circuit(modules*, main(c)) where : -; val modules* = map(fill-mod, modules(c)) -; -; -;;=============== TYPE INFERENCE DRIVER ===================== -;defn infer-widths (c:Circuit) : -; val [c*, cs] = generate-constraints(c) -; val solved = solve-widths(cs) -; fill-widths(c*, solved) -; -; -;;================ PAD WIDTHS =============================== -;defn pad-widths (c:Circuit) : -; ;Pad an expression to the given width -; defn pad-exp (e:Expression, w:Int) : -; match(type(e)) : -; (t:UIntType|SIntType) : -; val prev-w = width!(t) as IntWidth -; if width(prev-w) < w : -; val type* = put-width(t, IntWidth(w)) -; DoPrim(PAD-OP, list(e), list(w), type*) -; else : -; e -; (t) : -; e -; -; defn pad-exp (e:Expression, w:Width) : -; val w-value = width(w as IntWidth) -; pad-exp(e, w-value) -; -; ;Convenience -; defn max-width (es:Streamable<Expression>) : -; defn int-width (e:Expression) : -; width(width!(type(e)) as IntWidth) -; maximum(stream(int-width, es)) -; -; defn match-widths (es:List<Expression>) : -; val w = max-width(es) -; map(pad-exp{_, w}, es) -; -; ;Match widths for an expression -; defn match-exp-width (e:Expression) : -; match(map(match-exp-width, e)) : -; (e:DoPrim) : -; if contains?([BIT-AND-OP, BIT-OR-OP, BIT-XOR-OP, EQUAL-OP], op(e)) : -; val args* = match-widths(args(e)) -; DoPrim(op(e), args*, consts(e), type(e)) -; else if op(e) == MUX-OP : -; val args* = List(head(args(e)), match-widths(tail(args(e)))) -; DoPrim(op(e), args*, consts(e), type(e)) -; else : -; e -; (e) : e -; -; defn match-element-width (e:Element) : -; match(map(match-exp-width, e)) : -; (e:Register) : -; val w = width!(type(e)) -; val value* = pad-exp(value(e), w) -; Register(type(e), value*, enable(e)) -; (e:Memory) : -; val width = width!(type(type(e) as VectorType)) -; val writers* = -; for w in writers(e) map : -; WritePort(index(w), pad-exp(value(w), width), enable(w)) -; Memory(type(e), writers*) -; (e:Node) : -; val w = width!(type(e)) -; val value* = pad-exp(value(e), w) -; Node(type(e), value*) -; (e:Instance) : -; val mod-type = type(module(e)) as BundleType -; val ports* = -; for p in ports(e) map : -; val port-type = bundle-field-type(mod-type, key(p)) -; val port-val = pad-exp(value(p), width!(port-type)) -; key(p) => port-val -; Instance(type(e), module(e), ports*) -; -; ;Match widths for a command -; defn match-comm-width (c:Stmt) : -; match(map(match-exp-width, c)) : -; (c:LetRec) : -; val entries* = -; for e in entries(c) map : -; key(e) => match-element-width(value(e)) -; LetRec(entries*, match-comm-width(body(c))) -; (c:Connect) : -; val w = width!(type(loc(c))) -; val exp* = pad-exp(exp(c), w) -; Connect(loc(c), exp*) -; (c) : -; map(match-comm-width, c) -; -; defn match-mod-width (m:Module) : -; Module(name(m), ports(m), body*) where : -; val body* = match-comm-width(body(m)) -; -; Circuit(modules*, main(c)) where : -; val modules* = map(match-mod-width, modules(c)) -; -; -;;================== INLINING =============================== -;defn inline-instances (c:Circuit) : -; val module-table = HashTable<Symbol,Module>(symbol-hash) -; val inlined? = HashTable<Symbol,True|False>(symbol-hash) -; for m in modules(c) do : -; module-table[name(m)] = m -; inlined?[name(m)] = false -; -; ;Convert a module into a sequence of elements -; defn to-elements (m:Module, -; inst:Symbol, -; port-exps:List<KeyValue<Symbol,Expression>>) -> -; List<KeyValue<Symbol, Element>> : -; defn rename-exp (e:Expression) : -; match(e) : -; (e:WRef) : WRef(prefix(inst, name(e)), type(e), kind(e), dir(e)) -; (e) : map(rename-exp, e) -; -; defn to-elements (c:Stmt) -> List<KeyValue<Symbol,Element>> : -; match(c) : -; (c:LetRec) : -; val entries* = -; for entry in entries(c) map : -; val name* = prefix(inst, key(entry)) -; val element* = map(rename-exp, value(entry)) -; name* => element* -; val body* = to-elements(body(c)) -; append(entries*, body*) -; (c:Connect) : -; val ref = loc(c) as WRef -; val name* = prefix(inst, name(ref)) -; list(name* => Node(type(exp(c)), rename-exp(exp(c)))) -; (c:Begin) : -; map-append(to-elements, body(c)) -; -; val inputs = -; for p in ports(m) map-append : -; if gender(p) == INPUT : -; val port-exp = lookup!(port-exps, name(p)) -; val name* = prefix(inst, name(p)) -; list(name* => Node(type(port-exp), port-exp)) -; else : -; List() -; append(inputs, to-elements(body(m))) -; -; ;Inline all instances in the module -; defn inline-instances (m:Module) : -; defn rename-exp (e:Expression) : -; match(e) : -; (e:WSubfield) : -; val inst-exp = exp(e) as WRef -; val name* = prefix(name(inst-exp), name(e)) -; WRef(name*, type(e), NodeKind(), dir(e)) -; (e) : -; map(rename-exp, e) -; -; defn inline-elems (es:List<KeyValue<Symbol,Element>>) : -; for entry in es map-append : -; match(value(entry)) : -; (el:Instance) : -; val mod-name = name(module(el) as WRef) -; val module = inlined-module(mod-name) -; to-elements(module, key(entry), ports(el)) -; (el) : -; list(entry) -; -; defn inline-comm (c:Stmt) : -; match(map(rename-exp, c)) : -; (c:LetRec) : -; val entries* = inline-elems(entries(c)) -; LetRec(entries*, inline-comm(body(c))) -; (c) : -; map(inline-comm, c) -; -; Module(name(m), ports(m), inline-comm(body(m))) -; -; ;Retrieve the inlined instance of a module -; defn inlined-module (name:Symbol) : -; if inlined?[name] : -; module-table[name] -; else : -; val module* = inline-instances(module-table[name]) -; module-table[name] = module* -; inlined?[name] = true -; module* -; -; ;Return the fully inlined circuit -; val main-module = inlined-module(main(c)) -; Circuit(list(main-module), main(c)) - - -;;;================ UTILITIES ================================ -; -; -; -;defn* root-ref (i:Immediate) : -; match(i) : -; (f:Subfield) : root-ref(imm(f)) -; (ind:Index) : root-ref(imm(ind)) -; (r) : r -; -;;defn lookup<?T> (e: Streamable<KeyValue<Immediate,?T>>, i:Immediate) : -;; for entry in e search : -;; if eqv?(key(entry), i) : -;; value(entry) -;; -;;defn lookup!<?T> (e: Streamable<KeyValue<Immediate,?T>>, i:Immediate) : -;; lookup(e, i) as T -;; -;;============ CHECK IF NAMES ARE UNIQUE ==================== -;defn check-duplicate-symbols (names: Streamable<Symbol>, msg: String) : -; val dict = HashTable<Symbol, True>(symbol-hash) -; for name in names do: -; if key?(dict, name): -; throw $ PassException $ string-join $ -; [msg ": " name] -; else: -; dict[name] = true -; -;defn check-duplicates (t: Type) : -; match(t) : -; (t:BundleType) : -; val names = map(name, ports(t)) -; check-duplicate-symbols{names, string-join(_)} $ -; ["Duplicate port name in bundle "] -; do(check-duplicates{type(_)}, ports(t)) -; (t:VectorType) : -; check-duplicates(type(t)) -; (t) : false -; -;defn check-duplicates (c: Stmt) : -; match(c) : -; (c:DefWire) : check-duplicates(type(c)) -; (c:DefRegister) : check-duplicates(type(c)) -; (c:DefMemory) : check-duplicates(type(c)) -; (c) : do(check-duplicates, children(c)) -; -;defn defined-names (c: Stmt) : -; generate<Symbol> : -; loop(c) where : -; defn loop (c:Stmt) : -; match(c) : -; (c:Stmt&HasName) : yield(name(c)) -; (c) : do(loop, children(c)) -; -;defn check-duplicates (m: Module): -; ;Check all duplicate names in all types in all ports and body -; do(check-duplicates{type(_)}, ports(m)) -; check-duplicates(body(m)) -; -; ;Check all names defined in module -; val names = concat(stream(name, ports(m)), -; defined-names(body(m))) -; check-duplicate-symbols{names, string-join(_)} $ -; ["Duplicate definition name in module " name(m)] -; -;defn check-duplicates (c: Circuit) : -; ;Check all duplicate names in all modules -; do(check-duplicates, modules(c)) -; -; ;Check all defined modules -; val names = stream(name, modules(c)) -; check-duplicate-symbols(names, "Duplicate module name") -; -; - - - - - +; val modules** = for m in modules* map : +; Module(name(m),ports(m),mapr(remove-unknown-widths-w,body(m))) +; Circuit(modules**,main(c)) + +defn remove-unknowns-w (w:Width) -> Width : + match(w) : + (w:UnknownWidth) : VarWidth(gensym(`w)) + (w) : w +defn remove-unknowns (t:Type) -> Type : mapr(remove-unknowns-w,t) +defn infer-widths (c:Circuit) -> Circuit : + defn deepcopy (t:HashTable<Symbol,Type>) -> HashTable<Symbol,Type> : + t0 where : + val t0 = HashTable<Symbol,Type>(symbol-hash) + for x in t do : + t0[key(x)] = value(x) + + ;val c* = remove-unknown-widths(c) + ;println(c*) + val v = Vector<WGeq>() + val ports* = HashTable<Symbol,Type>(symbol-hash) + for m in modules(c) do : + ports*[name(m)] = remove-unknowns(BundleType(map(to-field,ports(m)))) + val modules* = for m in modules(c) map : + println-all(["====== MODULE(" name(m) ") ENV ======"]) + val h = build-environment(c,m,deepcopy(ports*)) + for x in h do: println(x) + println-all(["====================================="]) + val m* = gen-constraints(m,h,v) + println-all(["====== MODULE(" name(m) ") ======"]) + println(m*) + println-all(["====================================="]) + m* + println("======== ALL CONSTRAINTS ========") + for x in v do : println(x) + println("=================================") + val h = solve-constraints(to-list(v)) + println("======== SOLVED CONSTRAINTS ========") + for x in h do : println(x) + println("====================================") + replace-var-widths(Circuit(modules*,main(c)),h) + + +;================= Inline Instances ======================== +; Inlines instances. Assumes module with same name as the +; Circuit is the top level module + +defn inline-instances (c:Circuit) : + val h = HashTable<Symbol,Module>(symbol-hash) + val h-s = HashTable<Symbol,Stmt>(symbol-hash) + defn inline-inst (s:Stmt) -> Stmt : + match(map(inline-inst,s)) : + (s:DefInstance) : + val n = name(module(s) as WRef) + val m = h[n] + val body* = + if key?(h-s,n) : h-s[n] + else : + val v = Vector<Stmt>() + for p in ports(m) do : + add(v,DefWire(name(p),type(p))) + add(v,inline-inst(body(m))) + Begin(to-list(v)) + h-s[n] = body* + rename-s(body*,name(s)) + (s) : map(inline-inst-e,s) + defn inline-inst-e (e:Expression) -> Expression : + match(map(inline-inst-e,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)) + (k:MemKind) : e + (e) : e + 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)) + (k:MemKind) : e + (e) : e + defn rename-s (s:Stmt,n:Symbol) -> Stmt : + map{rename-e{_,n},_} $ match(map(rename-s{_,n},s)) : + (s:DefWire) : DefWire(rename(name(s),n),type(s)) + (s:DefInstance) : error("Shouldn't be here") + (s:DefMemory) : DefMemory(rename(name(s),n),type(s)) + (s:DefNode) : DefNode(rename(name(s),n),value(s)) + (s) : s + for m in modules(c) do : + h[name(m)] = m + val top = (for m in modules(c) find : name(m) == main(c)) as Module + Circuit(list(Module(name(top),ports(top),inline-inst(body(top)))),main(c)) + + +;================= Split Expressions ======================== +; Intended to only work on low firrtl + +defn split-exp (c:Circuit) : + defn split-exp-s (s:Stmt,v:Vector<Stmt>) -> False : + match(s) : + (s:Begin) : + defn f (s:Stmt) -> False: split-exp-s(s,v) + do(f,s) + (s:Conditionally) : error("Shouldn't be here") + (s) : add(v,map(split-exp-e{_,v},s)) + false + defn split-exp-e (e:Expression,v:Vector<Stmt>) -> Expression : + match(map(split-exp-e{_,v},e)): + (e:Subfield|DoPrim|ReadPort|Register|WritePort) : + val n = gensym(`T) + add(v,DefNode(n,e)) + WRef(n,type(e),NodeKind(),UNKNOWN-GENDER) + (e) : e -;;================ CLEANUP COMMANDS ========================= -;defn cleanup (c:Stmt) : -; match(c) : -; (c:Begin) : -; to-command $ generate<Stmt> : -; loop(c) where : -; defn loop (c:Stmt) : -; match(c) : -; (c:Begin) : do(loop, body(c)) -; (c:EmptyStmt) : false -; (c) : yield(cleanup(c)) -; (c) : map(cleanup{_ as Stmt}, c) -; -;defn cleanup (c:Circuit) : -; val modules* = -; for m in modules(c) map : -; map(cleanup, m) -; Circuit(modules*, main(c)) -; + Circuit{_,main(c)} $ + for m in modules(c) map : + val v = Vector<Stmt>() + split-exp-s(body(m),v) + Module(name(m),ports(m),Begin(to-list(v))) +;================= Bring to Real IR ======================== +; Returns a new Circuit with only real IR nodes. +defn to-real-ir (c:Circuit) : + defn to-exp (e:Expression) : + match(map(to-exp,e)) : + (e:WRef) : Ref(name(e), type(e)) + (e:WSubfield) : Subfield(exp(e),name(e),type(e)) + (e:WRegInit) : error("Shouldn't be here") + (e:WIndex) : error("Shouldn't be here") + (e) : e + defn to-stmt (s:Stmt) : + match(map(to-exp,s)) : + (e:WDefAccessor) : error("Shouldn't be here") + (e:ConnectToIndexed) : error("Shouldn't be here") + (e:ConnectFromIndexed) : error("Shouldn't be here") + (e) : map(to-stmt,e) -;;;============= SHIM ======================================== -;;defn shim (i:Immediate) -> Immediate : -;; match(i) : -;; (i:RegData) : -;; Ref(name(i), gender(i), type(i)) -;; (i:InstPort) : -;; val inst = Ref(name(i), UNKNOWN-GENDER, UnknownType()) -;; Subfield(inst, port(i), gender(i), type(i)) -;; (i:Subfield) : -;; val imm* = shim(imm(i)) -;; put-imm(i, imm*) -;; (i) : i -;; -;;defn shim (c:Stmt) -> Stmt : -;; val c* = map(shim{_ as Immediate}, c) -;; map(shim{_ as Stmt}, c*) -;; -;;defn shim (c:Circuit) -> Circuit : -;; val modules* = -;; for m in modules(c) map : -;; Module(name(m), ports(m), shim(body(m))) -;; Circuit(modules*, main(c)) -;; -;;;================== INLINE MODULES ========================= -;;defn cat-name (p: String|Symbol, s: String|Symbol) -> Symbol : -;; if p == "" or p == `this : ;; TODO: REMOVE THIS WHEN `THIS GETS REMOVED -;; to-symbol(s) -;; else if s == `this : ;; TODO: DITTO -;; to-symbol(p) -;; else : -;; symbol-join([p, "/", s]) -;; -;;defn inline-command (c: Stmt, mods: HashTable<Symbol, Module>, prefix: String, cmds: Vector<Stmt>) : -;; defn rename (n: Symbol) -> Symbol : -;; cat-name(prefix, n) -;; defn inline-name (i:Immediate) -> Symbol : -;; match(i) : -;; (r:Ref) : rename(name(r)) -;; (f:Subfield) : cat-name(inline-name(imm(f)), name(f)) -;; (f:Index) : cat-name(inline-name(imm(f)), to-string(value(f))) -;; defn inline-imm (i:Immediate) -> Ref : -;; Ref(inline-name(i), gender(i), type(i)) -;; match(c) : -;; (c:DefUInt) : add(cmds, DefUInt(rename(name(c)), value(c), width(c))) -;; (c:DefSInt) : add(cmds, DefSInt(rename(name(c)), value(c), width(c))) -;; (c:DefWire) : add(cmds, DefWire(rename(name(c)), type(c))) -;; (c:DefRegister) : add(cmds, DefRegister(rename(name(c)), type(c))) -;; (c:DefMemory) : add(cmds, DefMemory(rename(name(c)), type(c), size(c))) -;; (c:DefInstance) : inline-module(mods, mods[name(module(c))], to-string(rename(name(c))), cmds) -;; (c:DoPrim) : add(cmds, DoPrim(rename(name(c)), op(c), map(inline-imm, args(c)), consts(c))) -;; (c:DefAccessor) : add(cmds, DefAccessor(rename(name(c)), inline-imm(source(c)), gender(c), inline-imm(index(c)))) -;; (c:Connect) : add(cmds, Connect(inline-imm(loc(c)), inline-imm(exp(c)))) -;; (c:Begin) : do(inline-command{_, mods, prefix, cmds}, body(c)) -;; (c:EmptyStmt) : c -;; (c) : error("Unsupported command") -;; -;;defn inline-port (p: Port, prefix: String) -> Stmt : -;; DefWire(cat-name(prefix, name(p)), type(p)) -;; -;;defn inline-module (mods: HashTable<Symbol, Module>, mod: Module, prefix: String, cmds: Vector<Stmt>) : -;; do(add{cmds, _}, map(inline-port{_, prefix}, ports(mod))) -;; inline-command(body(mod), mods, prefix, cmds) -;; -;;defn inline-modules (c: Circuit) -> Circuit : -;; val cmds = Vector<Stmt>() -;; val mods = HashTable<Symbol, Module>(symbol-hash) -;; for mod in modules(c) do : -;; mods[name(mod)] = mod -;; val top = mods[main(c)] -;; inline-command(body(top), mods, "", cmds) -;; val main* = Module(name(top), ports(top), Begin(to-list(cmds))) -;; Circuit(list(main*), name(top)) -;; -;; -;;;============= FLO PRINTER ====================================== -;;;;; TODO: -;;;;; not supported gt, lte -;; -;;defn flo-op-name (op:PrimOp) -> String : -;; switch {op == _} : -;; ADD-OP : "add" -;; ADD-MOD-OP : "add" -;; MINUS-OP : "sub" -;; SUB-MOD-OP : "sub" -;; MUL-OP : "mul" ;; todo: signed version -;; DIV-OP : "div" ;; todo: signed version -;; MOD-OP : "mod" ;; todo: signed version -;; SHIFT-LEFT-OP : "lsh" ;; todo: signed version -;; SHIFT-RIGHT-OP : "rsh" -;; PAD-OP : "pad" ;; todo: signed version -;; BIT-AND-OP : "and" -;; BIT-OR-OP : "or" -;; BIT-XOR-OP : "xor" -;; CONCAT-OP : "cat" -;; BIT-SELECT-OP : "rsh" -;; BITS-SELECT-OP : "rsh" -;; LESS-OP : "lt" ;; todo: signed version -;; LESS-EQ-OP : "lte" ;; todo: swap args -;; GREATER-OP : "gt" ;; todo: swap args -;; GREATER-EQ-OP : "gte" ;; todo: signed version -;; EQUAL-OP : "eq" -;; MUX-OP : "mux" -;; else : error $ string-join $ -;; ["Unable to print Primop: " op] -;; -;;defn emit (o:OutputStream, top:Symbol, ports:HashTable<Symbol, Port>, lits:HashTable<Symbol, DefUInt>, elt) : -;; match(elt) : -;; (e:String|Symbol|Int) : -;; print(o, e) -;; (e:Ref) : -;; if key?(lits, name(e)) : -;; val lit = lits[name(e)] -;; print-all(o, [value(lit) "'" width(lit)]) -;; else : -;; if key?(ports, name(e)) : -;; print-all(o, [top "::"]) -;; print(o, name(e)) -;; (e:IntWidth) : -;; print(o, value(e)) -;; (e:PrimOp) : -;; print(o, flo-op-name(e)) -;; (e) : -;; println-all(["EMIT " e]) -;; error("Unable to emit") -;; -;;defn emit-all (o:OutputStream, top:Symbol, ports:HashTable<Symbol, Port>, lits:HashTable<Symbol, DefUInt>, elts: Streamable) : -;; for e in elts do : emit(o, top, ports, lits, e) -;; -;;defn prim-width (type:Type) -> Width : -;; match(type) : -;; (t:UIntType) : width(t) -;; (t:SIntType) : width(t) -;; (t) : error("Bad prim width type") -;; -;;defn emit-command (o:OutputStream, cmd:Stmt, top:Symbol, lits:HashTable<Symbol, DefUInt>, regs:HashTable<Symbol, DefRegister>, accs:HashTable<Symbol, DefAccessor>, ports:HashTable<Symbol, Port>, outs:HashTable<Symbol, Port>) : -;; match(cmd) : -;; (c:DefUInt) : -;; lits[name(c)] = c -;; (c:DefSInt) : -;; emit-all(o, top, ports, lits, [name(c) " = " value(c) "'" width(c) "\n"]) -;; (c:DoPrim) : ;; NEED TO FIGURE OUT WHEN WIDTHS ARE NECESSARY AND EXTRACT -;; emit-all(o, top, ports, lits, [name(c) " = " op(c)]) -;; for arg in args(c) do : -;; print(o, " ") -;; emit(o, top, ports, lits, arg) -;; for const in consts(c) do : -;; print(o, " ") -;; emit(o, top, ports, lits, const) -;; print("\n") -;; (c:DefRegister) : -;; regs[name(c)] = c -;; (c:DefMemory) : -;; emit-all(o, top, ports, lits, [name(c) " : mem'" prim-width(type(c)) " " size(c) "\n"]) -;; (c:DefAccessor) : -;; accs[name(c)] = c -;; (c:Connect) : -;; val dst = name(loc(c) as Ref) -;; val src = name(exp(c) as Ref) -;; if key?(regs, dst) : -;; val reg = regs[dst] -;; emit-all(o, top, ports, lits, [dst " = reg'" prim-width(type(reg)) " 0'" prim-width(type(reg)) " " exp(c) "\n"]) -;; else if key?(accs, dst) : -;; val acc = accs[dst] -;; ;; assert(gender(acc) == OUTPUT) -;; emit-all(o, top, ports, lits, [dst " = wr " source(acc) " " index(acc) " " exp(c) "\n"]) -;; else if key?(outs, dst) : -;; val out = outs[dst] -;; emit-all(o, top, ports, lits, [top "::" dst " = out'" prim-width(type(out)) " " exp(c) "\n"]) -;; else if key?(accs, src) : -;; val acc = accs[src] -;; ;; assert(gender(acc) == INPUT) -;; emit-all(o, top, ports, lits, [dst " = rd " source(acc) " " index(acc) "\n"]) -;; else : -;; emit-all(o, top, ports, lits, [dst " = mov " exp(c) "\n"]) -;; (c:Begin) : -;; do(emit-command{o, _, top, lits, regs, accs, ports, outs}, body(c)) -;; (c:DefWire|EmptyStmt) : -;; print("") -;; (c) : -;; error("Unable to print command") -;; -;;defn emit-module (o:OutputStream, m:Module) : -;; val regs = HashTable<Symbol, DefRegister>(symbol-hash) -;; val accs = HashTable<Symbol, DefAccessor>(symbol-hash) -;; val lits = HashTable<Symbol, DefUInt>(symbol-hash) -;; val outs = HashTable<Symbol, Port>(symbol-hash) -;; val portz = HashTable<Symbol, Port>(symbol-hash) -;; for port in ports(m) do : -;; portz[name(port)] = port -;; if gender(port) == OUTPUT : -;; outs[name(port)] = port -;; else if name(port) == `reset : -;; print-all(o, [name(m) "::reset = rst\n"]) -;; else : -;; print-all(o, [name(m) "::" name(port) " = " "in'" prim-width(type(port)) "\n"]) -;; emit-command(o, body(m), name(m), lits, regs, accs, portz, outs) -;; -;;public defn emit-circuit (o:OutputStream, c:Circuit) : -;; emit-module(o, modules(c)[0]) + Circuit(modules*, main(c)) where : + val modules* = + for m in modules(c) map : + Module(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 : "lte" ;; todo: swap args BROKEN + GREATER-US-OP : "lte" ;; todo: swap args BROKEN + GREATER-SU-OP : "lte" ;; todo: swap args BROKEN + GREATER-SS-OP : "lte" ;; todo: swap args BROKEN + GREATER-EQ-UU-OP : "lt" ;; todo: signed version + GREATER-EQ-US-OP : "lt" ;; todo: signed version + GREATER-EQ-SU-OP : "lt" ;; todo: signed version + GREATER-EQ-SS-OP : "lt" ;; 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 + ;AS-UINT-U-OP : + ;AS-UINT-S-OP : + ;AS-SINT-U-OP : + ;AS-SINT-S-OP : + SHIFT-LEFT-U-OP : "lsh" ;; todo: signed version + SHIFT-LEFT-S-OP : "lsh" ;; todo: signed version + SHIFT-RIGHT-U-OP : "rsh" + SHIFT-RIGHT-S-OP : "rsh" + ;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("Unknown width") + +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 : + ;; if in == 1: 1 else: to-int(ceil(log(in)/log(2))) + max(1, ceil-log2(in)) + +defn emit-all (o:OutputStream, es:Streamable, top:Symbol) : + for e in es do : + match(e) : + (ex:Expression) : emit!(o,e,top) + (ex:String) : print(o, ex) + (ex:Symbol) : print(o, ex) + ;; (ex:Int) : print-all(o, [ex "'" sizeof(ex)]) + (ex:Int) : print(o, ex) + (ex) : print(o, ex) + +defn emit! (o:OutputStream, e:Expression,top:Symbol) : + defn cmp-op? (op: PrimOp) -> True|False : + contains?([EQUAL-OP, NEQUAL-OP, GREATER-OP, LESS-EQ-OP, LESS-OP, GREATER-EQ-OP], op) + match(e) : + (e:Ref) : emit-all(o,[top "::" name(e)], top) + (e:UIntValue) : emit-all(o,[value(e) "'" sane-width(width(e))], top) + (e:SIntValue) : emit-all(o,[value(e) "'" sane-width(width(e))], top) + (e:Subfield) : emit-all(o,[exp(e) "/" name(e)], top) + (e:Index) : emit-all(o,[exp(e) "/" value(e)], top) + (e:Register) : + emit-all(o,["reg'" prim-width(type(e)) " " enable(e) " " value(e)], top) + (e:ReadPort) : + emit-all(o,["rd'" prim-width(type(e)) " " enable(e) " " mem(e) " " index(e)], top) + (e:DoPrim) : + if cmp-op?(op(e)) : + emit-all(o, [flo-op-name(op(e)) "'" prim-width(type(args(e)[0]))], top) + if op(e) == GREATER-OP or op(e) == LESS-EQ-OP : + emit-all(o, [" " args(e)[1] " " args(e)[0]], top) + else : + emit-all(o, [" " args(e)[0] " " args(e)[1]], top) + else if op(e) == BIT-SELECT-OP : + emit-all(o, [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(o, [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(o, [flo-op-name(op(e)) "'" w " " args(e)[0] " " consts(e)[1]], top) + else : + emit-all(o, [flo-op-name(op(e)) "'" prim-width(type(e))], top) + if op(e) == PAD-OP : + emit-all(o, [" " args(e)[0] " 0"], top) + else : + for arg in args(e) do : + print(o, " ") + emit!(o, arg, top) + for const in consts(e) do : + print(o, " ") + print(o, const) + (e) : print-all(o, ["EMIT(" e ")"]) + ;(e) : emit-all(o, ["mov'" prim-width(type(e)) " " e], top) ;TODO, not sure which one is right + +defn emit-s (o:OutputStream, 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(o, [top "::" name(s) " = mem'" prim-width(type(vtype)) " " size(vtype) "\n"], top) + (s:DefNode) : emit-all(o, [top "::" name(s) " = " value(s) "\n"], top) + (s:Begin) : do(emit-s{o, _, v, top}, body(s)) + (s:Connect) : + if loc(s) typeof WritePort : + val e = loc(s) as WritePort + val name = gensym(`F) + emit-all(o, [top "::" name " = wr'" prim-width(type(e)) " " enable(e) " " top "::" mem(e) " " index(e) " " exp(s) "\n"], top) + else : + val n = name(loc(s) as Ref) + if contains?(v,n) : + emit-all(o, [n " = out'" prim-width(type(loc(s))) " " exp(s) "\n"], top) + else : + emit-all(o, [top "::" n " = " exp(s) "\n"], top) + (s) : s + +defn emit-module (o:OutputStream, m:Module) : + val v = Vector<Symbol>() + for port in ports(m) do : + if name(port) ==`reset : + emit-all(o, [name(m) "::" name(port) " = rst'1\n"], name(m)) + else : switch {_ == direction(port)} : + INPUT : print-all(o, [name(m) "::" name(port) " = " "in'" prim-width(type(port)) "\n"]) + OUTPUT : add(v,name(port)) + emit-s(o, body(m), to-list(v), name(m)) + +public defn emit-flo (o:OutputStream, c:Circuit) : + emit-module(o, modules(c)[0]) + c ;============= DRIVER ====================================== public defn run-passes (c: Circuit, p: List<Char>) : @@ -2476,9 +2178,10 @@ public defn run-passes (c: Circuit, p: List<Char>) : if contains(p,'p') : do-stage("Initialize Registers", initialize-registers) if contains(p,'j') : do-stage("Expand Whens", expand-whens) if contains(p,'k') : do-stage("Infer Widths", infer-widths) - ;if contains(p,'n') : do-stage("Pad Widths", pad-widths) - ;if contains(p,'o') : do-stage("Inline Instances", inline-instances) - + if contains(p,'l') : do-stage("Inline Instances", inline-instances) + if contains(p,'m') : do-stage("Split Expressions", split-exp) + if contains(p,'n') : do-stage("Real IR", to-real-ir) + if contains(p,'o') : do-stage("To Flo", emit-flo{STANDARD-OUTPUT,_}) println("Done!") |
