diff options
| author | azidar | 2015-04-08 11:28:29 -0700 |
|---|---|---|
| committer | azidar | 2015-04-08 11:28:29 -0700 |
| commit | e5b9f6ec710e8573ce262330731bebc7524296e5 (patch) | |
| tree | 1494853a2939b20bb2c671d3c46daa29b76ecec3 /src | |
| parent | d4fdab6950b47379137fce750e4a3a6b262e750d (diff) | |
Finished expand whens. started infer widths. added pdf for people to view
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/stanza/firrtl-test-main.stanza | 1 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 184 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 699 |
3 files changed, 408 insertions, 476 deletions
diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza index e9cff931..f7d84600 100644 --- a/src/main/stanza/firrtl-test-main.stanza +++ b/src/main/stanza/firrtl-test-main.stanza @@ -22,6 +22,7 @@ defn set-printvars! (p:List<Char>) : if contains(p,'t') : PRINT-TYPES = true if contains(p,'k') : PRINT-KINDS = true if contains(p,'w') : PRINT-WIDTHS = true + if contains(p,'T') : PRINT-TWIDTHS = true if contains(p,'g') : PRINT-GENDERS = true if contains(p,'c') : PRINT-CIRCUITS = true diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 0fe5ef5b..5e03ab54 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -254,89 +254,123 @@ defmethod map (f: Stmt -> Stmt, c:Stmt) -> Stmt : (c:Begin) : Begin(map(f, body(c))) (c) : c -;================= HELPER FUNCTIONS USING MAP =================== -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 dor (f:Expression -> ?, e:Expression) -> False -defmethod dor (f:Expression -> ?, e:Expression) -> False : - f(e) - for x in e map : - dor(f,x) - x - false +public defmulti map<?T> (f: Width -> Width, c:?T&Expression) -> T +defmethod map (f: Width -> Width, c:Expression) -> Expression : + match(c) : + (c:UIntValue) : UIntValue(value(c),f(width(c))) + (c:SIntValue) : SIntValue(value(c),f(width(c))) + (c) : c -public defmulti dor (f:Expression -> ?, s:Stmt) -> False -defmethod dor (f:Expression -> ?, s:Stmt) -> False : - defn f* (x:Expression) : - dor(f,x) - x - map(f*,s) - false +public defmulti map<?T> (f: Width -> Width, c:?T&Type) -> T +defmethod map (f: Width -> Width, c:Type) -> Type : + match(c) : + (c:UIntType) : UIntType(f(width(c))) + (c:SIntType) : SIntType(f(width(c))) + (c) : c -public defmulti dor (f:Stmt -> ?, s:Stmt) -> False -defmethod dor (f:Stmt -> ?, s:Stmt) -> False : - f(s) - defn f* (x:Stmt) : - dor(f,x) - x - map(f*,s) - false +public defmulti map<?T> (f: Type -> Type, c:?T&Expression) -> T +defmethod map (f: Type -> Type, c:Expression) -> Expression : + match(c) : + (c:Ref) : Ref(name(c),f(type(c))) + (c:Subfield) : Subfield(exp(c),name(c),f(type(c))) + (c:Index) : Index(exp(c),value(c),f(type(c))) + (c:DoPrim) : DoPrim(op(c),args(c),consts(c),f(type(c))) + (c:ReadPort) : ReadPort(mem(c),index(c),f(type(c)),enable(c)) + (c:WritePort) : WritePort(mem(c),index(c),f(type(c)),enable(c)) + (c:Register) : Register(f(type(c)),value(c),enable(c)) + (c) : c -public defmulti sub-exps (s:Expression|Stmt) -> List<Expression> -defmethod sub-exps (e:Expression) -> List<Expression> : - val l = Vector<Expression>() - defn f (x:Expression) : add(l,x) - do(f,e) - to-list(l) -defmethod sub-exps (e:Stmt) -> List<Expression> : - val l = Vector<Expression>() - defn f (x:Expression) : add(l,x) - do(f,e) - to-list(l) +public defmulti map<?T> (f: Type -> Type, c:?T&Stmt) -> T +defmethod map (f: Type -> Type, c:Stmt) -> Stmt : + match(c) : + (c:DefWire) : DefWire(name(c),f(type(c))) + (c:DefRegister) : DefRegister(name(c),f(type(c))) + (c:DefMemory) : DefRegister(name(c),f(type(c))) + (c) : c -public defmulti sub-stmts (s:Stmt) -> List<Stmt> -defmethod sub-stmts (s:Stmt) : - val l = Vector<Stmt>() - defn f (x:Stmt) : add(l,x) - do(f,s) - to-list(l) +;================= 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 dor (f:Expression -> ?, e:Expression) -> False +;defmethod dor (f:Expression -> ?, e:Expression) -> False : +; f(e) +; for x in e map : +; dor(f,x) +; x +; false +; +;public defmulti dor (f:Expression -> ?, s:Stmt) -> False +;defmethod dor (f:Expression -> ?, s:Stmt) -> False : +; defn f* (x:Expression) : +; dor(f,x) +; x +; map(f*,s) +; false +; +;public defmulti dor (f:Stmt -> ?, s:Stmt) -> False +;defmethod dor (f:Stmt -> ?, s:Stmt) -> False : +; f(s) +; defn f* (x:Stmt) : +; dor(f,x) +; x +; map(f*,s) +; false +; +;public defmulti sub-exps (s:Expression|Stmt) -> List<Expression> +;defmethod sub-exps (e:Expression) -> List<Expression> : +; val l = Vector<Expression>() +; defn f (x:Expression) : add(l,x) +; do(f,e) +; to-list(l) +;defmethod sub-exps (e:Stmt) -> List<Expression> : +; val l = Vector<Expression>() +; defn f (x:Expression) : add(l,x) +; do(f,e) +; to-list(l) +; +;public defmulti sub-stmts (s:Stmt) -> List<Stmt> +;defmethod sub-stmts (s:Stmt) : +; val l = Vector<Stmt>() +; defn f (x:Stmt) : add(l,x) +; do(f,s) +; to-list(l) ;=================== ADAM OPS =============================== public defn split (s:String,c:Char) -> List<String> : - val empty = "" - defn next-word (s:String,i:Int) -> String|False : - if i == length(s) : false - else: - if (s[i] == c): substring(s,0,i) - else: next-word(s,i + 1) - - val next-str = next-word(s,0) - if next-str == false : list() - else if next-str == empty : split(substring(s,1,length(s)),c) + if not contains(to-list(s),c) : list(s) else : - val str = next-str as String - List(str,split(substring(s,length(str)+1,length(s)),c)) + val index = label<Int> ret : + var i = 0 + for c* in to-list(s) do : + if c* == c : ret(i) + else : + i = i + 1 + ret(0) + val h = substring(s,0,index) + val t = substring(s,index + 1,length(s)) + List(h,split(t,c)) public defn contains (l:List<Char>, c:Char) : label<True|False> myret : diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 2c0ad0ec..82187b7e 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -15,16 +15,18 @@ defn PassException (msg:String) : ;=============== WORKING IR ================================ definterface Kind +defstruct WireKind <: Kind defstruct RegKind <: Kind -defstruct AccessorKind <: Kind +defstruct InstanceKind <: Kind +defstruct ReadAccessorKind <: Kind +defstruct WriteAccessorKind <: Kind defstruct PortKind <: Kind -defstruct MemKind <: Kind defstruct NodeKind <: Kind ; All elems except structural memory, wires + +defstruct MemKind <: Kind defstruct ModuleKind <: Kind -defstruct InstanceKind <: Kind defstruct StructuralMemKind <: Kind ; Separate kind because need special treatment -defstruct ReadAccessorKind <: Kind -defstruct WriteAccessorKind <: Kind +defstruct AccessorKind <: Kind public definterface Gender public val MALE = new Gender @@ -150,12 +152,14 @@ defmethod type (exp:SIntValue) -> Type : SIntType(width(exp)) public var PRINT-TYPES : True|False = false public var PRINT-KINDS : True|False = false public var PRINT-WIDTHS : True|False = false +public var PRINT-TWIDTHS : True|False = false public var PRINT-GENDERS : True|False = false public var PRINT-CIRCUITS : True|False = false ;=== Printers === defmethod print (o:OutputStream, k:Kind) : print{o, _} $ match(k) : + (k:WireKind) : "wire" (k:RegKind) : "reg" (k:AccessorKind) : "accessor" (k:PortKind) : "port" @@ -171,7 +175,7 @@ defn hasGender (e:Expression|Stmt|Type|Port|Field) : e typeof WRef|WSubfield|WIndex|WDefAccessor|WRegInit defn hasWidth (e:Expression|Stmt|Type|Port|Field) : - e typeof UIntType|SIntType|UIntValue|SIntValue|WRegInit + e typeof UIntType|SIntType|UIntValue|SIntValue defn hasType (e:Expression|Stmt|Type|Port|Field) : e typeof Ref|Subfield|Index|DoPrim|WritePort|ReadPort|WRef|WSubfield @@ -185,6 +189,7 @@ 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) : @@ -197,6 +202,7 @@ defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field) : if any-debug?(e) : print(o,"@") if PRINT-KINDS and hasKind(e) : print-all(o,["<k:" kind(e as ?) ">"]) if PRINT-TYPES and hasType(e) : print-all(o,["<t:" wipe-width(type(e as ?)) ">"]) + if PRINT-TWIDTHS and hasType(e): print-all(o,["<t:" type(e as ?) ">"]) if PRINT-WIDTHS and hasWidth(e): print-all(o,["<w:" width(e as ?) ">"]) if PRINT-GENDERS and hasGender(e): print-all(o,["<g:" gender(e as ?) ">"]) @@ -241,6 +247,15 @@ defmethod map (f: Expression -> Expression, c:ConnectToIndexed) : defmethod map (f: Expression -> Expression, c:ConnectFromIndexed) : ConnectFromIndexed(f(index(c)), f(loc(c)), map(f, exps(c))) +defmethod map (f: Type -> Type, e: WRef) : + WRef(name(e), f(type(e)), kind(e), gender(e)) +defmethod map (f: Type -> Type, e: WRegInit) : + WRegInit(reg(e), name(e), f(type(e)), gender(e)) +defmethod map (f: Type -> Type, e: WSubfield) : + WSubfield(exp(e), name(e), f(type(e)), gender(e)) +defmethod map (f: Type -> Type, e: WIndex) : + WIndex(exp(e), value(e), f(type(e)), gender(e)) + ;================= Bring to Working IR ======================== ; Returns a new Circuit with Refs, Subfields, Indexes and DefAccessors ; replaced with IR-internal nodes that contain additional @@ -768,7 +783,7 @@ defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) (s:DefNode) : val s* = Begin $ list( DefWire(name(s),type(value(s))), - Connect(WRef(name(s),type(value(s)),NodeKind(),UNKNOWN-GENDER),value(s))) + Connect(WRef(name(s),type(value(s)),NodeKind(),FEMALE),value(s))) lower-stmt(s*) (s:Connect) : Begin{_} $ for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map : @@ -836,7 +851,7 @@ defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) defn get-entries (n:Symbol,t:Type) -> List<KeyValue<WRef,Flip>> : defn uniquify (w:WRef) -> WRef : - val name* = symbol-join([n "#" name(w)]) + val name* = symbol-join([n "$" name(w)]) WRef(name*,type(w),kind(w),gender(w)) match(t) : (t:BundleType) : @@ -953,7 +968,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) : to-symbol("~$init" % [y]) defn add-when (s:Stmt,h:HashTable<Symbol,Type>) -> Stmt : var inits = List<Stmt>() for kv in h do : @@ -1048,6 +1063,7 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False : if value(e1) == value(e2) : match(width(e1), width(e2)) : (w1:IntWidth,w2:IntWidth) : width(w1) == width(w2) + (w1,w2) : false else : false (e1:SIntValue,e2:SIntValue) : if value(e1) == value(e2) : @@ -1055,6 +1071,7 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False : (w1:IntWidth,w2:IntWidth) : width(w1) == width(w2) else : false (e1:WRef,e2:WRef) : name(e1) == name(e2) + ;(e1:DoPrim,e2:DoPrim) : TODO (e1:WRegInit,e2:WRegInit) : reg(e1) == reg(e2) and name(e1) == name(e2) (e1:WSubfield,e2:WSubfield) : name(e1) == name(e2) (e1,e2) : false @@ -1080,7 +1097,10 @@ defn NOT (e1:Expression) -> Expression : defn children (e:Expression) -> List<Expression> : val es = Vector<Expression>() - do(add{es,_},e) + defn f (e:Expression) : + add(es,e) + e + map(f,e) to-list(es) @@ -1137,97 +1157,112 @@ defn optimize (sv:SymbolicValue) -> SymbolicValue : (c:SVExp,a:SVExp) : if exp(c) == one and exp(a) == zero : SVExp(pred(sv)) else if exp(c) == zero and exp(a) == one : SVExp(NOT(pred(sv))) + else if exp(c) == exp(a) : c else : sv (c,a) : sv (sv) : sv ; ========== Expand When Utilz ========== -defstruct SSV : - stmt : Stmt - sv : SymbolicValue - -defmethod print (o:OutputStream, ssv:SSV) : - print-all(o, ["[ {" stmt(ssv) "} :: {" sv(ssv) "} ]"]) -defn new-table () -> HashTable<Symbol,SSV> : HashTable<Symbol,SSV>(symbol-hash) +defn deepcopy (t:HashTable<Symbol,SymbolicValue>) -> HashTable<Symbol,SymbolicValue> : + t0 where : + val t0 = HashTable<Symbol,SymbolicValue>(symbol-hash) + for x in t do : + t0[key(x)] = value(x) +defn get-unique-keys (ts:List<HashTable<Symbol,SymbolicValue>>) -> Vector<Symbol> : + t0 where : + val t0 = Vector<Symbol>() + for v in ts do : + for t in v do : + val duplicate? = for x in t0 any? : x == key(t) + if not duplicate? : add(t0,key(t)) +defn has-nul? (sv:SymbolicValue) -> True|False : + var has? = false + if sv typeof SVNul : has? = true + for x in sv dor : + if x typeof SVNul : has? = true + has? +defn remove-nul (sv:SymbolicValue) -> SymbolicValue : + match(map(remove-nul,sv)) : + (sv:SVMux) : + match(conseq(sv),alt(sv)) : + (c,a:SVNul) : c + (c:SVNul,a) : a + (c,a) : sv + (sv) : sv +defn to-exp (sv:SymbolicValue) -> Expression : + match(remove-nul(sv)) : + (sv:SVMux) : + DoPrim(MUX-UU-OP, + list(pred(sv),to-exp(conseq(sv)),to-exp(alt(sv))), + list(), + UIntType(IntWidth(1))) + (sv:SVExp) : exp(sv) + (sv) : error("Shouldn't be here") +defn reduce-or (l:List<True|False>) -> True|False : + if length(l) == 0 : false + else : head(l) or reduce-or(tail(l)) +defn reduce-or (l:List<Expression>) -> Expression : + if length(l) == 0 : zero + else : OR(head(l) reduce-or(tail(l))) ; ========= Expand When Pass =========== +; TODO: replace stmt with wr (WRefs). The KIND of wref will help figure out what to emit as far as +; declarations, especially with not declaring anything for ports. We need WRefs, and not just Kinds, +; because we need the name of the symbolic expression. I think? Or maybe we can use the key? -defn expand-whens-stmt (table:HashTable<Symbol,SSV>,enables:HashTable<Symbol,SymbolicValue>) -> Stmt : - defn has-nul? (sv:SymbolicValue) -> True|False : - var has? = false - if sv typeof SVNul : has? = true - for x in sv dor : - if x typeof SVNul : has? = true - has? - defn remove-nul (sv:SymbolicValue) -> SymbolicValue : - match(map(remove-nul,sv)) : - (sv:SVMux) : - match(conseq(sv),alt(sv)) : - (c,a:SVNul) : c - (c:SVNul,a) : a - (c,a) : sv - (sv) : sv - defn to-exp (sv:SymbolicValue) -> Expression : - match(remove-nul(sv)) : - (sv:SVMux) : - DoPrim(MUX-UU-OP, - list(pred(sv),to-exp(conseq(sv)),to-exp(alt(sv))), - list(), - UIntType(IntWidth(1))) - (sv:SVExp) : exp(sv) - (sv) : error("Shouldn't be here") +; 1) Build Table, Build Declaration List + +defn expand-whens (assign:HashTable<Symbol,SymbolicValue>, + kinds:HashTable<Symbol,Kind>, + stmts:HashTable<Symbol,Stmt>, + decs:Vector<Stmt>, + enables:HashTable<Symbol,SymbolicValue>) -> Stmt : - val declarations = Vector<Stmt>() - val connections = Vector<Stmt>() - for x in table do : - val [sym ssv] = [key(x) value(x)] - match(stmt(ssv)) : - (s:WDefAccessor) : - val ty = type(type(source(s)) as VectorType) - add(declarations,DefWire(sym,ty)) - switch {_ == gender(s)} : - FEMALE : - add{connections,_} $ - Connect{_,WRef(sym,ty,NodeKind(),MALE)} $ - WritePort(source(s),index(s),ty,to-exp(enables[sym])) - val sv* = remove-nul(sv(ssv)) - if sv* == SVNul : println("Uninitialized: ~" % [to-string(s)]) - else : - add{connections,_} $ - Connect{_,to-exp(sv*)} $ - WRef(name(stmt(ssv) as ?), UnknownType(), NodeKind(), FEMALE) - MALE : - add{connections,_} $ - Connect{WRef(sym,ty,NodeKind(),FEMALE),_} $ - ReadPort(source(s),index(s),ty,to-exp(enables[sym])) - (s:DefRegister) : - val sv* = remove-nul(sv(ssv)) - val exp* = - if sv* typeof SVNul : WRef(sym,type(s),NodeKind(),MALE) - else : to-exp(sv*) - add(declarations,s) - add{connections,_} $ - Connect{WRef(sym,type(s),NodeKind(),FEMALE),_} $ - Register(type(s),exp*,to-exp(enables[sym])) - (s) : - add(declarations,stmt(value(x))) - if has-nul?(sv(ssv)) : println("Uninitialized: ~" % [to-string(s)]);TODO actually collect error - else : - add{connections,_} $ - Connect{_,to-exp(sv(ssv))} $ - WRef(name(stmt(ssv) as ?), UnknownType(), NodeKind(), FEMALE) - - Begin(append(to-list(declarations),to-list(connections))) - -defn get-enables (table:HashTable<Symbol,SSV>) -> HashTable<Symbol,SymbolicValue> : - defn reduce-or (l:List<True|False>) -> True|False : - if length(l) == 0 : false - else : head(l) or reduce-or(tail(l)) - defn reduce-or (l:List<Expression>) -> Expression : - if length(l) == 0 : zero - else : OR(head(l) reduce-or(tail(l))) - + for x in assign do : + val [n sv] = [key(x) value(x)] + match(kinds[n]) : + (k:WriteAccessorKind) : + ;First create WritePort and assign from accessor-turned-wire + val s = stmts[n] as WDefAccessor + val t = type(type(source(s)) as VectorType) + val ref = WRef(n,t,k,MALE) + val wp = WritePort(source(s),index(s),t,to-exp(enables[n])) + add(decs,Connect(wp,ref)) + ;If initialized, assign input to accessor-turned-wire + val sv = remove-nul(assign[n]) + if sv == SVNul : println("Uninitialized: ~" % [to-string(n)]) ;TODO actually collect error + else : add(decs,Connect(ref,to-exp(sv))) + (k:ReadAccessorKind) : + val s = stmts[n] as WDefAccessor + val t = type(type(source(s)) as VectorType) + val ref = WRef(n,t,k,FEMALE) + val rp = ReadPort(source(s),index(s),t,to-exp(enables[n])) + add(decs,Connect(ref,rp)) + (k:RegKind) : + val s = stmts[n] as DefRegister + val ref = WRef(n,type(s),k,FEMALE) + val sv = remove-nul(assign[n]) + val reg = + if sv typeof SVNul : Register(type(s),UIntValue(0,width(type(s) as ?)),zero) + else : Register(type(s),to-exp(sv),to-exp(enables[n])) + add(decs,Connect(ref,reg)) + (k:InstanceKind) : + val s = stmts[n] as DefInstance + val x = split(to-string(n),'.') + val f = to-symbol(split(to-string(n),'.')[1]) + val ref = WSubfield(module(s),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]))) + (k) : + val s = stmts[n] as DefWire + val ref = WRef(n,type(s),k,FEMALE) + if has-nul?(assign[n]) : println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error + else : add(decs,Connect(ref,to-exp(assign[n]))) + Begin(to-list(decs)) + +defn get-enables (assign:HashTable<Symbol,SymbolicValue>, + kinds:HashTable<Symbol,Kind>) -> HashTable<Symbol,SymbolicValue> : defn get-read-enable (sym:Symbol,sv:SymbolicValue) -> Expression : defn active (e:Expression) -> True|False : match(e) : @@ -1253,97 +1288,108 @@ defn get-enables (table:HashTable<Symbol,SSV>) -> HashTable<Symbol,SymbolicValue (sv) : sv val enables = HashTable<Symbol,SymbolicValue>(symbol-hash) - for x in table do : + for x in assign do : val sym = key(x) - match(stmt(value(x))) : - (s:WDefAccessor) : switch {_ == gender(s)} : - FEMALE : enables[sym] = get-write-enable(sv(value(x))) - MALE : enables[sym] = SVExp{_} $ reduce-or{_} $ to-list{_} $ - for y in table stream : - get-read-enable(sym,sv(value(y))) - (s:DefRegister) : enables[sym] = get-write-enable(sv(value(x))) - (s) : s + match(kinds[sym]) : + (k:ReadAccessorKind) : + enables[sym] = SVExp{_} $ reduce-or{_} $ to-list{_} $ + for y in assign stream : + get-read-enable(sym,value(y)) + (k:WriteAccessorKind) : enables[sym] = get-write-enable(value(x)) + (k:RegKind) : enables[sym] = get-write-enable(value(x)) + (k) : k enables - -defn build-table (s:Stmt, table:HashTable<Symbol,SSV>) -> False : - println("=====================") + +defn build-tables (s:Stmt, + assign:HashTable<Symbol,SymbolicValue>, + kinds:HashTable<Symbol,Kind>, + decs:Vector<Stmt>, + stmts:HashTable<Symbol,Stmt>) -> False : match(s) : - (s:DefWire) : table[name(s)] = SSV(s SVNul()) - (s:DefNode) : table[name(s)] = SSV(s SVNul()) - (s:DefRegister) : table[name(s)] = SSV(s SVNul()) - (s:WDefAccessor) : table[name(s)] = SSV(s SVNul()) + (s:DefWire) : + add(decs,s) + kinds[name(s)] = WireKind() + assign[name(s)] = SVNul() + stmts[name(s)] = s + (s:DefNode) : add(decs,s) + (s:DefRegister) : + add(decs,DefWire(name(s),type(s))) + kinds[name(s)] = RegKind() + assign[name(s)] = SVNul() + stmts[name(s)] = s + (s:WDefAccessor) : + add(decs,DefWire(name(s),type(type(source(s)) as VectorType))) + assign[name(s)] = SVNul() + kinds[name(s)] = switch {_ == gender(s)} : + MALE : ReadAccessorKind() + FEMALE : WriteAccessorKind() + stmts[name(s)] = s (s:DefInstance) : + add(decs,s) for f in fields(type(module(s)) as BundleType) do : - table[to-symbol("~.~" % [name(s),name(f)])] = SSV(s SVNul()) - (s:DefMemory) : table[name(s)] = SSV(s SVNul()) + val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs + ;println-all(["In DefInst adding: " n]) + kinds[n] = InstanceKind() + assign[n] = SVNul() + stmts[n] = s + (s:DefMemory) : add(decs,s) (s:Conditionally) : - defn deepcopy (t:HashTable<Symbol,SSV>) -> HashTable<Symbol,SSV> : - t0 where : - val t0 = new-table() - for x in t do : - t0[key(x)] = SSV(stmt(value(x)),sv(value(x))) - defn get (t:HashTable<Symbol,SSV>,i:Symbol) -> SSV|False : - val kv = for x in t find : i == key(x) - match(kv) : - (e:False) : false - (e:KeyValue<Symbol,SSV>) : value(e) - defn get-unique-keys (ts:List<HashTable<Symbol,SSV>>) -> Vector<Symbol> : - t0 where : - val t0 = Vector<Symbol>() - for v in ts do : - for t in v do : - val duplicate? = for x in t0 any? : x == key(t) - if not duplicate? : add(t0,key(t)) - val table-c = deepcopy(table) - val table-a = deepcopy(table) - build-table(conseq(s),table-c) - build-table(alt(s),table-a) - for i in get-unique-keys(list(table-c,table-a)) do : - table[i] = match(get(table-c,i),get(table-a,i)) : - (c:SSV,a:SSV) : SSV(stmt(c),SVMux(pred(s),sv(c),sv(a))) - (c:SSV,a:False) : - if stmt(c) typeof DefWire|DefInstance : - SSV(stmt(c),sv(c)) - else : SSV(stmt(c),SVMux(pred(s),sv(c),SVNul())) - (c:False,a:SSV) : - if stmt(a) typeof DefWire|DefInstance : - SSV(stmt(a),sv(a)) - else : SSV(stmt(a),SVMux(pred(s),SVNul(),sv(a))) + val assign-c = deepcopy(assign) + val assign-a = deepcopy(assign) + build-tables(conseq(s),assign-c,kinds,decs,stmts) + build-tables(alt(s),assign-a,kinds,decs,stmts) + for i in get-unique-keys(list(assign-c,assign-a)) do : + assign[i] = match(get?(assign-c,i,false),get?(assign-a,i,false)) : ;TODO add to syntax highlighting + (c:SymbolicValue,a:SymbolicValue) : SVMux(pred(s),c,a) + (c:SymbolicValue,a:False) : + if kinds[i] typeof WireKind|InstanceKind|NodeKind : c + else : SVMux(pred(s),c,SVNul()) + (c:False,a:SymbolicValue) : + if kinds[i] typeof WireKind|InstanceKind|NodeKind : a + else : SVMux(pred(s),SVNul(),a) (c:False,a:False) : error("Shouldn't be here") - println("TABLE-C") - for x in table-c do : println(x) - println("TABLE-A") - for x in table-a do : println(x) - println("TABLE") - for x in table do : println(x) + ;println("TABLE-C") + ;for x in assign-c do : println(x) + ;println("TABLE-A") + ;for x in assign-a do : println(x) + ;println("TABLE") + ;for x in assign do : println(x) (s:Connect) : val key* = match(loc(s)) : (e:WRef) : name(e) - (e:WSubfield) : to-symbol("~.~" % [name(exp(e) as WRef),name(e)]) + (e:WSubfield) : symbol-join([name(exp(e) as ?) `. name(e)]) (e) : error("Shouldn't be here with ~" % [e]) - table[key*] = SSV(stmt(table[key*]) SVExp(exp(s))); TODO, need to check all references are declared before this point - (s:Begin) : for s* in body(s) do: build-table(s*,table) + assign[key*] = SVExp(exp(s)); TODO, need to check all references are declared before this point + (s:Begin) : for s* in body(s) do: build-tables(s*,assign,kinds,decs,stmts) (s) : false defn expand-whens (m:Module) -> Module : - val table = new-table() - build-table(body(m),table) - val table* = HashTable<Symbol,SSV>(symbol-hash) - for x in table do : table*[key(x)] = SSV(stmt(value(x)) optimize(sv(value(x)))) - val enables = get-enables(table*) - val enables* = HashTable<Symbol,SymbolicValue>(symbol-hash) - for x in enables do : enables*[key(x)] = optimize(value(x)) + val assign = HashTable<Symbol,SymbolicValue>(symbol-hash) + val decs = Vector<Stmt>() + val kinds = HashTable<Symbol,Kind>(symbol-hash) + val stmts = HashTable<Symbol,Stmt>(symbol-hash) + + for p in ports(m) do : + if direction(p) == OUTPUT : + assign[name(p)] = SVNul() + kinds[name(p)] = PortKind() + stmts[name(p)] = DefWire(name(p),type(p)) - println("Original Table") - for x in table do : println(x) - println("Optimized Table") - for x in table* do : println(x) - println("Enable Table") + build-tables(body(m),assign,kinds,decs,stmts) + for x in assign do : assign[key(x)] = optimize(value(x)) + val enables = get-enables(assign,kinds) + for x in enables do : enables[key(x)] = optimize(value(x)) + + println("Assigns") + for x in assign do : println(x) + println("Kinds") + for x in kinds do : println(x) + println("Decs") + for x in decs do : println(x) + println("Enables") for x in enables do : println(x) - println("Optimized Enable Table") - for x in enables* do : println(x) - Module(name(m),ports(m),expand-whens-stmt(table*,enables*)) + Module(name(m),ports(m),expand-whens(assign,kinds,stmts,decs,enables)) defn expand-whens (c:Circuit) -> Circuit : Circuit(modules*, main(c)) where : @@ -1352,248 +1398,100 @@ defn expand-whens (c:Circuit) -> Circuit : expand-whens(m) +;;================ INFER WIDTHS ============================= +; First, you replace all unknown widths with a unique width +; variable. +; Then, you collect all width constraints. +; Then, you solve width constraints. +; Finally, you replace all width variables with the solved +; widths. - -;;================ EXPAND WHENS ============================= -;definterface SymbolicValue -;defstruct ExpValue <: SymbolicValue : -; exp: Expression -;defstruct WhenValue <: SymbolicValue : -; pred: Expression -; conseq: SymbolicValue -; alt: SymbolicValue -;defstruct VoidValue <: SymbolicValue -; -;defmethod print (o:OutputStream, sv:SymbolicValue) : -; match(sv) : -; (sv:VoidValue) : print(o, "VOID") -; (sv:WhenValue) : print-all(o, ["(" pred(sv) "? " conseq(sv) " : " alt(sv) ")"]) -; (sv:ExpValue) : print(o, exp(sv)) -; -;defn key-eqv? (e1:Expression, e2:Expression) : -; match(e1, e2) : -; (e1:WRef, e2:WRef) : -; name(e1) == name(e2) -; (e1:WSubfield, e2:WSubfield) : -; name(e1) == name(e2) and -; key-eqv?(exp(e1), exp(e2)) -; (e1, e2) : -; false -; -;defn merge-env (pred: Expression, -; con-env: List<KeyValue<Expression,SymbolicValue>>, -; alt-env: List<KeyValue<Expression,SymbolicValue>>) : -; val merged = Vector<KeyValue<Expression, SymbolicValue>>() -; defn new-key? (k:Expression) : -; for entry in merged none? : -; key-eqv?(key(entry), k) -; -; defn sv (env:List<KeyValue<Expression,SymbolicValue>>, k:Expression) : -; for entry in env search : -; if key-eqv?(key(entry), k) : -; value(entry) -; -; for k in stream(key, concat(con-env, alt-env)) do : -; if new-key?(k) : -; match(sv(con-env, k), sv(alt-env, k)) : -; (a:SymbolicValue, b:SymbolicValue) : -; if a == b : -; add(merged, k => a) -; else : -; add(merged, k => WhenValue(pred, a, b)) -; (a:SymbolicValue, b:False) : -; add(merged, k => a) -; (a:False, b:SymbolicValue) : -; add(merged, k => b) -; (a:False, b:False) : -; false -; -; to-list(merged) -; -;defn simplify-env (env: List<KeyValue<Expression,SymbolicValue>>) : -; val merged = Vector<KeyValue<Expression, SymbolicValue>>() -; defn new-key? (k:Expression) : -; for entry in merged none? : -; key-eqv?(key(entry), k) -; for entry in env do : -; if new-key?(key(entry)) : -; add(merged, entry) -; to-list(merged) -; -;defn expand-whens (m:Module) : -; val commands = Vector<Stmt>() -; val elements = Vector<KeyValue<Symbol,Element>>() -; defn eval (c:Stmt, env:List<KeyValue<Expression,SymbolicValue>>) -> -; List<KeyValue<Expression,SymbolicValue>> : -; match(c) : -; (c:LetRec) : -; do(add{elements, _}, entries(c)) -; eval(body(c), env) -; (c:DefWire) : -; add(commands, c) -; val wire-ref = WRef(name(c), type(c), NodeKind(), INPUT) -; List(wire-ref => VoidValue(), env) -; (c:DefRegister) : -; add(commands, c) -; val reg-ref = WRef(name(c), type(c), RegKind(), INPUT) -; List(reg-ref => VoidValue(), env) -; (c:DefInstance) : -; add(commands, c) -; val entries = let : -; val module-type = type(module(c)) as BundleType -; val input-ports = to-list $ -; for p in ports(module-type) filter : -; gender(p) == INPUT -; val inst-ref = WRef(name(c), module-type, InstanceKind(), OUTPUT) -; for p in input-ports map : -; WSubfield(inst-ref, name(p), type(p), INPUT) => VoidValue() -; append(entries, env) -; (c:DefMemory) : -; add(commands, c) -; env -; (c:WDefAccessor) : -; add(commands, c) -; if dir(c) == INPUT : -; val access-ref = WRef(name(c), type(source(c)), AccessorKind(), dir(c)) -; List(access-ref => VoidValue(), env) -; else : -; env -; (c:Conditionally) : -; val con-env = eval(conseq(c), env) -; val alt-env = eval(alt(c), env) -; merge-env(pred(c), con-env, alt-env) -; (c:Begin) : -; var env:List<KeyValue<Expression,SymbolicValue>> = env -; for c in body(c) do : -; env = eval(c, env) -; env -; (c:Connect) : -; List(loc(c) => ExpValue(exp(c)), env) -; (c:EmptyStmt) : -; env -; -; defn convert-symbolic (key:Expression, sv:SymbolicValue) : -; match(sv) : -; (sv:VoidValue) : -; throw $ PassException $ string-join $ [ -; "No default value for " key "."] -; (sv:ExpValue) : -; exp(sv) -; (sv:WhenValue) : -; defn multiplex-exp (pred:Expression, conseq:Expression, alt:Expression) : -; DoPrim(MUX-OP, list(pred, conseq, alt), List(), type(conseq)) -; multiplex-exp(pred(sv), -; convert-symbolic(key, conseq(sv)) -; convert-symbolic(key, alt(sv))) -; -; ;Compute final environment -; val env0 = let : -; val output-ports = to-list $ -; for p in ports(m) filter : -; gender(p) == OUTPUT -; for p in output-ports map : -; val port-ref = WRef(name(p), type(p), PortKind(), INPUT) -; port-ref => VoidValue() -; val env* = simplify-env(eval(body(m), env0)) -; -; ;Make new body -; val body* = Begin(list(defs, LetRec(elems, connections))) where : -; val defs = Begin(to-list(commands)) -; val elems = to-list(elements) -; val connections = Begin $ -; for entry in env* map : -; val sv = convert-symbolic(key(entry), value(entry)) -; Connect(key(entry), sv) -; -; ;Final module -; Module(name(m), ports(m), body*) -; -;defn expand-whens (c:Circuit) : -; val modules* = map(expand-whens, modules(c)) -; Circuit(modules*, main(c)) +;defstruct VarWidth <: Width : +; name: Symbol ; +;defmethod print (o:OutputStream, w:VarWidth) : +; print(o,name(w)) ; -;;================ STRUCTURAL FORM ========================== +;;defn remove-var-widths (c:Circuit) -> Circuit : ; -;defn structural-form (m:Module) : -; val elements = Vector<(() -> KeyValue<Symbol,Element>)>() -; val connected = HashTable<Symbol, Expression>(symbol-hash) -; val write-accessors = HashTable<Symbol, List<WDefAccessor>>(symbol-hash) -; val read-accessors = HashTable<Symbol, WDefAccessor>(symbol-hash) -; val inst-ports = HashTable<Symbol, List<KeyValue<Symbol, Expression>>>(symbol-hash) -; val port-connects = Vector<Connect>() +;;defn solve-constraints (l:List<WCon>) -> HashTable<Symbol,Int> : +; +;defn gen-constraints (m:Module) -> List<WCon> : +; val v = Vector<WCon>() +; val h = HashTable<Symbol,Width>(symbol-hash) ; -; defn scan (c:Stmt) : -; match(c) : -; (c:Connect) : -; match(loc(c)) : -; (loc:WRef) : -; match(kind(loc)) : -; (k:PortKind) : add(port-connects, c) -; (k) : connected[name(loc)] = exp(c) -; (loc:WSubfield) : -; val inst = exp(loc) as WRef -; val entry = name(loc) => exp(c) -; inst-ports[name(inst)] = List(entry, get?(inst-ports, name(inst), List())) -; (c:LetRec) : -; for e in entries(c) do : -; add(elements, {e}) -; scan(body(c)) -; (c:DefWire) : -; add{elements, _} $ fn () : -; name(c) => Node(type(c), connected[name(c)]) -; (c:DefRegister) : -; add{elements, _} $ fn () : -; val one = UIntValue(1, UnknownWidth()) -; name(c) => Register(type(c), connected[name(c)], one) -; (c:DefInstance) : -; add{elements, _} $ fn () : -; name(c) => Instance(UnknownType(), module(c), inst-ports[name(c)]) -; (c:DefMemory) : -; add{elements, _} $ fn () : -; val ports = for a in get?(write-accessors, name(c), List()) map : -; val one = UIntValue(1, UnknownWidth()) -; WritePort(index(a), connected[name(a)], one) -; name(c) => Memory(type(c), ports) -; (c:WDefAccessor) : -; val mem = source(c) as WRef -; switch {dir(c) == _} : -; INPUT : -; write-accessors[name(mem)] = List(c, -; get?(write-accessors, name(mem), List())) -; OUTPUT : -; read-accessors[name(c)] = c -; (c) : -; do(scan, children(c)) ; -; defn make-read-ports (e:Expression) : +; defn get-width (e:Expression) -> Width : ; match(e) : -; (e:WRef) : -; match(kind(e)) : -; (k:AccessorKind) : -; val accessor = read-accessors[name(e)] -; ReadPort(source(accessor), index(accessor), type(e)) -; (k) : e -; (e) : map(make-read-ports, e) -; -; Module(name(m), ports(m), body*) where : -; scan(body(m)) -; val elems = to-list $ -; for e in elements stream : -; val entry = e() -; key(entry) => map(make-read-ports, value(entry)) -; val connect-ports = Begin $ to-list $ -; for c in port-connects stream : -; Connect(loc(c), make-read-ports(exp(c))) -; val body* = -; if empty?(elems) : connect-ports -; else : LetRec(elems, connect-ports) -; -;defn structural-form (c:Circuit) : -; val modules* = map(structural-form, modules(c)) -; Circuit(modules*, main(c)) -; +; (e:WRef) : +; val w = get-width(type(e)) +; add(v,WGeq(w,h[name(e)])) +; add(v,WGeq(h[name(e)],w)) +; w +; (e:WSubfield) : ;assumes only subfields are instances +; add(v,WGeq(w, +; defn gen-constraints (s:Stmt) -> Stmt : +; match(map(gen-constraints,s)) : +; +; +;defn remove-unknown-widths (c:Circuit) -> Circuit : +; defn remove-unknown-widths-wid (w:Width) -> Width : +; match(w) : +; (w:UnknownWidth) : VarWidth(gensym(`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) +; val modules* = for m in modules(c) map : +; Module{name(m),_,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) +; c* +; ;val l = gen-constraints(c*) +; ;val h = solve-constraints(l) +; ;replace-var-widths(c*,h) + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;==================== WIDTH INFERENCE ====================== ;defstruct WidthVar <: Width : ; name: Symbol @@ -2400,8 +2298,7 @@ public defn run-passes (c: Circuit, p: List<Char>) : if contains(p,'i') : do-stage("Expand Indexed Connects", expand-connect-indexed) if contains(p,'p') : do-stage("Initialize Registers", initialize-registers) if contains(p,'j') : do-stage("Expand Whens", expand-whens) - ;if contains(p,'l') : do-stage("Structural Form", structural-form) - ;if contains(p,'m') : do-stage("Infer Widths", infer-widths) + ;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) |
