diff options
Diffstat (limited to 'src/main/stanza/passes.stanza')
| -rw-r--r-- | src/main/stanza/passes.stanza | 482 |
1 files changed, 239 insertions, 243 deletions
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 1267d5f3..1b76b949 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -40,12 +40,6 @@ defstruct WRef <: Expression : kind: Kind gender: Gender with: (as-method => true) -defstruct WRegInit <: Expression : - reg: Expression - name: Symbol - type: Type with: (as-method => true) - gender: Gender with: (as-method => true) - defstruct WSubfield <: Expression : exp: Expression name: Symbol @@ -123,7 +117,6 @@ defn times (f1:Flip,f2:Flip) -> Flip : REVERSE : swap(f1) defn to-field (p:Port) -> Field : - Field(name(p),REVERSE,type(p)) if direction(p) == OUTPUT : Field(name(p),REVERSE,type(p)) else if direction(p) == INPUT : Field(name(p),DEFAULT,type(p)) else : error("Shouldn't be here") @@ -182,7 +175,7 @@ defmethod print (o:OutputStream, k:Kind) : (k:WriteAccessorKind) : "wacc" defn hasGender (e:Expression|Stmt|Type|Port|Field) : - e typeof WRef|WSubfield|WIndex|WDefAccessor|WRegInit + e typeof WRef|WSubfield|WIndex|WDefAccessor defn hasWidth (e:Expression|Stmt|Type|Port|Field) : e typeof UIntType|SIntType|UIntValue|SIntValue|Pad @@ -190,7 +183,7 @@ defn hasWidth (e:Expression|Stmt|Type|Port|Field) : defn hasType (e:Expression|Stmt|Type|Port|Field) : e typeof Ref|Subfield|Index|DoPrim|WritePort|ReadPort|WRef|WSubfield |WIndex|DefWire|DefRegister|DefMemory|Register - |VectorType|Port|Field|WRegInit|Pad + |VectorType|Port|Field|Pad defn hasKind (e:Expression|Stmt|Type|Port|Field) : e typeof WRef @@ -219,16 +212,12 @@ defmethod print (o:OutputStream, e:WRef) : print(o,name(e)) print-debug(o,e as ?) -defmethod print (o:OutputStream, e:WRegInit) : - print-all(o,[name(e)]) - print-debug(o,e as ?) - defmethod print (o:OutputStream, e:WSubfield) : print-all(o,[exp(e) "." name(e)]) print-debug(o,e as ?) defmethod print (o:OutputStream, e:WIndex) : - print-all(o,[exp(e) "." value(e)]) + print-all(o,[exp(e) "[" value(e) "]"]) print-debug(o,e as ?) defmethod print (o:OutputStream, s:WDefAccessor) : @@ -243,8 +232,6 @@ defmethod print (o:OutputStream, c:ConnectFromIndexed) : print-all(o, [loc(c) " := " exps(c) "[" index(c) "]"]) print-debug(o,c as ?) -defmethod map (f: Expression -> Expression, e: WRegInit) : - WRegInit(f(reg(e)), name(e), type(e), gender(e)) defmethod map (f: Expression -> Expression, e: WSubfield) : WSubfield(f(exp(e)), name(e), type(e), gender(e)) defmethod map (f: Expression -> Expression, e: WIndex) : @@ -259,8 +246,6 @@ defmethod map (f: Expression -> Expression, c:ConnectFromIndexed) : 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) : @@ -303,9 +288,7 @@ defn to-working-ir (c:Circuit) : defn to-exp (e:Expression) : match(map(to-exp,e)) : (e:Ref) : WRef(name(e), type(e), NodeKind(), UNKNOWN-GENDER) - (e:Subfield) : - if name(e) == `init : WRegInit(exp(e), to-symbol("~.init" % [name(exp(e) as WRef)]), type(e), UNKNOWN-GENDER) - else : WSubfield(exp(e), name(e), type(e), UNKNOWN-GENDER) + (e:Subfield) : WSubfield(exp(e), name(e), type(e), UNKNOWN-GENDER) (e:Index) : WIndex(exp(e), value(e), type(e), UNKNOWN-GENDER) (e) : e defn to-stmt (s:Stmt) : @@ -450,7 +433,6 @@ defn infer-exp-types (e:Expression, l:List<KeyValue<Symbol,Type>>) -> Expression match(r) : (e:WRef) : WRef(name(e), get-type(name(e),l),kind(e),gender(e)) (e:WSubfield) : WSubfield(exp(e),name(e), bundle-field-type(type(exp(e)),name(e)),gender(e)) - (e:WRegInit) : WRegInit(reg(e),name(e),get-type(name(reg(e) as WRef),l),gender(e)) (e:WIndex) : WIndex(exp(e),value(e), get-vector-subtype(type(exp(e))),gender(e)) (e:DoPrim) : lower-and-type-primop(e) ;DoPrim(op(e),args(e),consts(e),get-primop-rettype(e)) @@ -480,7 +462,7 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue< val [s*,l*] = infer-types(conseq(s),l) val [s**,l**] = infer-types(alt(s),l) [Conditionally(pred(s),s*,s**),l] - (s:Connect|EmptyStmt) : [s,l] + (s:Connect|OnReset|EmptyStmt) : [s,l] defn infer-types (m:Module, l:List<KeyValue<Symbol,Type>>) -> Module : val ptypes = @@ -568,6 +550,8 @@ defn resolve-genders (c:Circuit) : WDefAccessor(name(s),source*,index*,gender*) (s:Connect) : Connect(resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) + (s:OnReset) : + OnReset(resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) (s:Conditionally) : val pred* = resolve-expr(pred(s),MALE) val conseq* = resolve-stmt(conseq(s)) @@ -582,11 +566,6 @@ defn resolve-genders (c:Circuit) : WRef{name(e),type(e),kind(e),_} $ if gender == BI-GENDER : desired else : gender - (e:WRegInit) : - val gender = get-gender(name(reg(e) as WRef),desired) - WRegInit{reg(e),name(e),type(e),_} $ - if gender == BI-GENDER : desired - else : gender (e:WSubfield) : val field-flip = bundle-field-flip(name(e),type(exp(e))) val exp* = resolve-expr(exp(e),field-flip * desired) @@ -705,7 +684,6 @@ defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) defn calc-gender (g:Gender, e:Expression) -> Gender : match(e) : (e:WRef) : gender(e) - (e:WRegInit) : gender(e) (e:WSubfield) : if is-instance(exp(e)) : gender(e) else : calc-gender(bundle-field-flip(name(e),type(exp(e))) * g,exp(e)) @@ -725,6 +703,16 @@ defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) DefWire(name(s),type(value(s))), Connect(WRef(name(s),type(value(s)),NodeKind(),FEMALE),value(s))) lower-stmt(s*) + (s:OnReset) : Begin{_} $ + for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map : + println-debug(s) + val lgender = calc-gender(FEMALE,loc(s)) * value(l) + val rgender = calc-gender(MALE,exp(s)) * value(r) + println-debug(loc(s)) + println-debug(exp(s)) + switch fn ([x,y]) : lgender == x and rgender == y : + [FEMALE,MALE] : OnReset(key(l),key(r)) + [MALE,FEMALE] : OnReset(key(r),key(l)) (s:Connect) : Begin{_} $ for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map : println-debug(s) @@ -779,7 +767,6 @@ defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) defn expand-expr (e:Expression) -> List<KeyValue<Expression,Flip>> : match(e) : (e:WRef) : table[name(e)] - (e:WRegInit) : table[name(e)] (e:WSubfield) : val exps = expand-expr(exp(e)) val begin = index-of-elem(type(exp(e)) as BundleType,name(e)) @@ -827,12 +814,7 @@ defn lower-module (m:Module,table:HashTable<Symbol,List<KeyValue<Expression,Flip (s:DefWire) : table[name(s)] = get-entries(name(s),type(s)) (s:DefRegister) : val regs = get-entries(name(s),type(s)) - val init-sym = symbol-join([name(s),`\|.init|]) - val init-regs = for r in regs map : - val [e f] = [key(r) value(r)] - WRegInit(e,symbol-join([name(e),`\|.init|]),type(e),gender(e)) => f table[name(s)] = regs - table[init-sym] = init-regs (s:DefInstance) : val r = WRef(name(s),type(module(s)),InstanceKind(),FEMALE) val ports = table[name(module(s) as WRef)] @@ -918,70 +900,70 @@ defn expand-connect-indexed (c: Circuit) -> Circuit : ; This ensures proper behavior if this pass is run multiple ; times. -defn initialize-registers (c:Circuit) : - 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 : - val refreg = WRef(key(kv),value(kv),RegKind(),FEMALE) - val refwire = WRef(to-wire-name(key(kv)),value(kv),NodeKind(),MALE) - val connect = Connect(refreg,refwire) - inits = append(inits,list(connect)) - if empty?(inits) : s - else : - val pred = WRef(`reset, UIntType(IntWidth(1)), PortKind(), MALE) - val when-reset = Conditionally(pred,Begin(inits),Begin(List<Stmt>())) - Begin(list(s,when-reset)) - - defn rename (s:Stmt,h:HashTable<Symbol,True|False>) -> [Stmt HashTable<Symbol,Type>] : - val t = HashTable<Symbol,Type>(symbol-hash) - defn rename-expr (e:Expression) -> Expression : - match(map(rename-expr,e)) : - (e:WRegInit) : - val new-name = to-wire-name(name(reg(e) as WRef)) - WRef(new-name,type(reg(e)),RegKind(),gender(e)) - (e) : e - defn rename-stmt (s:Stmt) -> Stmt : - match(map(rename-stmt,s)) : - (s:DefRegister) : - if h[name(s)] : - t[name(s)] = type(s) - Begin(list(s,DefWire(to-wire-name(name(s)),type(s)))) - else : s - (s) : map(rename-expr,s) - [rename-stmt(s) t] - - defn init? (y:Symbol,s:Stmt) -> True|False : - var used? = false - defn has? (e:Expression) -> Expression : - match(map(has?,e)) : - (e:WRegInit) : - if name(reg(e) as WRef) == y : used? = true - (e) : map(has?,e) - e - map(has?,s) - used? - - defn using-init (s:Stmt,h:HashTable<Symbol,True|False>) -> Stmt : - match(s) : - (s:DefRegister) : h[name(s)] = false - (s) : - for x in h do : - h[key(x)] = value(x) or init?(key(x),s) - map(using-init{_,h},s) - - defn explicit-init-scope (s:Stmt) -> Stmt : - val h = HashTable<Symbol,True|False>(symbol-hash) - using-init(s,h) - ;println-debug(h) - val [s* t] = rename(s,h) - add-when(s*,t) - - Circuit(modules*, main(c)) where : - val modules* = - for m in modules(c) map : - Module(name(m), ports(m), body*) where : - val body* = explicit-init-scope(body(m)) +;defn initialize-registers (c:Circuit) : +; 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 : +; val refreg = WRef(key(kv),value(kv),RegKind(),FEMALE) +; val refwire = WRef(to-wire-name(key(kv)),value(kv),NodeKind(),MALE) +; val connect = Connect(refreg,refwire) +; inits = append(inits,list(connect)) +; if empty?(inits) : s +; else : +; val pred = WRef(`reset, UIntType(IntWidth(1)), PortKind(), MALE) +; val when-reset = Conditionally(pred,Begin(inits),Begin(List<Stmt>())) +; Begin(list(s,when-reset)) +; +; defn rename (s:Stmt,h:HashTable<Symbol,True|False>) -> [Stmt HashTable<Symbol,Type>] : +; val t = HashTable<Symbol,Type>(symbol-hash) +; defn rename-expr (e:Expression) -> Expression : +; match(map(rename-expr,e)) : +; (e:WRegInit) : +; val new-name = to-wire-name(name(reg(e) as WRef)) +; WRef(new-name,type(reg(e)),RegKind(),gender(e)) +; (e) : e +; defn rename-stmt (s:Stmt) -> Stmt : +; match(map(rename-stmt,s)) : +; (s:DefRegister) : +; if h[name(s)] : +; t[name(s)] = type(s) +; Begin(list(s,DefWire(to-wire-name(name(s)),type(s)))) +; else : s +; (s) : map(rename-expr,s) +; [rename-stmt(s) t] +; +; defn init? (y:Symbol,s:Stmt) -> True|False : +; var used? = false +; defn has? (e:Expression) -> Expression : +; match(map(has?,e)) : +; (e:WRegInit) : +; if name(reg(e) as WRef) == y : used? = true +; (e) : map(has?,e) +; e +; map(has?,s) +; used? +; +; defn using-init (s:Stmt,h:HashTable<Symbol,True|False>) -> Stmt : +; match(s) : +; (s:DefRegister) : h[name(s)] = false +; (s) : +; for x in h do : +; h[key(x)] = value(x) or init?(key(x),s) +; map(using-init{_,h},s) +; +; defn explicit-init-scope (s:Stmt) -> Stmt : +; val h = HashTable<Symbol,True|False>(symbol-hash) +; using-init(s,h) +; ;println-debug(h) +; val [s* t] = rename(s,h) +; add-when(s*,t) +; +; Circuit(modules*, main(c)) where : +; val modules* = +; for m in modules(c) map : +; Module(name(m), ports(m), body*) where : +; val body* = explicit-init-scope(body(m)) ;;================ EXPAND WHENS ============================= ; This pass does three things: remove last connect semantics, @@ -1018,7 +1000,6 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False : 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:Pad,e2:Pad) : width(e1) == width(e2) and value(e1) == value(e2) (e1:DoPrim,e2:DoPrim) : @@ -1146,15 +1127,15 @@ defn remove-nul (sv:SymbolicValue) -> SymbolicValue : (c:SVNul,a) : a (c,a) : sv (sv) : sv -defn to-exp (sv:SymbolicValue) -> Expression : +defn to-exp (sv:SymbolicValue) -> Expression|False : match(remove-nul(sv)) : (sv:SVMux) : DoPrim(MUX-UU-OP, - list(pred(sv),to-exp(conseq(sv)),to-exp(alt(sv))), + list(pred(sv),to-exp(conseq(sv)) as Expression,to-exp(alt(sv)) as Expression), list(), UIntType(IntWidth(1))) (sv:SVExp) : exp(sv) - (sv) : error("Shouldn't be here") + (sv:SVNul) : false defn reduce-or (l:List<True|False>) -> True|False : if length(l) == 0 : false else : head(l) or reduce-or(tail(l)) @@ -1169,58 +1150,76 @@ defn reduce-or (l:List<Expression>) -> Expression : ; 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 : - - 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 = to-symbol(split(to-string(n),'.')[0]) - val f = to-symbol(split(to-string(n),'.')[1]) - 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(sref,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 : +; assign: holds the symbolic value of a wref. +; resets: holds the symbolic value of connections under reset +; stmts: Used to hold the orignal type, as well as the mem/index for Write/ReadPorts +; kinds: Used to know the kind of reference, so we know whether we should error if it isn't initialized. We also know how we should declare the refernce. +; enables:Calculated off of assigns. + +; I think I'm going to restructure this so that not all information is held in the tables, but instead, we walk the graph again, and do stuff on declarations, and delete other stuff +defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stmt>,cons:Vector<Stmt>) -> Stmt : + match(map(expand-whens{_,table,decs,cons},s)) : + (s:DefNode|DefMemory) : add(decs,s) + (s:DefWire) : + add(decs,s) + add{cons,_} $ { + val ref = WRef(name(s),type(s),NodeKind(),FEMALE) + if has-nul?(table[name(s)]) : + println("Uninitialized: ~" % [to-string(name(s))]);TODO actually collect error + EmptyStmt() + else : Connect(ref,to-exp(table[name(s)]) as Expression) + }() + (s:DefRegister) : + add(decs,DefWire(name(s),type(s))) + add{cons,_} $ { + val ref = WRef(name(s),type(s),RegKind(),FEMALE) + val e = to-exp(table[name(s)]) + match(e) : + (e:False) : EmptyStmt() + (e:Expression) : Connect(ref,Register(type(s),e, to-exp(optimize $ get-write-enable(table[name(s)])) as Expression)) + }() + (s:WDefAccessor) : + val t = type(type(source(s)) as VectorType) + val n = name(s) + add(decs,DefWire(n,t)) + add{cons,_} $ { + switch {_ == gender(s)} : + MALE : + val ref = WRef(n,t,ReadAccessorKind(),FEMALE) + Begin $ list $ Connect(ref,ReadPort(source(s),index(s),t,get-read-enable(n,table))) + FEMALE : + val ref = WRef(n,t,WriteAccessorKind(),FEMALE) + val e = to-exp(table[n]) + val s* = match(e) : + (e:False) : + println("Uninitialized: ~" % [to-string(n)]) ;TODO actually collect error + EmptyStmt() + (e:Expression) : + Connect(ref,e) + val enable = (to-exp $ optimize $ get-write-enable(table[n])) as Expression + val wp = WritePort(source(s),index(s),t,enable as Expression) + Begin $ list(Connect(wp,ref),s*) + }() + (s:DefInstance) : + add(decs,s) + add{cons,_} $ Begin $ + for f in fields(type(module(s)) as BundleType) map : + if flip(f) == DEFAULT : + val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs + val x = to-symbol(split(to-string(n),'.')[0]) + val f = to-symbol(split(to-string(n),'.')[1]) + val ref = WRef(x,type(module(s)),InstanceKind(),FEMALE) + val sref = WSubfield(ref,f,bundle-field-type(type(module(s)),f),FEMALE) + if has-nul?(table[n]) : + println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error + EmptyStmt() + else : Connect(sref,to-exp(table[n]) as Expression) + else : EmptyStmt() + (s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : false + s + +defn get-read-enable (sym:Symbol,table:HashTable<Symbol,SymbolicValue>) -> Expression : + defn get-single-read-enable (sym:Symbol,sv:SymbolicValue) -> Expression : defn active (e:Expression) -> True|False : match(e) : (e:WRef) : name(e) == sym @@ -1232,124 +1231,123 @@ defn get-enables (assign:HashTable<Symbol,SymbolicValue>, if active(exp(sv)) : one else : zero (sv: SVMux) : - val e0 = get-read-enable(sym,SVExp(pred(sv))) - val e1 = get-read-enable(sym,conseq(sv)) - val e2 = get-read-enable(sym,alt(sv)) + val e0 = get-single-read-enable(sym,SVExp(pred(sv))) + val e1 = get-single-read-enable(sym,conseq(sv)) + val e2 = get-single-read-enable(sym,alt(sv)) if e1 == e2 : OR(e0,e1) else : OR(e0,OR(AND(pred(sv),e1),AND(NOT(pred(sv)),e2))) + DoPrim{BIT-OR-OP,_,list(),UIntType(IntWidth(1))} $ to-list $ + for y in table stream : get-single-read-enable(sym,value(y)) - defn get-write-enable (sv:SymbolicValue) -> SymbolicValue : - match(map(get-write-enable,sv)) : - (sv: SVExp) : SVExp(one) - (sv: SVNul) : SVExp(zero) - (sv) : sv - - val enables = HashTable<Symbol,SymbolicValue>(symbol-hash) - for x in assign do : - val sym = key(x) - 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 get-write-enable (sv:SymbolicValue) -> SymbolicValue : + match(map(get-write-enable,sv)) : + (sv: SVExp) : SVExp(one) + (sv: SVNul) : SVExp(zero) + (sv) : sv + +defn merge-resets (assign:HashTable<Symbol,SymbolicValue>, resets:HashTable<Symbol,SymbolicValue>) -> HashTable<Symbol,SymbolicValue> : + val table = HashTable<Symbol,SymbolicValue>(symbol-hash) + val reset = WRef(`reset, UnknownType(), PortKind(), MALE) + for i in get-unique-keys(list(assign,resets)) do : + table[i] = match(get?(assign,i,false),get?(resets,i,false)) : + (a:SymbolicValue,r:SymbolicValue) : SVMux(reset,r,a) + (a:SymbolicValue,r:False) : a + (a:False,r:SymbolicValue) : SVMux(reset,r,SVNul()) + (a:False,r:False) : error("Shouldn't be here") + table defn build-tables (s:Stmt, assign:HashTable<Symbol,SymbolicValue>, - kinds:HashTable<Symbol,Kind>, - decs:Vector<Stmt>, - stmts:HashTable<Symbol,Stmt>) -> False : + resets:HashTable<Symbol,SymbolicValue>, + flattn:HashTable<Symbol,True|False>, + ) -> False : match(s) : - (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() + (s:DefWire) : assign[name(s)] = SVNul() - stmts[name(s)] = s - (s:WDefAccessor) : - add(decs,DefWire(name(s),type(type(source(s)) as VectorType))) + flattn[name(s)] = true + (s:DefRegister|WDefAccessor) : assign[name(s)] = SVNul() - kinds[name(s)] = switch {_ == gender(s)} : - MALE : ReadAccessorKind() - FEMALE : WriteAccessorKind() - stmts[name(s)] = s - (s:DefInstance) : - add(decs,s) + flattn[name(s)] = false + (s:DefInstance) : ;TODO only add instance input ports. This probably involves correcting instance genders for f in fields(type(module(s)) as BundleType) do : - val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs - println-all-debug(["In DefInst adding: " n]) - kinds[n] = InstanceKind() - assign[n] = SVNul() - stmts[n] = s - (s:DefMemory) : add(decs,s) + if flip(f) == DEFAULT : + println-all-debug(["Instance: " s " has input " f]) + val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs + assign[n] = SVNul() + flattn[n] = true (s:Conditionally) : - 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 + defn combine (flattn:HashTable<Symbol,True|False>, + table-c:HashTable<Symbol,SymbolicValue>, + table-a:HashTable<Symbol,SymbolicValue>, + i:Symbol) -> SymbolicValue|False : + match(get?(table-c,i,false),get?(table-a,i,false)) : (c:SymbolicValue,a:SymbolicValue) : if c == a : c else : SVMux(pred(s),c,a) - (c:SymbolicValue,a:False) : - if kinds[i] typeof WireKind|InstanceKind|NodeKind : c + (c:SymbolicValue,a:False) : + if flattn[i] : c else : SVMux(pred(s),c,SVNul()) - (c:False,a:SymbolicValue) : - if kinds[i] typeof WireKind|InstanceKind|NodeKind : a + (c:False,a:SymbolicValue) : + if flattn[i] : a else : SVMux(pred(s),SVNul(),a) - (c:False,a:False) : error("Shouldn't be here") - println-debug("TABLE-C") - for x in assign-c do : println-debug(x) - println-debug("TABLE-A") - for x in assign-a do : println-debug(x) - println-debug("TABLE") - for x in assign do : println-debug(x) - (s:Connect) : + (c:False,a:False) : false + + val assign-c = deepcopy(assign) + val assign-a = deepcopy(assign) + val resets-c = deepcopy(resets) + val resets-a = deepcopy(resets) + build-tables(conseq(s),assign-c,resets-c,flattn) + build-tables(alt(s),assign-a,resets-a,flattn) + for i in get-unique-keys(list(assign-c,assign-a)) do : + assign[i] = combine(flattn,assign-c,assign-a,i) as SymbolicValue + val r = combine(flattn,resets-c,resets-a,i) + match(r) : + (r:SymbolicValue) : resets[i] = r + (r) : false + ;println-debug("TABLE-C") + ;for x in assign-c do : println-debug(x) + ;println-debug("TABLE-A") + ;for x in assign-a do : println-debug(x) + ;println-debug("TABLE") + ;for x in assign do : println-debug(x) + (s:Connect|OnReset) : val key* = match(loc(s)) : (e:WRef) : name(e) (e:WSubfield) : symbol-join([name(exp(e) as ?) `. name(e)]) (e) : error("Shouldn't be here with ~" % [e]) - 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 + if s typeof Connect : assign[key*] = SVExp(exp(s)) + if s typeof OnReset : resets[key*] = SVExp(exp(s)) + (s:Begin) : for s* in body(s) do: build-tables(s*,assign,resets,flattn) + (s:DefMemory|DefNode|EmptyStmt) : false defn expand-whens (m:Module) -> Module : 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) + val resets = HashTable<Symbol,SymbolicValue>(symbol-hash) + val flattn = HashTable<Symbol,True|False>(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)) + flattn[name(p)] = false - build-tables(body(m),assign,kinds,decs,stmts) - + build-tables(body(m),assign,resets,flattn) 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)) + for x in resets do : resets[key(x)] = optimize(value(x)) + ;val enables = get-enables(assign,kinds) + ;for x in enables do : enables[key(x)] = optimize(value(x)) - println-debug("Assigns") + println-debug("====== Assigns ======") for x in assign do : println-debug(x) - println-debug("Kinds") - for x in kinds do : println-debug(x) - println-debug("Decs") - for x in decs do : println-debug(x) - println-debug("Enables") - for x in enables do : println-debug(x) + println-debug("====== Resets ======") + for x in resets do : println-debug(x) - Module(name(m),ports(m),expand-whens(assign,kinds,stmts,decs,enables)) + val table = merge-resets(assign,resets) + println-debug("====== Table ======") + for x in table do : println-debug(x) + val decs = Vector<Stmt>() + val cons = Vector<Stmt>() + expand-whens(body(m),table,decs,cons) + Module(name(m),ports(m),Begin(append(to-list(decs),to-list(cons)))) defn expand-whens (c:Circuit) -> Circuit : Circuit(modules*, main(c)) where : @@ -1793,7 +1791,6 @@ defn to-real-ir (c:Circuit) : 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) : @@ -2039,7 +2036,6 @@ public defn run-passes (c: Circuit, p: List<Char>,file:String) : if contains(p,'X') or contains(p,'g') : do-stage("Expand Accessors", expand-accessors) if contains(p,'X') or contains(p,'h') : do-stage("Lower To Ground", lower-to-ground) if contains(p,'X') or contains(p,'i') : do-stage("Expand Indexed Connects", expand-connect-indexed) - if contains(p,'X') or contains(p,'j') : do-stage("Initialize Registers", initialize-registers) if contains(p,'X') or contains(p,'k') : do-stage("Expand Whens", expand-whens) if contains(p,'X') or contains(p,'l') : do-stage("Infer Widths", infer-widths) if contains(p,'X') or contains(p,'m') : do-stage("Inline Instances", inline-instances) |
