aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/stanza/firrtl-ir.stanza4
-rw-r--r--src/main/stanza/ir-parser.stanza1
-rw-r--r--src/main/stanza/ir-utils.stanza65
-rw-r--r--src/main/stanza/passes.stanza1669
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!")