diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/stanza/chirrtl.stanza | 323 | ||||
| -rw-r--r-- | src/main/stanza/compilers.stanza | 9 | ||||
| -rw-r--r-- | src/main/stanza/errors.stanza | 227 | ||||
| -rw-r--r-- | src/main/stanza/errorstemp.stanza | 994 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 33 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 20 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 154 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 650 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza2 | 2662 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza3 | 2687 | ||||
| -rw-r--r-- | src/main/stanza/primop.stanza | 28 |
11 files changed, 969 insertions, 6818 deletions
diff --git a/src/main/stanza/chirrtl.stanza b/src/main/stanza/chirrtl.stanza index 83a9e853..f9971323 100644 --- a/src/main/stanza/chirrtl.stanza +++ b/src/main/stanza/chirrtl.stanza @@ -3,11 +3,206 @@ defpackage firrtl/chirrtl : import verse import firrtl/ir2 import firrtl/ir-utils + import firrtl/primops -public defstruct ToIR <: Pass -public defmethod pass (b:ToIR) -> (Circuit -> Circuit) : to-ir -public defmethod name (b:ToIR) -> String : "To FIRRTL" -public defmethod short-name (b:ToIR) -> String : "to-firrtl" +; CHIRRTL Additional IR Nodes +public definterface MPortDir +public val MInfer = new MPortDir +public val MRead = new MPortDir +public val MWrite = new MPortDir +public val MReadWrite = new MPortDir + +defmethod print (o:OutputStream, m:MPortDir) : + switch { m == _ } : + MInfer : print(o,"infer") + MRead : print(o,"read") + MWrite : print(o,"write") + MReadWrite : print(o,"rdwr") + +public defstruct CDefMemory <: Stmt : ;LOW + info: FileInfo with: (as-method => true) + name: Symbol + type: Type + size: Int + seq?: True|False +public defstruct CDefMPort <: Stmt : + info: FileInfo with: (as-method => true) + name: Symbol + type: Type + mem: Symbol + exps: List<Expression> + direction: MPortDir + +defmethod print (o:OutputStream,c:CDefMemory) : + if seq?(c) : print-all(o, ["smem " name(c) " : " type(c) "[" size(c) "]"]) + else : print-all(o, ["cmem " name(c) " : " type(c) "[" size(c) "]"]) +defmethod map (f: Type -> Type, c:CDefMemory) -> CDefMemory : + CDefMemory(info(c),name(c),f(type(c)),size(c),seq?(c)) +defmethod map (f: Symbol -> Symbol, c:CDefMemory) -> CDefMemory : + CDefMemory(info(c),f(name(c)),type(c),size(c),seq?(c)) + +defmethod print (o:OutputStream,c:CDefMPort) : + print-all(o, [direction(c) " mport " name(c) " = " mem(c) "[" exps(c)[0] "], " exps(c)[1]]) +defmethod map (f: Expression -> Expression, c:CDefMPort) -> CDefMPort : + CDefMPort(info(c),name(c),type(c),mem(c),map(f,exps(c)),direction(c)) +defmethod map (f: Type -> Type, c:CDefMPort) -> CDefMPort : + CDefMPort(info(c),name(c),f(type(c)),mem(c),exps(c),direction(c)) +defmethod map (f: Symbol -> Symbol, c:CDefMPort) -> CDefMPort : + CDefMPort(info(c),f(name(c)),type(c),mem(c),exps(c),direction(c)) + + +;======================= Infer Chirrtl Types ====================== +public defstruct CInferTypes <: Pass +public defmethod pass (b:CInferTypes) -> (Circuit -> Circuit) : infer-types +public defmethod name (b:CInferTypes) -> String : "CInfer Types" +public defmethod short-name (b:CInferTypes) -> String : "c-infer-types" + +;--------------- Utils ----------------- + +defn set-type (s:Stmt,t:Type) -> Stmt : + match(s) : + (s:DefWire) : DefWire(info(s),name(s),t) + (s:DefRegister) : DefRegister(info(s),name(s),t,clock(s),reset(s),init(s)) + (s:CDefMemory) : CDefMemory(info(s),name(s),t,size(s),seq?(s)) + (s:CDefMPort) : CDefMPort(info(s),name(s),t,mem(s),exps(s),direction(s)) + (s:DefNode) : s + (s:DefPoison) : DefPoison(info(s),name(s),t) + +defn to-field (p:Port) -> Field : + if direction(p) == OUTPUT : Field(name(p),DEFAULT,type(p)) + else if direction(p) == INPUT : Field(name(p),REVERSE,type(p)) + else : error("Shouldn't be here") +defn module-type (m:Module) -> Type : + BundleType(for p in ports(m) map : to-field(p)) +defn field-type (v:Type,s:Symbol) -> Type : + match(v) : + (v:BundleType) : + val ft = for p in fields(v) find : name(p) == s + if ft != false : type(ft as Field) + else : UnknownType() + (v) : UnknownType() +defn sub-type (v:Type) -> Type : + match(v) : + (v:VectorType) : type(v) + (v) : UnknownType() + +;--------------- Pass ----------------- + +defn infer-types (c:Circuit) -> Circuit : + val module-types = HashTable<Symbol,Type>(symbol-hash) + defn infer-types (m:Module) -> Module : + val types = HashTable<Symbol,Type>(symbol-hash) + defn infer-types-e (e:Expression) -> Expression : + match(map(infer-types-e,e)) : + (e:Ref) : Ref(name(e), get?(types,name(e),UnknownType())) + (e:SubField) : SubField(exp(e),name(e),field-type(type(exp(e)),name(e))) + (e:SubIndex) : SubIndex(exp(e),value(e),sub-type(type(exp(e)))) + (e:SubAccess) : SubAccess(exp(e),index(e),sub-type(type(exp(e)))) + (e:DoPrim) : set-primop-type(e) + (e:Mux) : Mux(cond(e),tval(e),fval(e),mux-type(tval(e),tval(e))) + (e:ValidIf) : ValidIf(cond(e),value(e),type(value(e))) + (e:UIntValue|SIntValue) : e + defn infer-types-s (s:Stmt) -> Stmt : + match(s) : + (s:DefRegister) : + types[name(s)] = type(s) + map(infer-types-e,s) + s + (s:DefWire|DefPoison) : + types[name(s)] = type(s) + s + (s:DefNode) : + val s* = map(infer-types-e,s) + val t = type(value(s*)) + types[name(s*)] = t + s* + (s:DefMemory) : + types[name(s)] = get-type(s) + s + (s:CDefMPort) : + val t = get?(types,mem(s),UnknownType()) + types[name(s)] = t + CDefMPort(info(s),name(s),t,mem(s),exps(s),direction(s)) + (s:CDefMemory) : + types[name(s)] = type(s) + s + (s:DefInstance) : + types[name(s)] = get?(module-types,module(s),UnknownType()) + s + (s) : map{infer-types-e,_} $ map(infer-types-s,s) + for p in ports(m) do : + types[name(p)] = type(p) + match(m) : + (m:InModule) : + InModule(info(m),name(m),ports(m),infer-types-s(body(m))) + (m:ExModule) : m + + ; MAIN + for m in modules(c) do : + module-types[name(m)] = module-type(m) + Circuit{info(c), _, main(c) } $ + for m in modules(c) map : + infer-types(m) + +;========================================== + +public defstruct CInferMDir <: Pass +public defmethod pass (b:CInferMDir) -> (Circuit -> Circuit) : infer-mdir +public defmethod name (b:CInferMDir) -> String : "CInfer MDir" +public defmethod short-name (b:CInferMDir) -> String : "cinfer-mdir" + +defn infer-mdir (c:Circuit) -> Circuit : + defn infer-mdir (m:Module) -> Module : + val mports = HashTable<Symbol,MPortDir>(symbol-hash) + defn infer-mdir-e (e:Expression,dir:MPortDir) -> Expression : + match(map(infer-mdir-e{_,dir},e)) : + (e:Ref) : + if key?(mports,name(e)) : + val new_mport_dir = + switch fn ([x,y]) : mports[name(e)] == x and dir == y : + [MInfer,MInfer] : error("Shouldn't be here") + [MInfer,MWrite] : MWrite + [MInfer,MRead] : MRead + [MWrite,MInfer] : error("Shouldn't be here") + [MWrite,MWrite] : MWrite + [MWrite,MRead] : MReadWrite + [MRead,MInfer] : error("Shouldn't be here") + [MRead,MWrite] : MReadWrite + [MRead,MRead] : MRead + mports[name(e)] = new_mport_dir + e + (e) : e + defn infer-mdir-s (s:Stmt) -> Stmt : + match(s) : + (s:CDefMPort) : + mports[name(s)] = direction(s) + map(infer-mdir-e{_,MRead},s) + (s:Connect|BulkConnect) : + infer-mdir-e(exp(s),MRead) + infer-mdir-e(loc(s),MWrite) + s + (s) : map{infer-mdir-e{_,MRead},_} $ map(infer-mdir-s,s) + defn set-mdir-s (s:Stmt) -> Stmt : + match(s) : + (s:CDefMPort) : + CDefMPort(info(s),name(s),type(s),mem(s),exps(s),mports[name(s)]) + (s) : map(set-mdir-s,s) + match(m) : + (m:InModule) : + infer-mdir-s(body(m)) + InModule(info(m),name(m),ports(m),set-mdir-s(body(m))) + (m:ExModule) : m + + ; MAIN + Circuit{info(c), _, main(c) } $ + for m in modules(c) map : + infer-mdir(m) + +;========================================== +public defstruct RemoveCHIRRTL <: Pass +public defmethod pass (b:RemoveCHIRRTL) -> (Circuit -> Circuit) : remove-chirrtl +public defmethod name (b:RemoveCHIRRTL) -> String : "Remove CHIRRTL" +public defmethod short-name (b:RemoveCHIRRTL) -> String : "remove-chirrtl" defstruct MPort : name : Symbol @@ -20,27 +215,38 @@ defstruct DataRef : exp : Expression male : Symbol female : Symbol + mask : Symbol public definterface Gender public val MALE = new Gender public val FEMALE = new Gender defn create-exps (e:Expression) -> List<Expression> : - match(type(e)) : - (t:UIntType|SIntType|ClockType) : list(e) - (t:BundleType) : - for f in fields(t) map-append : - create-exps(SubField(e,name(f),type(f))) - (t:VectorType) : - for i in 0 to size(t) map-append : - create-exps(SubIndex(e,i,type(t))) - -defn to-ir (c:Circuit) : - defn to-ir-m (m:InModule) -> InModule : + match(e) : + (e:Mux) : + for (e1 in create-exps(tval(e)), e2 in create-exps(fval(e))) map : + Mux(cond(e),e1,e2,mux-type(e1,e2)) + (e:ValidIf) : + for e1 in create-exps(value(e)) map : + ValidIf(cond(e),e1,type(e1)) + (e) : + match(type(e)) : + (t:UIntType|SIntType|ClockType) : list(e) + (t:BundleType) : + for f in fields(t) map-append : + create-exps(SubField(e,name(f),type(f))) + (t:VectorType) : + for i in 0 to size(t) map-append : + create-exps(SubIndex(e,i,type(t))) + (t:UnknownType) : list(e) + +defn remove-chirrtl (c:Circuit) : + defn remove-chirrtl-m (m:InModule) -> InModule : val hash = HashTable<Symbol,MPorts>(symbol-hash) val sh = get-sym-hash(m,keys(v-keywords)) val repl = HashTable<Symbol,DataRef>(symbol-hash) val ut = UnknownType() + val mport-types = HashTable<Symbol,Type>(symbol-hash) defn EMPs () -> MPorts : MPorts(Vector<MPort>(),Vector<MPort>(),Vector<MPort>()) defn collect-mports (s:Stmt) -> Stmt : @@ -57,9 +263,10 @@ defn to-ir (c:Circuit) : defn collect-refs (s:Stmt) -> Stmt : match(s) : (s:CDefMemory) : + mport-types[name(s)] = type(s) val stmts = Vector<Stmt>() val naddr = firrtl-gensym(`GEN,sh) - val taddr = UIntType(IntWidth(ceil-log2(size(s)))) + val taddr = UIntType(IntWidth(max(1,ceil-log2(size(s))))) add(stmts,DefPoison(info(s),naddr,taddr)) val ndata = firrtl-gensym(`GEN,sh) val tdata = type(s) @@ -72,7 +279,7 @@ defn to-ir (c:Circuit) : for r in vec do : add(stmts,Connect(info(s),SubField(SubField(Ref(name(s),ut),name(r),ut),en,taddr),zero)) defn set-write (vec:List<MPort>,data:Symbol,mask:Symbol) -> False : - val tmask = type(create-mask(`blah,type(s))) + val tmask = create-mask(type(s)) for r in vec do : add(stmts,Connect(info(s),SubField(SubField(Ref(name(s),ut),name(r),ut),data,tdata),Ref(ndata,tdata))) for x in create-exps(SubField(SubField(Ref(name(s),ut),name(r),ut),mask,tmask)) do : @@ -97,23 +304,25 @@ defn to-ir (c:Circuit) : val mem = DefMemory(info(s),name(s),type(s),size(s),1,read-l,map(name,rds),map(name,wrs),map(name,rws)) Begin $ List(mem,to-list(stmts)) (s:CDefMPort) : + mport-types[name(s)] = mport-types[mem(s)] val addrs = Vector<Symbol>() val ens = Vector<Symbol>() val masks = Vector<Symbol>() switch { _ == direction(s) } : MReadWrite : - repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`wdata,`rdata) - add(addrs,`addr) + repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`rdata,`wdata,`wmask) + add(addrs,`waddr) + add(addrs,`raddr) add(ens,`wen) add(ens,`ren) add(masks,`wmask) MWrite : - repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`data,`data) + repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`data,`data,`mask) add(addrs,`addr) add(ens,`en) add(masks,`mask) - else : ; TODO add MWrite for mask - repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`data,`data) + else : + repl[name(s)] = DataRef(SubField(Ref(mem(s),ut),name(s),ut),`data,`data,`blah) add(addrs,`addr) add(ens,`en) @@ -122,39 +331,65 @@ defn to-ir (c:Circuit) : add(stmts,Connect(info(s),SubField(SubField(Ref(mem(s),ut),name(s),ut),x,ut),exps(s)[0])) for x in ens do : add(stmts,Connect(info(s),SubField(SubField(Ref(mem(s),ut),name(s),ut),x,ut),one)) - for x in masks do : - add(stmts,Connect(info(s),SubField(SubField(Ref(mem(s),ut),name(s),ut),x,ut),exps(s)[2])) Begin $ to-list $ stmts (s) : map(collect-refs,s) - defn to-ir-e (e:Expression,g:Gender) -> Expression : - match(map(to-ir-e{_,g},e)) : - (e:Ref) : - if key?(repl,name(e)) : - val vt = repl[name(e)] - switch {g == _ }: - MALE : SubField(exp(vt),male(vt),ut) - FEMALE : SubField(exp(vt),female(vt),ut) - else : e - (e) : e - defn to-ir-s (s:Stmt) -> Stmt : + defn remove-chirrtl-s (s:Stmt) -> Stmt : + var has-write-mport? = false + defn remove-chirrtl-e (e:Expression,g:Gender) -> Expression : + match(map(remove-chirrtl-e{_,g},e)) : + (e:Ref) : + if key?(repl,name(e)) : + val vt = repl[name(e)] + switch {g == _ }: + MALE : SubField(exp(vt),male(vt),type(e)) + FEMALE : + has-write-mport? = true + SubField(exp(vt),female(vt),type(e)) + else : e + (e) : e + defn get-mask (e:Expression) -> Expression : + match(map(get-mask,e)) : + (e:Ref) : + if key?(repl,name(e)) : + val vt = repl[name(e)] + val t = create-mask(type(e)) + SubField(exp(vt),mask(vt),t) + else : e + (e) : e match(s) : (s:Connect) : - val loc* = to-ir-e(loc(s),FEMALE) - val roc* = to-ir-e(exp(s),MALE) - Connect(info(s),loc*,roc*) + val stmts = Vector<Stmt>() + val roc* = remove-chirrtl-e(exp(s),MALE) + val loc* = remove-chirrtl-e(loc(s),FEMALE) + add(stmts,Connect(info(s),loc*,roc*)) + if has-write-mport? : + val e = get-mask(loc(s)) + for x in create-exps(e) do : + add(stmts,Connect(info(s),x,one)) + if length(stmts) > 1 : Begin(to-list(stmts)) + else : stmts[0] (s:BulkConnect) : - val loc* = to-ir-e(loc(s),FEMALE) - val roc* = to-ir-e(exp(s),MALE) - BulkConnect(info(s),loc*,roc*) - (s) : map(to-ir-e{_,MALE}, map(to-ir-s,s)) + val stmts = Vector<Stmt>() + val loc* = remove-chirrtl-e(loc(s),FEMALE) + val roc* = remove-chirrtl-e(exp(s),MALE) + add(stmts,BulkConnect(info(s),loc*,roc*)) + if has-write-mport? : + val ls = get-valid-points(type(loc(s)),type(exp(s)),DEFAULT,DEFAULT) + val locs = create-exps(get-mask(loc(s))) + for x in ls do : + val loc* = locs[x[0]] + add(stmts,Connect(info(s),loc*,one)) + if length(stmts) > 1 : Begin(to-list(stmts)) + else : stmts[0] + (s) : map(remove-chirrtl-e{_,MALE}, map(remove-chirrtl-s,s)) collect-mports(body(m)) val s* = collect-refs(body(m)) - InModule(info(m),name(m), ports(m), to-ir-s(s*)) + InModule(info(m),name(m), ports(m), remove-chirrtl-s(s*)) Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : match(m) : - (m:InModule) : to-ir-m(m) + (m:InModule) : remove-chirrtl-m(m) (m:ExModule) : m diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index de775648..3ca4f8da 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -50,7 +50,9 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> : ;RemoveSpecialChars() ;TempElimination() ; Needs to check number of uses ;=============== - ToIR() + CInferTypes() + CInferMDir() + RemoveCHIRRTL() ;=============== CheckHighForm() ;=============== @@ -64,6 +66,8 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> : InferWidths() CheckWidths() ;=============== + PullMuxes() + ;=============== ExpandConnects() ;=============== RemoveAccesses() @@ -94,6 +98,7 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> : InferWidths() CheckWidths() ;=============== + VerilogRename() Verilog(with-output(c)) ;=============== ;ToRealIR() @@ -121,7 +126,7 @@ public defmethod backend (c:StandardLoFIRRTL) -> List<Pass> : public defmethod passes (c:StandardLoFIRRTL) -> List<Pass> : to-list $ [ ;=============== - ToIR() + RemoveCHIRRTL() ;=============== CheckHighForm() ;=============== diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index 63199b4b..3e388a42 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -138,76 +138,44 @@ defn contains?<?T> (c:?T,cs:Streamable<?T>) -> True|False : if x == c : myret(true) false -;defstruct Trie : -; char : Char -; children : HashTable<Char,Trie> -; -;defn char-hash (c:Char) -> Int : symbol-hash(to-symbol(c)) -;defn new-trie (c:Char) -> Trie : Trie(c,HashTable<Char,Trie>(char-hash)) -;defn tail (s:String) -> String : substring(s,1,length(s)) -; -;defn insert-top (trie:Trie,symbol:Symbol) -> True|False : true -; insert(trie,string-join([" " symbol])) -; -;defn insert (trie:Trie,string:String) -> True|False : -; if length(string) == 0 : char(trie) -; -; val child = get?(children(trie),string[0],false) -; if length(string) == 1 : -; match(child) : -; (c:Trie) : false -; (c:False) : -; children(trie)[string[0]] = new-trie(string[0]) -; true -; else : -; match(child) : -; (c:Trie) : insert(c,tail(string)) -; (c:False) : -; val t = new-trie(string[0]) -; insert(t,tail(string)) -; children(trie)[string[0]] = t -; -;defn has? (trie:Trie, string:String) -> True|False : -; if length(string) == 0 : true -; if length(string) >= 1 : -; if key?(children(trie),string[0]) : -; has?(tail(string), children(trie)[string[0]]) -; else : false -; -;defn any-prefixes? (trie:Trie,delim:String) -> String|False : -; if has?(trie,delim) : -; val c = get-children-after(trie:Trie,delim:String) -; if length(keys(c)) > 1 : -; -; -; if length(partial-delim) == 0 : to-string(char(trie)) -; if length(partial-delim) == 1 : -; if key?(children(trie),partial-delim[0]) : any-prefixes?(...WAS HERE -; if char(trie) == partial-delim[0] : -; if length(keys(children(trie))) >= 2 : to-string(char(trie)) -; else : false -; else : -; label<String|False> myret : -; for x in children(trie) do : -; match(any-prefixes?(value(x),full-delim,full-delim)) : -; (s:False) : false -; (s:String) : myret(string-join([char(trie) s])) -; false -; else : -; label<String|False> myret : -; for x in children(trie) do : -; if char(trie) == partial-delim[0] : -; match(any-prefixes?(value(x),tail(partial-delim),full-delim)) : -; (s:False) : false -; (s:String) : myret(string-join([char(trie) s])) -; match(any-prefixes?(value(x),partial-delim,full-delim)) : -; (s:False) : false -; (s:String) : myret(string-join([char(trie) s])) -; match(any-prefixes?(value(x),full-delim,full-delim)) : -; (s:False) : false -; (s:String) : myret(string-join([char(trie) s])) -; false - +;--------------- Prefix Checker -------------------- + +defstruct Trie : + children : HashTable<Symbol,Trie> + end? : True|False with: (setter => set-end) + +defmethod print (o:OutputStream,t:Trie) : + print-all(o,["[end?:" end?(t) ",children:" children(t) "]"]) + +defn split (s:Symbol) -> List<Symbol> : + map(to-symbol,split(to-string(s),'$')) + +defn contains? (t:Trie,s:Symbol) -> True|False : + key?(children(t),s) + +defn empty? (t:Trie) -> True|False : + length(children(t)) == 0 + +defn add (t:Trie,ls:List<Symbol>) -> True|False : + var t*:Trie = t + var saw-end? = false + for x in ls do : + if end?(t*) : saw-end? = true + if contains?(t*,x) : t* = children(t*)[x] + else : + val temp = Trie(HashTable<Symbol,Trie>(symbol-hash),false) + children(t*)[x] = temp + t* = temp + set-end(t*,true) + saw-end? or not empty?(t*) + +defn contains? (t:Trie,ls:List<Symbol>) -> True|False : + var t*:Trie = t + label<True|False> myret : + for x in ls do : + if contains?(t*,x) : t* = children(t*)[x] + else : myret(false) + myret(end?(t*)) ;--------------- Check High Form Pass ------------------- public defn check-high-form (c:Circuit) -> Circuit : @@ -236,7 +204,7 @@ public defn check-high-form (c:Circuit) -> Circuit : NEQUAL-OP : correct-num(2,0) EQUIV-OP : correct-num(2,0) NEQUIV-OP : correct-num(2,0) - MUX-OP : correct-num(3,0) + ;MUX-OP : correct-num(3,0) PAD-OP : correct-num(1,1) AS-UINT-OP : correct-num(1,0) AS-SINT-OP : correct-num(1,0) @@ -290,10 +258,11 @@ public defn check-high-form (c:Circuit) -> Circuit : defn check-high-form-m (m:Module) -> Module : val names = HashTable<Symbol,True>(symbol-hash) val mnames = HashTable<Symbol,True>(symbol-hash) + val tries = Trie(HashTable<Symbol,Trie>(symbol-hash),false) defn check-high-form-e (e:Expression) -> Expression : defn valid-subexp (e:Expression) -> Expression : match(e) : - (e:Ref|SubField|SubIndex|SubAccess) : false + (e:Ref|SubField|SubIndex|SubAccess|Mux|ValidIf) : false (e) : add(errors,InvalidAccess()) e match(map(check-high-form-e,e)) : @@ -301,6 +270,7 @@ public defn check-high-form (c:Circuit) -> Circuit : if not key?(names,name(e)) : add(errors,UndeclaredReference(name(e))) (e:DoPrim) : check-high-form-primop(e) + (e:Mux|ValidIf) : e (e:UIntValue) : false (e:SubAccess) : valid-subexp(exp(e)) @@ -313,7 +283,9 @@ public defn check-high-form (c:Circuit) -> Circuit : defn check-name (name:Symbol) -> Symbol : if key?(names,name) : add(errors,NotUnique(name)) else : names[name] = true - name + val ls = split(name) + if add(tries,ls) : add(errors,IsPrefix(name)) + name sinfo! = info(s) map(check-name,s) map(check-high-form-t,s) @@ -391,6 +363,10 @@ defn IndexOnNonVector (info:FileInfo) : PassException $ string-join $ [info ": [module " mname "] Index illegal on non-vector type."] +defn AccessIndexNotUInt (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Access index must be a UInt type."] + defn IndexNotUInt (info:FileInfo) : PassException $ string-join $ [info ": [module " mname "] Index is not of UIntType."] @@ -435,9 +411,29 @@ defn OpNotAllSameType (info:FileInfo, op:Symbol) : PassException $ string-join $ [info ": [module " mname "] Primop " op " requires all operands to have the same type."] -defn NodeGroundType (info:FileInfo) : +defn NodePassiveType (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Node must be a passive type."] + +defn MuxSameType (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Must mux between equivalent types."] + +defn MuxPassiveTypes (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Must mux between passive types."] + +defn MuxCondUInt (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] A mux condition must be of type UInt."] + +defn ValidIfPassiveTypes (info:FileInfo) : PassException $ string-join $ - [info ": [module " mname "] Node must be a ground type."] + [info ": [module " mname "] Must validif a passive type."] + +defn ValidIfCondUInt (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] A validif condition must be of type UInt."] ;---------------- Helper Functions -------------- defmethod equal? (t1:Type,t2:Type) -> True|False : @@ -505,9 +501,9 @@ defn check-types-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) - NEQUAL-OP : false EQUIV-OP : all-same-type(args(e)) NEQUIV-OP : all-same-type(args(e)) - MUX-OP : - all-same-type(tail(args(e))) - is-uint(head(args(e))) + ;MUX-OP : + ; all-same-type(tail(args(e))) + ; is-uint(head(args(e))) PAD-OP : false AS-UINT-OP : false AS-SINT-OP : false @@ -517,20 +513,31 @@ defn check-types-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) - SHIFT-RIGHT-OP : false CONVERT-OP : false NEG-OP : false - BIT-NOT-OP : all-same-type(args(e)) - BIT-AND-OP : all-same-type(args(e)) - BIT-OR-OP : all-same-type(args(e)) - BIT-XOR-OP : all-same-type(args(e)) - BIT-SELECT-OP : false - BITS-SELECT-OP : false - BIT-AND-REDUCE-OP : all-uint(args(e)) - BIT-OR-REDUCE-OP : all-uint(args(e)) - BIT-XOR-REDUCE-OP : all-uint(args(e)) - CONCAT-OP : all-uint(args(e)) + BIT-NOT-OP : all-same-type(args(e)) ;can be either uint or sint + BIT-AND-OP : all-same-type(args(e)) ;can be either uint or sint + BIT-OR-OP : all-same-type(args(e)) ;can be either uint or sint + BIT-XOR-OP : all-same-type(args(e)) ;can be either uint or sint + BIT-SELECT-OP : false ;can be either uint or sint + BITS-SELECT-OP : false ;can be either uint or sint + BIT-AND-REDUCE-OP : false ;can be either uint or sint + BIT-OR-REDUCE-OP : false ;can be either uint or sint + BIT-XOR-REDUCE-OP : false ;can be either uint or sint + CONCAT-OP : false ;can be either uint or sint ;----------------- Check Types Pass --------------------- public defn check-types (c:Circuit) -> Circuit : val errors = Vector<PassException>() + defn passive? (t:Type) -> True|False : + match(t) : + (t:UIntType|SIntType) : true + (t:VectorType) : passive?(type(t)) + (t:BundleType) : + var p? = true + for x in fields(t) do : + if (flip(x) == REVERSE) : p? = false + if not passive?(type(x)) : p? = false + p? + (t) : true defn check-types-e (info:FileInfo,e:Expression) -> Expression : match(map(check-types-e{info,_},e)) : (e:WRef) : e @@ -549,7 +556,18 @@ public defn check-types (c:Circuit) -> Circuit : match(type(exp(e))) : (t:VectorType) : false (t) : add(errors,IndexOnNonVector(info)) + match(type(index(e))) : + (t:UIntType) : false + (t) : add(errors,AccessIndexNotUInt(info)) (e:DoPrim) : check-types-primop(e,errors,info) + (e:Mux) : + if type(tval(e)) != type(fval(e)) : add(errors,MuxSameType(info)) + if not passive?(type(e)) : add(errors,MuxPassiveTypes(info)) + if not passive?(type(e)) : add(errors,MuxPassiveTypes(info)) + if not (type(cond(e)) typeof UIntType) : add(errors,MuxCondUInt(info)) + (e:ValidIf) : + if not passive?(type(e)) : add(errors,ValidIfPassiveTypes(info)) + if not (type(cond(e)) typeof UIntType) : add(errors,ValidIfCondUInt(info)) (e:UIntValue|SIntValue) : false e @@ -590,8 +608,8 @@ public defn check-types (c:Circuit) -> Circuit : (s:Conditionally) : if type(pred(s)) != ut() : add(errors,PredNotUInt(info(s))) (s:DefNode) : - if not type(value(s)) typeof UIntType|SIntType : - add(errors,NodeGroundType(info(s))) + if not passive?(type(value(s))) : + add(errors,NodePassiveType(info(s))) (s) : false s }() @@ -647,12 +665,20 @@ public defn check-genders (c:Circuit) -> Circuit : defn check-gender (info:FileInfo,genders:HashTable<Symbol,Gender>,e:Expression,desired:Gender) -> False : val gender = get-gender(e,genders) val kind* = get-kind(e) - val flip? = - match(type(e)) : - (t:BundleType) : - for f in fields(t) any? : flip(f) == REVERSE - (t) : false + defn flip? (t:Type) -> True|False : + var f? = false + defn flip-rec (t:Type,f:Flip) -> Type : + match(t) : + (t:BundleType) : + for field in fields(t) do : + flip-rec(type(field),f * flip(field)) + (t:VectorType) : flip-rec(type(t),f) + (t) : if f == REVERSE : f? = true + t + flip-rec(t,DEFAULT) + f? + val has-flip? = flip?(type(e)) ;println(e) ;println(gender) ;println(desired) @@ -663,7 +689,7 @@ public defn check-genders (c:Circuit) -> Circuit : [MALE, FEMALE] : add(errors,WrongGender(info,to-symbol(e),as-srcsnk(desired),as-srcsnk(gender))) [FEMALE, MALE] : - if (kind* == PortKind() or kind* == InstanceKind()) and flip? == false : + if (kind* == PortKind() or kind* == InstanceKind()) and has-flip? == false : ; OK! false else : @@ -682,6 +708,8 @@ public defn check-genders (c:Circuit) -> Circuit : (e:DoPrim) : MALE (e:UIntValue) : MALE (e:SIntValue) : MALE + (e:Mux) : MALE + (e:ValidIf) : MALE defn check-genders-e (info:FileInfo,e:Expression,genders:HashTable<Symbol,Gender>) -> False : do(check-genders-e{info,_,genders},e) @@ -693,6 +721,8 @@ public defn check-genders (c:Circuit) -> Circuit : (e:DoPrim) : for e in args(e) do : check-gender(info,genders,e,MALE) + (e:Mux) : do(check-gender{info,genders,_,MALE},e) + (e:ValidIf) : do(check-gender{info,genders,_,MALE},e) (e:UIntValue) : false (e:SIntValue) : false @@ -706,7 +736,7 @@ public defn check-genders (c:Circuit) -> Circuit : (s:DefNode) : check-gender(info(s),genders,value(s),MALE) genders[name(s)] = MALE - (s:DefMemory) : genders[name(s)] = FEMALE + (s:DefMemory) : genders[name(s)] = MALE (s:WDefInstance) : genders[name(s)] = MALE (s:Connect) : check-gender(info(s),genders,loc(s),FEMALE) @@ -725,8 +755,7 @@ public defn check-genders (c:Circuit) -> Circuit : (s:Stop) : check-gender(info(s),genders,en(s),MALE) check-gender(info(s),genders,clk(s),MALE) - (s:Begin) : false - + (s:Begin|IsInvalid) : false for m in modules(c) do : mname = name(m) diff --git a/src/main/stanza/errorstemp.stanza b/src/main/stanza/errorstemp.stanza deleted file mode 100644 index 9c5043f2..00000000 --- a/src/main/stanza/errorstemp.stanza +++ /dev/null @@ -1,994 +0,0 @@ -defpackage firrtl/errors : - import core - import verse - import firrtl/ir2 - import firrtl/ir-utils - import firrtl/primops - import firrtl/passes - import firrtl-main - import bigint2 - -; TODO -; make sure it compiles, write tests, look over code to make sure its right -;========== ALL CHECKS ================= -;PARSER CHECK -; * No nested modules <- parser -; * Only modules in circuit (no statements or expressions) <- parser -; * Module must be a reference in inst declaration - -;AFTER ?????? -; o No combinational loops - -;================= High Form Check ========================== -; * Subexps of Subfield and Index can only be subfields, index, or refs -; * Can only connect to a Ref or Subfield or Index or WritePort -; * A module has the same name as main of circuit -; * mems cannot be a bundle with flips -; * instance module must have the same name as a defined module -; * Unique names per module -; * No name can be a prefix of any other name. -; * all references are declared -; * UInt only has positive ints -; * Vector types has positive size -; * Width sizes are positive -; * Primops have the correct number of arguments - -public defstruct CheckHighForm <: Pass -public defmethod pass (b:CheckHighForm) -> (Circuit -> Circuit) : check-high-form -public defmethod name (b:CheckHighForm) -> String : "High Form Check" -public defmethod short-name (b:CheckHighForm) -> String : "high-form-check" - -var sinfo! = FileInfo() - -;----------------- Errors ------------------------ -defn NotUnique (name:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Reference " name " does not have a unique name."] - -defn IsPrefix (prefix:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Symbol " prefix " is a prefix."] - -defn InvalidLOC () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Invalid connect to an expression that is not a reference or a WritePort."] - -defn NegUInt () : - PassException $ string-join $ - [sinfo! ": [module " mname "] UIntValue cannot be negative."] - -defn UndeclaredReference (name:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Reference " name " is not declared."] - -defn PoisonWithFlip (name:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Poison " name " cannot be a bundle type with flips."] - -defn MemWithFlip (name:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Memory " name " cannot be a bundle type with flips."] - -defn InvalidAccess () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Invalid access to non-reference."] - -defn NoTopModule (name:Symbol) : - PassException $ string-join $ - [sinfo! ": A single module must be named " name "."] - -defn ModuleNotDefined (name:Symbol) : - PassException $ string-join $ - [sinfo! ": Module " name " is not defined."] - -defn IncorrectNumArgs (op:Symbol, n:Int) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Primop " op " requires " n " expression arguments."] - -defn IncorrectNumConsts (op:Symbol, n:Int) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Primop " op " requires " n " integer arguments."] - -defn NegWidth () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Width cannot be negative or zero."] - -defn NegVecSize () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Vector type size cannot be negative."] - -defn NegMemSize () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Memory size cannot be negative or zero."] - -defn IllegalUnknownWidth () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Widths must be defined for memories and poison nodes."] - -defn BadPrintf (x:Char) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Bad printf format: \"%" x "\""];" - -defn BadPrintfTrailing () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Bad printf format: trailing \"%\""];" - -defn BadPrintfIncorrectNum () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Bad printf format: incorrect number of arguments"];" - - -;---------------- Helper Functions -------------- -defn has-flip? (t:Type) -> True|False : - var has? = false - defn find-flip (t:Type) -> Type : - match(t) : - (t:BundleType) : - for f in fields(t) do : - if flip(f) == REVERSE : has? = true - t - (t) : t - find-flip(t) - map(find-flip,t) - has? - -defn contains?<?T> (c:?T,cs:Streamable<?T>) -> True|False : - label<True|False> myret : - for x in cs do : - if x == c : myret(true) - false - -;defstruct Trie : -; char : Char -; children : HashTable<Char,Trie> -; -;defn char-hash (c:Char) -> Int : symbol-hash(to-symbol(c)) -;defn new-trie (c:Char) -> Trie : Trie(c,HashTable<Char,Trie>(char-hash)) -;defn tail (s:String) -> String : substring(s,1,length(s)) -; -;defn insert-top (trie:Trie,symbol:Symbol) -> True|False : true -; insert(trie,string-join([" " symbol])) -; -;defn insert (trie:Trie,string:String) -> True|False : -; if length(string) == 0 : char(trie) -; -; val child = get?(children(trie),string[0],false) -; if length(string) == 1 : -; match(child) : -; (c:Trie) : false -; (c:False) : -; children(trie)[string[0]] = new-trie(string[0]) -; true -; else : -; match(child) : -; (c:Trie) : insert(c,tail(string)) -; (c:False) : -; val t = new-trie(string[0]) -; insert(t,tail(string)) -; children(trie)[string[0]] = t -; -;defn has? (trie:Trie, string:String) -> True|False : -; if length(string) == 0 : true -; if length(string) >= 1 : -; if key?(children(trie),string[0]) : -; has?(tail(string), children(trie)[string[0]]) -; else : false -; -;defn any-prefixes? (trie:Trie,delim:String) -> String|False : -; if has?(trie,delim) : -; val c = get-children-after(trie:Trie,delim:String) -; if length(keys(c)) > 1 : -; -; -; if length(partial-delim) == 0 : to-string(char(trie)) -; if length(partial-delim) == 1 : -; if key?(children(trie),partial-delim[0]) : any-prefixes?(...WAS HERE -; if char(trie) == partial-delim[0] : -; if length(keys(children(trie))) >= 2 : to-string(char(trie)) -; else : false -; else : -; label<String|False> myret : -; for x in children(trie) do : -; match(any-prefixes?(value(x),full-delim,full-delim)) : -; (s:False) : false -; (s:String) : myret(string-join([char(trie) s])) -; false -; else : -; label<String|False> myret : -; for x in children(trie) do : -; if char(trie) == partial-delim[0] : -; match(any-prefixes?(value(x),tail(partial-delim),full-delim)) : -; (s:False) : false -; (s:String) : myret(string-join([char(trie) s])) -; match(any-prefixes?(value(x),partial-delim,full-delim)) : -; (s:False) : false -; (s:String) : myret(string-join([char(trie) s])) -; match(any-prefixes?(value(x),full-delim,full-delim)) : -; (s:False) : false -; (s:String) : myret(string-join([char(trie) s])) -; false - - -;--------------- Check High Form Pass ------------------- -public defn check-high-form (c:Circuit) -> Circuit : - val errors = Vector<PassException>() - defn check-high-form-primop (e:DoPrim) -> False : - defn correct-num (ne:Int|False,nc:Int) -> False : - if not (ne typeof False) : - if length(args(e)) != ne as Int : add(errors,IncorrectNumArgs(to-symbol(op(e)),ne as Int)) - if length(consts(e)) != nc : add(errors,IncorrectNumConsts(to-symbol $ op(e),nc)) - - switch {op(e) == _} : - ADD-OP : correct-num(2,0) - SUB-OP : correct-num(2,0) - MUL-OP : correct-num(2,0) - DIV-OP : correct-num(2,0) - MOD-OP : correct-num(2,0) - QUO-OP : correct-num(2,0) - REM-OP : correct-num(2,0) - ADD-WRAP-OP : correct-num(2,0) - SUB-WRAP-OP : correct-num(2,0) - LESS-OP : correct-num(2,0) - LESS-EQ-OP : correct-num(2,0) - GREATER-OP : correct-num(2,0) - GREATER-EQ-OP : correct-num(2,0) - EQUAL-OP : correct-num(2,0) - NEQUAL-OP : correct-num(2,0) - EQUIV-OP : correct-num(2,0) - NEQUIV-OP : correct-num(2,0) - MUX-OP : correct-num(3,0) - PAD-OP : correct-num(1,1) - AS-UINT-OP : correct-num(1,0) - AS-SINT-OP : correct-num(1,0) - DYN-SHIFT-LEFT-OP : correct-num(2,0) - DYN-SHIFT-RIGHT-OP : correct-num(2,0) - SHIFT-LEFT-OP : correct-num(1,1) - SHIFT-RIGHT-OP : correct-num(1,1) - CONVERT-OP : correct-num(1,0) - NEG-OP : correct-num(1,0) - BIT-NOT-OP : correct-num(1,0) - BIT-AND-OP : correct-num(2,0) - BIT-OR-OP : correct-num(2,0) - BIT-XOR-OP : correct-num(2,0) - BIT-AND-REDUCE-OP : correct-num(false,0) - BIT-OR-REDUCE-OP : correct-num(false,0) - BIT-XOR-REDUCE-OP : correct-num(false,0) - CONCAT-OP : correct-num(2,0) - BIT-SELECT-OP : correct-num(1,1) - BITS-SELECT-OP : correct-num(1,2) - - defn check-fstring (s:String,i:Int) -> False : - val valid-formats = "bedxs" - var percent = false - var ret = true - var npercents = 0 - for x in s do : - if (not contains?(valid-formats,x)) and percent : - add(errors,BadPrintf(x)) - if x == '%' : npercents = npercents + 1 - percent = x == '%' - if percent : add(errors,BadPrintfTrailing()) - if npercents != i : add(errors,BadPrintfIncorrectNum()) - defn check-valid-loc (e:Expression) -> False : - match(e) : - (e:UIntValue|SIntValue|DoPrim) : - add(errors,InvalidLOC()) - (e) : false - defn check-high-form-w (w:Width) -> Width : - match(w) : - (w:IntWidth) : - if width(w) <= to-long(0) : add(errors,NegWidth()) - w - (w) : w - defn check-high-form-t (t:Type) -> Type : - match(map(check-high-form-t,t)) : - (t:VectorType) : - if size(t) < 0 : add(errors,NegVecSize()) - (t) : false - map(check-high-form-w,t) - - defn check-high-form-m (m:Module) -> Module : - val names = HashTable<Symbol,True>(symbol-hash) - val mnames = HashTable<Symbol,True>(symbol-hash) - defn check-high-form-e (e:Expression) -> Expression : - defn valid-subexp (e:Expression) -> Expression : - match(e) : - (e:Ref|SubField|SubIndex|SubAccess) : false - (e) : add(errors,InvalidAccess()) - e - match(map(check-high-form-e,e)) : - (e:Ref) : - if not key?(names,name(e)) : - add(errors,UndeclaredReference(name(e))) - (e:DoPrim) : check-high-form-primop(e) - (e:UIntValue) : false - (e:SubAccess) : - valid-subexp(exp(e)) - e - (e) : map(valid-subexp,e) - map(check-high-form-w,e) - map(check-high-form-t,e) - e - defn check-high-form-s (s:Stmt) -> Stmt : - defn check-name (name:Symbol) -> Symbol : - if key?(names,name) : add(errors,NotUnique(name)) - else : names[name] = true - name - sinfo! = info(s) - map(check-name,s) - map(check-high-form-t,s) - map(check-high-form-e,s) - match(s) : - (s:DefWire|DefRegister|DefNode|Conditionally|Stop|Begin) : false - (s:DefPoison) : - if has-flip?(type(s)) : add(errors, PoisonWithFlip(name(s))) - check-high-form-t(type(s)) - (s:DefMemory) : - if has-flip?(data-type(s)) : add(errors, MemWithFlip(name(s))) - if depth(s) <= 0 : add(errors,NegMemSize()) - (s:DefInstance) : - if not contains?(module(s),map(name,modules(c))) : - add(errors, ModuleNotDefined(module(s))) - (s:Connect) : check-valid-loc(loc(s)) - (s:Print) : check-fstring(string(s),length(args(s))) - (s:BulkConnect) : check-valid-loc(loc(s)) - (s) : false - - map(check-high-form-s,s) - - mname = name(m) - for m in modules(c) do : - mnames[name(m)] = true - for p in ports(m) do : - names[name(p)] = true - map(check-high-form-t,type(p)) - map(check-high-form-w,type(p)) - - match(m) : - (m:ExModule) : false - (m:InModule) : check-high-form-s(body(m)) - m - - var number-top-m = 0 - for m in modules(c) do : - if name(m) == main(c) : number-top-m = number-top-m + 1 - check-high-form-m(m) - sinfo! = info!(c) - if number-top-m != 1 : add(errors,NoTopModule(main(c))) - throw(PassExceptions(errors)) when not empty?(errors) - c - -;==================== CHECK TYPES ===================== -; o Subfields are only on bundles, before type inference <- need to not error, just do unknown-type -; o Indexes are only on vectors -; o pred in conditionally must be of type UInt -; o enable/index in read/writeports must be UInt -; o node's value cannot be a bundle with a flip in it -; o := has same types -; o 2nd arg in dshr/l must be UInt, in general do primops -; o clock must be ClockType -; o reset must be UInt<1> - -public defstruct CheckTypes <: Pass -public defmethod pass (b:CheckTypes) -> (Circuit -> Circuit) : check-types -public defmethod name (b:CheckTypes) -> String : "Check Types" -public defmethod short-name (b:CheckTypes) -> String : "check-types" - -;----------------- Errors --------------------- -defn SubfieldNotInBundle (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Subfield " name " is not in bundle."] - -defn SubfieldOnNonBundle (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Subfield " name " is accessed on a non-bundle."] - -defn IndexTooLarge (info:FileInfo, value:Int) : - PassException $ string-join $ - [info ": [module " mname "] Index with value " value " is too large."] - -defn IndexOnNonVector (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Index illegal on non-vector type."] - -defn IndexNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Index is not of UIntType."] - -defn EnableNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Enable is not of UIntType."] - -defn InvalidConnect (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Type mismatch."] - -defn PrintfArgNotGround (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Printf arguments must be either UIntType or SIntType."] - -defn ReqClk (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Requires a clock typed signal."] - -defn EnNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Enable must be a UIntType typed signal."] - -defn PredNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Predicate not a UIntType."] - -defn OpNotGround (info:FileInfo, op:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Primop " op " cannot operate on non-ground types."] - -defn OpNotUInt (info:FileInfo, op:Symbol,e:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Primop " op " requires argument " e " to be a UInt type."] - -defn OpNotAllUInt (info:FileInfo, op:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Primop " op " requires all arguments to be UInt type."] - -defn OpNotAllSameType (info:FileInfo, op:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Primop " op " requires all operands to have the same type."] - -defn NodeIllegalFlips (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Node cannot be a bundle type with flips."] - -defn OnResetIllegalFlips (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] The register in onreset cannot be a bundle type with flips."] - -;---------------- Helper Functions -------------- -defmethod equal? (t1:Type,t2:Type) -> True|False : - match(t1,t2) : - (t1:ClockType,t2:ClockType) : true - (t1:UIntType,t2:UIntType) : true - (t1:SIntType,t2:SIntType) : true - (t1:BundleType,t2:BundleType) : - var same? = true - for (f1 in fields(t1),f2 in fields(t2)) do : - if flip(f1) != flip(f2) : same? = false - if name(f1) != name(f2) : same? = false - if type(f1) != type(f2) : same? = false - same? - (t1:VectorType,t2:VectorType) : - if type(t1) == type(t2) and size(t1) == size(t2) : true - else : false - (t1,t2) : false - -defn ut () -> UIntType : UIntType(UnknownWidth()) -defn st () -> SIntType : SIntType(UnknownWidth()) - -defn check-types-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) -> False : - defn all-same-type (ls:List<Expression>) -> False : - var error? = false - for x in ls do : - if type(head(ls)) != type(x) : - error? = true - if error? : add(errors,OpNotAllSameType(info,to-symbol $ op(e))) - defn all-ground (ls:List<Expression>) -> False : - var error? = false - for x in ls do : - if not (type(x) typeof UIntType or type(x) typeof SIntType) : - error? = true - if error? : add(errors,OpNotGround(info,to-symbol $ op(e))) - defn all-uint (ls:List<Expression>) -> False : - var error? = false - for x in ls do : - if not (type(x) typeof UIntType) : - error? = true - if error? : add(errors,OpNotAllUInt(info,to-symbol $ op(e))) - defn is-uint (x:Expression) -> False : - var error? = false - if not (type(x) typeof UIntType) : - error? = true - if error? : add(errors,OpNotUInt(info,to-symbol $ op(e),to-symbol(x))) - - all-ground(args(e)) - - switch {op(e) == _} : - ADD-OP : false - SUB-OP : false - MUL-OP : false - DIV-OP : false - MOD-OP : false - QUO-OP : false - REM-OP : false - ADD-WRAP-OP : false - SUB-WRAP-OP : false - LESS-OP : false - LESS-EQ-OP : false - GREATER-OP : false - GREATER-EQ-OP : false - EQUAL-OP : false - NEQUAL-OP : false - EQUIV-OP : all-same-type(args(e)) - NEQUIV-OP : all-same-type(args(e)) - MUX-OP : - all-same-type(tail(args(e))) - is-uint(head(args(e))) - PAD-OP : false - AS-UINT-OP : false - AS-SINT-OP : false - DYN-SHIFT-LEFT-OP : is-uint(args(e)[1]) - DYN-SHIFT-RIGHT-OP : is-uint(args(e)[1]) - SHIFT-LEFT-OP : false - SHIFT-RIGHT-OP : false - CONVERT-OP : false - NEG-OP : false - BIT-NOT-OP : all-same-type(args(e)) - BIT-AND-OP : all-same-type(args(e)) - BIT-OR-OP : all-same-type(args(e)) - BIT-XOR-OP : all-same-type(args(e)) - BIT-SELECT-OP : false - BITS-SELECT-OP : false - BIT-AND-REDUCE-OP : all-uint(args(e)) - BIT-OR-REDUCE-OP : all-uint(args(e)) - BIT-XOR-REDUCE-OP : all-uint(args(e)) - CONCAT-OP : all-uint(args(e)) - -;----------------- Check Types Pass --------------------- -public defn check-types (c:Circuit) -> Circuit : - val errors = Vector<PassException>() - defn check-types-e (info:FileInfo,e:Expression) -> Expression : - match(map(check-types-e{info,_},e)) : - (e:WRef) : e - (e:WSubField) : - match(type(exp(e))) : - (t:BundleType) : - val ft = for p in fields(t) find : name(p) == name(e) - if ft == false : add(errors,SubfieldNotInBundle(info,name(e))) - (t) : add(errors,SubfieldOnNonBundle(info,name(e))) - (e:WSubIndex) : - match(type(exp(e))) : - (t:VectorType) : - if value(e) >= size(t) : add(errors,IndexTooLarge(info,value(e))) - (t) : add(errors,IndexOnNonVector(info)) - (e:WSubAccess) : - match(type(exp(e))) : - (t:VectorType) : false - (t) : add(errors,IndexOnNonVector(info)) - (e:DoPrim) : check-types-primop(e,errors,info) - (e:UIntValue|SIntValue) : false - e - - defn bulk-equals? (t1:Type,t2:Type) -> True|False : - match(t1,t2) : - (t1:BundleType,t2:BundleType) : - var same? = true - for (f1 in fields(t1),f2 in fields(t2)) do : - if name(f1) == name(f2) : - if flip(f1) != flip(f2) : same? = false - if not bulk-equals?(type(f1),type(f2)) : same? = false - same? - (t1:ClockType,t2:ClockType) : true - (t1:UIntType,t2:UIntType) : true - (t1:SIntType,t2:SIntType) : true - (t1:VectorType,t2:VectorType) : - if bulk-equals?(type(t1),type(t2)) : true - else : false - (t1,t2) : false - - defn check-types-s (s:Stmt) -> Stmt : - map{check-types-s,_} $ { - match(map(check-types-e{info(s),_},s)) : - (s:Connect) : - if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s))) - (s:BulkConnect) : - if not bulk-equals?(type(loc(s)),type(exp(s))) : - add(errors,InvalidConnect(info(s))) - (s:Stop) : - if type(clk(s)) != ClockType() : add(errors,ReqClk(info(s))) - if type(en(s)) != ut() : add(errors,EnNotUInt(info(s))) - (s:Print) : - for x in args(s) do : - if type(x) != ut() and type(x) != st(): - add(errors,PrintfArgNotGround(info(s))) - if type(clk(s)) != ClockType() : add(errors,ReqClk(info(s))) - if type(en(s)) != ut() : add(errors,EnNotUInt(info(s))) - (s:Conditionally) : - if type(pred(s)) != ut() : add(errors,PredNotUInt(info(s))) - (s:DefNode) : - if has-flip?(type(value(s))) : add(errors,NodeIllegalFlips(info(s))) - (s) : false - s }() - - for m in modules(c) do : - mname = name(m) - match(m) : - (m:ExModule) : false - (m:InModule) : check-types-s(body(m)) - throw(PassExceptions(errors)) when not empty?(errors) - c - -;================= GENDER CHECK ========================== -; o Nodes always male -; o Accessors only have one gender, unless rdwr -; o output/input only one gender -; o correctly check for the base bundle - -public defstruct CheckGenders <: Pass -public defmethod pass (b:CheckGenders) -> (Circuit -> Circuit) : check-genders -public defmethod name (b:CheckGenders) -> String : "Check Genders" -public defmethod short-name (b:CheckGenders) -> String : "check-genders" - -;----------------- Errors --------------------- -defn WrongGender (info:FileInfo,expr:Symbol,wrong:Symbol,right:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Expression " expr " is used as a " wrong " but can only be used as a " right "."] - -;---------------- Helper Functions -------------- -defn dir-to-gender (d:Direction) -> Gender : - switch {_ == d} : - INPUT : MALE - OUTPUT : FEMALE ;BI-GENDER - -defn as-srcsnk (g:Gender) -> Symbol : - switch {_ == g} : - MALE : `source - FEMALE : `sink - UNKNOWN-GENDER : `unknown - BI-GENDER : `sourceOrSink - -;----------------- Check Genders Pass --------------------- - -public defn check-genders (c:Circuit) -> Circuit : - val errors = Vector<PassException>() - defn get-kind (e:Expression) -> Kind : - match(e) : - (e:WRef) : kind(e) - (e:WSubField) : get-kind(exp(e)) - (e:WSubIndex) : get-kind(exp(e)) - (e:WSubAccess) : get-kind(exp(e)) - (e) : NodeKind() - - defn check-gender (info:FileInfo,genders:HashTable<Symbol,Gender>,e:Expression,desired:Gender) -> False : - val gender = get-gender(e,genders) - val kind* = get-kind(e) - val flip? = - match(type(e)) : - (t:BundleType) : - for f in fields(t) any? : flip(f) == REVERSE - (t) : false - - ;println(e) - ;println(gender) - ;println(desired) - ;println(kind*) - ;println(desired == gender) - ;if gender != desired and gender != BI-GENDER: - switch fn ([x,y]) : gender == x and desired == y : - [MALE, FEMALE] : - add(errors,WrongGender(info,to-symbol(e),as-srcsnk(desired),as-srcsnk(gender))) - [FEMALE, MALE] : - if (kind* == PortKind() or kind* == InstanceKind()) and flip? == false : - ; OK! - false - else : - ; Not Ok! - add(errors,WrongGender(info,to-symbol(e),as-srcsnk(desired),as-srcsnk(gender))) - else : false - - defn get-gender (e:Expression,genders:HashTable<Symbol,Gender>) -> Gender : - match(e) : - (e:WRef) : genders[name(e)] - (e:WSubField) : - val f = {_ as Field} $ for f in fields(type(exp(e)) as BundleType) find : name(f) == name(e) - get-gender(exp(e),genders) * flip(f) - (e:WSubIndex) : get-gender(exp(e),genders) - (e:WSubAccess) : get-gender(exp(e),genders) - (e:DoPrim) : MALE - (e:UIntValue) : MALE - (e:SIntValue) : MALE - - defn check-genders-e (info:FileInfo,e:Expression,genders:HashTable<Symbol,Gender>) -> False : - do(check-genders-e{info,_,genders},e) - match(e) : - (e:WRef) : false - (e:WSubField) : false - (e:WSubIndex) : false - (e:WSubAccess) : false - (e:DoPrim) : - for e in args(e) do : - check-gender(info,genders,e,MALE) - (e:UIntValue) : false - (e:SIntValue) : false - - defn check-genders-s (s:Stmt,genders:HashTable<Symbol,Gender>) -> False : - do(check-genders-e{info(s),_:Expression,genders},s) - do(check-genders-s{_:Stmt,genders},s) - match(s) : - (s:DefWire) : genders[name(s)] = BI-GENDER - (s:DefPoison) : genders[name(s)] = MALE - (s:DefRegister) : genders[name(s)] = BI-GENDER - (s:DefNode) : - check-gender(info(s),genders,value(s),MALE) - genders[name(s)] = MALE - (s:DefMemory) : genders[name(s)] = FEMALE - (s:WDefInstance) : genders[name(s)] = MALE - (s:Connect) : - check-gender(info(s),genders,loc(s),FEMALE) - check-gender(info(s),genders,exp(s),MALE) - (s:Print) : - for x in args(s) do : - check-gender(info(s),genders,x,MALE) - check-gender(info(s),genders,en(s),MALE) - check-gender(info(s),genders,clk(s),MALE) - (s:BulkConnect) : - check-gender(info(s),genders,loc(s),FEMALE) - check-gender(info(s),genders,exp(s),MALE) - (s:Conditionally) : - check-gender(info(s),genders,pred(s),MALE) - (s:Empty) : false - (s:Stop) : - check-gender(info(s),genders,en(s),MALE) - check-gender(info(s),genders,clk(s),MALE) - (s:Begin) : false - - - for m in modules(c) do : - mname = name(m) - val genders = HashTable<Symbol,Gender>(symbol-hash) - for p in ports(m) do : - genders[name(p)] = dir-to-gender(direction(p)) - match(m) : - (m:ExModule) : false - (m:InModule) : check-genders-s(body(m),genders) - throw(PassExceptions(errors)) when not empty?(errors) - c - -;================= Width Check ========================== -;AFTER WIDTH INFERENCE -; * No names -; * No Unknowns -; * All widths are positive -; * widths are large enough to contain value - - -public defstruct CheckWidths <: Pass -public defmethod pass (b:CheckWidths) -> (Circuit -> Circuit) : check-width -public defmethod name (b:CheckWidths) -> String : "Width Check" -public defmethod short-name (b:CheckWidths) -> String : "width-check" - -;----------------- Errors ------------------------ - -defn UninferredWidth (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Uninferred width."] - -defn WidthTooSmall (info:FileInfo,v:String) : - PassException $ string-join $ - [info ": [module " mname "] Width too small for constant " v "."] - -;---------------- Helper Functions -------------- - -;--------------- Check Width Pass ------------------- -public defn check-width (c:Circuit) -> Circuit : - val errors = Vector<PassException>() - - defn check-width-m (m:Module) -> False : - defn check-width-w (info:FileInfo,w:Width) -> Width : - match(w) : - (w:IntWidth) : - if width(w) <= to-long(0) : add(errors,NegWidth()) - (w) : - add(errors,UninferredWidth(info)) - w - - defn check-width-e (info:FileInfo,e:Expression) -> Expression : - match(map(check-width-e{info,_},e)) : - (e:UIntValue) : - match(width(e)) : - (w:IntWidth) : - if max(to-long(1),to-long(req-num-bits(value(e)) - 1)) > width(w) : - add(errors,WidthTooSmall(info,to-string(value(e)))) - (w) : add(errors,UninferredWidth(info)) - check-width-w(info,width(e)) - (e:SIntValue) : - match(width(e)) : - (w:IntWidth) : - if to-long(req-num-bits(value(e))) > width(w) : - add(errors,WidthTooSmall(info,to-string(value(e)))) - (w) : add(errors,UninferredWidth(info)) - check-width-w(info,width(e)) - (e:DoPrim) : false - (e) : false - - ;mapr(check-width-w{info,_},type(map(check-width-e{info,_},e))) - e - - defn check-width-s (s:Stmt) -> Stmt : - sinfo! = info(s) - map(check-width-e{info(s),_},map(check-width-s,s)) - map(mapr{check-width-w{info(s),_},_:Type},s) - - for p in ports(m) do : - mapr(check-width-w{info(p),_},type(p)) - - match(m) : - (m:ExModule) : false - (m:InModule) : check-width-s(body(m)) - false - - for m in modules(c) do : - mname = name(m) - check-width-m(m) - throw(PassExceptions(errors)) when not empty?(errors) - c - - -;================ Initialization Check ================== -; Error on all componenents that are not connected to. - -public defstruct CheckInitialization <: Pass -public defmethod pass (b:CheckInitialization) -> (Circuit -> Circuit) : check-init -public defmethod name (b:CheckInitialization) -> String : "Check Initialization" -public defmethod short-name (b:CheckInitialization) -> String : "check-init" - -;----------------- Errors ------------------------ - -defn RefNotInitialized (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Reference " name " is not fully initialized."] - -;------------ Helper Functions ------------- - -;------------ Pass ------------------ - -public defn check-init (c:Circuit) : - val errors = Vector<PassException>() - - defn check-init-m (m:InModule) : - defn get-name (e:Expression) -> Symbol : - match(e) : - (e:WRef) : name(e) - (e:WSubField) : symbol-join([get-name(exp(e)) `. name(e)]) - (e) : error("Shouldn't be here") - defn has-void? (e:Expression) -> True|False : - var void? = false - defn has-void (e:Expression) -> Expression : - match(e) : - (e:WVoid) : - void? = true - e - (e) : map(has-void,e) - has-void(e) - void? - defn check-init-s (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : - if has-void?(exp(s)) : add(errors,RefNotInitialized(info(s),get-name(loc(s)))) - s - (s) : map(check-init-s,s) - - check-init-s(body(m)) - - for m in modules(c) do : - mname = name(m) - match(m) : - (m:InModule) : check-init-m(m) - (m) : false - - throw(PassExceptions(errors)) when not empty?(errors) - c - -;;================= Low Form Check ========================== -;;AFTER LOWERING -;; o All things connect to once -;; o no reg -;; o no accessors -;; o only vecs are for memories -;; o no bundles (future, will have them for mems) -;; o only predicated conditional connects -; -;public defstruct CheckLowForm <: Pass -;public defmethod pass (b:CheckLowForm) -> (Circuit -> Circuit) : check-low-form -;public defmethod name (b:CheckLowForm) -> String : "Low Form Check" -;public defmethod short-name (b:CheckLowForm) -> String : "low-form-check" -; -;;----------------- Errors ------------------------ -;defn InvalidVec (info:FileInfo,name:Symbol) : -; PassException $ string-join $ -; [info ": [module " mname "] Expression " name " has an illegal vector type."] -; -;defn InvalidBundle (info:FileInfo,name:Symbol) : -; PassException $ string-join $ -; [info ": [module " mname "] Expression " name " has an illegal bundle type."] -; -;defn NoWhen (info:FileInfo) : -; PassException $ string-join $ -; [info ": [module " mname "] Illegal when statement. No when statements with multiple statements are allowed in low firrtl."] -; -;defn SingleAssignment (info:FileInfo,name:Symbol) : -; PassException $ string-join $ -; [info ": [module " mname "] Illegal assignment to " name ". Wires can only be assigned to once."] -; -;defn NoOnReset (info:FileInfo) : -; PassException $ string-join $ -; [info ": [module " mname "] Invalid use of on-reset. No on-resets are allowed in low firrtl."] -; -;defn NoBulkConnect (info:FileInfo) : -; PassException $ string-join $ -; [info ": [module " mname "] Invalid use of <>. No <>'s are allowed in low firrtl."] -; -;;---------------- Helper Functions -------------- -; -;;--------------- Check Low Form Pass ------------------- -;public defn check-low-form (c:Circuit) -> Circuit : -; val errors = Vector<PassException>() -; -; defn check-low-form-t (info:FileInfo,t:Type,name:Symbol) -> False : -; match(t) : -; (t:VectorType) : add(errors,InvalidVec(info,name)) -; (t:BundleType) : add(errors,InvalidBundle(info,name)) -; (t) : false -; -; defn check-low-form-m (m:Module) -> False : -; for p in ports(m) do : -; check-low-form-t(info(p),type(p),name(p)) -; -; val assigned? = HashTable<Symbol,True>(symbol-hash) -; val insts = Vector<Symbol>() -; val mems = Vector<Symbol>() -; defn check-correct-exp (info:FileInfo,e:Expression) -> False : -; do(check-correct-exp{info,_:Expression},e) -; match(e) : -; (e:Ref) : -; if contains?(insts,name(e)) : -; for f in fields(type(e) as BundleType) do : -; check-low-form-t(info,type(f),name(e)) -; if contains?(mems,name(e)) : -; check-low-form-t(info,type(type(e) as VectorType),name(e)) -; (e) : false ;check-low-form-t(info,type(e),to-symbol $ to-string(e)) -; defn check-low-form-s (s:Stmt) -> False : -; match(s) : -; (s:DefWire) : -; check-low-form-t(info(s),type(s),name(s)) -; (s:DefPoison) : -; check-low-form-t(info(s),type(s),name(s)) -; (s:DefMemory) : -; check-low-form-t(info(s),type(s),name(s)) -; add(mems,name(s)) -; (s:DefInstance) : -; for f in fields(type(module(s)) as BundleType) do : -; check-low-form-t(info(s),type(f),name(s)) -; add(insts,name(s)) -; (s:DefNode) : -; check-correct-exp(info(s),value(s)) -; (s:Print) : -; for x in args(s) do : -; check-correct-exp(info(s),x) -; (s:DefRegister) : false -; (s:DefAccessor) : false -; (s:Conditionally) : -; if (not alt(s) typeof Empty) or (conseq(s) typeof Begin) : add(errors,NoWhen(info(s))) -; (s:OnReset) : add(errors,NoOnReset(info(s))) -; (s:BulkConnect) : add(errors,NoBulkConnect(info(s))) -; (s:Connect) : -; check-correct-exp(info(s),exp(s)) -; match(loc(s)) : -; (e:Ref|Subfield) : -; val n* = to-symbol $ to-string $ e -; if key?(assigned?,n*) : add(errors,SingleAssignment(info(s),n*)) -; else : assigned?[to-symbol $ to-string $ e] = true -; (e) : check-correct-exp(info(s),e) -; (s:Empty) : false -; (s:Stop) : false -; (s:Begin) : do(check-low-form-s,s) -; -; match(m) : -; (m:ExModule) : false -; (m:InModule) : check-low-form-s(body(m)) -; false -; -; for m in modules(c) do : -; mname = name(m) -; check-low-form-m(m) -; throw(PassExceptions(errors)) when not empty?(errors) -; c -; diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index d9586df9..4d906c70 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -45,7 +45,7 @@ public val NEQUAL-OP = new PrimOp public val EQUAL-OP = new PrimOp public val NEQUIV-OP = new PrimOp public val EQUIV-OP = new PrimOp -public val MUX-OP = new PrimOp +;public val MUX-OP = new PrimOp public val PAD-OP = new PrimOp public val AS-UINT-OP = new PrimOp public val AS-SINT-OP = new PrimOp @@ -84,6 +84,15 @@ public defstruct SubAccess <: Expression : exp: Expression index: Expression type: Type with: (as-method => true) +public defstruct Mux <: Expression : + cond: Expression + tval: Expression + fval: Expression + type: Type with: (as-method => true) +public defstruct ValidIf <: Expression : + cond: Expression + value: Expression + type: Type with: (as-method => true) public defstruct UIntValue <: Expression : value: BigInt width: Width @@ -147,6 +156,9 @@ public defstruct Connect <: Stmt : ;LOW info: FileInfo with: (as-method => true) loc: Expression exp: Expression +public defstruct IsInvalid <: Stmt : ;LOW + info: FileInfo with: (as-method => true) + exp: Expression public defstruct Stop <: Stmt : ;LOW info: FileInfo with: (as-method => true) ret: Int @@ -161,25 +173,6 @@ public defstruct Print <: Stmt : ;LOW public defstruct Empty <: Stmt ;LOW -; CHIRRTL Features -public definterface MPortDir -public val MRead = new MPortDir -public val MWrite = new MPortDir -public val MReadWrite = new MPortDir - -public defstruct CDefMemory <: Stmt : ;LOW - info: FileInfo with: (as-method => true) - name: Symbol - type: Type - size: Int - seq?: True|False -public defstruct CDefMPort <: Stmt : - info: FileInfo with: (as-method => true) - name: Symbol - mem: Symbol - exps: List<Expression> - direction: MPortDir - public definterface Type public defstruct UIntType <: Type : width: Width diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index fa103fe3..e1083d50 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -6,6 +6,7 @@ defpackage firrtl/parser : import firrtl/lexer import bigint2 import firrtl/ir-utils + import firrtl/chirrtl ;======= Convenience Types =========== definterface MStat @@ -75,7 +76,7 @@ OPERATORS[`eq] = EQUAL-OP OPERATORS[`neq] = NEQUAL-OP OPERATORS[`eqv] = EQUIV-OP OPERATORS[`neqv] = NEQUIV-OP -OPERATORS[`mux] = MUX-OP +;OPERATORS[`mux] = MUX-OP OPERATORS[`pad] = PAD-OP OPERATORS[`neg] = NEG-OP OPERATORS[`asUInt] = AS-UINT-OP @@ -264,11 +265,13 @@ defsyntax firrtl : stmt = (smem ?name:#id! #:! ?t:#vectype! ) : CDefMemory(first-info(form),name,type(t),size(t),true) stmt = (read mport ?name:#id! #=! ?mem:#id! (@get ?index:#exp!) ?clk:#exp!) : - CDefMPort(first-info(form),name,mem,list(index,clk),MRead) - stmt = (write mport ?name:#id! #=! ?mem:#id! (@get ?index:#exp!) ?clk:#exp! ?mask:#exp!) : - CDefMPort(first-info(form),name,mem,list(index,clk,mask),MWrite) - stmt = (rdwr mport ?name:#id! #=! ?mem:#id! (@get ?index:#exp!) ?clk:#exp! ?mask:#exp!) : - CDefMPort(first-info(form),name,mem,list(index,clk,mask),MReadWrite) + CDefMPort(first-info(form),name,UnknownType(),mem,list(index,clk),MRead) + stmt = (write mport ?name:#id! #=! ?mem:#id! (@get ?index:#exp!) ?clk:#exp!) : + CDefMPort(first-info(form),name,UnknownType(),mem,list(index,clk),MWrite) + stmt = (rdwr mport ?name:#id! #=! ?mem:#id! (@get ?index:#exp!) ?clk:#exp!) : + CDefMPort(first-info(form),name,UnknownType(),mem,list(index,clk),MReadWrite) + stmt = (infer mport ?name:#id! #=! ?mem:#id! (@get ?index:#exp!) ?clk:#exp!) : + CDefMPort(first-info(form),name,UnknownType(),mem,list(index,clk),MInfer) stmt = (mem ?name:#id! #:! (?ms:#mstat ...)) : defn grab (f:MStat -> True|False) : @@ -294,6 +297,7 @@ defsyntax firrtl : stmt = (?x:#exp <= ?y:#exp!) : Connect(first-info(form),x, y) ;> stmt = (?x:#exp <- ?y:#exp!) : BulkConnect(first-info(form),x, y);> + stmt = (?x:#exp is invalid) : IsInvalid(first-info(form),x) ;stmt = ((?s:#stmt ?rest ...)) : ; Begin(List(s, parse-stmts(rest))) @@ -362,6 +366,10 @@ defsyntax firrtl : val num-bits = req-num-bits(v as Int) SIntValue(BigIntLit(v as Int,num-bits), IntWidth(num-bits)) + expterm = (mux(?cond:#exp ?tval:#exp ?fval:#exp)) : + Mux(cond,tval,fval,UnknownType()) + expterm = (validif(?cond:#exp ?value:#exp)) : + ValidIf(cond,value,UnknownType()) expterm = (?op:#sym(?es:#exp ... ?ints:#int ... ?rest ...)) : if not empty?(rest) : FPE(rest, "Illegal operands to primitive operator.") diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 7a9cff31..7d4c30b2 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -39,7 +39,7 @@ public defn firrtl-gensym (s:Symbol,sym-hash:HashTable<Symbol,Int>) -> Symbol : symbol-join([s delin num]) else : sym-hash[s] = 0 - s + symbol-join([s delin 0]) val s* = to-string(s) val i* = generated?(s*) val nex = match(i*) : @@ -113,7 +113,20 @@ public defn EQV (e1:Expression,e2:Expression) -> Expression : DoPrim(EQUIV-OP,list(e1,e2),list(),type(e1)) public defn MUX (p:Expression,e1:Expression,e2:Expression) -> Expression : - DoPrim(MUX-OP,list(p,e1,e2),list(),type(e1)) + Mux(p,e1,e2,mux-type(type(e1),type(e2))) + +public defn mux-type (e1:Expression,e2:Expression) -> Type : + mux-type(type(e1),type(e2)) +public defn mux-type (t1:Type,t2:Type) -> Type : + if t1 == t2 : + match(t1,t2) : + (t1:UIntType,t2:UIntType) : UIntType(UnknownWidth()) + (t1:SIntType,t2:SIntType) : SIntType(UnknownWidth()) + (t1:VectorType,t2:VectorType) : VectorType(mux-type(type(t1),type(t2)),size(t1)) + (t1:BundleType,t2:BundleType) : + BundleType $ for (f1 in fields(t1),f2 in fields(t2)) map : + Field(name(f1),flip(f1),mux-type(type(f1),type(f2))) + else : UnknownType() public defn CAT (e1:Expression,e2:Expression) -> Expression : DoPrim(CONCAT-OP,list(e1,e2),list(),type(e1)) @@ -148,13 +161,113 @@ public defn list-hash (l:List) -> Int : turn-on-debug(false) i +;===== Type Expansion Algorithms ========= +public defn times (f1:Flip,f2:Flip) -> Flip : + switch {_ == f2} : + DEFAULT : f1 + REVERSE : swap(f1) +public defn swap (f:Flip) -> Flip : + switch {_ == f} : + DEFAULT : REVERSE + REVERSE : DEFAULT + +public defmulti get-type (s:Stmt) -> Type +public defmethod get-type (s:Stmt) -> Type : + match(s) : + (s:DefWire|DefPoison|DefRegister) : type(s) + (s:DefNode) : type(value(s)) + (s:DefMemory) : + val depth = depth(s) + ; Fields + val addr = Field(`addr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) + val en = Field(`en,DEFAULT,BoolType()) + val clk = Field(`clk,DEFAULT,ClockType()) + val def-data = Field(`data,DEFAULT,data-type(s)) + val rev-data = Field(`data,REVERSE,data-type(s)) + val rdata = Field(`rdata,REVERSE,data-type(s)) + val wdata = Field(`wdata,DEFAULT,data-type(s)) + val mask = Field(`mask,DEFAULT,create-mask(data-type(s))) + val wmask = Field(`wmask,DEFAULT,create-mask(data-type(s))) + val ren = Field(`ren,DEFAULT,UIntType(IntWidth(1))) + val wen = Field(`wen,DEFAULT,UIntType(IntWidth(1))) + val raddr = Field(`raddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) + val waddr = Field(`waddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) + + val read-type = BundleType(to-list([rev-data,addr,en,clk])) + val write-type = BundleType(to-list([def-data,mask,addr,en,clk])) + val readwrite-type = BundleType(to-list([wdata,wmask,waddr,wen,rdata,raddr,ren,clk])) + + val mem-fields = Vector<Field>() + for x in readers(s) do : + add(mem-fields,Field(x,REVERSE,read-type)) + for x in writers(s) do : + add(mem-fields,Field(x,REVERSE,write-type)) + for x in readwriters(s) do : + add(mem-fields,Field(x,REVERSE,readwrite-type)) + BundleType(to-list(mem-fields)) + (s:DefInstance) : UnknownType() + (s:Begin|Connect|BulkConnect|Stop|Print|Empty|IsInvalid) : UnknownType() + +public defn get-size (t:Type) -> Int : + val x = match(t) : + (t:BundleType) : + var sum = 0 + for f in fields(t) do : + sum = sum + get-size(type(f)) + sum + (t:VectorType) : size(t) * get-size(type(t)) + (t) : 1 + x +public defn get-valid-points (t1:Type,t2:Type,flip1:Flip,flip2:Flip) -> List<[Int,Int]> : + ;println-all(["Inside with t1:" t1 ",t2:" t2 ",f1:" flip1 ",f2:" flip2]) + match(t1,t2) : + (t1:UIntType,t2:UIntType) : + if flip1 == flip2 : list([0, 0]) + else: list() + (t1:SIntType,t2:SIntType) : + if flip1 == flip2 : list([0, 0]) + else: list() + (t1:BundleType,t2:BundleType) : + val points = Vector<[Int,Int]>() + var ilen = 0 + var jlen = 0 + for i in 0 to length(fields(t1)) do : + for j in 0 to length(fields(t2)) do : + ;println(i) + ;println(j) + ;println(ilen) + ;println(jlen) + val f1 = fields(t1)[i] + val f2 = fields(t2)[j] + if name(f1) == name(f2) : + val ls = get-valid-points(type(f1),type(f2),flip1 * flip(f1), + flip2 * flip(f2)) + for x in ls do : + add(points,[x[0] + ilen, x[1] + jlen]) + ;println(points) + jlen = jlen + get-size(type(fields(t2)[j])) + ilen = ilen + get-size(type(fields(t1)[i])) + jlen = 0 + to-list(points) + (t1:VectorType,t2:VectorType) : + val points = Vector<[Int,Int]>() + var ilen = 0 + var jlen = 0 + for i in 0 to min(size(t1),size(t2)) do : + val ls = get-valid-points(type(t1),type(t2),flip1,flip2) + for x in ls do : + add(points,[x[0] + ilen, x[1] + jlen]) + ilen = ilen + get-size(type(t1)) + jlen = jlen + get-size(type(t2)) + to-list(points) + ;============= Useful functions ============== -public defn create-mask (n:Symbol,dt:Type) -> Field : - Field{n,DEFAULT,_} $ match(dt) : - (t:VectorType) : VectorType(BoolType(),size(t)) +public defn create-mask (dt:Type) -> Type : + match(dt) : + (t:VectorType) : VectorType(create-mask(type(t)),size(t)) (t:BundleType) : val fields* = for f in fields(t) map : - Field(name(f),flip(f),BoolType()) + Field(name(f),flip(f),create-mask(type(f))) BundleType(fields*) (t:UIntType|SIntType) : BoolType() @@ -265,7 +378,7 @@ defmethod print (o:OutputStream, op:PrimOp) : NEQUIV-OP : "neqv" EQUAL-OP : "eq" NEQUAL-OP : "neq" - MUX-OP : "mux" + ;MUX-OP : "mux" PAD-OP : "pad" AS-UINT-OP : "asUInt" AS-SINT-OP : "asSInt" @@ -298,6 +411,10 @@ defmethod print (o:OutputStream, e:Expression) : print-all(o, [op(e) "("]) print-all(o, join(concat(args(e), consts(e)), ", ")) print(o, ")") + (e:Mux) : + print-all(o, ["mux(" cond(e) ", " tval(e) ", " fval(e) ")"]) + (e:ValidIf) : + print-all(o, ["validif(" cond(e) ", " value(e) ")"]) print-debug(o,e) defmethod print (o:OutputStream, c:Stmt) : @@ -340,6 +457,8 @@ defmethod print (o:OutputStream, c:Stmt) : do(print{o,_}, join(body(c), "\n")) (c:Connect) : print-all(o, [loc(c) " <= " exp(c)]) + (c:IsInvalid) : + print-all(o, [exp(c) " is invalid"]) (c:BulkConnect) : print-all(o, [loc(c) " <- " exp(c)]) (c:Empty) : @@ -350,25 +469,9 @@ defmethod print (o:OutputStream, c:Stmt) : print-all(o, ["printf(" clk(c) ", " en(c) ", "]) ;" print-all(o, join(List(escape(string(c)),args(c)), ", ")) print(o, ")") - (c:CDefMemory) : - if seq?(c) : - print-all(o, ["smem " name(c) " : " type(c) "[" size(c) "]"]) - else : - print-all(o, ["cmem " name(c) " : " type(c) "[" size(c) "]"]) - (c:CDefMPort) : - if direction(c) == MRead : - print-all(o, [direction(c) " mport " name(c) " = " mem(c) "[" exps(c)[0] "], " exps(c)[1]]) - else : - print-all(o, [direction(c) " mport " name(c) " = " mem(c) "[" exps(c)[0] "], " exps(c)[1] ", " exps(c)[2]]) if not c typeof Conditionally|Begin|Empty: print-debug(o,c) -defmethod print (o:OutputStream, m:MPortDir) : - switch { m == _ } : - MRead : print(o,"read") - MWrite : print(o,"write") - MReadWrite : print(o,"rdwr") - defmethod print (o:OutputStream, t:Type) : match(t) : (t:UnknownType) : @@ -445,6 +548,8 @@ defmethod map (f: Expression -> Expression, e:Expression) -> Expression : (e:SubIndex) : SubIndex(f(exp(e)), value(e), type(e)) (e:SubAccess) : SubAccess(f(exp(e)), f(index(e)), type(e)) (e:DoPrim) : DoPrim(op(e), map(f, args(e)), consts(e), type(e)) + (e:Mux) : Mux(f(cond(e)),f(tval(e)),f(fval(e)),type(e)) + (e:ValidIf) : ValidIf(f(cond(e)),f(value(e)),type(e)) (e) : e public defmulti map<?T> (f: Symbol -> Symbol, c:?T&Stmt) -> T @@ -467,6 +572,7 @@ defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : (c:Conditionally) : Conditionally(info(c),f(pred(c)), conseq(c), alt(c)) (c:Connect) : Connect(info(c),f(loc(c)), f(exp(c))) (c:BulkConnect) : BulkConnect(info(c),f(loc(c)), f(exp(c))) + (c:IsInvalid) : IsInvalid(info(c),f(exp(c))) (c:Stop) : Stop(info(c),ret(c),f(clk(c)),f(en(c))) (c:Print) : Print(info(c),string(c),map(f,args(c)),f(clk(c)),f(en(c))) (c) : c @@ -500,6 +606,8 @@ defmethod map (f: Type -> Type, c:Expression) -> Expression : (c:SubIndex) : SubIndex(exp(c),value(c),f(type(c))) (c:SubAccess) : SubAccess(exp(c),index(c),f(type(c))) (c:DoPrim) : DoPrim(op(c),args(c),consts(c),f(type(c))) + (c:Mux) : Mux(cond(c),tval(c),fval(c),f(type(c))) + (c:ValidIf) : ValidIf(cond(c),value(c),f(type(c))) (c) : c public defmulti map<?T> (f: Type -> Type, c:?T&Stmt) -> T diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index a5d72ba4..cf6db44d 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -76,6 +76,7 @@ defstruct WIndexer <: Expression : type: Type with: (as-method => true) gender : Gender with: (as-method => true) public defstruct WVoid <: Expression +public defstruct WInvalid <: Expression public defstruct WDefInstance <: Stmt : info: FileInfo with: (as-method => true) name: Symbol @@ -90,8 +91,8 @@ defn get-gender (s:Stmt|Port) -> Gender : match(s) : (s:DefWire|DefRegister) : BI-GENDER (s:WDefInstance|DefNode|DefInstance|DefPoison) : MALE - (s:Begin|Connect|BulkConnect|Stop|Print|Empty) : UNKNOWN-GENDER - (s:DefMemory) : FEMALE + (s:Begin|Connect|BulkConnect|Stop|Print|Empty|IsInvalid) : UNKNOWN-GENDER + (s:DefMemory) : MALE (p:Port) : switch { _ == direction(p) } : INPUT : MALE @@ -115,42 +116,10 @@ defmethod info (stmt:Empty) -> FileInfo : FileInfo() defmethod type (exp:UIntValue) -> Type : UIntType(width(exp)) defmethod type (exp:SIntValue) -> Type : SIntType(width(exp)) +defmethod type (exp:WVoid) -> Type : UnknownType() +defmethod type (exp:WInvalid) -> Type : UnknownType() -defn get-type (s:Stmt) -> Type : - match(s) : - (s:DefWire|DefPoison|DefRegister|WDefInstance) : type(s) - (s:DefNode) : type(value(s)) - (s:DefMemory) : - val depth = depth(s) - ; Fields - val addr = Field(`addr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - val en = Field(`en,DEFAULT,BoolType()) - val clk = Field(`clk,DEFAULT,ClockType()) - val def-data = Field(`data,DEFAULT,data-type(s)) - val rev-data = Field(`data,REVERSE,data-type(s)) - val rdata = Field(`rdata,REVERSE,data-type(s)) - val wdata = Field(`wdata,DEFAULT,data-type(s)) - val mask = create-mask(`mask,data-type(s)) - val wmask = create-mask(`wmask,data-type(s)) - val ren = Field(`ren,DEFAULT,UIntType(IntWidth(1))) - val wen = Field(`wen,DEFAULT,UIntType(IntWidth(1))) - val raddr = Field(`raddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - val waddr = Field(`waddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - - val read-type = BundleType(to-list([rev-data,addr,en,clk])) - val write-type = BundleType(to-list([def-data,mask,addr,en,clk])) - val readwrite-type = BundleType(to-list([wdata,wmask,waddr,wen,rdata,raddr,ren,clk])) - - val mem-fields = Vector<Field>() - for x in readers(s) do : - add(mem-fields,Field(x,DEFAULT,read-type)) - for x in writers(s) do : - add(mem-fields,Field(x,DEFAULT,write-type)) - for x in readwriters(s) do : - add(mem-fields,Field(x,DEFAULT,readwrite-type)) - BundleType(to-list(mem-fields)) - (s:DefInstance) : UnknownType() - (s:Begin|Connect|BulkConnect|Stop|Print|Empty) : UnknownType() +defmethod get-type (s:WDefInstance) -> Type : type(s) defmethod equal? (e1:Expression,e2:Expression) -> True|False : match(e1,e2) : @@ -168,6 +137,7 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False : (e1:WSubAccess,e2:WSubAccess) : (index(e1) == index(e2)) and (exp(e1) == exp(e2)) (e1:WVoid,e2:WVoid) : true + (e1:WInvalid,e2:WInvalid) : true (e1:WIndexer,e2:WIndexer) : var bool = (length(exps(e1)) == length(exps(e2))) for (e1* in exps(e1),e2* in exps(e2)) do : @@ -182,6 +152,13 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False : if not x == y : are-equal? = false are-equal? + (e1:Mux,e2:Mux) : + (cond(e1) == cond(e2)) and + (tval(e1) == tval(e2)) and + (fval(e1) == fval(e2)) + (e1:ValidIf,e2:ValidIf) : + (cond(e1) == cond(e2)) and + (value(e1) == value(e2)) (e1,e2) : false ; ================= PRINTERS =================== @@ -316,6 +293,9 @@ defmethod print (o:OutputStream, e:WSubAccess) : defmethod print (o:OutputStream, e:WVoid) : print(o,"VOID") print-debug(o,e as ?) +defmethod print (o:OutputStream, e:WInvalid) : + print(o,"INVALID") + print-debug(o,e as ?) defmethod print (o:OutputStream, c:WIndexer) : print-all(o, [exps(c) "[" index(c) "]"]) print-debug(o,c as ?) @@ -444,10 +424,6 @@ defn swap (g:Gender) -> Gender : MALE : FEMALE FEMALE : MALE BI-GENDER : BI-GENDER -defn swap (f:Flip) -> Flip : - switch {_ == f} : - DEFAULT : REVERSE - REVERSE : DEFAULT defn swap (d:Direction) -> Direction : switch {_ == d} : OUTPUT : INPUT @@ -464,11 +440,6 @@ public defn times (flip:Flip,g:Gender) -> Gender : switch {_ == flip} : DEFAULT : g REVERSE : swap(g) -public defn times (f1:Flip,f2:Flip) -> Flip : - switch {_ == f2} : - DEFAULT : f1 - REVERSE : swap(f1) - defn to-field (p:Port) -> Field : if direction(p) == OUTPUT : Field(name(p),DEFAULT,type(p)) else if direction(p) == INPUT : Field(name(p),REVERSE,type(p)) @@ -482,6 +453,23 @@ defn to-gender (d:Direction) -> Gender : INPUT: MALE OUTPUT: FEMALE +public defn mux-type-and-widths (e1:Expression,e2:Expression) -> Type : + mux-type-and-widths(type(e1),type(e2)) +public defn mux-type-and-widths (t1:Type,t2:Type) -> Type : + defn wmax (w1:Width,w2:Width) -> Width : + match(w1,w2) : + (w1:IntWidth,w2:IntWidth) : IntWidth(max(width(w1),width(w2))) + (w1,w2) : MaxWidth(list(w1,w2)) + if t1 == t2 : + match(t1,t2) : + (t1:UIntType,t2:UIntType) : UIntType(wmax(width(t1),width(t2))) + (t1:SIntType,t2:SIntType) : SIntType(wmax(width(t1),width(t2))) + (t1:VectorType,t2:VectorType) : VectorType(mux-type-and-widths(type(t1),type(t2)),size(t1)) + (t1:BundleType,t2:BundleType) : + BundleType $ for (f1 in fields(t1),f2 in fields(t2)) map : + Field(name(f1),flip(f1),mux-type-and-widths(type(f1),type(f2))) + else : UnknownType() + ;================= Remove Special Characters ======================== ; Returns a new Circuit where all names have all special characters ; removed, except _. @@ -713,11 +701,13 @@ defn infer-types (c:Circuit) -> Circuit : val types = HashTable<Symbol,Type>(symbol-hash) defn infer-types-e (e:Expression) -> Expression : match(map(infer-types-e,e)) : + (e:ValidIf) : ValidIf(cond(e),value(e),type(value(e))) (e:WRef) : WRef(name(e), types[name(e)],kind(e),gender(e)) (e:WSubField) : WSubField(exp(e),name(e),field-type(type(exp(e)),name(e)),gender(e)) (e:WSubIndex) : WSubIndex(exp(e),value(e),sub-type(type(exp(e))),gender(e)) (e:WSubAccess) : WSubAccess(exp(e),index(e),sub-type(type(exp(e))),gender(e)) (e:DoPrim) : set-primop-type(e) + (e:Mux) : Mux(cond(e),tval(e),fval(e),mux-type-and-widths(tval(e),fval(e))) (e:UIntValue|SIntValue) : e defn infer-types-s (s:Stmt) -> Stmt : match(s) : @@ -801,6 +791,9 @@ defn resolve-genders (c:Circuit) : defn resolve-s (s:Stmt) -> Stmt : match(s) : + (s:IsInvalid) : + val exp* = resolve-e(exp(s),FEMALE) + IsInvalid(info(s),exp*) (s:Connect) : val loc* = resolve-e(loc(s),FEMALE) val exp* = resolve-e(exp(s),MALE) @@ -820,25 +813,44 @@ defn resolve-genders (c:Circuit) : InModule(info(m),name(m),ports(m),body*) (m:ExModule) : m -;;============== EXPAND ACCESSORS ================================ -; This pass expands non-memory accessors into DecFromIndexer or -; ConnectFromIndexed. All elements of the vector are -; explicitly written out, then indexed. Depending on the gender -; of the accessor, it is transformed into DecFromIndexer (male) or -; DecToIndexer (female) - -;public defstruct ExpandAccesses <: Pass -;public defmethod pass (b:ExpandAccesses) -> (Circuit -> Circuit) : expand-accesses -;public defmethod name (b:ExpandAccesses) -> String : "Expand Accesses" -;public defmethod short-name (b:ExpandAccesses) -> String : "expand-accesses" -; - -defn expand-vector (e:Expression,g:Gender) -> List<Expression> : - val t = type(e) as VectorType - for i in 0 to size(t) map-append : - list(WSubIndex(e,i,type(t),g)) ;always be WRef|WSubField|WSubIndex - - +;============= Pull Muxes =============== + +public defstruct PullMuxes <: Pass +public defmethod pass (b:PullMuxes) -> (Circuit -> Circuit) : pull-muxes +public defmethod name (b:PullMuxes) -> String : "Pull Muxes" +public defmethod short-name (b:PullMuxes) -> String : "pull-muxes" + +defn pull-muxes (c:Circuit) -> Circuit : + defn pull-muxes-e (e:Expression) -> Expression : + map{pull-muxes-e,_} $ match(map(pull-muxes-e,e)) : + (e:WRef) : e + (e:WSubField) : + match(exp(e)) : + (e*:Mux) : Mux(cond(e*),WSubField(tval(e*),name(e),type(e),gender(e)),WSubField(fval(e*),name(e),type(e),gender(e)),type(e)) + (e*:ValidIf) : ValidIf(cond(e*),WSubField(value(e*),name(e),type(e),gender(e)),type(e)) + (e*) : e + (e:WSubIndex) : + match(exp(e)) : + (e*:Mux) : Mux(cond(e*),WSubIndex(tval(e*),value(e),type(e),gender(e)),WSubIndex(fval(e*),value(e),type(e),gender(e)),type(e)) + (e*:ValidIf) : ValidIf(cond(e*),WSubIndex(value(e*),value(e),type(e),gender(e)),type(e)) + (e*) : e + (e:WSubAccess) : + match(exp(e)) : + (e*:Mux) : Mux(cond(e*),WSubAccess(tval(e*),index(e),type(e),gender(e)),WSubAccess(fval(e*),index(e),type(e),gender(e)),type(e)) + (e*:ValidIf) : ValidIf(cond(e*),WSubAccess(value(e*),index(e),type(e),gender(e)),type(e)) + (e*) : e + (e:Mux) : e + (e:ValidIf) : e + (e) : e + + defn pull-muxes (s:Stmt) -> Stmt : + map(pull-muxes-e,map(pull-muxes,s)) + + Circuit{info(c),_,main(c)} $ + for m in modules(c) map : + match(m) : + (m:InModule) : InModule(info(m),name(m),ports(m),pull-muxes(body(m))) + (m:ExModule) : m ;================ EXPAND CONNECTS ================== public defstruct ExpandConnects <: Pass @@ -849,43 +861,28 @@ public defmethod short-name (b:ExpandConnects) -> String : "expand-connects" ;---------------- UTILS ------------------ defn get-size (e:Expression) -> Int : get-size(type(e)) -defn get-size (t:Type) -> Int : +defn get-flip (t:Type, i:Int, f:Flip) -> Flip : + if i >= get-size(t) : error("Shouldn't be here") val x = match(t) : - (t:BundleType) : - var sum = 0 - for f in fields(t) do : - sum = sum + get-size(type(f)) - sum - (t:VectorType) : size(t) * get-size(type(t)) - (t) : 1 + (t:UIntType|SIntType|ClockType) : f + (t:BundleType) : label<Flip> ret : + var n = i + for x in fields(t) do : + if n < get-size(type(x)) : + ret(get-flip(type(x),n,flip(x) * f)) + else : + n = n - get-size(type(x)) + error("Shouldn't be here") + (t:VectorType) : label<Flip> ret : + var n = i + for j in 0 to size(t) do : + if n < get-size(type(t)) : + ret(get-flip(type(t),n,f)) + else : + n = n - get-size(type(t)) + error("Shouldn't be here") x -val hashed-get-flip = HashTable<List,Flip>(list-hash) -defn get-flip (t:Type, i:Int, f:Flip) -> Flip : - if key?(hashed-get-flip,list(t,i,f)) : hashed-get-flip[list(t,i,f)] - else : - if i >= get-size(t) : error("Shouldn't be here") - val x = match(t) : - (t:UIntType|SIntType|ClockType) : f - (t:BundleType) : label<Flip> ret : - var n = i - for x in fields(t) do : - if n < get-size(type(x)) : - ret(get-flip(type(x),n,flip(x) * f)) - else : - n = n - get-size(type(x)) - error("Shouldn't be here") - (t:VectorType) : label<Flip> ret : - var n = i - for j in 0 to size(t) do : - if n < get-size(type(t)) : - ret(get-flip(type(t),n,f)) - else : - n = n - get-size(type(t)) - error("Shouldn't be here") - hashed-get-flip[list(t,i,f)] = x - x - defn get-point (e:Expression) -> Int : match(e) : (e:WRef) : 0 @@ -900,90 +897,107 @@ defn get-point (e:Expression) -> Int : value(e) * get-size(e) (e:WSubAccess) : get-point(exp(e)) -defn get-valid-points (t1:Type,t2:Type,flip1:Flip,flip2:Flip) -> List<[Int,Int]> : - ;println-all(["Inside with t1:" t1 ",t2:" t2 ",f1:" flip1 ",f2:" flip2]) - match(t1,t2) : - (t1:UIntType,t2:UIntType) : - if flip1 == flip2 : list([0, 0]) - else: list() - (t1:SIntType,t2:SIntType) : - if flip1 == flip2 : list([0, 0]) - else: list() - (t1:BundleType,t2:BundleType) : - val points = Vector<[Int,Int]>() - var ilen = 0 - var jlen = 0 - for i in 0 to length(fields(t1)) do : - for j in 0 to length(fields(t2)) do : - ;println(i) - ;println(j) - ;println(ilen) - ;println(jlen) - val f1 = fields(t1)[i] - val f2 = fields(t2)[j] - if name(f1) == name(f2) : - val ls = get-valid-points(type(f1),type(f2),flip1 * flip(f1), - flip2 * flip(f2)) - for x in ls do : - add(points,[x[0] + ilen, x[1] + jlen]) - println(points) - jlen = jlen + get-size(type(fields(t2)[j])) - ilen = ilen + get-size(type(fields(t1)[i])) - jlen = 0 - to-list(points) - (t1:VectorType,t2:VectorType) : - val points = Vector<[Int,Int]>() - var ilen = 0 - var jlen = 0 - for i in 0 to min(size(t1),size(t2)) do : - val ls = get-valid-points(type(t1),type(t2),flip1,flip2) - for x in ls do : - add(points,[x[0] + ilen, x[1] + jlen]) - ilen = ilen + get-size(type(t1)) - jlen = jlen + get-size(type(t2)) - to-list(points) - -val hashed-create-exps = HashTable<Expression,List<Expression>>(exp-hash) defn create-exps (n:Symbol, t:Type) -> List<Expression> : create-exps(WRef(n,t,ExpKind(),UNKNOWN-GENDER)) defn create-exps (e:Expression) -> List<Expression> : - match(type(e)) : - (t:UIntType|SIntType|ClockType) : list(e) - (t:BundleType) : - for f in fields(t) map-append : - create-exps(WSubField(e,name(f),type(f),gender(e) * flip(f))) - (t:VectorType) : - for i in 0 to size(t) map-append : - create-exps(WSubIndex(e,i,type(t),gender(e))) - -defn fast-create-exps (n:Symbol, t:Type) -> List<Expression> : - fast-create-exps(WRef(n,t,ExpKind(),UNKNOWN-GENDER)) -defn fast-create-exps (e:Expression) -> List<Expression> : - if key?(hashed-create-exps,e) : hashed-create-exps[e] - else : - val es = Vector<Expression>() - defn create-exps (e:Expression) -> False : + match(e) : + (e:Mux) : + for (e1 in create-exps(tval(e)), e2 in create-exps(fval(e))) map : + Mux(cond(e),e1,e2,mux-type-and-widths(e1,e2)) + (e:ValidIf) : + for e1 in create-exps(value(e)) map : + ValidIf(cond(e),e1,type(e1)) + (e) : match(type(e)) : - (t:UIntType|SIntType|ClockType) : add(es,e) + (t:UIntType|SIntType|ClockType) : list(e) (t:BundleType) : - for f in fields(t) do : + for f in fields(t) map-append : create-exps(WSubField(e,name(f),type(f),gender(e) * flip(f))) (t:VectorType) : - for i in 0 to size(t) do : + for i in 0 to size(t) map-append : create-exps(WSubIndex(e,i,type(t),gender(e))) - create-exps(e) - val x = to-list(es) - hashed-create-exps[e] = x - x + +defn gexp-hash (e:Expression) -> Int : + turn-off-debug(false) + val ls = to-list([mname `.... e `.... gender(e) `.... type(e)]) + ;val ls = to-list([e `.... gender(e) `.... type(e)]) + val i = symbol-hash(symbol-join(ls)) + ;val i = symbol-hash(to-symbol(to-string(e))) + turn-on-debug(false) + i +val hashed-create-exps = HashTable<Expression,List<Expression>>(gexp-hash) +defn fast-create-exps (n:Symbol, t:Type) -> List<Expression> : + fast-create-exps(WRef(n,t,ExpKind(),UNKNOWN-GENDER)) +defn fast-create-exps (e:Expression) -> List<Expression> : + if key?(hashed-create-exps,e) : + hashed-create-exps[e] + else : + match(e) : + (e:Mux) : + val x = for (e1 in create-exps(tval(e)), e2 in create-exps(fval(e))) map : + Mux(cond(e),e1,e2,mux-type-and-widths(e1,e2)) + hashed-create-exps[e] = x + x + (e:ValidIf) : + val x = for e1 in create-exps(value(e)) map : + ValidIf(cond(e),e1,type(e1)) + hashed-create-exps[e] = x + x + (e) : + val es = Vector<List<Expression>>() + match(type(e)) : + (t:UIntType|SIntType|ClockType) : add(es,list(e)) + (t:BundleType) : + for f in fields(t) do : + add(es,fast-create-exps(WSubField(e,name(f),type(f),gender(e) * flip(f)))) + (t:VectorType) : + for i in 0 to size(t) do : + add(es,fast-create-exps(WSubIndex(e,i,type(t),gender(e)))) + val x = append-all(es) + hashed-create-exps[e] = x + x ;---------------- Pass --------------------- defn expand-connects (c:Circuit) -> Circuit : defn expand-connects (m:InModule) -> InModule : mname = name(m) + val genders = HashTable<Symbol,Gender>(symbol-hash) defn expand-s (s:Stmt) -> Stmt : + defn set-gender (e:Expression) -> Expression : + match(map(set-gender,e)) : + (e:WRef) : WRef(name(e),type(e),kind(e),genders[name(e)]) + (e:WSubField) : + val f = {_ as Field} $ + for f in fields(type(exp(e)) as BundleType) find : + name(f) == name(e) + val gender* = gender(exp(e)) * flip(f) + WSubField(exp(e),name(e),type(e),gender*) + (e:WSubIndex) : WSubIndex(exp(e),value(e),type(e),gender(exp(e))) + (e:WSubAccess) : WSubAccess(exp(e),index(e),type(e),gender(exp(e))) + (e) : e match(s) : + (s:DefWire|DefRegister) : + genders[name(s)] = BI-GENDER + s + (s:WDefInstance|DefMemory|DefPoison|DefNode) : + genders[name(s)] = MALE + s + (s:IsInvalid) : + val n = get-size(exp(s)) + val invalids = Vector<Stmt>() + val exps = create-exps(exp(s)) + for i in 0 to n do : + val exp* = exps[i] + val gexp* = set-gender(exp*) + switch { _ == gender(gexp*) } : + BI-GENDER : add(invalids,IsInvalid(info(s),exp*)) + FEMALE : add(invalids,IsInvalid(info(s),exp*)) + else : false + if length(invalids) == 0 : Empty() + else if length(invalids) == 1 : invalids[0] + else : Begin(to-list(invalids)) (s:Connect) : val n = get-size(loc(s)) val connects = Vector<Stmt>() @@ -1012,6 +1026,8 @@ defn expand-connects (c:Circuit) -> Circuit : Begin(to-list(connects)) (s) : map(expand-s,s) + for p in ports(m) do : + genders[name(p)] = to-gender(direction(p)) InModule(info(m),name(m),ports(m),expand-s(body(m))) Circuit(info(c),modules*, main(c)) where : @@ -1037,39 +1053,34 @@ defstruct Location : defmethod print (o:OutputStream,x:Location) : print-all(o,["[" base(x) " , " guard(x) "]"]) - -val hashed-locations = HashTable<Expression,List<Location>>(exp-hash) defn get-locations (e:Expression) -> List<Location> : - if key?(hashed-locations,e) : hashed-locations[e] - else : - val x = match(e) : - (e:WRef) : map(Location{_,one},create-exps(e)) - (e:WSubIndex|WSubField) : - val ls = get-locations(exp(e)) - val start = get-point(e) - val end = start + get-size(e) - val stride = get-size(exp(e)) - val ls* = Vector<Location>() - var c = 0 - for i in 0 to length(ls) do : - if (i % stride >= start and i % stride < end) : - add(ls*,ls[i]) - to-list(ls*) - (e:WSubAccess) : - val ls = get-locations(exp(e)) - val stride = get-size(e) - val wrap = size(type(exp(e)) as VectorType) - val ls* = Vector<Location>() - var c = 0 - for i in 0 to length(ls) do : - if c % wrap == 0 : c = 0 - val base* = base(ls[i]) - val guard* = AND(guard(ls[i]),EQV(uint(c),index(e))) - add(ls*,Location(base*,guard*)) - if (i + 1) % stride == 0 : c = c + 1 - to-list(ls*) - hashed-locations[e] = x - x + match(e) : + (e:WRef) : map(Location{_,one},create-exps(e)) + (e:WSubIndex|WSubField) : + val ls = get-locations(exp(e)) + val start = get-point(e) + val end = start + get-size(e) + val stride = get-size(exp(e)) + val ls* = Vector<Location>() + var c = 0 + for i in 0 to length(ls) do : + if (i % stride >= start and i % stride < end) : + add(ls*,ls[i]) + to-list(ls*) + (e:WSubAccess) : + val ls = get-locations(exp(e)) + val stride = get-size(e) + val wrap = size(type(exp(e)) as VectorType) + val ls* = Vector<Location>() + var c = 0 + for i in 0 to length(ls) do : + if c % wrap == 0 : c = 0 + val base* = base(ls[i]) + val guard* = AND(guard(ls[i]),EQV(uint(c),index(e))) + add(ls*,Location(base*,guard*)) + if (i + 1) % stride == 0 : c = c + 1 + to-list(ls*) + defn has-access? (e:Expression) -> True|False : var ret = false defn rec-has-access (e:Expression) -> Expression : @@ -1094,6 +1105,8 @@ defn remove-access (c:Circuit) : defn remove-e (e:Expression) -> Expression : ;NOT RECURSIVE (except primops) INTENTIONALLY! match(e) : (e:DoPrim) : map(remove-e,e) + (e:Mux) : map(remove-e,e) + (e:ValidIf) : map(remove-e,e) (e:UIntValue|SIntValue) : e (e) : if has-access?(e) : @@ -1103,11 +1116,14 @@ defn remove-access (c:Circuit) : if foo == false : error("Shouldn't be here") else : val temp = create-temp(e) + val temps = create-exps(temp) + defn get-temp (i:Int) : + temps[i % length(temps)] for (x in rs, i in 0 to false) do : - if i == 0 : - add(stmts,Connect(info(s),temp,base(x))) + if i < length(temps) : + add(stmts,Connect(info(s),get-temp(i),base(x))) else : - add(stmts,Conditionally(info(s),guard(x),Connect(info(s),temp,base(x)),Empty())) + add(stmts,Conditionally(info(s),guard(x),Connect(info(s),get-temp(i),base(x)),Empty())) temp else : e val s* = match(s) : @@ -1198,6 +1214,7 @@ defn expand-whens (c:Circuit) -> Circuit : defn expand-whens (s:Stmt,netlist:HashTable<Expression,Expression>,p:Expression) -> Stmt : match(s) : (s:Connect) : netlist[loc(s)] = exp(s) + (s:IsInvalid) : netlist[exp(s)] = WInvalid() (s:Conditionally) : val exps = Vector<Expression>() defn prefetch (s:Stmt) -> Stmt: @@ -1214,7 +1231,14 @@ defn expand-whens (c:Circuit) -> Circuit : val value = get?(netlist,lvalue,false) match(value) : (value:Expression) : - netlist[lvalue] = MUX(pred(s),c-netlist[lvalue],value) + val tv = c-netlist[lvalue] + val fv = value + val res = match(tv,fv) : + (tv:WInvalid,fv:WInvalid) : WInvalid() + (tv:WInvalid,fv) : ValidIf(NOT(pred(s)),fv,type(fv)) + (tv,fv:WInvalid) : ValidIf(pred(s),tv,type(tv)) + (tv,fv) : Mux(pred(s),tv,fv,mux-type-and-widths(tv,fv)) + netlist[lvalue] = res (value:False) : netlist[lvalue] = c-netlist[lvalue] (s:Print) : @@ -1250,7 +1274,10 @@ defn expand-whens (c:Circuit) -> Circuit : val rvalue = if s typeof DefRegister : replace-void(e,netlist[e]) else : netlist[e] - add(connections,Connect(info(s),e,rvalue)) + val con = match(rvalue) : + (rvalue:WInvalid) : IsInvalid(info(s),e) + (rvalue) : Connect(info(s),e,rvalue) + add(connections,con) (s:DefPoison|DefNode) : add(stmts,s) (s) : map(create,s) @@ -1258,7 +1285,11 @@ defn expand-whens (c:Circuit) -> Circuit : create(body(m)) for p in ports(m) do : for e in get-female-refs(name(p),type(p),get-gender(p)) do : - add(connections,Connect(info(p),e,netlist[e])) + val rvalue = netlist[e] + val con = match(rvalue) : + (rvalue:WInvalid) : IsInvalid(info(p),e) + (rvalue) : Connect(info(p),e,rvalue) + add(connections,con) for x in simlist do : add(stmts,x) InModule(info(m),name(m),ports(m),Begin(list(Begin(to-list(stmts)),Begin(to-list(connections))))) @@ -1576,10 +1607,9 @@ defn infer-widths (c:Circuit) -> Circuit : get-constraints(type(t1),type(t2),f) defn get-constraints-e (e:Expression) -> Expression : match(map(get-constraints-e,e)) : - (e:DoPrim) : - if op(e) == MUX-OP : - constrain(width!(args(e)[0]),ONE) - constrain(ONE,width!(args(e)[0])) + (e:Mux) : + constrain(width!(cond(e)),ONE) + constrain(ONE,width!(cond(e))) e (e) : e defn get-constraints (s:Stmt) -> Stmt : @@ -1600,9 +1630,9 @@ defn infer-widths (c:Circuit) -> Circuit : (s:BulkConnect) : val ls = get-valid-points(type(loc(s)),type(exp(s)),DEFAULT,DEFAULT) for x in ls do : - println(x) - println(create-exps(loc(s))) - println(create-exps(exp(s))) + ;println(x) + ;println(create-exps(loc(s))) + ;println(create-exps(exp(s))) val loc* = create-exps(loc(s))[x[0]] val exp* = create-exps(exp(s))[x[1]] switch { _ == get-flip(type(loc(s)),x[0],DEFAULT) } : @@ -1735,7 +1765,7 @@ defn split-exp (m:InModule) -> InModule : defn split-exp-e (e:Expression,i:Int) -> Expression : match(map(split-exp-e{_,i + 1},e)) : (e:DoPrim) : - if i > 0 and op(e) != MUX-OP : split(e) + if i > 0 : split(e) else : e (e) : e match(map(split-exp-e{_,0},s)) : @@ -1961,16 +1991,16 @@ defn const-prop-e (e:Expression) -> Expression : match(map(const-prop-e,e)) : (e:DoPrim) : switch {op(e) == _} : - DYN-SHIFT-RIGHT-OP : - match(args(e)[1]) : - (x:UIntValue|SIntValue) : - DoPrim(SHIFT-RIGHT-OP,list(args(e)[0]),list(to-int(value(x))),UnknownType()) - (x) : e - DYN-SHIFT-LEFT-OP : - match(args(e)[1]) : - (x:UIntValue|SIntValue) : - DoPrim(SHIFT-LEFT-OP,list(args(e)[0]),list(to-int(value(x))),UnknownType()) - (x) : e + ;DYN-SHIFT-RIGHT-OP : + ; match(args(e)[1]) : + ; (x:UIntValue|SIntValue) : + ; DoPrim(SHIFT-RIGHT-OP,list(args(e)[0]),list(to-int(value(x))),UnknownType()) + ; (x) : e + ;DYN-SHIFT-LEFT-OP : + ; match(args(e)[1]) : + ; (x:UIntValue|SIntValue) : + ; DoPrim(SHIFT-LEFT-OP,list(args(e)[0]),list(to-int(value(x))),UnknownType()) + ; (x) : e SHIFT-RIGHT-OP : match(args(e)[0]) : (x:UIntValue) : @@ -2097,6 +2127,7 @@ public defn const-prop (c:Circuit) -> Circuit : ; (m:ExModule) : m ; (m:InModule) : condense-mems(m) + ;============= Lower Types ================ ; public defstruct LowerTypes <: Pass @@ -2162,6 +2193,16 @@ defn lower-data-mem (e:Expression) -> Expression : WSubField(p,to-symbol(names[2]),UnknownType(),UNKNOWN-GENDER) defn merge (a:Symbol,b:Symbol,x:Symbol) -> Symbol : symbol-join([a x b]) +val hashed-lowered-name = HashTable<Expression,Symbol>(gexp-hash) +defn fast-lowered-name (e:Expression) -> Symbol : + val x = get?(hashed-lowered-name,e,false) + match(x) : + (x:Symbol) : x + (x:False) : + match(e) : + (e:WRef) : name(e) + (e:WSubField) : merge(fast-lowered-name(exp(e)),name(e),`_) + (e:WSubIndex) : merge(fast-lowered-name(exp(e)),to-symbol(value(e)),`_) defn lowered-name (e:Expression) -> Symbol : match(e) : (e:WRef) : name(e) @@ -2202,7 +2243,9 @@ defn lower-types (m:Module) -> Module : else : e (k) : WRef(lowered-name(e),type(e),kind(e),gender(e)) (e:DoPrim) : map(lower-types-e,e) - match(map(lower-types-e,s)) : + (e:Mux) : map(lower-types-e,e) + (e:ValidIf) : map(lower-types-e,e) + match(s) : (s:DefWire|DefPoison) : if is-ground?(type(s)) : s else : @@ -2233,19 +2276,37 @@ defn lower-types (m:Module) -> Module : val es = create-exps(name(s),data-type(s)) Begin $ for e in es map : DefMemory(info(s),lowered-name(e),type(e),depth(s),write-latency(s),read-latency(s),readers(s),writers(s),readwriters(s)) + (s:IsInvalid) : + val s* = map(lower-types-e,s) + if kind(exp(s*)) typeof MemKind : + val es = lower-mem(exp(s*)) + Begin $ for e in es map : + IsInvalid(info(s*),e) + else : s* (s:Connect) : - if kind(loc(s)) typeof MemKind : - val es = lower-mem(loc(s)) + val s* = map(lower-types-e,s) + if kind(loc(s*)) typeof MemKind : + val es = lower-mem(loc(s*)) Begin $ for e in es map : - Connect(info(s),e,exp(s)) - else : s - (s) : map(lower-types,s) - - val ports* = - for p in ports(m) map-append : - val es = create-exps(WRef(name(p),type(p),PortKind(),to-gender(direction(p)))) - for e in es map : - Port(info(p),lowered-name(e),to-dir(gender(e)),type(e)) + Connect(info(s*),e,exp(s*)) + else : s* + (s:DefNode) : + val locs = create-exps(name(s),type(value(s))) + val n = length(locs) + val nodes = Vector<Stmt>() + val exps = create-exps(value(s)) + for i in 0 to n do : + val loc* = locs[i] + val exp* = exps[i] + add(nodes,DefNode(info(s),lowered-name(loc*),lower-types-e(exp*))) + if n == 1 : nodes[0] + else : Begin(to-list(nodes)) + (s) : map(lower-types-e,map(lower-types,s)) + + val ports* = for p in ports(m) map-append : + val es = create-exps(WRef(name(p),type(p),PortKind(),to-gender(direction(p)))) + for e in es map : + Port(info(p),lowered-name(e),to-dir(gender(e)),type(e)) match(m) : (m:ExModule) : ExModule(info(m),name(m),ports*) (m:InModule) : InModule(info(m),name(m),ports*,lower-types(body(m))) @@ -2254,6 +2315,36 @@ defn lower-types (c:Circuit) -> Circuit : Circuit{info(c),_,main(c)} $ for m in modules(c) map : lower-types(m) + + +;============ RENAME VERILOG KEYWORDS ============= + +public defstruct VerilogRename <: Pass +public defmethod pass (b:VerilogRename) -> (Circuit -> Circuit) : verilog-rename +public defmethod name (b:VerilogRename) -> String : "Verilog Rename" +public defmethod short-name (b:VerilogRename) -> String : "Verilog Rename" + +defn verilog-rename (c:Circuit) -> Circuit : + defn verilog-rename-n (n:Symbol) -> Symbol : + if key?(v-keywords,n) : symbol-join([n `$]) + else : n + defn verilog-rename-e (e:Expression) -> Expression : + match(e) : + (e:WRef) : WRef(verilog-rename-n(name(e)),type(e),kind(e),gender(e)) + (e) : map(verilog-rename-e,e) + defn verilog-rename-s (s:Stmt) -> Stmt : + map{verilog-rename-n,_} $ + map{verilog-rename-e,_} $ + map(verilog-rename-s,s) + + Circuit{info(c),_,main(c)} $ + for m in modules(c) map : + val ports* = for p in ports(m) map : + Port(info(p),verilog-rename-n(name(p)),direction(p),type(p)) + match(m) : + (m:InModule) : InModule(info(m),name(m),ports*,verilog-rename-s(body(m))) + (m:ExModule) : m + ;============ VERILOG ============== public defstruct Verilog <: Pass : @@ -2298,17 +2389,24 @@ defn long! (t:Type) -> Long : w = w + long!(type(f)) w (t:VectorType) : to-long(size(t)) * long!(type(t)) + (t:ClockType) : to-long(1) defn rand-string (t:Type) -> Streamable : val w* = ((long!(t) + to-long(31)) / to-long(32)) - ["{" w* "{" ran "}};"] + ["{" w* "{" ran "}}"] defn emit (x:?) : emit(x,0) defn emit (x:?, top:Int) : + defn cast (e:Expression) -> ? : + match(type(e)) : + (t:UIntType) : e + (t:SIntType) : ["$signed(" e ")"] match(x) : (e:Expression) : turn-off-debug(false) match(e) : (e:DoPrim) : emit(op-stream(e), top + 1) + (e:Mux) : emit([cond(e) " ? " cast(tval(e)) " : " cast(fval(e))],top + 1) + (e:ValidIf) : emit([cast(value(e))],top + 1) (e:WRef) : print(e) (e:WSubField) : print(lowered-name(e)) (e:WSubAccess) : print-all([lowered-name(exp(e)) "[" lowered-name(index(e)) "]"]) @@ -2384,7 +2482,7 @@ defn op-stream (doprim:DoPrim) -> Streamable : EQUIV-OP : [cast-if(a0()) " == " cast-if(a1())] NEQUAL-OP : [cast-if(a0()) " != " cast-if(a1())] EQUAL-OP : [cast-if(a0()) " == " cast-if(a1())] - MUX-OP : [a0() " ? " cast(a1()) " : " cast(a2())] + ;MUX-OP : [a0() " ? " cast(a1()) " : " cast(a2())] PAD-OP : val w = long!(type(a0())) val diff = (to-long(c0()) - w) @@ -2437,6 +2535,10 @@ defn emit-verilog (m:InModule) -> Module : defn build-netlist (s:Stmt) -> Stmt : match(s) : (s:Connect) : netlist[loc(s)] = exp(s) + (s:IsInvalid) : + val n = firrtl-gensym(`GEN,namehash) + val e = wref(n,type(exp(s))) + netlist[exp(s)] = e (s:Conditionally) : add(simlist,s) (s:DefNode) : val e = WRef(name(s),get-type(s),NodeKind(),MALE) @@ -2446,6 +2548,7 @@ defn emit-verilog (m:InModule) -> Module : val portdefs = Vector<Streamable>() val declares = Vector<Streamable>() + val instdeclares = Vector<Streamable>() val assigns = Vector<Streamable>() val at-clock = HashTable<Expression,Vector<Streamable>>(exp-hash) val initials = Vector<Streamable>() @@ -2455,52 +2558,45 @@ defn emit-verilog (m:InModule) -> Module : (t:VectorType) : add(declares,[b " " type(t) " " n " [0:" size(t) - 1 "];"]) (t) : add(declares,[b " " t " " n ";"]) defn assign (e:Expression,value:Expression) : - add(assigns,["assign " e " = " value]) + add(assigns,["assign " e " = " value ";"]) defn update-and-reset (r:Expression,clk:Expression,reset?:Expression,init:Expression) : if not key?(at-clock,clk) : at-clock[clk] = Vector<Streamable>() - - defn mux? (e:Expression) -> True|False : - match(e) : - (e:DoPrim) : - if (op(e) == MUX-OP) : true - else : false - (e) : false - defn add-update (e:Expression,tabs:String) : - if mux?(e) : - val e* = e as DoPrim - add(at-clock[clk],[tabs "if(" args(e*)[0] ") begin"]) - add-update(args(e*)[1],string-join([tabs tab])) - add(at-clock[clk],[tabs "end else begin"]) - add-update(args(e*)[2],string-join([tabs tab])) - add(at-clock[clk],[tabs "end"]) - else : - if e == r : add(at-clock[clk],[tabs ";"]) - else : add(at-clock[clk],[tabs r " <= " e ";"]) - - add-update(MUX(reset?,init,netlist[r]),"");" + match(e) : + (e:Mux) : + add(at-clock[clk],[tabs "if(" cond(e) ") begin"]) + add-update(tval(e),string-join([tabs tab])) + add(at-clock[clk],[tabs "end else begin"]) + add-update(fval(e),string-join([tabs tab])) + add(at-clock[clk],[tabs "end"]) + (e) : + if e == r : add(at-clock[clk],[tabs ";"]) + else : add(at-clock[clk],[tabs r " <= " e ";"]) + val tv = init + val fv = netlist[r] + add-update(Mux(reset?,tv,fv,mux-type-and-widths(tv,fv)),"");" defn update (e:Expression,value:Expression,clk:Expression,en:Expression) : if not key?(at-clock,clk) : at-clock[clk] = Vector<Streamable>() if en == one : - add(at-clock[clk],[e " <= " value]) + add(at-clock[clk],[e " <= " value ";"]) else : add(at-clock[clk],["if(" en ") begin"]) - add(at-clock[clk],[tab e " <= " value]) + add(at-clock[clk],[tab e " <= " value ";"]) add(at-clock[clk],["end"]) defn initialize (e:Expression) : - add(initials,[e " = " rand-string(type(e))]) + add(initials,[e " = " rand-string(type(e)) ";"]) defn initialize-mem (n:Symbol,i:Int,t:Type) : add(initials,["for (initvar = 0; initvar < " i "; initvar = initvar+1)"]) val index = WRef(`initvar,UnknownType(),ExpKind(),UNKNOWN-GENDER) - add(initials,[tab WSubAccess(wref(n,t),index,UnknownType(),FEMALE), " = " rand-string(t)]) + add(initials,[tab WSubAccess(wref(n,t),index,UnknownType(),FEMALE), " = " rand-string(t) ";"]) defn instantiate (n:Symbol,m:Symbol,es:List<Expression>) : - add(declares,[m " " n " ("]) - for (e in es,i in 1 to false) do : + add(instdeclares,[m " " n " ("]) + for (e in es,i in 0 to false) do : val s = [tab "." remove-root(e) "(" lowered-name(e) ")"] - if i == length(es) : add(declares,[s ","]) - else : add(declares,s) - add(declares,[");"]) + if i != length(es) - 1 : add(instdeclares,[s ","]) + else : add(instdeclares,s) + add(instdeclares,[");"]) for e in es do : declare(`wire,lowered-name(e),type(e)) val e* = WRef(lowered-name(e),type(e),kind(e),gender(e)) @@ -2514,10 +2610,10 @@ defn emit-verilog (m:InModule) -> Module : add(at-clock[clk],[tab "end"]) add(at-clock[clk],["`endif"]) defn stop (ret:Int) -> Streamable : - ["$fdisplay(32/'h80000002," ret ");$finish;"] + ["$fdisplay(32'h80000002,\"" ret "\");$finish;"] defn printf (str:String,args:List<Expression>) -> Streamable : val str* = join(List(escape(str),args),",") - ["$fwrite(32/'h80000002," str* ");"] + ["$fwrite(32'h80000002," str* ");"] defn delay (e:Expression, n:Int, clk:Expression) -> Expression : var e* = e for i in 0 to n do : @@ -2552,9 +2648,14 @@ defn emit-verilog (m:InModule) -> Module : val e = wref(name(s),type(s)) update-and-reset(e,clock(s),reset(s),init(s)) initialize(e) + (s:IsInvalid) : + val wref = netlist[exp(s)] as WRef + declare(`reg,name(wref),type(exp(s))) + initialize(wref) (s:DefPoison) : - declare(`reg,name(s),type(s)) - val e = wref(name(s),type(s)) + val n = name(s) + val e = wref(n,type(s)) + declare(`reg,n,type(e)) initialize(e) (s:DefNode) : declare(`wire,name(s),type(value(s))) @@ -2593,7 +2694,7 @@ defn emit-verilog (m:InModule) -> Module : val addr* = delay(addr,read-latency(s),clk) val en* = delay(en,read-latency(s),clk) val mem-port = WSubAccess(mem,addr*,UnknownType(),UNKNOWN-GENDER) - update(data,mem-port,clk,en*) ; m.r.data <= m[addr*] + assign(data,mem-port) for w in writers(s) do : val data = mem-exp(w,`data) @@ -2650,7 +2751,7 @@ defn emit-verilog (m:InModule) -> Module : val raddr* = delay(raddr,read-latency(s),clk) val ren* = delay(ren,read-latency(s),clk) val rmem-port = WSubAccess(mem,raddr*,UnknownType(),UNKNOWN-GENDER) - update(rdata,rmem-port,clk,ren*) + assign(rdata,rmem-port) ; Write assign(wdata,netlist[wdata]) @@ -2671,12 +2772,15 @@ defn emit-verilog (m:InModule) -> Module : emit(["module " name(m) "("]) if !empty?(portdefs) : for (x in portdefs, i in 0 to false) do : - if i != length(portdefs) : emit([tab x ","]) + if i != length(portdefs) - 1 : emit([tab x ","]) else : emit([tab x]) emit([");"]) if !empty?(declares) : for x in declares do : emit([tab x]) + + if !empty?(instdeclares) : + for x in instdeclares do : emit([tab x]) if !empty?(assigns) : for x in assigns do : emit([tab x]) diff --git a/src/main/stanza/passes.stanza2 b/src/main/stanza/passes.stanza2 deleted file mode 100644 index 787b8429..00000000 --- a/src/main/stanza/passes.stanza2 +++ /dev/null @@ -1,2662 +0,0 @@ -defpackage firrtl/passes : - import core - import verse - import firrtl/ir2 - import firrtl/ir-utils - import firrtl/primops - import firrtl-main - import firrtl/errors - import bigint2 - -;============== Pass List ================ -public val standard-passes = to-list $ [ - CheckHighForm() - ;TempElimination() - ToWorkingIR() - Resolve() - ResolveKinds() - ;CheckKinds() - InferTypes() - ;CheckTypes() - ResolveGenders() - ;CheckGenders() - ;ExpandAccessors() - ;LowerToGround() - ;ExpandIndexedConnects() - ;InlineIndexed() - ExpandWhens() - InferWidths() - ;Inline() - SplitExp() - ;CheckLowForm() - ;ToRealIR() - ;Pad() - ] -;=============== WORKING IR ================================ -public definterface Kind -public defstruct WireKind <: Kind -public defstruct PoisonKind <: Kind -public defstruct RegKind <: Kind -public defstruct InstanceKind <: Kind -public defstruct PortKind <: Kind -public defstruct NodeKind <: Kind -public defstruct MemKind <: Kind : - ports : List<Symbol> -public defstruct ExpKind <: Kind - -public definterface Gender -public val MALE = new Gender -public val FEMALE = new Gender -public val UNKNOWN-GENDER = new Gender -public val BI-GENDER = new Gender - -public defstruct WRef <: Expression : - name: Symbol - type: Type with: (as-method => true) - kind: Kind with: (as-method => true) - gender: Gender with: (as-method => true) -public defstruct WSubField <: Expression : - exp: Expression - name: Symbol - type: Type with: (as-method => true) - gender: Gender with: (as-method => true) -public defstruct WSubIndex <: Expression : - exp: Expression - value: Int - type: Type with: (as-method => true) - gender: Gender with: (as-method => true) -public defstruct WSubAccess <: Expression : - exp: Expression - index: Expression - type: Type with: (as-method => true) - gender: Gender with: (as-method => true) -defstruct WIndexer <: Expression : - exps: List<Expression> - index: Expression - type: Type with: (as-method => true) - gender : Gender with: (as-method => true) -public defstruct WVoid <: Expression -public defstruct WDefInstance <: Stmt : - info: FileInfo with: (as-method => true) - name: Symbol - module: Symbol - type: Type - -defmulti gender (e:Expression) -> Gender -defmethod gender (e:Expression) : - MALE - -defn get-gender (s:Stmt|Port) -> Gender : - match(s) : - (s:DefWire|DefRegister) : BI-GENDER - (s:WDefInstance|DefNode|DefInstance|DefPoison) : MALE - (s:Begin|Connect|BulkConnect|Stop|Print|Empty) : UNKNOWN-GENDER - (s:DefMemory) : FEMALE - (p:Port) : - switch { _ == direction(p) } : - INPUT : MALE - OUTPUT : FEMALE - -public defmulti kind (e:Expression) -> Kind -defmethod kind (e:Expression) : - match(e) : - (e:WRef) : kind(e) - (e:WSubField) : kind(exp(e)) - (e:WSubIndex) : kind(exp(e)) - (e:WIndexer) : - val k = kind(exps(e)[0]) - for x in exps(e) do : - if k != kind(x) : error("All kinds of exps of WIndexer must be the same") - k - (e) : ExpKind() - -defmethod info (stmt:Begin) -> FileInfo : FileInfo() -defmethod info (stmt:Empty) -> FileInfo : FileInfo() - -defmethod type (exp:UIntValue) -> Type : UIntType(width(exp)) -defmethod type (exp:SIntValue) -> Type : SIntType(width(exp)) - -defn get-type (s:Stmt) -> Type : - match(s) : - (s:DefWire|DefPoison|DefRegister|WDefInstance) : type(s) - (s:DefNode) : type(value(s)) - (s:DefMemory) : - val depth = depth(s) - ; Fields - val addr = Field(`addr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - val en = Field(`en,DEFAULT,BoolType()) - val clk = Field(`clk,DEFAULT,ClockType()) - val def-data = Field(`data,DEFAULT,data-type(s)) - val rev-data = Field(`data,REVERSE,data-type(s)) - val rdata = Field(`rdata,REVERSE,data-type(s)) - val wdata = Field(`wdata,DEFAULT,data-type(s)) - val mask = create-mask(`mask,data-type(s)) - val wmask = create-mask(`wmask,data-type(s)) - val ren = Field(`ren,DEFAULT,UIntType(IntWidth(1))) - val wen = Field(`wen,DEFAULT,UIntType(IntWidth(1))) - val raddr = Field(`raddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - val waddr = Field(`waddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - - val read-type = BundleType(to-list([rev-data,addr,en,clk])) - val write-type = BundleType(to-list([def-data,mask,addr,en,clk])) - val readwrite-type = BundleType(to-list([wdata,wmask,waddr,wen,rdata,raddr,ren,clk])) - - val mem-fields = Vector<Field>() - for x in readers(s) do : - add(mem-fields,Field(x,DEFAULT,read-type)) - for x in writers(s) do : - add(mem-fields,Field(x,DEFAULT,write-type)) - for x in readwriters(s) do : - add(mem-fields,Field(x,DEFAULT,readwrite-type)) - BundleType(to-list(mem-fields)) - (s:DefInstance) : UnknownType() - (s:Begin|Connect|BulkConnect|Stop|Print|Empty) : UnknownType() - -defmethod equal? (e1:Expression,e2:Expression) -> True|False : - match(e1,e2) : - (e1:UIntValue,e2:UIntValue) : - if value(e1) == value(e2) : width(e1) == width(e2) - else : false - (e1:SIntValue,e2:SIntValue) : - if value(e1) == value(e2) : width(e1) == width(e2) - else : false - (e1:WRef,e2:WRef) : name(e1) == name(e2) - (e1:WSubField,e2:WSubField) : - (name(e1) == name(e2)) and (exp(e1) == exp(e2)) - (e1:WSubIndex,e2:WSubIndex) : - (value(e1) == value(e2)) and (exp(e1) == exp(e2)) - (e1:WSubAccess,e2:WSubAccess) : - (index(e1) == index(e2)) and (exp(e1) == exp(e2)) - (e1:WVoid,e2:WVoid) : true - (e1:WIndexer,e2:WIndexer) : - var bool = (length(exps(e1)) == length(exps(e2))) - for (e1* in exps(e1),e2* in exps(e2)) do : - bool = bool and (e1* == e2*) - bool and (index(e1) == index(e2)) - (e1:DoPrim,e2:DoPrim) : - var are-equal? = op(e1) == op(e2) - for (x in args(e1),y in args(e2)) do : - if not x == y : - are-equal? = false - for (x in consts(e1),y in consts(e2)) do : - if not x == y : - are-equal? = false - are-equal? - (e1,e2) : false - -; ================= PRINTERS =================== -defmethod print (o:OutputStream, g:Gender) : - print{o, _} $ - switch {g == _} : - MALE : "m" - FEMALE: "f" - BI-GENDER : "b" - UNKNOWN-GENDER: "u" - -;============== DEBUG STUFF ============================= -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 -public var PRINT-DEBUG : True|False = false -public var PRINT-INFO : True|False = false - -;========= TO TURN OFF =========== - -var old-PRINT-TYPES : True|False = false -var old-PRINT-KINDS : True|False = false -var old-PRINT-WIDTHS : True|False = false -var old-PRINT-TWIDTHS : True|False = false -var old-PRINT-GENDERS : True|False = false -var old-PRINT-CIRCUITS : True|False = false -var old-PRINT-DEBUG : True|False = false -var old-PRINT-INFO : True|False = false -defmethod turn-off-debug (x:False) : - old-PRINT-TYPES = PRINT-TYPES - old-PRINT-KINDS = PRINT-KINDS - old-PRINT-WIDTHS = PRINT-WIDTHS - old-PRINT-TWIDTHS = PRINT-TWIDTHS - old-PRINT-GENDERS = PRINT-GENDERS - old-PRINT-CIRCUITS = PRINT-CIRCUITS - old-PRINT-DEBUG = PRINT-DEBUG - old-PRINT-INFO = PRINT-INFO - PRINT-TYPES = false - PRINT-KINDS = false - PRINT-WIDTHS = false - PRINT-TWIDTHS = false - PRINT-GENDERS = false - PRINT-CIRCUITS = false - PRINT-DEBUG = false - PRINT-INFO = false - -defmethod turn-on-debug (x:False) : - PRINT-TYPES = old-PRINT-TYPES - PRINT-KINDS = old-PRINT-KINDS - PRINT-WIDTHS = old-PRINT-WIDTHS - PRINT-TWIDTHS = old-PRINT-TWIDTHS - PRINT-GENDERS = old-PRINT-GENDERS - PRINT-CIRCUITS = old-PRINT-CIRCUITS - PRINT-DEBUG = old-PRINT-DEBUG - PRINT-INFO = old-PRINT-INFO - -;=== ThePrinters === - -public defn println-all-debug (l:?) -> False : - if PRINT-DEBUG : println-all(l) - else : false - -public defn println-debug (s:?) -> False : - if PRINT-DEBUG : println(s) - else : false - -defmethod print (o:OutputStream, k:Kind) : - print{o, _} $ - match(k) : - (k:WireKind) : "wire" - (k:PoisonKind) : "poison" - (k:RegKind) : "reg" - (k:PortKind) : "port" - (k:MemKind) : "mem" - (k:NodeKind) : "node" - (k:InstanceKind) : "inst" - (k:ExpKind) : "exp" - -defn hasGender (e:?) : - e typeof Expression - -defn hasWidth (e:?) : - e typeof UIntType|SIntType|UIntValue|SIntValue - -defn hasType (e:?) : - e typeof Expression|DefWire|DefRegister|DefPoison - |VectorType|Port|UIntValue|SIntValue - -defn hasKind (e:?) : - e typeof Expression - -defn hasInfo (e:?) : - e typeof Stmt|Port|Circuit|Module - -defn any-debug? (e:?) : - (hasGender(e) and PRINT-GENDERS) or - (hasType(e) and PRINT-TYPES) or - (hasWidth(e) and PRINT-WIDTHS) or - (hasKind(e) and PRINT-KINDS) or - (hasInfo(e) and PRINT-INFO) - -defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|Module|Circuit) : - defn wipe-width (t:Type) -> Type : - match(t) : - (t:UIntType) : UIntType(UnknownWidth()) - (t:SIntType) : SIntType(UnknownWidth()) - (t) : map(wipe-width,t) - - 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 ?) ">"]) - if PRINT-INFO and hasInfo(e): print-all(o,["<i:" info(e as ?) ">"]) - -defmethod print (o:OutputStream, e:WRef) : - print(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:WSubIndex) : - print-all(o,[exp(e) "[" value(e) "]"]) - print-debug(o,e as ?) -defmethod print (o:OutputStream, e:WSubAccess) : - print-all(o,[exp(e) "[" index(e) "]"]) - print-debug(o,e as ?) -defmethod print (o:OutputStream, e:WVoid) : - print(o,"VOID") - print-debug(o,e as ?) -defmethod print (o:OutputStream, c:WIndexer) : - print-all(o, [exps(c) "[" index(c) "]"]) - print-debug(o,c as ?) -defmethod print (o:OutputStream, c:WDefInstance) : - print-all(o, ["inst " name(c) " of " module(c) " : " type(c)]) - print-debug(o,c as ?) - - -defmethod map (f: Expression -> Expression, e: WSubField) : - WSubField(f(exp(e)), name(e), type(e), gender(e)) -defmethod map (f: Expression -> Expression, e: WSubIndex) : - WSubIndex(f(exp(e)), value(e), type(e), gender(e)) -defmethod map (f: Expression -> Expression, e: WSubAccess) : - WSubAccess(f(exp(e)), f(index(e)), type(e), gender(e)) - -defmethod map (f: Type -> Type, e: WRef) : - WRef(name(e), f(type(e)), kind(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: WSubIndex) : - WSubIndex(exp(e), value(e), f(type(e)), gender(e)) -defmethod map (f: Type -> Type, e: WSubAccess) : - WSubAccess(exp(e), index(e), f(type(e)), gender(e)) - -defmethod map (f: Type -> Type, s: WDefInstance) : - WDefInstance(info(s),name(s),module(s),f(type(s))) - -;================ WIDTH LIBRARY ==================== - -public val ONE = IntWidth(1) -public defstruct VarWidth <: Width : - name: Symbol -public defstruct PlusWidth <: Width : - arg1 : Width - arg2 : Width -public defstruct MinusWidth <: Width : - arg1 : Width - arg2 : Width -public defstruct MaxWidth <: Width : - args : List<Width> -public defstruct ExpWidth <: Width : - arg1 : Width -val width-name-hash = HashTable<Symbol,Int>(symbol-hash) - -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:ExpWidth) : ExpWidth(f(arg1(w))) - (w) : w - -public defmethod print (o:OutputStream, w:VarWidth) : - print(o,name(w)) -public defmethod print (o:OutputStream, w:MaxWidth) : - print-all(o,["max" args(w)]) -public defmethod print (o:OutputStream, w:PlusWidth) : - print-all(o,[ "(" arg1(w) " + " arg2(w) ")"]) -public defmethod print (o:OutputStream, w:MinusWidth) : - print-all(o,[ "(" arg1(w) " - " arg2(w) ")"]) -public defmethod print (o:OutputStream, w:ExpWidth) : - print-all(o,[ "exp(" arg1(w) ")"]) - -defn remove-unknowns-w (w:Width) -> Width : - match(w) : - (w:UnknownWidth) : VarWidth(firrtl-gensym(`w,width-name-hash)) - (w) : w -defn remove-unknowns (t:Type) -> Type : mapr(remove-unknowns-w,t) - -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:PlusWidth,w2:PlusWidth) : - (arg1(w1) == arg1(w2) and arg2(w1) == arg2(w2)) or (arg1(w1) == arg2(w2) and arg2(w1) == arg1(w2)) - (w1:MinusWidth,w2:MinusWidth) : - (arg1(w1) == arg1(w2) and arg2(w1) == arg2(w2)) or (arg1(w1) == arg2(w2) and arg2(w1) == arg1(w2)) - (w1:ExpWidth,w2:ExpWidth) : arg1(w1) == arg1(w2) - (w1:UnknownWidth,w2:UnknownWidth) : true - (w1,w2) : false -;================ WORKING IR UTILS ========================= -;defn plus (g1:Gender,g2:Gender) -> Gender : -; switch fn ([x,y]) : g1 == x and g2 == y : -; [FEMALE,MALE] : UNKNOWN-GENDER -; [MALE,FEMALE] : UNKNOWN-GENDER -; [MALE,MALE] : MALE -; [FEMALE,FEMALE] : FEMALE -; [BI-GENDER,MALE] : MALE -; [BI-GENDER,FEMALE] : FEMALE -; [MALE,BI-GENDER] : MALE -; [FEMALE,BI-GENDER] : FEMALE - -; These functions do not error, but return Unknown Type -defn module-type (m:Module) -> Type : - BundleType(for p in ports(m) map : to-field(p)) -defn field-type (v:Type,s:Symbol) -> Type : - match(v) : - (v:BundleType) : - val ft = for p in fields(v) find : name(p) == s - if ft != false : type(ft as Field) - else : UnknownType() - (v) : UnknownType() -defn sub-type (v:Type) -> Type : - match(v) : - (v:VectorType) : type(v) - (v) : UnknownType() -defn field-flip (v:Type,s:Symbol) -> Flip : - match(v) : - (v:BundleType) : - val ft = for p in fields(v) find : name(p) == s - if ft != false : flip(ft as Field) - else : DEFAULT ;This will get caught later - (v) : DEFAULT - -defn swap (g:Gender) -> Gender : - switch {_ == g} : - UNKNOWN-GENDER : UNKNOWN-GENDER - MALE : FEMALE - FEMALE : MALE - BI-GENDER : BI-GENDER -defn swap (f:Flip) -> Flip : - switch {_ == f} : - DEFAULT : REVERSE - REVERSE : DEFAULT -defn swap (d:Direction) -> Direction : - switch {_ == d} : - OUTPUT : INPUT - INPUT : OUTPUT - -public defn times (flip:Flip,d:Direction) -> Direction : - flip * d -public defn times (d:Direction,flip:Flip) -> Direction : - switch {_ == flip} : - DEFAULT : d - REVERSE : swap(d) -public defn times (g:Gender,flip:Flip) -> Gender : flip * g -public defn times (flip:Flip,g:Gender) -> Gender : - switch {_ == flip} : - DEFAULT : g - REVERSE : swap(g) -public defn times (f1:Flip,f2:Flip) -> Flip : - switch {_ == f2} : - DEFAULT : f1 - REVERSE : swap(f1) - -defn to-field (p:Port) -> Field : - if direction(p) == OUTPUT : Field(name(p),DEFAULT,type(p)) - else if direction(p) == INPUT : Field(name(p),REVERSE,type(p)) - else : error("Shouldn't be here") -defn to-dir (g:Gender) -> Direction : - switch {_ == g} : - MALE : INPUT - FEMALE : OUTPUT -defn to-gender (d:Direction) -> Gender : - switch {_ == d} : - INPUT: MALE - OUTPUT: FEMALE - -;================= Remove Special Characters ======================== -; Returns a new Circuit where all names have all special characters -; removed, except _. -; -;public defstruct RemoveSpecialChars <: Pass -;public defmethod pass (b:RemoveSpecialChars) -> (Circuit -> Circuit) : remove-special-chars -;public defmethod name (b:RemoveSpecialChars) -> String : "Remove Special Characters" -;public defmethod short-name (b:RemoveSpecialChars) -> String : "rem-spec-chars" -; -;;------------ Helper Functions ------------- -; -;defn get-new-string (n:Char) -> String : -; switch {n == _} : -; '_' : "__" -; '~' : "$A" -; '!' : "$B" -; '@' : "$C" -; '#' : "$D" -; '$' : "$E" -; '%' : "$F" -; '^' : "$G" -; '*' : "$H" -; '-' : "$I" -; '+' : "$J" -; '=' : "$K" -; '?' : "$L" -; '/' : "$M" -; else : to-string(n) -; -;;------------ Pass ------------------ -; -;defn remove-special-chars (c:Circuit) : -; defn rename (n:Symbol) -> Symbol : -; val v = Vector<String>() -; for c in to-string(n) do : -; add(v,get-new-string(c)) -; val n* = symbol-join(v) -; if key?(v-keywords,n*) : -; symbol-join([n* `_]) -; else : -; n* -; defn rename-t (t:Type) -> Type : -; match(t) : -; (t:BundleType) : BundleType $ -; for f in fields(t) map : -; Field(rename(name(f)),flip(f),rename-t(type(f))) -; (t:VectorType) : VectorType(rename-t(type(t)),size(t)) -; (t) : t -; defn rename-e (e:Expression) -> Expression : -; match(e) : -; (e:Ref) : Ref(rename(name(e)),rename-t(type(e))) -; (e:Subfield) : Subfield(rename-e(exp(e)),rename(name(e)),rename-t(type(e))) -; (e:Index) : Index(rename-e(exp(e)),value(e),rename-t(type(e))) -; (e:DoPrim) : DoPrim{op(e),_,consts(e),rename-t(type(e))} $ for x in args(e) map : rename-e(x) -; (e:UIntValue) : e -; (e:SIntValue) : e -; defn rename-s (s:Stmt) -> Stmt : -; match(s) : -; (s:DefWire) : DefWire(info(s),rename(name(s)),rename-t(type(s))) -; (s:DefPoison) : DefPoison(info(s),rename(name(s)),rename-t(type(s))) -; (s:DefRegister) : DefRegister(info(s),rename(name(s)),rename-t(type(s)),rename-e(clock(s)),rename-e(reset(s))) -; (s:WDefInstance) : WDefInstance(info(s),rename(name(s)),rename-e(module(s))) -; (s:DefMemory) : DefMemory(info(s),rename(name(s)),rename-t(type(s)),seq?(s),rename-e(clock(s)),size(s)) -; (s:DefNode) : DefNode(info(s),rename(name(s)),rename-e(value(s))) -; (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),rename-e(source(s)),rename-e(index(s)),acc-dir(s)) -; (s:Conditionally) : Conditionally(info(s),rename-e(pred(s)),rename-s(conseq(s)),rename-s(alt(s))) -; (s:Begin) : Begin $ for b in body(s) map : rename-s(b) -; (s:OnReset) : OnReset(info(s),rename-e(loc(s)),rename-e(exp(s))) -; (s:BulkConnect) : BulkConnect(info(s),rename-e(loc(s)),rename-e(exp(s))) -; (s:Connect) : Connect(info(s),rename-e(loc(s)),rename-e(exp(s))) -; (s:EmptyStmt) : s -; (s:StopStmt) : s -; (s:PrintfStmt) : PrintfStmt(info(s),string(s),map(rename-e,args(s))) -; -; Circuit(info(c),modules*, rename(main(c))) where : -; val modules* = -; for m in modules(c) map : -; match(m) : -; (m:InModule) : -; val ports* = for p in ports(m) map : -; Port(info(p),rename(name(p)),direction(p),rename-t(type(p))) -; InModule(info(m),rename(name(m)), ports*, rename-s(body(m))) -; (m:ExModule) : m - - -;================= Temporary Variable Elimination ======================== -; Returns a new Circuit where temporary variables are removed and returns -; the resulting nested expression -;public defstruct TempElimination <: Pass -;public defmethod pass (b:TempElimination) -> (Circuit -> Circuit) : temp-elimination -;public defmethod name (b:TempElimination) -> String : "Temp Elimination" -;public defmethod short-name (b:TempElimination) -> String : "temp-elim" -; -;defn temp-elimination (c:Circuit) : -; defn is-temp? (n:Symbol) -> True|False : -; to-string(n)[0] == 'T' -; defn temp-elim (m:InModule) : -; val h = HashTable<Symbol,Expression>(symbol-hash) -; defn temp-elim-e (e:Expression) : -; match(map(temp-elim-e,e)) : -; (e:Ref) : -; if key?(h,name(e)) : h[name(e)] -; else : e -; (e) : e -; defn temp-elim-s (s:Stmt) : -; match(map(temp-elim-e,s)) : -; (s:DefNode) : -; if is-temp?(name(s)) : -; h[name(s)] = value(s) -; EmptyStmt() -; else : s -; (s) : map(temp-elim-s,s) -; InModule(info(m),name(m), ports(m), temp-elim-s(body(m))) -; -; Circuit(info(c),modules*, main(c)) where : -; val modules* = -; for m in modules(c) map : -; match(m) : -; (m:InModule) : temp-elim(m) -; (m:ExModule) : m - -;================= Bring to Working IR ======================== -; Returns a new Circuit with Refs, Subfields, Indexes and DefAccessors -; replaced with IR-internal nodes that contain additional -; information (kind, gender) - -public defstruct ToWorkingIR <: Pass -public defmethod pass (b:ToWorkingIR) -> (Circuit -> Circuit) : to-working-ir -public defmethod name (b:ToWorkingIR) -> String : "Working IR" -public defmethod short-name (b:ToWorkingIR) -> String : "to-working-ir" - -defn to-working-ir (c:Circuit) : - defn to-exp (e:Expression) -> Expression : - match(map(to-exp,e)) : - (e:Ref) : WRef(name(e), type(e), NodeKind(), UNKNOWN-GENDER) - (e:SubField) : WSubField(exp(e), name(e), type(e), UNKNOWN-GENDER) - (e:SubIndex) : WSubIndex(exp(e), value(e), type(e), UNKNOWN-GENDER) - (e:SubAccess) : WSubAccess(exp(e), index(e), type(e), UNKNOWN-GENDER) - (e) : e - defn to-stmt (s:Stmt) -> Stmt : - match(map(to-exp,s)) : - (s:DefInstance) : WDefInstance(info(s),name(s),module(s),UnknownType()) - (s) : map(to-stmt,s) - - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - match(m) : - (m:InModule) : InModule(info(m),name(m), ports(m), to-stmt(body(m))) - (m:ExModule) : m - -;=============== Resolve Kinds ============================= -; It is useful for the compiler to know information about -; objects referenced. This information is stored in the kind -; field in WRef. This pass walks the graph and returns a new -; Circuit where all WRef kinds are resolved -public defstruct ResolveKinds <: Pass -public defmethod pass (b:ResolveKinds) -> (Circuit -> Circuit) : resolve-kinds -public defmethod name (b:ResolveKinds) -> String : "Resolve Kinds" -public defmethod short-name (b:ResolveKinds) -> String : "resolve-kinds" - -defn resolve-kinds (c:Circuit) : - defn resolve (body:Stmt, kinds:HashTable<Symbol,Kind>) : - defn resolve-stmt (s:Stmt) -> Stmt : - map{resolve-expr,_} $ - map(resolve-stmt,s) - - defn resolve-expr (e:Expression) -> Expression : - match(e) : - (e:WRef) : WRef(name(e),type(e),kinds[name(e)],gender(e)) - (e) : map(resolve-expr,e) - - resolve-stmt(body) - - defn find (m:Module, kinds:HashTable<Symbol,Kind>) : - defn find-stmt (s:Stmt) -> Stmt : - match(s) : - (s:DefWire) : kinds[name(s)] = WireKind() - (s:DefPoison) : kinds[name(s)] = PoisonKind() - (s:DefNode) : kinds[name(s)] = NodeKind() - (s:DefRegister) : kinds[name(s)] = RegKind() - (s:WDefInstance) : kinds[name(s)] = InstanceKind() - (s:DefMemory) : kinds[name(s)] = MemKind(append-all([readers(s) writers(s) readwriters(s)])) - (s) : false - map(find-stmt,s) - - for p in ports(m) do : - kinds[name(p)] = PortKind() - match(m) : - (m:InModule) : find-stmt(body(m)) - (m:ExModule) : false - - defn resolve-kinds (m:Module, c:Circuit) -> Module : - val kinds = HashTable<Symbol,Kind>(symbol-hash) - find(m,kinds) - match(m) : - (m:InModule) : - val body! = resolve(body(m),kinds) - InModule(info(m),name(m),ports(m),body!) - (m:ExModule) : ExModule(info(m),name(m),ports(m)) - - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - resolve-kinds(m,c) - -;============== INFER TYPES ================================ - -; ------------------ Utils ------------------------- - -defn set-type (s:Stmt,t:Type) -> Stmt : - match(s) : - (s:DefWire) : DefWire(info(s),name(s),t) - (s:DefRegister) : DefRegister(info(s),name(s),t,clock(s),reset(s),init(s)) - (s:DefMemory) : DefMemory(info(s),name(s),t,depth(s),write-latency(s),read-latency(s),readers(s),writers(s),readwriters(s)) - (s:DefNode) : s - (s:DefPoison) : DefPoison(info(s),name(s),t) - - -; ------------------ Pass ------------------------- -public defstruct InferTypes <: Pass -public defmethod pass (b:InferTypes) -> (Circuit -> Circuit) : infer-types -public defmethod name (b:InferTypes) -> String : "Infer Types" -public defmethod short-name (b:InferTypes) -> String : "infer-types" - -defn infer-types (c:Circuit) -> Circuit : - val module-types = HashTable<Symbol,Type>(symbol-hash) - defn infer-types (m:Module) -> Module : - val types = HashTable<Symbol,Type>(symbol-hash) - defn infer-types-e (e:Expression) -> Expression : - match(map(infer-types-e,e)) : - (e:WRef) : WRef(name(e), types[name(e)],kind(e),gender(e)) - (e:WSubField) : WSubField(exp(e),name(e),field-type(type(exp(e)),name(e)),gender(e)) - (e:WSubIndex) : WSubIndex(exp(e),value(e),sub-type(type(exp(e))),gender(e)) - (e:WSubAccess) : WSubAccess(exp(e),index(e),sub-type(type(exp(e))),gender(e)) - (e:DoPrim) : set-primop-type(e) - (e:UIntValue|SIntValue) : e - defn infer-types-s (s:Stmt) -> Stmt : - match(s) : - (s:DefRegister) : - val t = remove-unknowns(get-type(s)) - types[name(s)] = t - map(infer-types-e,set-type(s,t)) - (s:DefWire|DefPoison|DefNode) : - val s* = map(infer-types-e,s) - val t = remove-unknowns(get-type(s*)) - types[name(s*)] = t - set-type(s*,t) - (s:DefMemory) : - val t = remove-unknowns(get-type(s)) - types[name(s)] = t - val dt = remove-unknowns(data-type(s)) - set-type(s,dt) - (s:WDefInstance) : - types[name(s)] = module-types[module(s)] - WDefInstance(info(s),name(s),module(s),module-types[module(s)]) - (s) : map{infer-types-e,_} $ map(infer-types-s,s) - for p in ports(m) do : - types[name(p)] = type(p) - match(m) : - (m:InModule) : - InModule(info(m),name(m),ports(m),infer-types-s(body(m))) - (m:ExModule) : m - - ; MAIN - val modules* = - for m in modules(c) map : - val ports* = - for p in ports(m) map : - Port(info(p),name(p),direction(p),remove-unknowns(type(p))) - match(m) : - (m:InModule) : InModule(info(m),name(m),ports*,body(m)) - (m:ExModule) : ExModule(info(m),name(m),ports*) - - for m in modules* do : - module-types[name(m)] = module-type(m) - Circuit{info(c), _, main(c) } $ - for m in modules* map : - infer-types(m) - -;============= RESOLVE GENDER ============================ -; To ensure a proper circuit, we must ensure that assignments -; only work on expressions that can be assigned to. Similarly, -; we must ensure that only expressions that can be read from -; are used to assign from. This invariant requires each -; expression's gender to be inferred. -; Various elements can be bi-gender (e.g. wires) and can -; thus be treated as either female or male. Conversely, some -; elements are single-gender (e.g. accessors, ports). -public defstruct ResolveGenders <: Pass -public defmethod pass (b:ResolveGenders) -> (Circuit -> Circuit) : resolve-genders -public defmethod name (b:ResolveGenders) -> String : "Resolve Genders" -public defmethod short-name (b:ResolveGenders) -> String : "resolve-genders" - -defn resolve-genders (c:Circuit) : - defn resolve-e (e:Expression,g:Gender) -> Expression : - match(e) : - (e:WRef) : WRef(name(e),type(e),kind(e),g) - (e:WSubField) : - val exp* = - switch { _ == field-flip(type(exp(e)),name(e)) } : - DEFAULT : resolve-e(exp(e),g) - REVERSE : resolve-e(exp(e),swap(g)) - WSubField(exp*,name(e),type(e),g) - (e:WSubIndex) : - val exp* = resolve-e(exp(e),g) - WSubIndex(exp*,value(e),type(e),g) - (e:WSubAccess) : - val exp* = resolve-e(exp(e),g) - val index* = resolve-e(index(e),MALE) - WSubAccess(exp*,index*,type(e),g) - (e:WIndexer) : - val exps* = map(resolve-e{_,g},exps(e)) - val index* = resolve-e(index(e),MALE) - WIndexer(exps*,index*,type(e),g) - (e) : map(resolve-e{_,g},e) - - defn resolve-s (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : - val loc* = resolve-e(loc(s),FEMALE) - val exp* = resolve-e(exp(s),MALE) - Connect(info(s),loc*,exp*) - (s:BulkConnect) : - val loc* = resolve-e(loc(s),FEMALE) - val exp* = resolve-e(exp(s),MALE) - BulkConnect(info(s),loc*,exp*) - (s) : - map{resolve-s,_} $ map(resolve-e{_,MALE},s) - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - match(m) : - (m:InModule) : - val body* = resolve-s(body(m)) - InModule(info(m),name(m),ports(m),body*) - (m:ExModule) : m - -;;============== EXPAND ACCESSORS ================================ -; This pass expands non-memory accessors into DecFromIndexer or -; ConnectFromIndexed. All elements of the vector are -; explicitly written out, then indexed. Depending on the gender -; of the accessor, it is transformed into DecFromIndexer (male) or -; DecToIndexer (female) - -;public defstruct ExpandAccesses <: Pass -;public defmethod pass (b:ExpandAccesses) -> (Circuit -> Circuit) : expand-accesses -;public defmethod name (b:ExpandAccesses) -> String : "Expand Accesses" -;public defmethod short-name (b:ExpandAccesses) -> String : "expand-accesses" -; - -defn expand-vector (e:Expression,g:Gender) -> List<Expression> : - val t = type(e) as VectorType - for i in 0 to size(t) map-append : - list(WSubIndex(e,i,type(t),g)) ;always be WRef|WSubField|WSubIndex - - - -;================ EXPAND CONNECTS ================== -public defstruct ExpandConnects <: Pass -public defmethod pass (b:ExpandConnects) -> (Circuit -> Circuit) : expand-connects -public defmethod name (b:ExpandConnects) -> String : "Expand Connects" -public defmethod short-name (b:ExpandConnects) -> String : "expand-connects" - -;---------------- UTILS ------------------ -defn get-size (e:Expression) -> Int : get-size(type(e)) -defn get-size (t:Type) -> Int : - match(t) : - (t:BundleType) : - var sum = 0 - for f in fields(t) do : - sum = sum + get-size(type(f)) - sum - (t:VectorType) : size(t) * get-size(type(t)) - (t) : 1 -defn get-flip (t:Type, i:Int, f:Flip) -> Flip : - if i >= get-size(t) : error("Shouldn't be here") - match(t) : - (t:UIntType|SIntType|ClockType) : f - (t:BundleType) : label<Flip> ret : - var n = i - for x in fields(t) do : - if n < get-size(type(x)) : - ret(get-flip(type(x),n,flip(x) * f)) - else : - n = n - get-size(type(x)) - error("Shouldn't be here") - (t:VectorType) : label<Flip> ret : - var n = i - for j in 0 to size(t) do : - if n < get-size(type(t)) : - ret(get-flip(type(t),n,f)) - else : - n = n - get-size(type(t)) - error("Shouldn't be here") -defn get-point (e:Expression) -> Int : - match(e) : - (e:WRef) : 0 - (e:WSubField) : - var i = 0 - for f in fields(type(exp(e)) as BundleType) find : - val b = name(f) == name(e) - if not b : i = i + get-size(type(f)) - b - i - (e:WSubIndex) : - value(e) * get-size(e) - (e:WSubAccess) : - get-point(exp(e)) -defn get-valid-points (t1:Type,t2:Type,flip1:Flip,flip2:Flip) -> List<[Int,Int]> : - ;println-all(["Inside with t1:" t1 ",t2:" t2 ",f1:" flip1 ",f2:" flip2]) - match(t1,t2) : - (t1:UIntType,t2:UIntType) : - if flip1 == flip2 : list([0, 0]) - else: list() - (t1:SIntType,t2:SIntType) : - if flip1 == flip2 : list([0, 0]) - else: list() - (t1:BundleType,t2:BundleType) : - val points = Vector<[Int,Int]>() - var ilen = 0 - var jlen = 0 - for i in 0 to length(fields(t1)) do : - for j in 0 to length(fields(t2)) do : - ;println(i) - ;println(j) - ;println(ilen) - ;println(jlen) - val f1 = fields(t1)[i] - val f2 = fields(t2)[j] - if name(f1) == name(f2) : - val ls = get-valid-points(type(f1),type(f2),flip1 * flip(f1), - flip2 * flip(f2)) - for x in ls do : - add(points,[x[0] + ilen, x[1] + jlen]) - println(points) - jlen = jlen + get-size(type(fields(t2)[j])) - ilen = ilen + get-size(type(fields(t1)[i])) - jlen = 0 - to-list(points) - (t1:VectorType,t2:VectorType) : - val points = Vector<[Int,Int]>() - var ilen = 0 - var jlen = 0 - for i in 0 to min(size(t1),size(t2)) do : - val ls = get-valid-points(type(t1),type(t2),flip1,flip2) - for x in ls do : - add(points,[x[0] + ilen, x[1] + jlen]) - ilen = ilen + get-size(type(t1)) - jlen = jlen + get-size(type(t2)) - to-list(points) - - -defn create-exps (n:Symbol, t:Type) -> List<Expression> : - create-exps(WRef(n,t,ExpKind(),UNKNOWN-GENDER)) -defn create-exps (e:Expression) -> List<Expression> : - match(type(e)) : - (t:UIntType|SIntType|ClockType) : list(e) - (t:BundleType) : - for f in fields(t) map-append : - create-exps(WSubField(e,name(f),type(f),gender(e) * flip(f))) - (t:VectorType) : - for i in 0 to size(t) map-append : - create-exps(WSubIndex(e,i,type(t),gender(e))) - -val hashed-create-exps = HashTable<Expression,List<Expression>>(exp-hash) -defn fast-create-exps (n:Symbol, t:Type) -> List<Expression> : - fast-create-exps(WRef(n,t,ExpKind(),UNKNOWN-GENDER)) -defn fast-create-exps (e:Expression) -> List<Expression> : - if key?(hashed-create-exps,e) : hashed-create-exps[e] - else : - val es = Vector<Expression>() - defn create-exps (e:Expression) -> False : - match(type(e)) : - (t:UIntType|SIntType|ClockType) : add(es,e) - (t:BundleType) : - for f in fields(t) do : - create-exps(WSubField(e,name(f),type(f),gender(e) * flip(f))) - (t:VectorType) : - for i in 0 to size(t) do : - create-exps(WSubIndex(e,i,type(t),gender(e))) - create-exps(e) - val x = to-list(es) - hashed-create-exps[e] = x - x - -;---------------- Pass --------------------- - -defn expand-connects (c:Circuit) -> Circuit : - defn expand-connects (m:InModule) -> InModule : - defn expand-s (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : - val n = get-size(loc(s)) - val connects = Vector<Stmt>() - val locs = fast-create-exps(loc(s)) - val exps = fast-create-exps(exp(s)) - for i in 0 to n do : - val loc* = locs[i] - val exp* = exps[i] - add{connects,_} $ - switch { _ == get-flip(type(loc(s)),i,DEFAULT) } : - DEFAULT : Connect(info(s),loc*,exp*) - REVERSE : Connect(info(s),exp*,loc*) - Begin(to-list(connects)) - (s:BulkConnect) : - val ls = get-valid-points(type(loc(s)),type(exp(s)),DEFAULT,DEFAULT) - val connects = Vector<Stmt>() - val locs = fast-create-exps(loc(s)) - val exps = fast-create-exps(exp(s)) - for x in ls do : - val loc* = locs[x[0]] - val exp* = exps[x[1]] - add{connects,_} $ - switch { _ == get-flip(type(loc(s)),x[0],DEFAULT) } : - DEFAULT : Connect(info(s),loc*,exp*) - REVERSE : Connect(info(s),exp*,loc*) - Begin(to-list(connects)) - (s) : map(expand-s,s) - - InModule(info(m),name(m),ports(m),expand-s(body(m))) - - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : expand-connects(m) - - -;;;================ REPLACE INDEXERS ========================= -; This pass inlines all accessors to non-memory vector typed -; components. - -public defstruct RemoveAccesses <: Pass -public defmethod pass (b:RemoveAccesses) -> (Circuit -> Circuit) : remove-access -public defmethod name (b:RemoveAccesses) -> String : "Remove Accesses" -public defmethod short-name (b:RemoveAccesses) -> String : "remove-access" - -defstruct Location : - base : Expression - guard : Expression -defmethod print (o:OutputStream,x:Location) : - print-all(o,["[" base(x) " , " guard(x) "]"]) - - -val hashed-locations = HashTable<Expression,List<Location>>(exp-hash) -defn get-locations (e:Expression) -> List<Location> : - if key?(hashed-locations,e) : hashed-locations[e] - else : - val x = match(e) : - (e:WRef) : map(Location{_,one},fast-create-exps(e)) - (e:WSubIndex|WSubField) : - val ls = get-locations(exp(e)) - val start = get-point(e) - val end = start + get-size(e) - val stride = get-size(exp(e)) - val ls* = Vector<Location>() - var c = 0 - for i in 0 to length(ls) do : - if (i % stride >= start and i % stride < end) : - add(ls*,ls[i]) - to-list(ls*) - (e:WSubAccess) : - val ls = get-locations(exp(e)) - val stride = get-size(e) - val wrap = size(type(exp(e)) as VectorType) - val ls* = Vector<Location>() - var c = 0 - for i in 0 to length(ls) do : - if c % wrap == 0 : c = 0 - val base* = base(ls[i]) - val guard* = AND(guard(ls[i]),EQV(uint(c),index(e))) - add(ls*,Location(base*,guard*)) - if (i + 1) % stride == 0 : c = c + 1 - to-list(ls*) - hashed-locations[e] = x - x - -defn remove-access (c:Circuit) : - defn remove-m (m:InModule) -> InModule : - val sh = get-sym-hash(m,keys(v-keywords)) - defn remove-s (s:Stmt) -> Stmt : - val stmts = Vector<Stmt>() - defn create-temp (e:Expression) -> Expression : - val n = firrtl-gensym(`GEN,sh) - add(stmts,DefWire(info(s),n,type(e))) - WRef(n,type(e),kind(e),gender(e)) - defn remove-e (e:Expression) -> Expression : ;NOT RECURSIVE (except primops) INTENTIONALLY! - match(e) : - (e:DoPrim) : map(remove-e,e) - (e:UIntValue|SIntValue) : e - (e) : - val rs = get-locations(e) - val foo = for x in rs find : - (guard(x)) != one - if foo == false : e - else : - val temp = create-temp(e) - for (x in rs, i in 0 to false) do : - if i == 0 : - add(stmts,Connect(info(s),temp,base(x))) - else : - add(stmts,Conditionally(info(s),guard(x),Connect(info(s),temp,base(x)),Empty())) - temp - val s* = match(s) : - (s:Connect) : - val ls = get-locations(loc(s)) - val loc* = - if length(ls) == 1 and guard(head(ls)) == one : loc(s) - else : - val temp = create-temp(loc(s)) - for x in ls do : - add(stmts,Conditionally(info(s),guard(x),Connect(info(s),base(x),temp),Empty())) - temp - Connect(info(s),loc*,remove-e(exp(s))) - (s) : map{remove-s,_} $ map(remove-e,s) - add(stmts,s*) - if length(stmts) != 1 : Begin(to-list(stmts)) - else : stmts[0] - - InModule(info(m),name(m),ports(m),remove-s(body(m))) - - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : remove-m(m) - -;;================ EXPAND WHENS ============================= -; This pass does three things: remove last connect semantics, -; remove conditional blocks, and eliminate concept of scoping. - -public defstruct ExpandWhens <: Pass -public defmethod pass (b:ExpandWhens) -> (Circuit -> Circuit) : expand-whens -public defmethod name (b:ExpandWhens) -> String : "Expand Whens" -public defmethod short-name (b:ExpandWhens) -> String : "expand-whens" - -; ========== Expand When Utilz ========== - -defn get-entries (hash:HashTable<Expression,Expression>,exps:Streamable<Expression>) -> HashTable<Expression,Expression> : - val hash* = HashTable<Expression,Expression>(exp-hash) - for e in exps do : - val value = get?(hash,e,false) - match(value) : - (value:Expression) : hash*[e] = value - (value:False) : false - hash* -defn get-female-refs (n:Symbol,t:Type,g:Gender) -> List<Expression> : - val exps = fast-create-exps(WRef(n,t,ExpKind(),g)) - val exps* = Vector<Expression>() - for i in 0 to length(exps) do : - switch { _ == get-gender(t,i,g)} : - BI-GENDER : add(exps*,exps[i]) - FEMALE : add(exps*,exps[i]) - else : false - to-list(exps*) -defn get-gender (t:Type, i:Int, g:Gender) -> Gender : - val f = get-flip(t,i,DEFAULT) - g * f -defn print-hash (h:HashTable<Expression,Expression>) : - for x in h do : - println(x) - -; ------------ Pass ------------------- -defn expand-whens (c:Circuit) -> Circuit : - defn void-all (m:InModule) -> InModule : - defn void-all-s (s:Stmt) -> Stmt : - match(s) : - (s:DefWire|DefRegister|WDefInstance|DefMemory) : - val voids = Vector<Stmt>() - for e in get-female-refs(name(s),get-type(s),get-gender(s)) do : - add(voids,Connect(info(s),e,WVoid())) - Begin(List(s,to-list(voids))) - (s) : map(void-all-s,s) - val voids = Vector<Stmt>() - for p in ports(m) do : - for e in get-female-refs(name(p),type(p),get-gender(p)) do : - add(voids,Connect(info(p),e,WVoid())) - val body* = void-all-s(body(m)) - InModule(info(m),name(m),ports(m),Begin(list(Begin(to-list(voids)),body*))) - - defn expand-whens (m:InModule) -> [HashTable<Expression,Expression> Vector<Stmt>] : - val simlist = Vector<Stmt>() - defn expand-whens (s:Stmt,netlist:HashTable<Expression,Expression>,p:Expression) -> Stmt : - match(s) : - (s:Connect) : netlist[loc(s)] = exp(s) - (s:Conditionally) : - val exps = Vector<Expression>() - defn prefetch (s:Stmt) -> Stmt: - match(s) : - (s:Connect) : - add(exps,loc(s)) - s - (s) : map(prefetch,s) - prefetch(conseq(s)) - val c-netlist = get-entries(netlist,exps) - expand-whens(conseq(s),c-netlist,AND(p,pred(s))) - expand-whens(alt(s),netlist,AND(p,NOT(pred(s)))) - for lvalue in keys(c-netlist) do : - val value = get?(netlist,lvalue,false) - match(value) : - (value:Expression) : - netlist[lvalue] = MUX(pred(s),c-netlist[lvalue],value) - (value:False) : - netlist[lvalue] = c-netlist[lvalue] - (s:Print) : - if p == one : add(simlist,s) - else : add(simlist,Print(info(s),string(s),args(s),clk(s),AND(p,en(s)))) - (s:Stop) : - if p == one : add(simlist,s) - else : add(simlist,Stop(info(s),ret(s),clk(s),AND(p,en(s)))) - (s) : map(expand-whens{_,netlist,p},s) - s - val netlist = HashTable<Expression,Expression>(exp-hash) - expand-whens(body(m),netlist,one) - - ;println("Netlist:") - ;println(netlist) - ;println("Simlist:") - ;println(simlist) - [ netlist simlist ] - - defn create-module (netlist:HashTable<Expression,Expression>,simlist:Vector<Stmt>,m:InModule) -> InModule : - val stmts = Vector<Stmt>() - val connections = Vector<Stmt>() - defn replace-void (e:Expression,rvalue:Expression) -> Expression : - match(rvalue) : - (rv:WVoid) : e - (rv) : map(replace-void{e,_},rv) - defn create (s:Stmt) -> Stmt : - match(s) : - (s:DefWire|DefRegister|WDefInstance|DefMemory) : - add(stmts,s) - for e in get-female-refs(name(s),get-type(s),get-gender(s)) do : - val rvalue = - if s typeof DefRegister : replace-void(e,netlist[e]) - else : netlist[e] - add(connections,Connect(info(s),e,rvalue)) - (s:DefPoison|DefNode) : - add(stmts,s) - (s) : map(create,s) - s - create(body(m)) - for p in ports(m) do : - for e in get-female-refs(name(p),type(p),get-gender(p)) do : - add(connections,Connect(info(p),e,netlist[e])) - for x in simlist do : - add(stmts,x) - InModule(info(m),name(m),ports(m),Begin(list(Begin(to-list(stmts)),Begin(to-list(connections))))) - - val voided-modules = - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : - val m* = void-all(m as InModule) - m* - val modules* = - for m in voided-modules map : - match(m) : - (m:ExModule) : m - (m:InModule) : - val [netlist simlist] = expand-whens(m) - create-module(netlist,simlist,m) - Circuit(info(c),modules*,main(c)) - -;;================ Module Duplication ================== -; Duplicates modules so that no module is instantiated -; more than once. - -;public defstruct ModuleDuplication <: Pass -;public defmethod pass (b:ModuleDuplication) -> (Circuit -> Circuit) : module-duplication -;public defmethod name (b:ModuleDuplication) -> String : "Module Duplication" -;public defmethod short-name (b:ModuleDuplication) -> String : "mod-dup" -; -;;------------ Helper Functions ------------- -; -;;------------ Pass ------------------ -; -;public defn module-duplication (c:Circuit) : -; val modules* = Vector<Module>() -; val m-names = HashTable<Symbol,Int>(symbol-hash) -; defn rename (n:Symbol) -> Symbol : -; val int = get?(m-names,n,0) -; m-names[n] = int + 1 -; val n* = symbol-join([n module-expand-delin int]) -; val m = for x in modules(c) find : name(x) == n -; match(m) : -; (m:InModule) : add(modules*,InModule(info(m),n*, ports(m), rename-s(body(m)))) -; (m:ExModule) : add(modules*,ExModule(info(m),n*, ports(m))) -; (m:False) : error("Shouldn't be here") -; n* -; -; defn rename-e (e:Expression) -> Expression : -; match(e) : -; (e:Ref) : Ref(rename(name(e)),type(e)) -; (e) : error("Shouldn't be here") -; defn rename-s (s:Stmt) -> Stmt : -; match(s) : -; (s:WDefInstance) : WDefInstance(info(s),name(s),rename-e(module(s))) -; (s) : map(rename-s,s) -; -; val top = for m in modules(c) find : name(m) == main(c) -; match(top) : -; (m:InModule) : add(modules*,InModule(info(m),name(m), ports(m), rename-s(body(m)))) -; (m:ExModule) : m -; (m:False) : error("Shouldn't be here") -; -; Circuit(info(c),to-list(modules*), main(c)) -; -; -;;;================ Deadcode Elimination =================== -;; Walks the circuit, starting from the outputs from the top -;; level module. All components that are not reached are -;; deleted -; -;public defstruct DeadcodeElimination <: Pass -;public defmethod pass (b:DeadcodeElimination) -> (Circuit -> Circuit) : deadcode-elimination -;public defmethod name (b:DeadcodeElimination) -> String : "Deadcode Elimination" -;public defmethod short-name (b:DeadcodeElimination) -> String : "deadcode-elim" -; -;;------------ Helper Functions ------------- -; -;;------------ Pass ------------------ -; -;public defn deadcode-elimination (c:Circuit) : c -; -;;;================ 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. -;; Low FIRRTL Pass. -public defstruct InferWidths <: Pass -public defmethod pass (b:InferWidths) -> (Circuit -> Circuit) : infer-widths -public defmethod name (b:InferWidths) -> String : "Infer Widths" -public defmethod short-name (b:InferWidths) -> String : "infer-widths" - -public definterface Constraint -public defstruct WGeq <: Constraint : - loc : Width - exp : Width -public defmethod print (o:OutputStream, c:WGeq) : - print-all(o,[ loc(c) " >= " exp(c)]) -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 solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Width> : - 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:PlusWidth) : - match(arg1(w),arg2(w)) : - (w1:IntWidth,w2:IntWidth) : IntWidth(plus(width(w1),width(w2))) - (w1,w2) : w - (w:MinusWidth) : - match(arg1(w),arg2(w)) : - (w1:IntWidth,w2:IntWidth) : IntWidth(minus(width(w1),width(w2))) - (w1,w2) : w - (w:ExpWidth) : - match(arg1(w)) : - (w1:IntWidth) : IntWidth(pow(to-long(2),width(w1)) - to-long(1)) - (w1) : w - (w) : w - defn substitute (w:Width,h:HashTable<Symbol,Width>) -> Width : - ;println-all-debug(["Substituting for [" w "]"]) - val w* = simplify(w) - ;println-all-debug(["After Simplify: [" w* "]"]) - match(map(substitute{_,h},simplify(w))) : - (w:VarWidth) : - ;println-debug("matched varwidth!") - if contains?(name(w),h) : - ;println-debug("Contained!") - ;println-all-debug(["Width: " w]) - ;println-all-debug(["Accessed: " h[name(w)]]) - val t = simplify(substitute(h[name(w)],h)) - ;val t = h[name(w)] - ;println-all-debug(["Width after sub: " t]) - h[name(w)] = t - t - else : w - (w): - ;println-all-debug(["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-debug(["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:MinusWidth) : - if arg1(w) == VarWidth(n) : arg1(w) - else : w - (w) : w - ;println-all-debug(["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? - - ; 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-debug("======== UNIQUE CONSTRAINTS ========") - for x in u do : println-debug(x) - println-debug("====================================") - - val f = HashTable<Symbol,Width>(symbol-hash) - val o = Vector<Symbol>() - for x in u do : - println-debug("==== SOLUTIONS TABLE ====") - for x in f do : println-debug(x) - println-debug("=========================") - - val [n e] = [key(x) value(x)] - - val e-sub = substitute(e,f) - println-debug(["Solving " n " => " e]) - println-debug(["After Substitute: " n " => " e-sub]) - println-debug("==== SOLUTIONS TABLE (Post Substitute) ====") - for x in f do : println-debug(x) - println-debug("=========================") - val e* = remove-cycle{n,_} $ e-sub - ;println-debug(["After Remove Cycle: " n " => " e*]) - if not self-rec?(n,e*) : - ;println-all-debug(["Not rec!: " n " => " e*]) - ;println-all-debug(["Adding [" n "=>" e* "] to Solutions Table"]) - add(o,n) - f[n] = e* - - println-debug("Forward Solved Constraints") - for x in f do : println-debug(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-debug(["SOLVE BACK: [" n " => " f[n] "]"]) - println-debug("==== SOLUTIONS TABLE ====") - for x in b do : println-debug(x) - println-debug("=========================") - val e* = simplify(b-sub(f[n],b)) - println-all-debug(["BACK RETURN: [" n " => " e* "]"]) - b[n] = e* - println-debug("==== SOLUTIONS TABLE (Post backsolve) ====") - for x in b do : println-debug(x) - println-debug("=========================") - b - -public defn width! (t:Type) -> Width : - match(t) : - (t:UIntType) : width(t) - (t:SIntType) : width(t) - (t:ClockType) : IntWidth(1) - (t) : error("No width!") -public defn width! (e:Expression) -> Width : width!(type(e)) - -defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit : - defn evaluate (w:Width) -> Width : - defn apply (a:Long|False,f:(Long) -> Long) -> Long|False : - if a typeof Long : f(a as Long) - else : false - defn apply (a:Long|False,b:Long|False, f: (Long,Long) -> Long) -> Long|False : - if a typeof Long and b typeof Long : f(a as Long, b as Long) - else : false - defn apply-l (l:List<Long|False>,f:(Long,Long) -> Long) -> Long|False : - if length(l) == 0 : to-long(0) - else : apply(head(l),apply-l(tail(l),f),f) - defn max (a:Long,b:Long) -> Long : - if a >= b : a - else : b - defn solve (w:Width) -> False|Long : - match(w) : - (w:VarWidth) : - val w* = get?(h,name(w),false) - match(w*) : - (w:VarWidth) : false - (w:False) : false - (w) : solve(w as Width) - (w:MaxWidth) : apply-l(map(solve,args(w)),max) - (w:PlusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{plus(_,_)}) - (w:MinusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{minus(_,_)}) - (w:ExpWidth) : apply(to-long(2),solve(arg1(w)),{minus(pow(_,_),to-long(1))}) - (w:IntWidth) : width(w) - (w) : - println(w) - error("Shouldn't be here") - - val s = solve(w) - match(s) : - (s:Long) : IntWidth(s) - (s) : w - - defn reduce-var-widths-w (w:Width) -> Width : - println-all-debug(["REPLACE: " w]) - val w* = evaluate(w) - println-all-debug(["WITH: " w*]) - w* - - val modules* = for m in modules(c) map : - val ports* = for p in ports(m) map : - Port(info(p),name(p),direction(p),mapr(reduce-var-widths-w,type(p))) - - match(m) : - (m:ExModule) : ExModule(info(m),name(m),ports*) - (m:InModule) : InModule(info(m),name(m),ports*,mapr(reduce-var-widths-w,body(m))) - - Circuit(info(c),modules*,main(c)) - -defn infer-widths (c:Circuit) -> Circuit : - val v = Vector<WGeq>() - defn constrain (w1:Width,w2:Width) -> False : constrain(w1,w2,DEFAULT) - defn constrain (w1:Width,w2:Width,f:Flip) -> False : - switch { _ == f } : - DEFAULT : add(v,WGeq(w1,w2)) - REVERSE : add(v,WGeq(w2,w1)) - defn get-constraints (t1:Type,t2:Type,f:Flip) -> False : - match(t1,t2) : - (t1:UIntType,t2:UIntType) : constrain(width(t1),width(t2)) - (t1:SIntType,t2:SIntType) : constrain(width(t1),width(t2)) - (t1:BundleType,t2:BundleType) : - for (f1 in fields(t1),f2 in fields(t2)) do : - get-constraints(type(f1),type(f2),flip(f1) * f) - (t1:VectorType,t2:VectorType) : - get-constraints(type(t1),type(t2),f) - defn get-constraints-e (e:Expression) -> Expression : - match(map(get-constraints-e,e)) : - (e:DoPrim) : - if op(e) == MUX-OP : - constrain(width!(args(e)[0]),ONE) - constrain(ONE,width!(args(e)[0])) - e - (e) : e - defn get-constraints (s:Stmt) -> Stmt : - match(map(get-constraints-e,s)) : - (s:Connect) : - ;constrain(width!(loc(s)),width!(exp(s))) - ;s - val n = get-size(loc(s)) - val ce-loc = fast-create-exps(loc(s)) - val ce-exp = fast-create-exps(exp(s)) - for i in 0 to n do : - val loc* = ce-loc[i] - val exp* = ce-exp[i] - switch { _ == get-flip(type(loc(s)),i,DEFAULT) } : - DEFAULT : constrain(width!(loc*),width!(exp*)) - REVERSE : constrain(width!(exp*),width!(loc*)) - s - (s:BulkConnect) : - val ls = get-valid-points(type(loc(s)),type(exp(s)),DEFAULT,DEFAULT) - for x in ls do : - println(x) - println(fast-create-exps(loc(s))) - println(fast-create-exps(exp(s))) - val loc* = fast-create-exps(loc(s))[x[0]] - val exp* = fast-create-exps(exp(s))[x[1]] - switch { _ == get-flip(type(loc(s)),x[0],DEFAULT) } : - DEFAULT : constrain(width!(loc*),width!(exp*)) - REVERSE : constrain(width!(exp*),width!(loc*)) - s - (s:DefRegister) : - constrain(width!(reset(s)),ONE) - constrain(ONE,width!(reset(s))) - get-constraints(type(s),type(init(s)),DEFAULT) - s - (s:Conditionally) : - add(v,WGeq(width!(pred(s)),ONE)) - add(v,WGeq(ONE,width!(pred(s)))) - map(get-constraints,s) - (s) : map(get-constraints,s) - - for m in modules(c) do : - match(m) : - (m:InModule) : get-constraints(body(m)) - (m) : false - println-debug("======== ALL CONSTRAINTS ========") - for x in v do : println-debug(x) - println-debug("=================================") - val h = solve-constraints(to-list(v)) - println-debug("======== SOLVED CONSTRAINTS ========") - for x in h do : println-debug(x) - println-debug("====================================") - reduce-var-widths(Circuit(info(c),modules(c),main(c)),h) - -; ================ All Resolving Passes ================ -public defstruct Resolve <: Pass -public defmethod pass (b:Resolve) -> (Circuit -> Circuit) : resolve -public defmethod name (b:Resolve) -> String : "Resolve" -public defmethod short-name (b:Resolve) -> String : "resolve" - -defn resolve (c:Circuit) -> Circuit : - infer-widths $ - resolve-genders $ - infer-types $ - resolve-kinds $ c - -;;================= Inline Instances ======================== -;; Inlines instances. Assumes module with same name as the -;; Circuit is the top level module -;public defstruct Inline <: Pass -;public defmethod pass (b:Inline) -> (Circuit -> Circuit) : inline-instances -;public defmethod name (b:Inline) -> String : "Inline Instances" -;public defmethod short-name (b:Inline) -> String : "inline-instances" -; -;defn inline-instances (c:Circuit) : -; val h = HashTable<Symbol,InModule>(symbol-hash) -; val h-s = HashTable<Symbol,Stmt>(symbol-hash) -; defn inline-inst (s:Stmt) -> Stmt : -; match(map(inline-inst,s)) : -; (s:WDefInstance) : -; 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(info(s),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) inline-delin name(e)]),type(e),k,gender(e)) -; (k:MemKind) : e -; (e) : e -; defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n inline-delin 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) inline-delin 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(info(s),rename(name(s),n),type(s)) -; (s:DefPoison) : DefPoison(info(s),rename(name(s),n),type(s)) -; (s:DefRegister) : DefRegister(info(s),rename(name(s),n),type(s),clock(s),reset(s)) -; (s:WDefInstance) : error("Shouldn't be here") -; (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s),clock(s),size(s)) -; (s:DefNode) : DefNode(info(s),rename(name(s),n),value(s)) -; (s) : s -; for m in modules(c) do : -; match(m) : -; (m:ExModule) : error("Cannot inline with external modules") -; (m:InModule) : h[name(m)] = m -; val top = (for m in modules(c) find : name(m) == main(c)) as InModule -; Circuit(info(c),list(InModule(info(top),name(top),ports(top),inline-inst(body(top)))),main(c)) - -;;================= Split Expressions ======================== -;; Intended to only work on low firrtl -public defstruct SplitExp <: Pass -public defmethod pass (b:SplitExp) -> (Circuit -> Circuit) : split-exp -public defmethod name (b:SplitExp) -> String : "Split Expressions" -public defmethod short-name (b:SplitExp) -> String : "split-expressions" - -defn split-exp (m:InModule) -> InModule : - val v = Vector<Stmt>() - val sh = get-sym-hash(m,keys(v-keywords)) - defn split-exp-s (s:Stmt) -> Stmt : - val base = match(s) : - (s:Connect) : lowered-name(loc(s)) - (s:DefNode) : name(s) - (s:DefRegister) : name(s) - (s) : `F - defn split (e:Expression) -> Expression : - val n = firrtl-gensym(`GEN,sh) - add(v,DefNode(info(s),n,e)) - WRef(n,type(e),kind(e),gender(e)) - defn split-exp-e (e:Expression,i:Int) -> Expression : - match(map(split-exp-e{_,i + 1},e)) : - (e:DoPrim) : - if i > 0 : split(e) - else : e - (e) : e - match(map(split-exp-e{_,0},s)) : - (s:Begin) : map(split-exp-s,s) - (s) : - add(v,s) - s - split-exp-s(body(m)) - InModule(info(m),name(m),ports(m),Begin(to-list(v))) - -defn split-exp (c:Circuit) -> Circuit : - val modules* = for m in modules(c) map : - match(m) : - (m:InModule) : split-exp(m) - (m:ExModule) : m - Circuit(info(c),modules*,main(c)) - - -;;================= Special Rename ======================== -;; Returns a new Circuit with only real IR nodes. -;public defstruct SpecialRename <: Pass : -; original-sym : Symbol -; new-sym : Symbol -;public defmethod pass (b:SpecialRename) -> (Circuit -> Circuit) : special-rename{original-sym(b),new-sym(b),_:Circuit} -;public defmethod name (b:SpecialRename) -> String : "Special Rename" -;public defmethod short-name (b:SpecialRename) -> String : "special-rename" -; -;public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) : -; defn rename (s:Symbol) -> Symbol : -; val y = Vector<String>() -; val os = to-string $ original-sym -; val ns = to-string $ new-sym -; defn rename (st:String) -> False : -; if st == os : -; add(y,ns) -; else if length(st) <= length(os) : -; add(y,st) -; else : -; if substring(st,0,length(os)) == os : -; add(y,ns) -; ;println(st) -; ;println(substring(st,length(os),length(st))) -; rename(substring(st,length(os),length(st))) -; else : -; add(y,substring(st,0,1)) -; rename(substring(st,1,length(st))) -; rename(to-string(s)) -; to-symbol $ string-join $ to-list(y) -; defn to-type (t:Type) -> Type : -; match(map(to-type,t)) : -; (t:BundleType) : BundleType $ -; for f in fields(t) map : Field(rename(name(f)),flip(f),type(f)) -; (t) : t -; defn to-exp (e:Expression) -> Expression : -; map{to-type,_} $ match(map(to-exp,e)) : -; (e:Ref) : Ref(rename(name(e)), type(e)) -; (e:Subfield) : Subfield(exp(e),rename(name(e)),type(e)) -; (e) : e -; defn to-stmt (s:Stmt) -> Stmt : -; map{to-type,_} $ match(map(to-exp,s)) : -; (s:DefWire) : DefWire(info(s),rename(name(s)),type(s)) -; (s:DefPoison) : DefPoison(info(s),rename(name(s)),type(s)) -; (s:DefRegister) : DefRegister(info(s),rename(name(s)),type(s),clock(s),reset(s)) -; (s:WDefInstance) : WDefInstance(info(s),rename(name(s)),module(s)) -; (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s),clock(s),size(s)) -; (s:DefNode) : DefNode(info(s),rename(name(s)),value(s)) -; (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),source(s),index(s),acc-dir(s)) -; (s) : map(to-stmt,s) -; -; defn to-port (p:Port) -> Port : Port(info(p),rename(name(p)),direction(p),type(p)) -; -; Circuit(info(c),modules*, main(c)) where : -; val modules* = -; for m in modules(c) map : -; match(m) : -; (m:InModule) : InModule(info(m),name(m), map(to-port,ports(m)), to-stmt(body(m))) -; (m:ExModule) : m -; -; -;;========== Pad Widths ================== -; -;public defstruct Pad <: Pass -;public defmethod pass (b:Pad) -> (Circuit -> Circuit) : pad-widths -;public defmethod name (b:Pad) -> String : "Pad Widths" -; -;;------------ Helper Functions -------------- -;defn int-width! (t:Type) -> Long : -; match(width!(t)) : -; (w:IntWidth) : width(w) -; (w) : error("Non-int width") -; -;defn set-width (desired:Long,t:Type) -> Type : -; match(t) : -; (t:UIntType) : UIntType(IntWidth(desired)) -; (t:SIntType) : SIntType(IntWidth(desired)) -; (t) : error("Non-ground type") -; -;defn lmax (l1:Long, l2:Long) -> Long : -; if l1 > l2 : l1 -; else : l2 -; -;;------------- Pad Widths ------------------- -; -;defn pad-widths-e (desired:Long,e:Expression) -> Expression : -; defn trim (desired:Long, e:Expression) : -; ;; println-all(["TRIM " desired " e " e]) -; DoPrim(BITS-SELECT-OP,list(e),list(to-int(to-string(desired)) - 1, 0),set-width(desired,type(e))) -; defn pad (desired:Long, e:Expression) : -; ;; println-all(["PAD " desired " e " e]) -; DoPrim(PAD-OP,list(e),list(to-int $ to-string(desired)),set-width(desired,type(e))) -; defn trim-pad (desired:Long, e:Expression) : -; val i = int-width!(type(e)) -; if i > desired : trim(desired, e) -; else if i == desired : e -; else : pad(desired, e) -; defn self-pad-widths-e (e:Expression) -> Expression : -; pad-widths-e(int-width!(type(e)), e) -; ;; println-all(["PAD-E " desired " " e]) -; match(e) : -; (e:DoPrim) : -; val new-desired = reduce(lmax, to-long(0), map(int-width!{type(_)}, args(e))) -; ;; println-all([" NEW DESIRED " new-desired]) -; val e* = -; if contains?([CONCAT-OP, DYN-SHIFT-RIGHT-OP, DYN-SHIFT-LEFT-OP], op(e)) : -; DoPrim(op(e), map(self-pad-widths-e, args(e)), consts(e), type(e)) -; else if contains?([MUX-OP], op(e)) : -; DoPrim(op(e), list(pad-widths-e(to-long(1), args(e)[0]), pad-widths-e(new-desired, args(e)[1]), pad-widths-e(new-desired, args(e)[2])), consts(e), type(e)) -; else : -; map(pad-widths-e{new-desired,_},e) -; trim-pad(desired, e*) -; (e:Ref|Subfield|Index) : -; trim-pad(desired, e) -; (e:UIntValue) : -; val i = int-width!(type(e)) -; if i > desired : trim(desired, e) -; else : UIntValue(value(e),IntWidth(desired)) -; (e:SIntValue) : -; val i = int-width!(type(e)) -; if i > desired : trim(desired, e) -; else : SIntValue(value(e),IntWidth(desired)) -; (e) : error(to-string $ e) -; -;defn pad-widths-s (s:Stmt) -> Stmt : -; ;; println-all(["PAD-S " s]) -; match(map(pad-widths-s,s)) : -; (s:Connect) : -; val i = int-width!(type(loc(s))) -; val loc* = pad-widths-e(i,loc(s)) -; val exp* = pad-widths-e(i,exp(s)) -; Connect(info(s),loc*,exp*) -; (s:PrintfStmt) : -; val args* = for x in args(s) map : -; val i = int-width!(type(x)) -; pad-widths-e(i,x) -; PrintfStmt(info(s),string(s),args*) -; (s:DefNode) : -; val i = int-width!(type(value(s))) -; val exp* = pad-widths-e(i,value(s)) -; DefNode(info(s),name(s),exp*) -; (s:Conditionally) : -; val i = int-width!(type(pred(s))) -; val pred* = pad-widths-e(i,pred(s)) -; Conditionally(info(s),pred*,conseq(s),alt(s)) -; (s) : s -; -;public defn pad-widths (c:Circuit) -> Circuit : -; Circuit{info(c),_,main(c)} $ -; for m in modules(c) map : -; match(m) : -; (m:ExModule) : m -; (m:InModule) : InModule(info(m),name(m),ports(m),pad-widths-s(body(m))) -; -; - -;============== Common Subexpression Elimination =========== -;NOT DONE - -;public defstruct CSE <: Pass -;public defmethod pass (b:CSE) -> (Circuit -> Circuit) : const-prop -;public defmethod name (b:CSE) -> String : "Common Subexpression Elimination" -;public defmethod short-name (b:ConstProp) -> String : "cse" -; -;defn cse-m (m:InModule) -> InModule : -; val cse-hash = HashTable<Expression,Int>(exp-hash) -; val placed? = HashTable<Expression,True|False>(exp-hash) -; -; defn cse-s (s:Stmt) -> Stmt : -; val stmts = Vector<Stmt>() -; defn cse-e (e:Expression) -> Expression -; match(s) : -; -; defn build-e (e:Expression) -> Expression : -; match(e) : -; (e:DoPrim) : -; if key?(cse-hash,e) : -; cse-hash[e] = cse-hash[e] + 1 -; else : -; cse-hash[e] = 1 -; placed?[e] = false -; (e) : e -; defn build-s (s:Stmt) -> Stmt : map{build-s,_} $ map(build-e,s) -; -; build-s(body(m)) -; InModule(info(m),name(m),ports(m),cse-s(body(m))) -; -;public defn cse (c:Circuit) -> Circuit : -; Circuit{info(c),_,main(c)} $ -; for m in modules(c) map : -; match(m) : -; (m:ExModule) : m -; (m:InModule) : cse-m(m) - - - -;;============= Constant Propagation ================ -; -public defstruct ConstProp <: Pass -public defmethod pass (b:ConstProp) -> (Circuit -> Circuit) : const-prop -public defmethod name (b:ConstProp) -> String : "Constant Propagation" -public defmethod short-name (b:ConstProp) -> String : "const-prop" - -defn const-prop-e (e:Expression) -> Expression : - match(map(const-prop-e,e)) : - (e:DoPrim) : - switch {op(e) == _} : - DYN-SHIFT-RIGHT-OP : - match(args(e)[1]) : - (x:UIntValue|SIntValue) : - DoPrim(SHIFT-RIGHT-OP,list(args(e)[0]),list(to-int(value(x))),UnknownType()) - (x) : e - DYN-SHIFT-LEFT-OP : - match(args(e)[1]) : - (x:UIntValue|SIntValue) : - DoPrim(SHIFT-LEFT-OP,list(args(e)[0]),list(to-int(value(x))),UnknownType()) - (x) : e - SHIFT-RIGHT-OP : - match(args(e)[0]) : - (x:UIntValue) : - val b = rsh(value(x),consts(e)[0]) - UIntValue(b,width(type(e) as UIntType)) - (x:SIntValue) : - val b = rsh(value(x),consts(e)[0]) - SIntValue(b,width(type(e) as SIntType)) - (x) : e - BITS-SELECT-OP : - match(args(e)[0]) : - (x:UIntValue) : - val b = bits(value(x),consts(e)[0] + 1,consts(e)[1]) - UIntValue(b,width(type(e) as UIntType)) - (x) : e - BIT-SELECT-OP : - match(args(e)[0]) : - (x:UIntValue) : - val i = bit(value(x),consts(e)[0]) - UIntValue(i,width(type(e) as UIntType)) - (x) : e - else : e - (e) : e - -defn const-prop-s (s:Stmt) -> Stmt : - map{const-prop-e,_} $ map(const-prop-s,s) - -public defn const-prop (c:Circuit) -> Circuit : - Circuit{info(c),_,main(c)} $ - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : InModule(info(m),name(m),ports(m),const-prop-s(body(m))) - -;============= Condense Mems ================ -; -;public defstruct CondenseMems <: Pass -;public defmethod pass (b:CondenseMems) -> (Circuit -> Circuit) : condense-mems -;public defmethod name (b:CondenseMems) -> String : "Condense Mems" -;public defmethod short-name (b:CondenseMems) -> String : "condense-mems" -; -;;------------- Utils --------------- -; -;defn concat (es:List<Expression>) -> Expression : -; if length(es) == 1 : head(es) -; else : CAT(head(es),cat(tail(es))) -;defn cast (t:Type,e:Expression) -> Expression : -; match(t) : -; (t:UIntType) : e -; (t:SIntType) : DoPrim(AS-SINT-OP,list(e),list(),SIntType(get-width(t))) -;defn get-width-index (e:Expression) -> Long : -; match(e) : -; (e:WRef) : 0 -; (e:WSubField) : -; var w = get-width-index(exp(e)) -; var found? = false -; for f in fields(type(exp(e)) as BundleType) do : -; if name(f) == name(e) : -; found? = true -; if found? == false : -; w = w + get-width(type(f)) -; w -; (e:WSubIndex) : -; get-width-index(exp(e)) + get-width(type(e)) * value(e) -;defn root-ref (e:Expression) -> Expression : -; match(e) : -; (e:WRef) : e -; (e:WSubField|WSubIndex) : root-ref(e) -;defn flatten (e:Expression) -> Expression : -; match(e) : -; (e:WRef) : e -; (e:WSubField|WSubIndex) : -; val base = get-width-index(e) -; val off = get-width(type(e)) -; DoPrim(BITS-SELECT-OP,list(root-ref(e)),list(base,off),UIntType(IntWidth(off))) -; -;;------------- Pass ------------------ - -;defn condense-mems (m:InModule) -> InModule : -; val mem-assigns = HashTable<Expression,Expression>(exp-hash) -; defn collect-mems (s:Stmt) -> Stmt : -; match(s) : -; (s:Connect) : -; defn condense-mems-e (e:Expression) -> Expression : -; val e* = match(e) : -; (e:WRef|WSubField|WSubIndex) : -; if (kind(e) typeof MemKind) : cast(type(e),flatten(e)) -; else : e -; (e:UIntValue|SIntValue) : e -; (e:DoPrim) : map(condense-mems-e,e) -; defn condense-mems (s:Stmt) -> Stmt : -; match(s) : -; (s:DefMemory) : -; val stmts = Vector<Stmt>() -; val s* = map(flatten,s) -; add(stmts,s*) -; val mem = WRef(name(s),type(s),MemKind(),UNKNOWN-GENDER) -; for f in fields(type(s) as BundleType) do : -; val data-name = -; if contains?(writers(s),name(f)) : `data -; else if contains(readwriters(s),name(f)) : `wdata -; else : false -; match(data-name) : -; (f:False) : false -; (n:Symbol) : -; val port = WSubField(mem,name(f),type(f),UNKNOWN-GENDER) -; val es = create-exps(WSubField(port,n,field-type(type(port),n),UNKNOWN-GENDER)) -; val e* = concat $ for e in es map : -; map(condense-mems-e,mem-assigns[e]) -; add(stmts,Connect(info(s),WSubField(port,n,data-type(s*),UNKNOWN-GENDER),e*)) -; Begin(to-list(stmts)) -; (s:Connect) : -; if kind(loc(s)) typeof MemKind : EmptyStmt() -; else : map(condense-mems-e, s) -; (s) : map{condense-mems,_} $ map(condense-mems-e, s) -; InModule(info(m),name(m),ports(m),condense-mems(body(m))) -; -;defn condense-mems (c:Circuit) -> Circuit : -; Circuit{info(c),_,main(c)} $ -; for m in modules(c) map : -; match(m) : -; (m:ExModule) : m -; (m:InModule) : condense-mems(m) - -;============= Lower Types ================ -; -public defstruct LowerTypes <: Pass -public defmethod pass (b:LowerTypes) -> (Circuit -> Circuit) : lower-types -public defmethod name (b:LowerTypes) -> String : "Lower Types" -public defmethod short-name (b:LowerTypes) -> String : "lower-types" - -;------------- Utils --------------- -defn is-ground? (t:Type) -> True|False : - match(t) : - (t:UIntType|SIntType) : true - (t) : false -defn data? (ex:Expression) -> True|False : - match(kind(ex)) : - (k:MemKind) : match(ex) : - (ex:WRef|WSubIndex) : false - (ex:WSubField) : - var yes? = switch { _ == name(ex) } : - `wdata : true - `rdata : true - `data : true - `mask : true - else : false - yes? and match(exp(ex)) : - (e:WSubField) : - contains?(ports(kind(e) as MemKind),name(e)) and (exp(e) typeof WRef) - (e) : false - (ex) : false - (k) : false - -defn expand-name (e:Expression) -> List<Symbol> : - val names = Vector<Symbol>() - defn expand-name-e (e:Expression) -> Expression : - match(map(expand-name-e,e)) : - (e:WRef) : add(names,name(e)) - (e:WSubField) : add(names,name(e)) - (e:WSubIndex) : add(names,to-symbol(value(e))) - e - expand-name-e(e) - to-list(names) - - -defn lower-other-mem (e:Expression, dt:Type) -> List<Expression> : - val names = expand-name(e) - if length(names) < 3 : error("Shouldn't be here") - for x in fast-create-exps(names[0],dt) map : - var base = lowered-name(x) - for (x in names,i in 0 to false) do : - if i >= 3 : base = symbol-join([base `_ x]) - val m = WRef(base, UnknownType(), kind(e), UNKNOWN-GENDER) - val p = WSubField(m,to-symbol(names[1]),UnknownType(),UNKNOWN-GENDER) - WSubField(p,to-symbol(names[2]),UnknownType(),UNKNOWN-GENDER) - -defn lower-data-mem (e:Expression) -> Expression : - val names = expand-name(e) - if length(names) < 3 : error("Shouldn't be here") - else : - var base = names[0] - for (x in names,i in 0 to false) do : - if i >= 3 : base = symbol-join([base `_ x]) - val m = WRef(base, UnknownType(), kind(e), UNKNOWN-GENDER) - val p = WSubField(m,to-symbol(names[1]),UnknownType(),UNKNOWN-GENDER) - WSubField(p,to-symbol(names[2]),UnknownType(),UNKNOWN-GENDER) - -defn merge (a:Symbol,b:Symbol,x:Symbol) -> Symbol : symbol-join([a x b]) -defn lowered-name (e:Expression) -> Symbol : - match(e) : - (e:WRef) : name(e) - (e:WSubField) : merge(lowered-name(exp(e)),name(e),`_) - (e:WSubIndex) : merge(lowered-name(exp(e)),to-symbol(value(e)),`_) -defn root-ref (e:Expression) -> WRef : - match(e) : - (e:WRef) : e - (e:WSubField|WSubIndex|WSubAccess) : root-ref(exp(e)) - (e:WIndexer) : root-ref(exps(e)[0]) - -;------------- Pass ------------------ - -defn lower-types (m:Module) -> Module : - val mdt = HashTable<Symbol,Type>(symbol-hash) - defn lower-types (s:Stmt) -> Stmt : - defn lower-mem (e:Expression) -> List<Expression> : - val names = expand-name(e) - if contains?([`data `mask `rdata `wdata `wmask],names[2]) : - list(lower-data-mem(e)) - else : - lower-other-mem(e,mdt[name(root-ref(e))]) - defn lower-types-e (e:Expression) -> Expression : - match(e) : - (e:WRef|UIntValue|SIntValue) : e - (e:WSubField) : - match(kind(e)) : - (k:InstanceKind) : - val names = expand-name(e) - var n = names[1] - for (x in names,i in 0 to false) do : - if i > 1 : n = symbol-join([n `_ x]) - WSubField(root-ref(e),n,type(e),gender(e)) - (k:MemKind) : - if not gender(e) == FEMALE : - lower-mem(e)[0] - else : e - (k) : WRef(lowered-name(e),type(e),kind(e),gender(e)) - (e:WSubIndex) : WRef(lowered-name(e),type(e),kind(e),gender(e)) - (e:DoPrim) : map(lower-types-e,e) - match(map(lower-types-e,s)) : - (s:DefWire|DefPoison) : - if is-ground?(type(s)) : s - else : - val es = fast-create-exps(name(s),type(s)) - Begin $ for (e in es, i in 0 to false) map : - defn replace-type (t:Type) -> Type : type(e) - defn replace-name (n:Symbol) -> Symbol : lowered-name(e) - map{replace-name,_} $ map(replace-type,s) - (s:DefRegister) : - if is-ground?(type(s)) : s - else : - val es = fast-create-exps(name(s),type(s)) - Begin $ for (e in es, i in 0 to false) map : - val init = lower-types-e(fast-create-exps(init(s))[i]) - DefRegister(info(s),lowered-name(e),type(e),clock(s),reset(s),init) - (s:WDefInstance) : - val fields* = for f in fields(type(s) as BundleType) map-append : - val es = fast-create-exps(WRef(name(f),type(f),ExpKind(),flip(f) * MALE)) - for e in es map : - switch { _ == gender(e) } : - MALE : Field(lowered-name(e),DEFAULT,type(f)) - FEMALE : Field(lowered-name(e),REVERSE,type(f)) - WDefInstance(info(s),name(s),module(s),BundleType(fields*)) - (s:DefMemory) : - mdt[name(s)] = data-type(s) - if is-ground?(data-type(s)) : s - else : - val es = fast-create-exps(name(s),data-type(s)) - Begin $ for e in es map : - DefMemory(info(s),lowered-name(e),type(e),depth(s),write-latency(s),read-latency(s),readers(s),writers(s),readwriters(s)) - (s:Connect) : - if kind(loc(s)) typeof MemKind : - val es = lower-mem(loc(s)) - Begin $ for e in es map : - Connect(info(s),e,exp(s)) - else : s - (s) : map(lower-types,s) - - val ports* = - for p in ports(m) map-append : - val es = fast-create-exps(WRef(name(p),type(p),PortKind(),to-gender(direction(p)))) - for e in es map : - Port(info(p),lowered-name(e),to-dir(gender(e)),type(e)) - match(m) : - (m:ExModule) : ExModule(info(m),name(m),ports*) - (m:InModule) : InModule(info(m),name(m),ports*,lower-types(body(m))) - -defn lower-types (c:Circuit) -> Circuit : - Circuit{info(c),_,main(c)} $ - for m in modules(c) map : lower-types(m) - -;============ VERILOG ============== - -public defstruct Verilog <: Pass : - with-output: (() -> False) -> False -public defmethod pass (b:Verilog) -> (Circuit -> Circuit) : emit-verilog{with-output(b),_} -public defmethod name (b:Verilog) -> String : "To Verilog" -public defmethod short-name (b:Verilog) -> String : "To Verilog" - -;============ Utilz ============= -defstruct VIndent -defstruct VRandom -val tab = VIndent() -val ran = VRandom() -defn wref (n:Symbol,t:Type) : WRef(n,t,ExpKind(),UNKNOWN-GENDER) -defn escape (s:String) -> String : - val s* = Vector<String>() - add(s*,"\"");" - var percent = false - for c in s do : - if c == '\n' : - add(s*,"\\n") - else : - if c == 'x' and percent : - add(s*,"h") - else : add(s*,to-string(c)) - percent = c == '%' - add(s*,"\"");" - string-join(s*) -defn remove-root (ex:Expression) -> Expression : - match(exp(ex as WSubField)) : - (e:WSubField) : remove-root(e) - (e:WRef) : WRef(name(ex as WSubField),type(ex),InstanceKind(),UNKNOWN-GENDER) -defn !empty? (s:Vector) -> True|False : - if length(s) == 0 : false - else : true -defn long! (t:Type) -> Long : - match(t) : - (t:UIntType|SIntType) : width(width(t) as IntWidth) - (t:BundleType) : - var w = to-long(0) - for f in fields(t) do : - w = w + long!(type(f)) - w - (t:VectorType) : to-long(size(t)) * long!(type(t)) - -defn rand-string (t:Type) -> Streamable : - val w* = ((long!(t) + to-long(31)) / to-long(32)) - ["{" w* "{" ran "}};"] -defn emit (x:?) : emit(x,0) -defn emit (x:?, top:Int) : - match(x) : - (e:Expression) : - turn-off-debug(false) - match(e) : - (e:DoPrim) : emit(op-stream(e), top + 1) - (e:WRef) : print(e) - (e:WSubField) : print(lowered-name(e)) - (e:WSubAccess) : print-all([lowered-name(exp(e)) "[" lowered-name(index(e)) "]"]) - (e:WSubIndex) : print(e) - (e:UIntValue|SIntValue) : v-print(e) - turn-on-debug(false) - (t:Type) : - match(t) : - (t:UIntType|SIntType) : - val w = long!(t) - to-long(1) - if w > to-long(0) : print-all(["[" w ":0]"]) - else : print("");" - (t:ClockType) : print("");" - (t:VectorType) : - emit(type(t), top + 1) - print-all(["[" size(t) - 1 ":0]"]) - (t) : println(t) - - (p:Direction) : - switch {_ == p} : - INPUT : print("input") - OUTPUT : print("output") - (s:Symbol) : print(s) - (i:Int) : print(i) - (i:Long) : print(i) - (s:String) : print(s) - (t:VIndent) : print(" ") - (r:VRandom) : print("$random") - (s:Streamable) : - for x in s do : - emit(x, top + 1) - if top == 0 : print("\n") - -;------------- PASS ----------------- -defn v-print (e:UIntValue|SIntValue) : - val str = to-string(value(e)) - val out = substring(str,1,length(str) - 1) - print $ string-join $ match(e) : - (e:UIntValue) : [long!(type(e)) "'" out] - (e:SIntValue) : [long!(type(e)) "'s" out] -defn op-stream (doprim:DoPrim) -> Streamable : - defn cast-if (e:Expression) -> ? : - val signed? = for x in args(doprim) any? : type(x) typeof SIntType - if not signed? : e - else : match(type(e)) : - (t:SIntType) : ["$signed(" e ")"] - (t:UIntType) : ["$signed({1'b0," e "})"] - defn cast (e:Expression) -> ? : - match(type(doprim)) : - (t:UIntType) : e - (t:SIntType) : ["$signed(" e ")"] - defn a0 () -> Expression : args(doprim)[0] - defn a1 () -> Expression : args(doprim)[1] - defn a2 () -> Expression : args(doprim)[2] - defn c0 () -> Int : consts(doprim)[0] - defn c1 () -> Int : consts(doprim)[1] - - switch {_ == op(doprim)} : - ADD-OP : [cast-if(a0()) " + " cast-if(a1())] - SUB-OP : [cast-if(a0()) " - " cast-if(a1())] - MUL-OP : [cast-if(a0()) " * " cast-if(a1()) ] - DIV-OP : [cast-if(a0()) " / " cast-if(a1()) ] - MOD-OP : [cast-if(a0()) " % " cast-if(a1()) ] - QUO-OP : [cast-if(a0()) " / " cast-if(a1()) ] - REM-OP : [cast-if(a0()) " % " cast-if(a1()) ] - ADD-WRAP-OP : [cast-if(a0()), " + " cast-if(a1())] - SUB-WRAP-OP : [cast-if(a0()), " - " cast-if(a1())] - LESS-OP : [cast-if(a0()) " < " cast-if(a1())] - LESS-EQ-OP : [cast-if(a0()) " <= " cast-if(a1())] - GREATER-OP : [cast-if(a0()) " > " cast-if(a1())] - GREATER-EQ-OP : [cast-if(a0()) " >= " cast-if(a1())] - NEQUIV-OP : [cast-if(a0()) " != " cast-if(a1())] - EQUIV-OP : [cast-if(a0()) " == " cast-if(a1())] - NEQUAL-OP : [cast-if(a0()) " != " cast-if(a1())] - EQUAL-OP : [cast-if(a0()) " == " cast-if(a1())] - MUX-OP : [a0() " ? " cast(a1()) " : " cast(a2())] - PAD-OP : - val w = long!(type(a0())) - val diff = (to-long(c0()) - w) - if w == to-long(0) : [ a0() ] - else : match(type(doprim)) : - (t:SIntType) : ["{{" diff "{" a0() "[" w - to-long(1) "]}}, " a0() " }"] - (t) : ["{{" diff "'d0 }, " a0() " }"] - AS-UINT-OP : ["$unsigned(" a0() ")"] - AS-SINT-OP : ["$signed(" a0() ")"] - DYN-SHIFT-LEFT-OP : [cast(a0()) " << " a1()] - DYN-SHIFT-RIGHT-OP : - match(type(doprim)) : - (t:SIntType) : [cast(a0()) " >>> " a1()] - (t) : [cast(a0()) " >> " a1()] - SHIFT-LEFT-OP : [cast(a0()) " << " c0()] - SHIFT-RIGHT-OP : [cast(a0()) "[" long!(type(a0())) - to-long(1) ":" c0() "]"] - NEG-OP : ["-{" cast(a0()) "}"] - CONVERT-OP : - match(type(a0())) : - (t:UIntType) : ["{1'b0," cast(a0()) "}"] - (t:SIntType) : [cast(a0())] - BIT-NOT-OP : ["~ " cast(a0())] - BIT-AND-OP : [cast(a0()) " & " cast(a1())] - BIT-OR-OP : [cast(a0()) " | " cast(a1())] - BIT-XOR-OP : [cast(a0()) " ^ " cast(a1())] - CONCAT-OP : ["{" cast(a0()) "," cast(a1()) "}"] - BIT-SELECT-OP : [cast(a0()) "[" c0() "]"] - BITS-SELECT-OP : [cast(a0()) "[" c0() ":" c1() "]"] - BIT-AND-REDUCE-OP : - val v = Vector<Streamable>() - for b in 0 to to-int(long!(type(doprim))) do : - add(v,[cast(a0()) "[" b "]"]) - join(v," & ") - BIT-OR-REDUCE-OP : - val v = Vector<Streamable>() - for b in 0 to to-int(long!(type(doprim))) do : - add(v,[cast(a0() ) "[" b "]"]) - join(v," | ") - BIT-XOR-REDUCE-OP : - val v = Vector<Streamable>() - for b in 0 to to-int(long!(type(doprim))) do : - add(v,[cast(a0() ) "[" b "]"]) - join(v," ^ ") - -defn emit-verilog (m:InModule) -> Module : - val netlist = HashTable<Expression,Expression>(exp-hash) - val simlist = Vector<Stmt>() - val namehash = get-sym-hash(m,keys(v-keywords)) - defn build-netlist (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : netlist[loc(s)] = exp(s) - (s:Conditionally) : add(simlist,s) - (s:DefNode) : - val e = WRef(name(s),get-type(s),NodeKind(),MALE) - netlist[e] = value(s) - (s) : map(build-netlist,s) - s - - val portdefs = Vector<Streamable>() - val declares = Vector<Streamable>() - val assigns = Vector<Streamable>() - val at-clock = HashTable<Expression,Vector<Streamable>>(exp-hash) - val initials = Vector<Streamable>() - val simulates = Vector<Streamable>() - defn declare (b:Symbol,n:Symbol,t:Type) : - match(t) : - (t:VectorType) : add(declares,[b " " type(t) " " n " [0:" size(t) - 1 "];"]) - (t) : add(declares,[b " " t " " n ";"]) - defn assign (e:Expression,value:Expression) : - add(assigns,["assign " e " = " value]) - defn update-and-reset (e:Expression,clk:Expression,reset?:Expression,init:Expression) : - if not key?(at-clock,clk) : - at-clock[clk] = Vector<Streamable>() - add(at-clock[clk],["if(" reset? ") begin"]) - add(at-clock[clk],[tab e " <= " init]) - add(at-clock[clk],["end else"]) - add(at-clock[clk],[tab e " <= " netlist[e]]) - add(at-clock[clk],["end"]) - defn update (e:Expression,value:Expression,clk:Expression,en:Expression) : - if not key?(at-clock,clk) : - at-clock[clk] = Vector<Streamable>() - if en == one : - add(at-clock[clk],[e " <= " value]) - else : - add(at-clock[clk],["if(" en ") begin"]) - add(at-clock[clk],[tab e " <= " value]) - add(at-clock[clk],["end"]) - defn initialize (e:Expression) : - add(initials,[e " = " rand-string(type(e))]) - defn initialize-mem (n:Symbol,i:Int,t:Type) : - add(initials,["for (initvar = 0; initvar < " i "; initvar = initvar+1)"]) - val index = WRef(`initvar,UnknownType(),ExpKind(),UNKNOWN-GENDER) - add(initials,[tab WSubAccess(wref(n,t),index,UnknownType(),FEMALE), " = " rand-string(t)]) - defn instantiate (n:Symbol,m:Symbol,es:List<Expression>) : - add(declares,[m " " n " ("]) - for (e in es,i in 1 to false) do : - val s = [tab "." remove-root(e) "(" lowered-name(e) ")"] - if i == length(es) : add(declares,[s ","]) - else : add(declares,s) - add(declares,[");"]) - for e in es do : - declare(`wire,lowered-name(e),type(e)) - val e* = WRef(lowered-name(e),type(e),kind(e),gender(e)) - if (gender(e) == FEMALE) : assign(e*,netlist[e]) - defn simulate (clk:Expression,en:Expression,s:Streamable) : - if not key?(at-clock,clk) : - at-clock[clk] = Vector<Streamable>() - add(at-clock[clk],["`ifndef SYNTHESIS"]) - add(at-clock[clk],[tab "if(" en ") begin"]) - add(at-clock[clk],[tab tab s]) - add(at-clock[clk],[tab "end"]) - add(at-clock[clk],["`endif"]) - defn stop (ret:Int) -> Streamable : - ["$fdisplay(32/'h80000002," ret ");$finish;"] - defn printf (str:String,args:List<Expression>) -> Streamable : - val str* = join(List(escape(str),args),",") - ["$fdisplay(32/'h80000002," str* ");"] - defn delay (e:Expression, n:Int, clk:Expression) -> Expression : - var e* = e - for i in 0 to n do : - val name = firrtl-gensym(`GEN,namehash) - declare(`reg,name,type(e)) - val e** = WRef(name,type(e),ExpKind(),UNKNOWN-GENDER) - update(e**,e*,clk,one) - e* = e** - e* - defn build-ports () : - for (p in ports(m),i in 0 to false) do : - var end = ",\n" - if length(ports(m)) - 1 == i : - end = "\n);\n" - switch {_ == direction(p)} : - INPUT : - add(portdefs,[direction(p) " " type(p) " " name(p) ]) - OUTPUT : - add(portdefs,[direction(p) " " type(p) " " name(p) ]) - val e* = WRef(name(p),type(p),PortKind(),FEMALE) - assign(e*,netlist[e*]) - if length(ports(m)) == 0 : print(");\n") - defn build-streams (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : s - (s:DefWire) : - declare(`wire,name(s),type(s)) - val e = wref(name(s),type(s)) - assign(e,netlist[e]) - (s:DefRegister) : - declare(`reg,name(s),type(s)) - val e = wref(name(s),type(s)) - update-and-reset(e,clock(s),reset(s),init(s)) - initialize(e) - (s:DefPoison) : - declare(`reg,name(s),type(s)) - val e = wref(name(s),type(s)) - initialize(e) - (s:DefNode) : - declare(`wire,name(s),type(value(s))) - assign(WRef(name(s),type(value(s)),NodeKind(),MALE),value(s)) - (s:Stop) : simulate(clk(s),en(s),stop(ret(s))) - (s:Print) : simulate(clk(s),en(s),printf(string(s),args(s))) - (s:WDefInstance) : - val es = fast-create-exps(WRef(name(s),type(s),InstanceKind(),MALE)) - instantiate(name(s),module(s),es) - (s:DefMemory) : - val mem = WRef(name(s),get-type(s),MemKind(append-all([readers(s) writers(s) readwriters(s)])),UNKNOWN-GENDER) - defn mem-exp (p:Symbol,f:Symbol) : - val t1 = field-type(type(mem),p) - val t2 = field-type(t1,f) - WSubField{_,f,t2,UNKNOWN-GENDER} $ - WSubField{_,p,t1,UNKNOWN-GENDER} $ - mem - - declare(`reg,name(s),VectorType(data-type(s),depth(s))) - initialize-mem(name(s),depth(s),data-type(s)) - for r in readers(s) do : - val data = mem-exp(r,`data) - val addr = mem-exp(r,`addr) - val en = mem-exp(r,`en) - val clk = mem-exp(r,`clk) - - declare(`wire,lowered-name(data),type(data)) - declare(`wire,lowered-name(addr),type(addr)) - declare(`wire,lowered-name(en),type(en)) - declare(`wire,lowered-name(clk),type(clk)) - - ; Read port - assign(addr,netlist[addr]) ;Connects value to m.r.addr - assign(en,netlist[en]) ;Connects value to m.r.en - assign(clk,netlist[clk]) ;Connects value to m.r.clk - val addr* = delay(addr,read-latency(s),clk) - val en* = delay(en,read-latency(s),clk) - val mem-port = WSubAccess(mem,addr*,UnknownType(),UNKNOWN-GENDER) - update(data,mem-port,clk,en*) ; m.r.data <= m[addr*] - - for w in writers(s) do : - val data = mem-exp(w,`data) - val addr = mem-exp(w,`addr) - val mask = mem-exp(w,`mask) - val en = mem-exp(w,`en) - val clk = mem-exp(w,`clk) - - declare(`wire,lowered-name(data),type(data)) - declare(`wire,lowered-name(addr),type(addr)) - declare(`wire,lowered-name(mask),type(mask)) - declare(`wire,lowered-name(en),type(en)) - declare(`wire,lowered-name(clk),type(clk)) - - ; Write port - assign(data,netlist[data]) - assign(addr,netlist[addr]) - assign(mask,netlist[mask]) - assign(en,netlist[en]) - assign(clk,netlist[clk]) - - val data* = delay(data,write-latency(s) - 1,clk) - val addr* = delay(addr,write-latency(s) - 1,clk) - val mask* = delay(mask,write-latency(s) - 1,clk) - val en* = delay(en,write-latency(s) - 1,clk) - val mem-port = WSubAccess(mem,addr*,UnknownType(),UNKNOWN-GENDER) - update(mem-port,data*,clk,AND(en*,mask*)) - - for rw in readwriters(s) do : - val rdata = mem-exp(rw,`rdata) - val raddr = mem-exp(rw,`raddr) - val ren = mem-exp(rw,`ren) - val wdata = mem-exp(rw,`wdata) - val waddr = mem-exp(rw,`waddr) - val wmask = mem-exp(rw,`wmask) - val wen = mem-exp(rw,`wen) - val clk = mem-exp(rw,`clk) - - declare(`wire,lowered-name(rdata),type(rdata)) - declare(`wire,lowered-name(raddr),type(raddr)) - declare(`wire,lowered-name(ren),type(ren)) - declare(`wire,lowered-name(wdata),type(wdata)) - declare(`wire,lowered-name(waddr),type(waddr)) - declare(`wire,lowered-name(wmask),type(wmask)) - declare(`wire,lowered-name(wen),type(wen)) - declare(`wire,lowered-name(clk),type(clk)) - - ; Both - assign(clk,netlist[clk]) - - ; Read - assign(raddr,netlist[raddr]) - assign(ren,netlist[ren]) - val raddr* = delay(raddr,read-latency(s),clk) - val ren* = delay(ren,read-latency(s),clk) - val rmem-port = WSubAccess(mem,raddr*,UnknownType(),UNKNOWN-GENDER) - update(rdata,rmem-port,clk,ren*) - - ; Write - assign(wdata,netlist[wdata]) - assign(waddr,netlist[waddr]) - assign(wmask,netlist[wmask]) - assign(wen,netlist[wen]) - - val wdata* = delay(wdata,write-latency(s) - 1,clk) - val waddr* = delay(waddr,write-latency(s) - 1,clk) - val wmask* = delay(wmask,write-latency(s) - 1,clk) - val wen* = delay(wen,write-latency(s) - 1,clk) - val wmem-port = WSubAccess(mem,waddr*,UnknownType(),UNKNOWN-GENDER) - update(wmem-port,wdata*,clk,AND(wen*,wmask*)) - (s:Begin) : map(build-streams,s) - s - - defn emit-streams () : - emit(["module " name(m) "("]) - if !empty?(portdefs) : - for (x in portdefs, i in 0 to false) do : - if i != length(portdefs) : emit([tab x ","]) - else : emit([tab x]) - emit([");"]) - - if !empty?(declares) : - for x in declares do : emit([tab x]) - - if !empty?(assigns) : - for x in assigns do : emit([tab x]) - - if !empty?(initials) : - emit(["`ifndef SYNTHESIS"]) - emit([" integer initvar;"]) - emit([" initial begin"]) - emit([" #0.002;"]) - for x in initials do : - emit([tab x]) - emit([" end"]) - emit(["`endif"]) - - for clk-stream in at-clock do : - if !empty?(value(clk-stream)) : - emit([tab "always @(posedge " key(clk-stream) ") begin"]) - for x in value(clk-stream) do : - emit([tab tab x]) - emit([tab "end"]) - - emit(["endmodule"]) - - build-netlist(body(m)) - build-ports() - build-streams(body(m)) - emit-streams() - m - -defn emit-verilog (with-output:(() -> False) -> False, c:Circuit) : - with-output $ fn () : - for m in modules(c) do : - match(m) : - (m:InModule) : emit-verilog(m) - (m:ExModule) : false - c - - diff --git a/src/main/stanza/passes.stanza3 b/src/main/stanza/passes.stanza3 deleted file mode 100644 index 0dc664e7..00000000 --- a/src/main/stanza/passes.stanza3 +++ /dev/null @@ -1,2687 +0,0 @@ -defpackage firrtl/passes : - import core - import verse - import firrtl/ir2 - import firrtl/ir-utils - import firrtl/primops - import firrtl-main - import firrtl/errors - import bigint2 - -;============== Pass List ================ -public val standard-passes = to-list $ [ - CheckHighForm() - ;TempElimination() - ToWorkingIR() - Resolve() - ResolveKinds() - ;CheckKinds() - InferTypes() - ;CheckTypes() - ResolveGenders() - ;CheckGenders() - ;ExpandAccessors() - ;LowerToGround() - ;ExpandIndexedConnects() - ;InlineIndexed() - ExpandWhens() - InferWidths() - ;Inline() - SplitExp() - ;CheckLowForm() - ;ToRealIR() - ;Pad() - ] -;=============== WORKING IR ================================ -public definterface Kind -public defstruct WireKind <: Kind -public defstruct PoisonKind <: Kind -public defstruct RegKind <: Kind -public defstruct InstanceKind <: Kind -public defstruct PortKind <: Kind -public defstruct NodeKind <: Kind -public defstruct MemKind <: Kind : - ports : List<Symbol> -public defstruct ExpKind <: Kind - -public definterface Gender -public val MALE = new Gender -public val FEMALE = new Gender -public val UNKNOWN-GENDER = new Gender -public val BI-GENDER = new Gender - -public defstruct WRef <: Expression : - name: Symbol - type: Type with: (as-method => true) - kind: Kind with: (as-method => true) - gender: Gender with: (as-method => true) -public defstruct WSubField <: Expression : - exp: Expression - name: Symbol - type: Type with: (as-method => true) - gender: Gender with: (as-method => true) -public defstruct WSubIndex <: Expression : - exp: Expression - value: Int - type: Type with: (as-method => true) - gender: Gender with: (as-method => true) -public defstruct WSubAccess <: Expression : - exp: Expression - index: Expression - type: Type with: (as-method => true) - gender: Gender with: (as-method => true) -defstruct WIndexer <: Expression : - exps: List<Expression> - index: Expression - type: Type with: (as-method => true) - gender : Gender with: (as-method => true) -public defstruct WVoid <: Expression -public defstruct WDefInstance <: Stmt : - info: FileInfo with: (as-method => true) - name: Symbol - module: Symbol - type: Type - -defmulti gender (e:Expression) -> Gender -defmethod gender (e:Expression) : - MALE - -defn get-gender (s:Stmt|Port) -> Gender : - match(s) : - (s:DefWire|DefRegister) : BI-GENDER - (s:WDefInstance|DefNode|DefInstance|DefPoison) : MALE - (s:Begin|Connect|BulkConnect|Stop|Print|Empty) : UNKNOWN-GENDER - (s:DefMemory) : FEMALE - (p:Port) : - switch { _ == direction(p) } : - INPUT : MALE - OUTPUT : FEMALE - -public defmulti kind (e:Expression) -> Kind -defmethod kind (e:Expression) : - match(e) : - (e:WRef) : kind(e) - (e:WSubField) : kind(exp(e)) - (e:WSubIndex) : kind(exp(e)) - (e:WIndexer) : - val k = kind(exps(e)[0]) - for x in exps(e) do : - if k != kind(x) : error("All kinds of exps of WIndexer must be the same") - k - (e) : ExpKind() - -defmethod info (stmt:Begin) -> FileInfo : FileInfo() -defmethod info (stmt:Empty) -> FileInfo : FileInfo() - -defmethod type (exp:UIntValue) -> Type : UIntType(width(exp)) -defmethod type (exp:SIntValue) -> Type : SIntType(width(exp)) - -defn get-type (s:Stmt) -> Type : - match(s) : - (s:DefWire|DefPoison|DefRegister|WDefInstance) : type(s) - (s:DefNode) : type(value(s)) - (s:DefMemory) : - val depth = depth(s) - ; Fields - val addr = Field(`addr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - val en = Field(`en,DEFAULT,BoolType()) - val clk = Field(`clk,DEFAULT,ClockType()) - val def-data = Field(`data,DEFAULT,data-type(s)) - val rev-data = Field(`data,REVERSE,data-type(s)) - val rdata = Field(`rdata,REVERSE,data-type(s)) - val wdata = Field(`wdata,DEFAULT,data-type(s)) - val mask = create-mask(`mask,data-type(s)) - val wmask = create-mask(`wmask,data-type(s)) - val ren = Field(`ren,DEFAULT,UIntType(IntWidth(1))) - val wen = Field(`wen,DEFAULT,UIntType(IntWidth(1))) - val raddr = Field(`raddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - val waddr = Field(`waddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - - val read-type = BundleType(to-list([rev-data,addr,en,clk])) - val write-type = BundleType(to-list([def-data,mask,addr,en,clk])) - val readwrite-type = BundleType(to-list([wdata,wmask,waddr,wen,rdata,raddr,ren,clk])) - - val mem-fields = Vector<Field>() - for x in readers(s) do : - add(mem-fields,Field(x,DEFAULT,read-type)) - for x in writers(s) do : - add(mem-fields,Field(x,DEFAULT,write-type)) - for x in readwriters(s) do : - add(mem-fields,Field(x,DEFAULT,readwrite-type)) - BundleType(to-list(mem-fields)) - (s:DefInstance) : UnknownType() - (s:Begin|Connect|BulkConnect|Stop|Print|Empty) : UnknownType() - -defmethod equal? (e1:Expression,e2:Expression) -> True|False : - match(e1,e2) : - (e1:UIntValue,e2:UIntValue) : - if value(e1) == value(e2) : width(e1) == width(e2) - else : false - (e1:SIntValue,e2:SIntValue) : - if value(e1) == value(e2) : width(e1) == width(e2) - else : false - (e1:WRef,e2:WRef) : name(e1) == name(e2) - (e1:WSubField,e2:WSubField) : - (name(e1) == name(e2)) and (exp(e1) == exp(e2)) - (e1:WSubIndex,e2:WSubIndex) : - (value(e1) == value(e2)) and (exp(e1) == exp(e2)) - (e1:WSubAccess,e2:WSubAccess) : - (index(e1) == index(e2)) and (exp(e1) == exp(e2)) - (e1:WVoid,e2:WVoid) : true - (e1:WIndexer,e2:WIndexer) : - var bool = (length(exps(e1)) == length(exps(e2))) - for (e1* in exps(e1),e2* in exps(e2)) do : - bool = bool and (e1* == e2*) - bool and (index(e1) == index(e2)) - (e1:DoPrim,e2:DoPrim) : - var are-equal? = op(e1) == op(e2) - for (x in args(e1),y in args(e2)) do : - if not x == y : - are-equal? = false - for (x in consts(e1),y in consts(e2)) do : - if not x == y : - are-equal? = false - are-equal? - (e1,e2) : false - -; ================= PRINTERS =================== -defmethod print (o:OutputStream, g:Gender) : - print{o, _} $ - switch {g == _} : - MALE : "m" - FEMALE: "f" - BI-GENDER : "b" - UNKNOWN-GENDER: "u" - -;============== DEBUG STUFF ============================= -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 -public var PRINT-DEBUG : True|False = false -public var PRINT-INFO : True|False = false - -;========= TO TURN OFF =========== - -var old-PRINT-TYPES : True|False = false -var old-PRINT-KINDS : True|False = false -var old-PRINT-WIDTHS : True|False = false -var old-PRINT-TWIDTHS : True|False = false -var old-PRINT-GENDERS : True|False = false -var old-PRINT-CIRCUITS : True|False = false -var old-PRINT-DEBUG : True|False = false -var old-PRINT-INFO : True|False = false -defmethod turn-off-debug (x:False) : - old-PRINT-TYPES = PRINT-TYPES - old-PRINT-KINDS = PRINT-KINDS - old-PRINT-WIDTHS = PRINT-WIDTHS - old-PRINT-TWIDTHS = PRINT-TWIDTHS - old-PRINT-GENDERS = PRINT-GENDERS - old-PRINT-CIRCUITS = PRINT-CIRCUITS - old-PRINT-DEBUG = PRINT-DEBUG - old-PRINT-INFO = PRINT-INFO - PRINT-TYPES = false - PRINT-KINDS = false - PRINT-WIDTHS = false - PRINT-TWIDTHS = false - PRINT-GENDERS = false - PRINT-CIRCUITS = false - PRINT-DEBUG = false - PRINT-INFO = false - -defmethod turn-on-debug (x:False) : - PRINT-TYPES = old-PRINT-TYPES - PRINT-KINDS = old-PRINT-KINDS - PRINT-WIDTHS = old-PRINT-WIDTHS - PRINT-TWIDTHS = old-PRINT-TWIDTHS - PRINT-GENDERS = old-PRINT-GENDERS - PRINT-CIRCUITS = old-PRINT-CIRCUITS - PRINT-DEBUG = old-PRINT-DEBUG - PRINT-INFO = old-PRINT-INFO - -;=== ThePrinters === - -public defn println-all-debug (l:?) -> False : - if PRINT-DEBUG : println-all(l) - else : false - -public defn println-debug (s:?) -> False : - if PRINT-DEBUG : println(s) - else : false - -defmethod print (o:OutputStream, k:Kind) : - print{o, _} $ - match(k) : - (k:WireKind) : "wire" - (k:PoisonKind) : "poison" - (k:RegKind) : "reg" - (k:PortKind) : "port" - (k:MemKind) : "mem" - (k:NodeKind) : "node" - (k:InstanceKind) : "inst" - (k:ExpKind) : "exp" - -defn hasGender (e:?) : - e typeof Expression - -defn hasWidth (e:?) : - e typeof UIntType|SIntType|UIntValue|SIntValue - -defn hasType (e:?) : - e typeof Expression|DefWire|DefRegister|DefPoison - |VectorType|Port|UIntValue|SIntValue - -defn hasKind (e:?) : - e typeof Expression - -defn hasInfo (e:?) : - e typeof Stmt|Port|Circuit|Module - -defn any-debug? (e:?) : - (hasGender(e) and PRINT-GENDERS) or - (hasType(e) and PRINT-TYPES) or - (hasWidth(e) and PRINT-WIDTHS) or - (hasKind(e) and PRINT-KINDS) or - (hasInfo(e) and PRINT-INFO) - -defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|Module|Circuit) : - defn wipe-width (t:Type) -> Type : - match(t) : - (t:UIntType) : UIntType(UnknownWidth()) - (t:SIntType) : SIntType(UnknownWidth()) - (t) : map(wipe-width,t) - - 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 ?) ">"]) - if PRINT-INFO and hasInfo(e): print-all(o,["<i:" info(e as ?) ">"]) - -defmethod print (o:OutputStream, e:WRef) : - print(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:WSubIndex) : - print-all(o,[exp(e) "[" value(e) "]"]) - print-debug(o,e as ?) -defmethod print (o:OutputStream, e:WSubAccess) : - print-all(o,[exp(e) "[" index(e) "]"]) - print-debug(o,e as ?) -defmethod print (o:OutputStream, e:WVoid) : - print(o,"VOID") - print-debug(o,e as ?) -defmethod print (o:OutputStream, c:WIndexer) : - print-all(o, [exps(c) "[" index(c) "]"]) - print-debug(o,c as ?) -defmethod print (o:OutputStream, c:WDefInstance) : - print-all(o, ["inst " name(c) " of " module(c) " : " type(c)]) - print-debug(o,c as ?) - - -defmethod map (f: Expression -> Expression, e: WSubField) : - WSubField(f(exp(e)), name(e), type(e), gender(e)) -defmethod map (f: Expression -> Expression, e: WSubIndex) : - WSubIndex(f(exp(e)), value(e), type(e), gender(e)) -defmethod map (f: Expression -> Expression, e: WSubAccess) : - WSubAccess(f(exp(e)), f(index(e)), type(e), gender(e)) - -defmethod map (f: Type -> Type, e: WRef) : - WRef(name(e), f(type(e)), kind(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: WSubIndex) : - WSubIndex(exp(e), value(e), f(type(e)), gender(e)) -defmethod map (f: Type -> Type, e: WSubAccess) : - WSubAccess(exp(e), index(e), f(type(e)), gender(e)) - -defmethod map (f: Type -> Type, s: WDefInstance) : - WDefInstance(info(s),name(s),module(s),f(type(s))) - -;================ WIDTH LIBRARY ==================== - -public val ONE = IntWidth(1) -public defstruct VarWidth <: Width : - name: Symbol -public defstruct PlusWidth <: Width : - arg1 : Width - arg2 : Width -public defstruct MinusWidth <: Width : - arg1 : Width - arg2 : Width -public defstruct MaxWidth <: Width : - args : List<Width> -public defstruct ExpWidth <: Width : - arg1 : Width -val width-name-hash = HashTable<Symbol,Int>(symbol-hash) - -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:ExpWidth) : ExpWidth(f(arg1(w))) - (w) : w - -public defmethod print (o:OutputStream, w:VarWidth) : - print(o,name(w)) -public defmethod print (o:OutputStream, w:MaxWidth) : - print-all(o,["max" args(w)]) -public defmethod print (o:OutputStream, w:PlusWidth) : - print-all(o,[ "(" arg1(w) " + " arg2(w) ")"]) -public defmethod print (o:OutputStream, w:MinusWidth) : - print-all(o,[ "(" arg1(w) " - " arg2(w) ")"]) -public defmethod print (o:OutputStream, w:ExpWidth) : - print-all(o,[ "exp(" arg1(w) ")"]) - -defn remove-unknowns-w (w:Width) -> Width : - match(w) : - (w:UnknownWidth) : VarWidth(firrtl-gensym(`w,width-name-hash)) - (w) : w -defn remove-unknowns (t:Type) -> Type : mapr(remove-unknowns-w,t) - -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:PlusWidth,w2:PlusWidth) : - (arg1(w1) == arg1(w2) and arg2(w1) == arg2(w2)) or (arg1(w1) == arg2(w2) and arg2(w1) == arg1(w2)) - (w1:MinusWidth,w2:MinusWidth) : - (arg1(w1) == arg1(w2) and arg2(w1) == arg2(w2)) or (arg1(w1) == arg2(w2) and arg2(w1) == arg1(w2)) - (w1:ExpWidth,w2:ExpWidth) : arg1(w1) == arg1(w2) - (w1:UnknownWidth,w2:UnknownWidth) : true - (w1,w2) : false -;================ WORKING IR UTILS ========================= -;defn plus (g1:Gender,g2:Gender) -> Gender : -; switch fn ([x,y]) : g1 == x and g2 == y : -; [FEMALE,MALE] : UNKNOWN-GENDER -; [MALE,FEMALE] : UNKNOWN-GENDER -; [MALE,MALE] : MALE -; [FEMALE,FEMALE] : FEMALE -; [BI-GENDER,MALE] : MALE -; [BI-GENDER,FEMALE] : FEMALE -; [MALE,BI-GENDER] : MALE -; [FEMALE,BI-GENDER] : FEMALE - -; These functions do not error, but return Unknown Type -defn module-type (m:Module) -> Type : - BundleType(for p in ports(m) map : to-field(p)) -defn field-type (v:Type,s:Symbol) -> Type : - match(v) : - (v:BundleType) : - val ft = for p in fields(v) find : name(p) == s - if ft != false : type(ft as Field) - else : UnknownType() - (v) : UnknownType() -defn sub-type (v:Type) -> Type : - match(v) : - (v:VectorType) : type(v) - (v) : UnknownType() -defn field-flip (v:Type,s:Symbol) -> Flip : - match(v) : - (v:BundleType) : - val ft = for p in fields(v) find : name(p) == s - if ft != false : flip(ft as Field) - else : DEFAULT ;This will get caught later - (v) : DEFAULT - -defn swap (g:Gender) -> Gender : - switch {_ == g} : - UNKNOWN-GENDER : UNKNOWN-GENDER - MALE : FEMALE - FEMALE : MALE - BI-GENDER : BI-GENDER -defn swap (f:Flip) -> Flip : - switch {_ == f} : - DEFAULT : REVERSE - REVERSE : DEFAULT -defn swap (d:Direction) -> Direction : - switch {_ == d} : - OUTPUT : INPUT - INPUT : OUTPUT - -public defn times (flip:Flip,d:Direction) -> Direction : - flip * d -public defn times (d:Direction,flip:Flip) -> Direction : - switch {_ == flip} : - DEFAULT : d - REVERSE : swap(d) -public defn times (g:Gender,flip:Flip) -> Gender : flip * g -public defn times (flip:Flip,g:Gender) -> Gender : - switch {_ == flip} : - DEFAULT : g - REVERSE : swap(g) -public defn times (f1:Flip,f2:Flip) -> Flip : - switch {_ == f2} : - DEFAULT : f1 - REVERSE : swap(f1) - -defn to-field (p:Port) -> Field : - if direction(p) == OUTPUT : Field(name(p),DEFAULT,type(p)) - else if direction(p) == INPUT : Field(name(p),REVERSE,type(p)) - else : error("Shouldn't be here") -defn to-dir (g:Gender) -> Direction : - switch {_ == g} : - MALE : INPUT - FEMALE : OUTPUT -defn to-gender (d:Direction) -> Gender : - switch {_ == d} : - INPUT: MALE - OUTPUT: FEMALE - -;================= Remove Special Characters ======================== -; Returns a new Circuit where all names have all special characters -; removed, except _. -; -;public defstruct RemoveSpecialChars <: Pass -;public defmethod pass (b:RemoveSpecialChars) -> (Circuit -> Circuit) : remove-special-chars -;public defmethod name (b:RemoveSpecialChars) -> String : "Remove Special Characters" -;public defmethod short-name (b:RemoveSpecialChars) -> String : "rem-spec-chars" -; -;;------------ Helper Functions ------------- -; -;defn get-new-string (n:Char) -> String : -; switch {n == _} : -; '_' : "__" -; '~' : "$A" -; '!' : "$B" -; '@' : "$C" -; '#' : "$D" -; '$' : "$E" -; '%' : "$F" -; '^' : "$G" -; '*' : "$H" -; '-' : "$I" -; '+' : "$J" -; '=' : "$K" -; '?' : "$L" -; '/' : "$M" -; else : to-string(n) -; -;;------------ Pass ------------------ -; -;defn remove-special-chars (c:Circuit) : -; defn rename (n:Symbol) -> Symbol : -; val v = Vector<String>() -; for c in to-string(n) do : -; add(v,get-new-string(c)) -; val n* = symbol-join(v) -; if key?(v-keywords,n*) : -; symbol-join([n* `_]) -; else : -; n* -; defn rename-t (t:Type) -> Type : -; match(t) : -; (t:BundleType) : BundleType $ -; for f in fields(t) map : -; Field(rename(name(f)),flip(f),rename-t(type(f))) -; (t:VectorType) : VectorType(rename-t(type(t)),size(t)) -; (t) : t -; defn rename-e (e:Expression) -> Expression : -; match(e) : -; (e:Ref) : Ref(rename(name(e)),rename-t(type(e))) -; (e:Subfield) : Subfield(rename-e(exp(e)),rename(name(e)),rename-t(type(e))) -; (e:Index) : Index(rename-e(exp(e)),value(e),rename-t(type(e))) -; (e:DoPrim) : DoPrim{op(e),_,consts(e),rename-t(type(e))} $ for x in args(e) map : rename-e(x) -; (e:UIntValue) : e -; (e:SIntValue) : e -; defn rename-s (s:Stmt) -> Stmt : -; match(s) : -; (s:DefWire) : DefWire(info(s),rename(name(s)),rename-t(type(s))) -; (s:DefPoison) : DefPoison(info(s),rename(name(s)),rename-t(type(s))) -; (s:DefRegister) : DefRegister(info(s),rename(name(s)),rename-t(type(s)),rename-e(clock(s)),rename-e(reset(s))) -; (s:WDefInstance) : WDefInstance(info(s),rename(name(s)),rename-e(module(s))) -; (s:DefMemory) : DefMemory(info(s),rename(name(s)),rename-t(type(s)),seq?(s),rename-e(clock(s)),size(s)) -; (s:DefNode) : DefNode(info(s),rename(name(s)),rename-e(value(s))) -; (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),rename-e(source(s)),rename-e(index(s)),acc-dir(s)) -; (s:Conditionally) : Conditionally(info(s),rename-e(pred(s)),rename-s(conseq(s)),rename-s(alt(s))) -; (s:Begin) : Begin $ for b in body(s) map : rename-s(b) -; (s:OnReset) : OnReset(info(s),rename-e(loc(s)),rename-e(exp(s))) -; (s:BulkConnect) : BulkConnect(info(s),rename-e(loc(s)),rename-e(exp(s))) -; (s:Connect) : Connect(info(s),rename-e(loc(s)),rename-e(exp(s))) -; (s:EmptyStmt) : s -; (s:StopStmt) : s -; (s:PrintfStmt) : PrintfStmt(info(s),string(s),map(rename-e,args(s))) -; -; Circuit(info(c),modules*, rename(main(c))) where : -; val modules* = -; for m in modules(c) map : -; match(m) : -; (m:InModule) : -; val ports* = for p in ports(m) map : -; Port(info(p),rename(name(p)),direction(p),rename-t(type(p))) -; InModule(info(m),rename(name(m)), ports*, rename-s(body(m))) -; (m:ExModule) : m - - -;================= Temporary Variable Elimination ======================== -; Returns a new Circuit where temporary variables are removed and returns -; the resulting nested expression -;public defstruct TempElimination <: Pass -;public defmethod pass (b:TempElimination) -> (Circuit -> Circuit) : temp-elimination -;public defmethod name (b:TempElimination) -> String : "Temp Elimination" -;public defmethod short-name (b:TempElimination) -> String : "temp-elim" -; -;defn temp-elimination (c:Circuit) : -; defn is-temp? (n:Symbol) -> True|False : -; to-string(n)[0] == 'T' -; defn temp-elim (m:InModule) : -; val h = HashTable<Symbol,Expression>(symbol-hash) -; defn temp-elim-e (e:Expression) : -; match(map(temp-elim-e,e)) : -; (e:Ref) : -; if key?(h,name(e)) : h[name(e)] -; else : e -; (e) : e -; defn temp-elim-s (s:Stmt) : -; match(map(temp-elim-e,s)) : -; (s:DefNode) : -; if is-temp?(name(s)) : -; h[name(s)] = value(s) -; EmptyStmt() -; else : s -; (s) : map(temp-elim-s,s) -; InModule(info(m),name(m), ports(m), temp-elim-s(body(m))) -; -; Circuit(info(c),modules*, main(c)) where : -; val modules* = -; for m in modules(c) map : -; match(m) : -; (m:InModule) : temp-elim(m) -; (m:ExModule) : m - -;================= Bring to Working IR ======================== -; Returns a new Circuit with Refs, Subfields, Indexes and DefAccessors -; replaced with IR-internal nodes that contain additional -; information (kind, gender) - -public defstruct ToWorkingIR <: Pass -public defmethod pass (b:ToWorkingIR) -> (Circuit -> Circuit) : to-working-ir -public defmethod name (b:ToWorkingIR) -> String : "Working IR" -public defmethod short-name (b:ToWorkingIR) -> String : "to-working-ir" - -defn to-working-ir (c:Circuit) : - defn to-exp (e:Expression) -> Expression : - match(map(to-exp,e)) : - (e:Ref) : WRef(name(e), type(e), NodeKind(), UNKNOWN-GENDER) - (e:SubField) : WSubField(exp(e), name(e), type(e), UNKNOWN-GENDER) - (e:SubIndex) : WSubIndex(exp(e), value(e), type(e), UNKNOWN-GENDER) - (e:SubAccess) : WSubAccess(exp(e), index(e), type(e), UNKNOWN-GENDER) - (e) : e - defn to-stmt (s:Stmt) -> Stmt : - match(map(to-exp,s)) : - (s:DefInstance) : WDefInstance(info(s),name(s),module(s),UnknownType()) - (s) : map(to-stmt,s) - - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - match(m) : - (m:InModule) : InModule(info(m),name(m), ports(m), to-stmt(body(m))) - (m:ExModule) : m - -;=============== Resolve Kinds ============================= -; It is useful for the compiler to know information about -; objects referenced. This information is stored in the kind -; field in WRef. This pass walks the graph and returns a new -; Circuit where all WRef kinds are resolved -public defstruct ResolveKinds <: Pass -public defmethod pass (b:ResolveKinds) -> (Circuit -> Circuit) : resolve-kinds -public defmethod name (b:ResolveKinds) -> String : "Resolve Kinds" -public defmethod short-name (b:ResolveKinds) -> String : "resolve-kinds" - -defn resolve-kinds (c:Circuit) : - defn resolve (body:Stmt, kinds:HashTable<Symbol,Kind>) : - defn resolve-stmt (s:Stmt) -> Stmt : - map{resolve-expr,_} $ - map(resolve-stmt,s) - - defn resolve-expr (e:Expression) -> Expression : - match(e) : - (e:WRef) : WRef(name(e),type(e),kinds[name(e)],gender(e)) - (e) : map(resolve-expr,e) - - resolve-stmt(body) - - defn find (m:Module, kinds:HashTable<Symbol,Kind>) : - defn find-stmt (s:Stmt) -> Stmt : - match(s) : - (s:DefWire) : kinds[name(s)] = WireKind() - (s:DefPoison) : kinds[name(s)] = PoisonKind() - (s:DefNode) : kinds[name(s)] = NodeKind() - (s:DefRegister) : kinds[name(s)] = RegKind() - (s:WDefInstance) : kinds[name(s)] = InstanceKind() - (s:DefMemory) : kinds[name(s)] = MemKind(append-all([readers(s) writers(s) readwriters(s)])) - (s) : false - map(find-stmt,s) - - for p in ports(m) do : - kinds[name(p)] = PortKind() - match(m) : - (m:InModule) : find-stmt(body(m)) - (m:ExModule) : false - - defn resolve-kinds (m:Module, c:Circuit) -> Module : - val kinds = HashTable<Symbol,Kind>(symbol-hash) - find(m,kinds) - match(m) : - (m:InModule) : - val body! = resolve(body(m),kinds) - InModule(info(m),name(m),ports(m),body!) - (m:ExModule) : ExModule(info(m),name(m),ports(m)) - - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - resolve-kinds(m,c) - -;============== INFER TYPES ================================ - -; ------------------ Utils ------------------------- - -defn set-type (s:Stmt,t:Type) -> Stmt : - match(s) : - (s:DefWire) : DefWire(info(s),name(s),t) - (s:DefRegister) : DefRegister(info(s),name(s),t,clock(s),reset(s),init(s)) - (s:DefMemory) : DefMemory(info(s),name(s),t,depth(s),write-latency(s),read-latency(s),readers(s),writers(s),readwriters(s)) - (s:DefNode) : s - (s:DefPoison) : DefPoison(info(s),name(s),t) - - -; ------------------ Pass ------------------------- -public defstruct InferTypes <: Pass -public defmethod pass (b:InferTypes) -> (Circuit -> Circuit) : infer-types -public defmethod name (b:InferTypes) -> String : "Infer Types" -public defmethod short-name (b:InferTypes) -> String : "infer-types" - -defn infer-types (c:Circuit) -> Circuit : - val module-types = HashTable<Symbol,Type>(symbol-hash) - defn infer-types (m:Module) -> Module : - val types = HashTable<Symbol,Type>(symbol-hash) - defn infer-types-e (e:Expression) -> Expression : - match(map(infer-types-e,e)) : - (e:WRef) : WRef(name(e), types[name(e)],kind(e),gender(e)) - (e:WSubField) : WSubField(exp(e),name(e),field-type(type(exp(e)),name(e)),gender(e)) - (e:WSubIndex) : WSubIndex(exp(e),value(e),sub-type(type(exp(e))),gender(e)) - (e:WSubAccess) : WSubAccess(exp(e),index(e),sub-type(type(exp(e))),gender(e)) - (e:DoPrim) : set-primop-type(e) - (e:UIntValue|SIntValue) : e - defn infer-types-s (s:Stmt) -> Stmt : - match(s) : - (s:DefRegister) : - val t = remove-unknowns(get-type(s)) - types[name(s)] = t - map(infer-types-e,set-type(s,t)) - (s:DefWire|DefPoison|DefNode) : - val s* = map(infer-types-e,s) - val t = remove-unknowns(get-type(s*)) - types[name(s*)] = t - set-type(s*,t) - (s:DefMemory) : - val t = remove-unknowns(get-type(s)) - types[name(s)] = t - val dt = remove-unknowns(data-type(s)) - set-type(s,dt) - (s:WDefInstance) : - types[name(s)] = module-types[module(s)] - WDefInstance(info(s),name(s),module(s),module-types[module(s)]) - (s) : map{infer-types-e,_} $ map(infer-types-s,s) - for p in ports(m) do : - types[name(p)] = type(p) - match(m) : - (m:InModule) : - InModule(info(m),name(m),ports(m),infer-types-s(body(m))) - (m:ExModule) : m - - ; MAIN - val modules* = - for m in modules(c) map : - val ports* = - for p in ports(m) map : - Port(info(p),name(p),direction(p),remove-unknowns(type(p))) - match(m) : - (m:InModule) : InModule(info(m),name(m),ports*,body(m)) - (m:ExModule) : ExModule(info(m),name(m),ports*) - - for m in modules* do : - module-types[name(m)] = module-type(m) - Circuit{info(c), _, main(c) } $ - for m in modules* map : - infer-types(m) - -;============= RESOLVE GENDER ============================ -; To ensure a proper circuit, we must ensure that assignments -; only work on expressions that can be assigned to. Similarly, -; we must ensure that only expressions that can be read from -; are used to assign from. This invariant requires each -; expression's gender to be inferred. -; Various elements can be bi-gender (e.g. wires) and can -; thus be treated as either female or male. Conversely, some -; elements are single-gender (e.g. accessors, ports). -public defstruct ResolveGenders <: Pass -public defmethod pass (b:ResolveGenders) -> (Circuit -> Circuit) : resolve-genders -public defmethod name (b:ResolveGenders) -> String : "Resolve Genders" -public defmethod short-name (b:ResolveGenders) -> String : "resolve-genders" - -defn resolve-genders (c:Circuit) : - defn resolve-e (e:Expression,g:Gender) -> Expression : - match(e) : - (e:WRef) : WRef(name(e),type(e),kind(e),g) - (e:WSubField) : - val exp* = - switch { _ == field-flip(type(exp(e)),name(e)) } : - DEFAULT : resolve-e(exp(e),g) - REVERSE : resolve-e(exp(e),swap(g)) - WSubField(exp*,name(e),type(e),g) - (e:WSubIndex) : - val exp* = resolve-e(exp(e),g) - WSubIndex(exp*,value(e),type(e),g) - (e:WSubAccess) : - val exp* = resolve-e(exp(e),g) - val index* = resolve-e(index(e),MALE) - WSubAccess(exp*,index*,type(e),g) - (e:WIndexer) : - val exps* = map(resolve-e{_,g},exps(e)) - val index* = resolve-e(index(e),MALE) - WIndexer(exps*,index*,type(e),g) - (e) : map(resolve-e{_,g},e) - - defn resolve-s (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : - val loc* = resolve-e(loc(s),FEMALE) - val exp* = resolve-e(exp(s),MALE) - Connect(info(s),loc*,exp*) - (s:BulkConnect) : - val loc* = resolve-e(loc(s),FEMALE) - val exp* = resolve-e(exp(s),MALE) - BulkConnect(info(s),loc*,exp*) - (s) : - map{resolve-s,_} $ map(resolve-e{_,MALE},s) - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - match(m) : - (m:InModule) : - val body* = resolve-s(body(m)) - InModule(info(m),name(m),ports(m),body*) - (m:ExModule) : m - -;;============== EXPAND ACCESSORS ================================ -; This pass expands non-memory accessors into DecFromIndexer or -; ConnectFromIndexed. All elements of the vector are -; explicitly written out, then indexed. Depending on the gender -; of the accessor, it is transformed into DecFromIndexer (male) or -; DecToIndexer (female) - -;public defstruct ExpandAccesses <: Pass -;public defmethod pass (b:ExpandAccesses) -> (Circuit -> Circuit) : expand-accesses -;public defmethod name (b:ExpandAccesses) -> String : "Expand Accesses" -;public defmethod short-name (b:ExpandAccesses) -> String : "expand-accesses" -; - -defn expand-vector (e:Expression,g:Gender) -> List<Expression> : - val t = type(e) as VectorType - for i in 0 to size(t) map-append : - list(WSubIndex(e,i,type(t),g)) ;always be WRef|WSubField|WSubIndex - - - -;================ EXPAND CONNECTS ================== -public defstruct ExpandConnects <: Pass -public defmethod pass (b:ExpandConnects) -> (Circuit -> Circuit) : expand-connects -public defmethod name (b:ExpandConnects) -> String : "Expand Connects" -public defmethod short-name (b:ExpandConnects) -> String : "expand-connects" - -;---------------- UTILS ------------------ -val hashed-get-flip = HashTable<TIF,Flip>(tif-hash) -val hashed-create-exps = HashTable<Expression,List<Expression>>(exp-hash) -val hashed-locations = HashTable<Expression,List<Location>>(exp-hash) -;defn clear-hashes () : -; hashed-get-flip = HashTable<TIF,Flip>(tif-hash) -; hashed-create-exps = HashTable<Expression,List<Expression>>(exp-hash) -; hashed-locations = HashTable<Expression,List<Location>>(exp-hash) - -defn get-size (e:Expression) -> Int : get-size(type(e)) -defn get-size (t:Type) -> Int : - match(t) : - (t:BundleType) : - var sum = 0 - for f in fields(t) do : - sum = sum + get-size(type(f)) - sum - (t:VectorType) : size(t) * get-size(type(t)) - (t) : 1 -defstruct TIF : - type : Type - int : Int - flip : Flip -defn tif-hash (tif:TIF) -> Int : - turn-off-debug(false) - val i = symbol-hash(to-symbol(string-join(map(to-string,list(type(tif) int(tif) flip(tif)))))) - turn-on-debug(false) - i - -defn get-flip (t:Type, i:Int, f:Flip) -> Flip : - if key?(hashed-get-flip,TIF(t,i,f)) : hashed-get-flip[TIF(t,i,f)] - else : - if i >= get-size(t) : error("Shouldn't be here") - val x = match(t) : - (t:UIntType|SIntType|ClockType) : f - (t:BundleType) : label<Flip> ret : - var n = i - for x in fields(t) do : - if n < get-size(type(x)) : - ret(get-flip(type(x),n,flip(x) * f)) - else : - n = n - get-size(type(x)) - error("Shouldn't be here") - (t:VectorType) : label<Flip> ret : - var n = i - for j in 0 to size(t) do : - if n < get-size(type(t)) : - ret(get-flip(type(t),n,f)) - else : - n = n - get-size(type(t)) - error("Shouldn't be here") - hashed-get-flip[TIF(t,i,f)] = x - x - -defn get-point (e:Expression) -> Int : - match(e) : - (e:WRef) : 0 - (e:WSubField) : - var i = 0 - for f in fields(type(exp(e)) as BundleType) find : - val b = name(f) == name(e) - if not b : i = i + get-size(type(f)) - b - i - (e:WSubIndex) : - value(e) * get-size(e) - (e:WSubAccess) : - get-point(exp(e)) -defn get-valid-points (t1:Type,t2:Type,flip1:Flip,flip2:Flip) -> List<[Int,Int]> : - ;println-all(["Inside with t1:" t1 ",t2:" t2 ",f1:" flip1 ",f2:" flip2]) - match(t1,t2) : - (t1:UIntType,t2:UIntType) : - if flip1 == flip2 : list([0, 0]) - else: list() - (t1:SIntType,t2:SIntType) : - if flip1 == flip2 : list([0, 0]) - else: list() - (t1:BundleType,t2:BundleType) : - val points = Vector<[Int,Int]>() - var ilen = 0 - var jlen = 0 - for i in 0 to length(fields(t1)) do : - for j in 0 to length(fields(t2)) do : - ;println(i) - ;println(j) - ;println(ilen) - ;println(jlen) - val f1 = fields(t1)[i] - val f2 = fields(t2)[j] - if name(f1) == name(f2) : - val ls = get-valid-points(type(f1),type(f2),flip1 * flip(f1), - flip2 * flip(f2)) - for x in ls do : - add(points,[x[0] + ilen, x[1] + jlen]) - println(points) - jlen = jlen + get-size(type(fields(t2)[j])) - ilen = ilen + get-size(type(fields(t1)[i])) - jlen = 0 - to-list(points) - (t1:VectorType,t2:VectorType) : - val points = Vector<[Int,Int]>() - var ilen = 0 - var jlen = 0 - for i in 0 to min(size(t1),size(t2)) do : - val ls = get-valid-points(type(t1),type(t2),flip1,flip2) - for x in ls do : - add(points,[x[0] + ilen, x[1] + jlen]) - ilen = ilen + get-size(type(t1)) - jlen = jlen + get-size(type(t2)) - to-list(points) - - -defn create-exps (n:Symbol, t:Type) -> List<Expression> : - create-exps(WRef(n,t,ExpKind(),UNKNOWN-GENDER)) -defn create-exps (e:Expression) -> List<Expression> : - match(type(e)) : - (t:UIntType|SIntType|ClockType) : list(e) - (t:BundleType) : - for f in fields(t) map-append : - create-exps(WSubField(e,name(f),type(f),gender(e) * flip(f))) - (t:VectorType) : - for i in 0 to size(t) map-append : - create-exps(WSubIndex(e,i,type(t),gender(e))) - -defn fast-create-exps (n:Symbol, t:Type) -> List<Expression> : - fast-create-exps(WRef(n,t,ExpKind(),UNKNOWN-GENDER)) -defn fast-create-exps (e:Expression) -> List<Expression> : - if key?(hashed-create-exps,e) : hashed-create-exps[e] - else : - val es = Vector<Expression>() - defn create-exps (e:Expression) -> False : - match(type(e)) : - (t:UIntType|SIntType|ClockType) : add(es,e) - (t:BundleType) : - for f in fields(t) do : - create-exps(WSubField(e,name(f),type(f),gender(e) * flip(f))) - (t:VectorType) : - for i in 0 to size(t) do : - create-exps(WSubIndex(e,i,type(t),gender(e))) - create-exps(e) - val x = to-list(es) - hashed-create-exps[e] = x - x - -;---------------- Pass --------------------- - -defn expand-connects (c:Circuit) -> Circuit : - defn expand-connects (m:InModule) -> InModule : - ;clear-hashes() - defn expand-s (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : - val n = get-size(loc(s)) - val connects = Vector<Stmt>() - val locs = fast-create-exps(loc(s)) - val exps = fast-create-exps(exp(s)) - for i in 0 to n do : - val loc* = locs[i] - val exp* = exps[i] - add{connects,_} $ - switch { _ == get-flip(type(loc(s)),i,DEFAULT) } : - DEFAULT : Connect(info(s),loc*,exp*) - REVERSE : Connect(info(s),exp*,loc*) - Begin(to-list(connects)) - (s:BulkConnect) : - val ls = get-valid-points(type(loc(s)),type(exp(s)),DEFAULT,DEFAULT) - val connects = Vector<Stmt>() - val locs = fast-create-exps(loc(s)) - val exps = fast-create-exps(exp(s)) - for x in ls do : - val loc* = locs[x[0]] - val exp* = exps[x[1]] - add{connects,_} $ - switch { _ == get-flip(type(loc(s)),x[0],DEFAULT) } : - DEFAULT : Connect(info(s),loc*,exp*) - REVERSE : Connect(info(s),exp*,loc*) - Begin(to-list(connects)) - (s) : map(expand-s,s) - - - InModule(info(m),name(m),ports(m),expand-s(body(m))) - - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : expand-connects(m) - - -;;;================ REPLACE INDEXERS ========================= -; This pass inlines all accessors to non-memory vector typed -; components. - -public defstruct RemoveAccesses <: Pass -public defmethod pass (b:RemoveAccesses) -> (Circuit -> Circuit) : remove-access -public defmethod name (b:RemoveAccesses) -> String : "Remove Accesses" -public defmethod short-name (b:RemoveAccesses) -> String : "remove-access" - -defstruct Location : - base : Expression - guard : Expression -defmethod print (o:OutputStream,x:Location) : - print-all(o,["[" base(x) " , " guard(x) "]"]) - -defn get-locations (e:Expression) -> List<Location> : - if key?(hashed-locations,e) : hashed-locations[e] - else : - val x = match(e) : - (e:WRef) : map(Location{_,one},fast-create-exps(e)) - (e:WSubIndex|WSubField) : - val ls = get-locations(exp(e)) - val start = get-point(e) - val end = start + get-size(e) - val stride = get-size(exp(e)) - val ls* = Vector<Location>() - var c = 0 - for i in 0 to length(ls) do : - if (i % stride >= start and i % stride < end) : - add(ls*,ls[i]) - to-list(ls*) - (e:WSubAccess) : - val ls = get-locations(exp(e)) - val stride = get-size(e) - val wrap = size(type(exp(e)) as VectorType) - val ls* = Vector<Location>() - var c = 0 - for i in 0 to length(ls) do : - if c % wrap == 0 : c = 0 - val base* = base(ls[i]) - val guard* = AND(guard(ls[i]),EQV(uint(c),index(e))) - add(ls*,Location(base*,guard*)) - if (i + 1) % stride == 0 : c = c + 1 - to-list(ls*) - hashed-locations[e] = x - x - -defn remove-access (c:Circuit) : - defn remove-m (m:InModule) -> InModule : - val sh = get-sym-hash(m,keys(v-keywords)) - ;clear-hashes() - defn remove-s (s:Stmt) -> Stmt : - val stmts = Vector<Stmt>() - defn create-temp (e:Expression) -> Expression : - val n = firrtl-gensym(`GEN,sh) - add(stmts,DefWire(info(s),n,type(e))) - WRef(n,type(e),kind(e),gender(e)) - defn remove-e (e:Expression) -> Expression : ;NOT RECURSIVE (except primops) INTENTIONALLY! - match(e) : - (e:DoPrim) : map(remove-e,e) - (e:UIntValue|SIntValue) : e - (e) : - val rs = get-locations(e) - val foo = for x in rs find : - (guard(x)) != one - if foo == false : e - else : - val temp = create-temp(e) - for (x in rs, i in 0 to false) do : - if i == 0 : - add(stmts,Connect(info(s),temp,base(x))) - else : - add(stmts,Conditionally(info(s),guard(x),Connect(info(s),temp,base(x)),Empty())) - temp - val s* = match(s) : - (s:Connect) : - val ls = get-locations(loc(s)) - val loc* = - if length(ls) == 1 and guard(head(ls)) == one : loc(s) - else : - val temp = create-temp(loc(s)) - for x in ls do : - add(stmts,Conditionally(info(s),guard(x),Connect(info(s),base(x),temp),Empty())) - temp - Connect(info(s),loc*,remove-e(exp(s))) - (s) : map{remove-s,_} $ map(remove-e,s) - add(stmts,s*) - if length(stmts) != 1 : Begin(to-list(stmts)) - else : stmts[0] - - InModule(info(m),name(m),ports(m),remove-s(body(m))) - - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : remove-m(m) - -;;================ EXPAND WHENS ============================= -; This pass does three things: remove last connect semantics, -; remove conditional blocks, and eliminate concept of scoping. - -public defstruct ExpandWhens <: Pass -public defmethod pass (b:ExpandWhens) -> (Circuit -> Circuit) : expand-whens -public defmethod name (b:ExpandWhens) -> String : "Expand Whens" -public defmethod short-name (b:ExpandWhens) -> String : "expand-whens" - -; ========== Expand When Utilz ========== - -defn get-entries (hash:HashTable<Expression,Expression>,exps:Streamable<Expression>) -> HashTable<Expression,Expression> : - val hash* = HashTable<Expression,Expression>(exp-hash) - for e in exps do : - val value = get?(hash,e,false) - match(value) : - (value:Expression) : hash*[e] = value - (value:False) : false - hash* -defn get-female-refs (n:Symbol,t:Type,g:Gender) -> List<Expression> : - val exps = fast-create-exps(WRef(n,t,ExpKind(),g)) - val exps* = Vector<Expression>() - for i in 0 to length(exps) do : - switch { _ == get-gender(t,i,g)} : - BI-GENDER : add(exps*,exps[i]) - FEMALE : add(exps*,exps[i]) - else : false - to-list(exps*) -defn get-gender (t:Type, i:Int, g:Gender) -> Gender : - val f = get-flip(t,i,DEFAULT) - g * f -defn print-hash (h:HashTable<Expression,Expression>) : - for x in h do : - println(x) - -; ------------ Pass ------------------- -defn expand-whens (c:Circuit) -> Circuit : - defn void-all (m:InModule) -> InModule : - ;clear-hashes() - defn void-all-s (s:Stmt) -> Stmt : - match(s) : - (s:DefWire|DefRegister|WDefInstance|DefMemory) : - val voids = Vector<Stmt>() - for e in get-female-refs(name(s),get-type(s),get-gender(s)) do : - add(voids,Connect(info(s),e,WVoid())) - Begin(List(s,to-list(voids))) - (s) : map(void-all-s,s) - val voids = Vector<Stmt>() - for p in ports(m) do : - for e in get-female-refs(name(p),type(p),get-gender(p)) do : - add(voids,Connect(info(p),e,WVoid())) - val body* = void-all-s(body(m)) - InModule(info(m),name(m),ports(m),Begin(list(Begin(to-list(voids)),body*))) - - defn expand-whens (m:InModule) -> [HashTable<Expression,Expression> Vector<Stmt>] : - val simlist = Vector<Stmt>() - defn expand-whens (s:Stmt,netlist:HashTable<Expression,Expression>,p:Expression) -> Stmt : - match(s) : - (s:Connect) : netlist[loc(s)] = exp(s) - (s:Conditionally) : - val exps = Vector<Expression>() - defn prefetch (s:Stmt) -> Stmt: - match(s) : - (s:Connect) : - add(exps,loc(s)) - s - (s) : map(prefetch,s) - prefetch(conseq(s)) - val c-netlist = get-entries(netlist,exps) - expand-whens(conseq(s),c-netlist,AND(p,pred(s))) - expand-whens(alt(s),netlist,AND(p,NOT(pred(s)))) - for lvalue in keys(c-netlist) do : - val value = get?(netlist,lvalue,false) - match(value) : - (value:Expression) : - netlist[lvalue] = MUX(pred(s),c-netlist[lvalue],value) - (value:False) : - netlist[lvalue] = c-netlist[lvalue] - (s:Print) : - if p == one : add(simlist,s) - else : add(simlist,Print(info(s),string(s),args(s),clk(s),AND(p,en(s)))) - (s:Stop) : - if p == one : add(simlist,s) - else : add(simlist,Stop(info(s),ret(s),clk(s),AND(p,en(s)))) - (s) : map(expand-whens{_,netlist,p},s) - s - val netlist = HashTable<Expression,Expression>(exp-hash) - expand-whens(body(m),netlist,one) - - ;println("Netlist:") - ;println(netlist) - ;println("Simlist:") - ;println(simlist) - [ netlist simlist ] - - defn create-module (netlist:HashTable<Expression,Expression>,simlist:Vector<Stmt>,m:InModule) -> InModule : - val stmts = Vector<Stmt>() - val connections = Vector<Stmt>() - ;clear-hashes() - defn replace-void (e:Expression,rvalue:Expression) -> Expression : - match(rvalue) : - (rv:WVoid) : e - (rv) : map(replace-void{e,_},rv) - defn create (s:Stmt) -> Stmt : - match(s) : - (s:DefWire|DefRegister|WDefInstance|DefMemory) : - add(stmts,s) - for e in get-female-refs(name(s),get-type(s),get-gender(s)) do : - val rvalue = - if s typeof DefRegister : replace-void(e,netlist[e]) - else : netlist[e] - add(connections,Connect(info(s),e,rvalue)) - (s:DefPoison|DefNode) : - add(stmts,s) - (s) : map(create,s) - s - create(body(m)) - for p in ports(m) do : - for e in get-female-refs(name(p),type(p),get-gender(p)) do : - add(connections,Connect(info(p),e,netlist[e])) - for x in simlist do : - add(stmts,x) - InModule(info(m),name(m),ports(m),Begin(list(Begin(to-list(stmts)),Begin(to-list(connections))))) - - val voided-modules = - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : - val m* = void-all(m as InModule) - m* - val modules* = - for m in voided-modules map : - match(m) : - (m:ExModule) : m - (m:InModule) : - val [netlist simlist] = expand-whens(m) - create-module(netlist,simlist,m) - Circuit(info(c),modules*,main(c)) - -;;================ Module Duplication ================== -; Duplicates modules so that no module is instantiated -; more than once. - -;public defstruct ModuleDuplication <: Pass -;public defmethod pass (b:ModuleDuplication) -> (Circuit -> Circuit) : module-duplication -;public defmethod name (b:ModuleDuplication) -> String : "Module Duplication" -;public defmethod short-name (b:ModuleDuplication) -> String : "mod-dup" -; -;;------------ Helper Functions ------------- -; -;;------------ Pass ------------------ -; -;public defn module-duplication (c:Circuit) : -; val modules* = Vector<Module>() -; val m-names = HashTable<Symbol,Int>(symbol-hash) -; defn rename (n:Symbol) -> Symbol : -; val int = get?(m-names,n,0) -; m-names[n] = int + 1 -; val n* = symbol-join([n module-expand-delin int]) -; val m = for x in modules(c) find : name(x) == n -; match(m) : -; (m:InModule) : add(modules*,InModule(info(m),n*, ports(m), rename-s(body(m)))) -; (m:ExModule) : add(modules*,ExModule(info(m),n*, ports(m))) -; (m:False) : error("Shouldn't be here") -; n* -; -; defn rename-e (e:Expression) -> Expression : -; match(e) : -; (e:Ref) : Ref(rename(name(e)),type(e)) -; (e) : error("Shouldn't be here") -; defn rename-s (s:Stmt) -> Stmt : -; match(s) : -; (s:WDefInstance) : WDefInstance(info(s),name(s),rename-e(module(s))) -; (s) : map(rename-s,s) -; -; val top = for m in modules(c) find : name(m) == main(c) -; match(top) : -; (m:InModule) : add(modules*,InModule(info(m),name(m), ports(m), rename-s(body(m)))) -; (m:ExModule) : m -; (m:False) : error("Shouldn't be here") -; -; Circuit(info(c),to-list(modules*), main(c)) -; -; -;;;================ Deadcode Elimination =================== -;; Walks the circuit, starting from the outputs from the top -;; level module. All components that are not reached are -;; deleted -; -;public defstruct DeadcodeElimination <: Pass -;public defmethod pass (b:DeadcodeElimination) -> (Circuit -> Circuit) : deadcode-elimination -;public defmethod name (b:DeadcodeElimination) -> String : "Deadcode Elimination" -;public defmethod short-name (b:DeadcodeElimination) -> String : "deadcode-elim" -; -;;------------ Helper Functions ------------- -; -;;------------ Pass ------------------ -; -;public defn deadcode-elimination (c:Circuit) : c -; -;;;================ 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. -;; Low FIRRTL Pass. -public defstruct InferWidths <: Pass -public defmethod pass (b:InferWidths) -> (Circuit -> Circuit) : infer-widths -public defmethod name (b:InferWidths) -> String : "Infer Widths" -public defmethod short-name (b:InferWidths) -> String : "infer-widths" - -public definterface Constraint -public defstruct WGeq <: Constraint : - loc : Width - exp : Width -public defmethod print (o:OutputStream, c:WGeq) : - print-all(o,[ loc(c) " >= " exp(c)]) -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 solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Width> : - 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:PlusWidth) : - match(arg1(w),arg2(w)) : - (w1:IntWidth,w2:IntWidth) : IntWidth(plus(width(w1),width(w2))) - (w1,w2) : w - (w:MinusWidth) : - match(arg1(w),arg2(w)) : - (w1:IntWidth,w2:IntWidth) : IntWidth(minus(width(w1),width(w2))) - (w1,w2) : w - (w:ExpWidth) : - match(arg1(w)) : - (w1:IntWidth) : IntWidth(pow(to-long(2),width(w1)) - to-long(1)) - (w1) : w - (w) : w - defn substitute (w:Width,h:HashTable<Symbol,Width>) -> Width : - ;println-all-debug(["Substituting for [" w "]"]) - val w* = simplify(w) - ;println-all-debug(["After Simplify: [" w* "]"]) - match(map(substitute{_,h},simplify(w))) : - (w:VarWidth) : - ;println-debug("matched varwidth!") - if contains?(name(w),h) : - ;println-debug("Contained!") - ;println-all-debug(["Width: " w]) - ;println-all-debug(["Accessed: " h[name(w)]]) - val t = simplify(substitute(h[name(w)],h)) - ;val t = h[name(w)] - ;println-all-debug(["Width after sub: " t]) - h[name(w)] = t - t - else : w - (w): - ;println-all-debug(["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-debug(["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:MinusWidth) : - if arg1(w) == VarWidth(n) : arg1(w) - else : w - (w) : w - ;println-all-debug(["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? - - ; 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-debug("======== UNIQUE CONSTRAINTS ========") - for x in u do : println-debug(x) - println-debug("====================================") - - val f = HashTable<Symbol,Width>(symbol-hash) - val o = Vector<Symbol>() - for x in u do : - println-debug("==== SOLUTIONS TABLE ====") - for x in f do : println-debug(x) - println-debug("=========================") - - val [n e] = [key(x) value(x)] - - val e-sub = substitute(e,f) - println-debug(["Solving " n " => " e]) - println-debug(["After Substitute: " n " => " e-sub]) - println-debug("==== SOLUTIONS TABLE (Post Substitute) ====") - for x in f do : println-debug(x) - println-debug("=========================") - val e* = remove-cycle{n,_} $ e-sub - ;println-debug(["After Remove Cycle: " n " => " e*]) - if not self-rec?(n,e*) : - ;println-all-debug(["Not rec!: " n " => " e*]) - ;println-all-debug(["Adding [" n "=>" e* "] to Solutions Table"]) - add(o,n) - f[n] = e* - - println-debug("Forward Solved Constraints") - for x in f do : println-debug(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-debug(["SOLVE BACK: [" n " => " f[n] "]"]) - println-debug("==== SOLUTIONS TABLE ====") - for x in b do : println-debug(x) - println-debug("=========================") - val e* = simplify(b-sub(f[n],b)) - println-all-debug(["BACK RETURN: [" n " => " e* "]"]) - b[n] = e* - println-debug("==== SOLUTIONS TABLE (Post backsolve) ====") - for x in b do : println-debug(x) - println-debug("=========================") - b - -public defn width! (t:Type) -> Width : - match(t) : - (t:UIntType) : width(t) - (t:SIntType) : width(t) - (t:ClockType) : IntWidth(1) - (t) : error("No width!") -public defn width! (e:Expression) -> Width : width!(type(e)) - -defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit : - defn evaluate (w:Width) -> Width : - defn apply (a:Long|False,f:(Long) -> Long) -> Long|False : - if a typeof Long : f(a as Long) - else : false - defn apply (a:Long|False,b:Long|False, f: (Long,Long) -> Long) -> Long|False : - if a typeof Long and b typeof Long : f(a as Long, b as Long) - else : false - defn apply-l (l:List<Long|False>,f:(Long,Long) -> Long) -> Long|False : - if length(l) == 0 : to-long(0) - else : apply(head(l),apply-l(tail(l),f),f) - defn max (a:Long,b:Long) -> Long : - if a >= b : a - else : b - defn solve (w:Width) -> False|Long : - match(w) : - (w:VarWidth) : - val w* = get?(h,name(w),false) - match(w*) : - (w:VarWidth) : false - (w:False) : false - (w) : solve(w as Width) - (w:MaxWidth) : apply-l(map(solve,args(w)),max) - (w:PlusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{plus(_,_)}) - (w:MinusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{minus(_,_)}) - (w:ExpWidth) : apply(to-long(2),solve(arg1(w)),{minus(pow(_,_),to-long(1))}) - (w:IntWidth) : width(w) - (w) : - println(w) - error("Shouldn't be here") - - val s = solve(w) - match(s) : - (s:Long) : IntWidth(s) - (s) : w - - defn reduce-var-widths-w (w:Width) -> Width : - println-all-debug(["REPLACE: " w]) - val w* = evaluate(w) - println-all-debug(["WITH: " w*]) - w* - - val modules* = for m in modules(c) map : - val ports* = for p in ports(m) map : - Port(info(p),name(p),direction(p),mapr(reduce-var-widths-w,type(p))) - - match(m) : - (m:ExModule) : ExModule(info(m),name(m),ports*) - (m:InModule) : InModule(info(m),name(m),ports*,mapr(reduce-var-widths-w,body(m))) - - Circuit(info(c),modules*,main(c)) - -defn infer-widths (c:Circuit) -> Circuit : - val v = Vector<WGeq>() - defn constrain (w1:Width,w2:Width) -> False : constrain(w1,w2,DEFAULT) - defn constrain (w1:Width,w2:Width,f:Flip) -> False : - switch { _ == f } : - DEFAULT : add(v,WGeq(w1,w2)) - REVERSE : add(v,WGeq(w2,w1)) - defn get-constraints (t1:Type,t2:Type,f:Flip) -> False : - match(t1,t2) : - (t1:UIntType,t2:UIntType) : constrain(width(t1),width(t2)) - (t1:SIntType,t2:SIntType) : constrain(width(t1),width(t2)) - (t1:BundleType,t2:BundleType) : - for (f1 in fields(t1),f2 in fields(t2)) do : - get-constraints(type(f1),type(f2),flip(f1) * f) - (t1:VectorType,t2:VectorType) : - get-constraints(type(t1),type(t2),f) - defn get-constraints-e (e:Expression) -> Expression : - match(map(get-constraints-e,e)) : - (e:DoPrim) : - if op(e) == MUX-OP : - constrain(width!(args(e)[0]),ONE) - constrain(ONE,width!(args(e)[0])) - e - (e) : e - defn get-constraints (s:Stmt) -> Stmt : - match(map(get-constraints-e,s)) : - (s:Connect) : - ;constrain(width!(loc(s)),width!(exp(s))) - ;s - val n = get-size(loc(s)) - val ce-loc = fast-create-exps(loc(s)) - val ce-exp = fast-create-exps(exp(s)) - for i in 0 to n do : - val loc* = ce-loc[i] - val exp* = ce-exp[i] - switch { _ == get-flip(type(loc(s)),i,DEFAULT) } : - DEFAULT : constrain(width!(loc*),width!(exp*)) - REVERSE : constrain(width!(exp*),width!(loc*)) - s - (s:BulkConnect) : - val ls = get-valid-points(type(loc(s)),type(exp(s)),DEFAULT,DEFAULT) - for x in ls do : - println(x) - println(fast-create-exps(loc(s))) - println(fast-create-exps(exp(s))) - val loc* = fast-create-exps(loc(s))[x[0]] - val exp* = fast-create-exps(exp(s))[x[1]] - switch { _ == get-flip(type(loc(s)),x[0],DEFAULT) } : - DEFAULT : constrain(width!(loc*),width!(exp*)) - REVERSE : constrain(width!(exp*),width!(loc*)) - s - (s:DefRegister) : - constrain(width!(reset(s)),ONE) - constrain(ONE,width!(reset(s))) - get-constraints(type(s),type(init(s)),DEFAULT) - s - (s:Conditionally) : - add(v,WGeq(width!(pred(s)),ONE)) - add(v,WGeq(ONE,width!(pred(s)))) - map(get-constraints,s) - (s) : map(get-constraints,s) - - for m in modules(c) do : - match(m) : - (m:InModule) : get-constraints(body(m)) - (m) : false - println-debug("======== ALL CONSTRAINTS ========") - for x in v do : println-debug(x) - println-debug("=================================") - val h = solve-constraints(to-list(v)) - println-debug("======== SOLVED CONSTRAINTS ========") - for x in h do : println-debug(x) - println-debug("====================================") - reduce-var-widths(Circuit(info(c),modules(c),main(c)),h) - -; ================ All Resolving Passes ================ -public defstruct Resolve <: Pass -public defmethod pass (b:Resolve) -> (Circuit -> Circuit) : resolve -public defmethod name (b:Resolve) -> String : "Resolve" -public defmethod short-name (b:Resolve) -> String : "resolve" - -defn resolve (c:Circuit) -> Circuit : - infer-widths $ - resolve-genders $ - infer-types $ - resolve-kinds $ c - -;;================= Inline Instances ======================== -;; Inlines instances. Assumes module with same name as the -;; Circuit is the top level module -;public defstruct Inline <: Pass -;public defmethod pass (b:Inline) -> (Circuit -> Circuit) : inline-instances -;public defmethod name (b:Inline) -> String : "Inline Instances" -;public defmethod short-name (b:Inline) -> String : "inline-instances" -; -;defn inline-instances (c:Circuit) : -; val h = HashTable<Symbol,InModule>(symbol-hash) -; val h-s = HashTable<Symbol,Stmt>(symbol-hash) -; defn inline-inst (s:Stmt) -> Stmt : -; match(map(inline-inst,s)) : -; (s:WDefInstance) : -; 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(info(s),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) inline-delin name(e)]),type(e),k,gender(e)) -; (k:MemKind) : e -; (e) : e -; defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n inline-delin 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) inline-delin 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(info(s),rename(name(s),n),type(s)) -; (s:DefPoison) : DefPoison(info(s),rename(name(s),n),type(s)) -; (s:DefRegister) : DefRegister(info(s),rename(name(s),n),type(s),clock(s),reset(s)) -; (s:WDefInstance) : error("Shouldn't be here") -; (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s),clock(s),size(s)) -; (s:DefNode) : DefNode(info(s),rename(name(s),n),value(s)) -; (s) : s -; for m in modules(c) do : -; match(m) : -; (m:ExModule) : error("Cannot inline with external modules") -; (m:InModule) : h[name(m)] = m -; val top = (for m in modules(c) find : name(m) == main(c)) as InModule -; Circuit(info(c),list(InModule(info(top),name(top),ports(top),inline-inst(body(top)))),main(c)) - -;;================= Split Expressions ======================== -;; Intended to only work on low firrtl -public defstruct SplitExp <: Pass -public defmethod pass (b:SplitExp) -> (Circuit -> Circuit) : split-exp -public defmethod name (b:SplitExp) -> String : "Split Expressions" -public defmethod short-name (b:SplitExp) -> String : "split-expressions" - -defn split-exp (m:InModule) -> InModule : - val v = Vector<Stmt>() - val sh = get-sym-hash(m,keys(v-keywords)) - defn split-exp-s (s:Stmt) -> Stmt : - val base = match(s) : - (s:Connect) : lowered-name(loc(s)) - (s:DefNode) : name(s) - (s:DefRegister) : name(s) - (s) : `F - defn split (e:Expression) -> Expression : - val n = firrtl-gensym(`GEN,sh) - add(v,DefNode(info(s),n,e)) - WRef(n,type(e),kind(e),gender(e)) - defn split-exp-e (e:Expression,i:Int) -> Expression : - match(map(split-exp-e{_,i + 1},e)) : - (e:DoPrim) : - if i > 0 : split(e) - else : e - (e) : e - match(map(split-exp-e{_,0},s)) : - (s:Begin) : map(split-exp-s,s) - (s) : - add(v,s) - s - split-exp-s(body(m)) - InModule(info(m),name(m),ports(m),Begin(to-list(v))) - -defn split-exp (c:Circuit) -> Circuit : - val modules* = for m in modules(c) map : - match(m) : - (m:InModule) : split-exp(m) - (m:ExModule) : m - Circuit(info(c),modules*,main(c)) - - -;;================= Special Rename ======================== -;; Returns a new Circuit with only real IR nodes. -;public defstruct SpecialRename <: Pass : -; original-sym : Symbol -; new-sym : Symbol -;public defmethod pass (b:SpecialRename) -> (Circuit -> Circuit) : special-rename{original-sym(b),new-sym(b),_:Circuit} -;public defmethod name (b:SpecialRename) -> String : "Special Rename" -;public defmethod short-name (b:SpecialRename) -> String : "special-rename" -; -;public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) : -; defn rename (s:Symbol) -> Symbol : -; val y = Vector<String>() -; val os = to-string $ original-sym -; val ns = to-string $ new-sym -; defn rename (st:String) -> False : -; if st == os : -; add(y,ns) -; else if length(st) <= length(os) : -; add(y,st) -; else : -; if substring(st,0,length(os)) == os : -; add(y,ns) -; ;println(st) -; ;println(substring(st,length(os),length(st))) -; rename(substring(st,length(os),length(st))) -; else : -; add(y,substring(st,0,1)) -; rename(substring(st,1,length(st))) -; rename(to-string(s)) -; to-symbol $ string-join $ to-list(y) -; defn to-type (t:Type) -> Type : -; match(map(to-type,t)) : -; (t:BundleType) : BundleType $ -; for f in fields(t) map : Field(rename(name(f)),flip(f),type(f)) -; (t) : t -; defn to-exp (e:Expression) -> Expression : -; map{to-type,_} $ match(map(to-exp,e)) : -; (e:Ref) : Ref(rename(name(e)), type(e)) -; (e:Subfield) : Subfield(exp(e),rename(name(e)),type(e)) -; (e) : e -; defn to-stmt (s:Stmt) -> Stmt : -; map{to-type,_} $ match(map(to-exp,s)) : -; (s:DefWire) : DefWire(info(s),rename(name(s)),type(s)) -; (s:DefPoison) : DefPoison(info(s),rename(name(s)),type(s)) -; (s:DefRegister) : DefRegister(info(s),rename(name(s)),type(s),clock(s),reset(s)) -; (s:WDefInstance) : WDefInstance(info(s),rename(name(s)),module(s)) -; (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s),clock(s),size(s)) -; (s:DefNode) : DefNode(info(s),rename(name(s)),value(s)) -; (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),source(s),index(s),acc-dir(s)) -; (s) : map(to-stmt,s) -; -; defn to-port (p:Port) -> Port : Port(info(p),rename(name(p)),direction(p),type(p)) -; -; Circuit(info(c),modules*, main(c)) where : -; val modules* = -; for m in modules(c) map : -; match(m) : -; (m:InModule) : InModule(info(m),name(m), map(to-port,ports(m)), to-stmt(body(m))) -; (m:ExModule) : m -; -; -;;========== Pad Widths ================== -; -;public defstruct Pad <: Pass -;public defmethod pass (b:Pad) -> (Circuit -> Circuit) : pad-widths -;public defmethod name (b:Pad) -> String : "Pad Widths" -; -;;------------ Helper Functions -------------- -;defn int-width! (t:Type) -> Long : -; match(width!(t)) : -; (w:IntWidth) : width(w) -; (w) : error("Non-int width") -; -;defn set-width (desired:Long,t:Type) -> Type : -; match(t) : -; (t:UIntType) : UIntType(IntWidth(desired)) -; (t:SIntType) : SIntType(IntWidth(desired)) -; (t) : error("Non-ground type") -; -;defn lmax (l1:Long, l2:Long) -> Long : -; if l1 > l2 : l1 -; else : l2 -; -;;------------- Pad Widths ------------------- -; -;defn pad-widths-e (desired:Long,e:Expression) -> Expression : -; defn trim (desired:Long, e:Expression) : -; ;; println-all(["TRIM " desired " e " e]) -; DoPrim(BITS-SELECT-OP,list(e),list(to-int(to-string(desired)) - 1, 0),set-width(desired,type(e))) -; defn pad (desired:Long, e:Expression) : -; ;; println-all(["PAD " desired " e " e]) -; DoPrim(PAD-OP,list(e),list(to-int $ to-string(desired)),set-width(desired,type(e))) -; defn trim-pad (desired:Long, e:Expression) : -; val i = int-width!(type(e)) -; if i > desired : trim(desired, e) -; else if i == desired : e -; else : pad(desired, e) -; defn self-pad-widths-e (e:Expression) -> Expression : -; pad-widths-e(int-width!(type(e)), e) -; ;; println-all(["PAD-E " desired " " e]) -; match(e) : -; (e:DoPrim) : -; val new-desired = reduce(lmax, to-long(0), map(int-width!{type(_)}, args(e))) -; ;; println-all([" NEW DESIRED " new-desired]) -; val e* = -; if contains?([CONCAT-OP, DYN-SHIFT-RIGHT-OP, DYN-SHIFT-LEFT-OP], op(e)) : -; DoPrim(op(e), map(self-pad-widths-e, args(e)), consts(e), type(e)) -; else if contains?([MUX-OP], op(e)) : -; DoPrim(op(e), list(pad-widths-e(to-long(1), args(e)[0]), pad-widths-e(new-desired, args(e)[1]), pad-widths-e(new-desired, args(e)[2])), consts(e), type(e)) -; else : -; map(pad-widths-e{new-desired,_},e) -; trim-pad(desired, e*) -; (e:Ref|Subfield|Index) : -; trim-pad(desired, e) -; (e:UIntValue) : -; val i = int-width!(type(e)) -; if i > desired : trim(desired, e) -; else : UIntValue(value(e),IntWidth(desired)) -; (e:SIntValue) : -; val i = int-width!(type(e)) -; if i > desired : trim(desired, e) -; else : SIntValue(value(e),IntWidth(desired)) -; (e) : error(to-string $ e) -; -;defn pad-widths-s (s:Stmt) -> Stmt : -; ;; println-all(["PAD-S " s]) -; match(map(pad-widths-s,s)) : -; (s:Connect) : -; val i = int-width!(type(loc(s))) -; val loc* = pad-widths-e(i,loc(s)) -; val exp* = pad-widths-e(i,exp(s)) -; Connect(info(s),loc*,exp*) -; (s:PrintfStmt) : -; val args* = for x in args(s) map : -; val i = int-width!(type(x)) -; pad-widths-e(i,x) -; PrintfStmt(info(s),string(s),args*) -; (s:DefNode) : -; val i = int-width!(type(value(s))) -; val exp* = pad-widths-e(i,value(s)) -; DefNode(info(s),name(s),exp*) -; (s:Conditionally) : -; val i = int-width!(type(pred(s))) -; val pred* = pad-widths-e(i,pred(s)) -; Conditionally(info(s),pred*,conseq(s),alt(s)) -; (s) : s -; -;public defn pad-widths (c:Circuit) -> Circuit : -; Circuit{info(c),_,main(c)} $ -; for m in modules(c) map : -; match(m) : -; (m:ExModule) : m -; (m:InModule) : InModule(info(m),name(m),ports(m),pad-widths-s(body(m))) -; -; - -;============== Common Subexpression Elimination =========== -;NOT DONE - -;public defstruct CSE <: Pass -;public defmethod pass (b:CSE) -> (Circuit -> Circuit) : const-prop -;public defmethod name (b:CSE) -> String : "Common Subexpression Elimination" -;public defmethod short-name (b:ConstProp) -> String : "cse" -; -;defn cse-m (m:InModule) -> InModule : -; val cse-hash = HashTable<Expression,Int>(exp-hash) -; val placed? = HashTable<Expression,True|False>(exp-hash) -; -; defn cse-s (s:Stmt) -> Stmt : -; val stmts = Vector<Stmt>() -; defn cse-e (e:Expression) -> Expression -; match(s) : -; -; defn build-e (e:Expression) -> Expression : -; match(e) : -; (e:DoPrim) : -; if key?(cse-hash,e) : -; cse-hash[e] = cse-hash[e] + 1 -; else : -; cse-hash[e] = 1 -; placed?[e] = false -; (e) : e -; defn build-s (s:Stmt) -> Stmt : map{build-s,_} $ map(build-e,s) -; -; build-s(body(m)) -; InModule(info(m),name(m),ports(m),cse-s(body(m))) -; -;public defn cse (c:Circuit) -> Circuit : -; Circuit{info(c),_,main(c)} $ -; for m in modules(c) map : -; match(m) : -; (m:ExModule) : m -; (m:InModule) : cse-m(m) - - - -;;============= Constant Propagation ================ -; -public defstruct ConstProp <: Pass -public defmethod pass (b:ConstProp) -> (Circuit -> Circuit) : const-prop -public defmethod name (b:ConstProp) -> String : "Constant Propagation" -public defmethod short-name (b:ConstProp) -> String : "const-prop" - -defn const-prop-e (e:Expression) -> Expression : - match(map(const-prop-e,e)) : - (e:DoPrim) : - switch {op(e) == _} : - DYN-SHIFT-RIGHT-OP : - match(args(e)[1]) : - (x:UIntValue|SIntValue) : - DoPrim(SHIFT-RIGHT-OP,list(args(e)[0]),list(to-int(value(x))),UnknownType()) - (x) : e - DYN-SHIFT-LEFT-OP : - match(args(e)[1]) : - (x:UIntValue|SIntValue) : - DoPrim(SHIFT-LEFT-OP,list(args(e)[0]),list(to-int(value(x))),UnknownType()) - (x) : e - SHIFT-RIGHT-OP : - match(args(e)[0]) : - (x:UIntValue) : - val b = rsh(value(x),consts(e)[0]) - UIntValue(b,width(type(e) as UIntType)) - (x:SIntValue) : - val b = rsh(value(x),consts(e)[0]) - SIntValue(b,width(type(e) as SIntType)) - (x) : e - BITS-SELECT-OP : - match(args(e)[0]) : - (x:UIntValue) : - val b = bits(value(x),consts(e)[0] + 1,consts(e)[1]) - UIntValue(b,width(type(e) as UIntType)) - (x) : e - BIT-SELECT-OP : - match(args(e)[0]) : - (x:UIntValue) : - val i = bit(value(x),consts(e)[0]) - UIntValue(i,width(type(e) as UIntType)) - (x) : e - else : e - (e) : e - -defn const-prop-s (s:Stmt) -> Stmt : - map{const-prop-e,_} $ map(const-prop-s,s) - -public defn const-prop (c:Circuit) -> Circuit : - Circuit{info(c),_,main(c)} $ - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : InModule(info(m),name(m),ports(m),const-prop-s(body(m))) - -;============= Condense Mems ================ -; -;public defstruct CondenseMems <: Pass -;public defmethod pass (b:CondenseMems) -> (Circuit -> Circuit) : condense-mems -;public defmethod name (b:CondenseMems) -> String : "Condense Mems" -;public defmethod short-name (b:CondenseMems) -> String : "condense-mems" -; -;;------------- Utils --------------- -; -;defn concat (es:List<Expression>) -> Expression : -; if length(es) == 1 : head(es) -; else : CAT(head(es),cat(tail(es))) -;defn cast (t:Type,e:Expression) -> Expression : -; match(t) : -; (t:UIntType) : e -; (t:SIntType) : DoPrim(AS-SINT-OP,list(e),list(),SIntType(get-width(t))) -;defn get-width-index (e:Expression) -> Long : -; match(e) : -; (e:WRef) : 0 -; (e:WSubField) : -; var w = get-width-index(exp(e)) -; var found? = false -; for f in fields(type(exp(e)) as BundleType) do : -; if name(f) == name(e) : -; found? = true -; if found? == false : -; w = w + get-width(type(f)) -; w -; (e:WSubIndex) : -; get-width-index(exp(e)) + get-width(type(e)) * value(e) -;defn root-ref (e:Expression) -> Expression : -; match(e) : -; (e:WRef) : e -; (e:WSubField|WSubIndex) : root-ref(e) -;defn flatten (e:Expression) -> Expression : -; match(e) : -; (e:WRef) : e -; (e:WSubField|WSubIndex) : -; val base = get-width-index(e) -; val off = get-width(type(e)) -; DoPrim(BITS-SELECT-OP,list(root-ref(e)),list(base,off),UIntType(IntWidth(off))) -; -;;------------- Pass ------------------ - -;defn condense-mems (m:InModule) -> InModule : -; val mem-assigns = HashTable<Expression,Expression>(exp-hash) -; defn collect-mems (s:Stmt) -> Stmt : -; match(s) : -; (s:Connect) : -; defn condense-mems-e (e:Expression) -> Expression : -; val e* = match(e) : -; (e:WRef|WSubField|WSubIndex) : -; if (kind(e) typeof MemKind) : cast(type(e),flatten(e)) -; else : e -; (e:UIntValue|SIntValue) : e -; (e:DoPrim) : map(condense-mems-e,e) -; defn condense-mems (s:Stmt) -> Stmt : -; match(s) : -; (s:DefMemory) : -; val stmts = Vector<Stmt>() -; val s* = map(flatten,s) -; add(stmts,s*) -; val mem = WRef(name(s),type(s),MemKind(),UNKNOWN-GENDER) -; for f in fields(type(s) as BundleType) do : -; val data-name = -; if contains?(writers(s),name(f)) : `data -; else if contains(readwriters(s),name(f)) : `wdata -; else : false -; match(data-name) : -; (f:False) : false -; (n:Symbol) : -; val port = WSubField(mem,name(f),type(f),UNKNOWN-GENDER) -; val es = create-exps(WSubField(port,n,field-type(type(port),n),UNKNOWN-GENDER)) -; val e* = concat $ for e in es map : -; map(condense-mems-e,mem-assigns[e]) -; add(stmts,Connect(info(s),WSubField(port,n,data-type(s*),UNKNOWN-GENDER),e*)) -; Begin(to-list(stmts)) -; (s:Connect) : -; if kind(loc(s)) typeof MemKind : EmptyStmt() -; else : map(condense-mems-e, s) -; (s) : map{condense-mems,_} $ map(condense-mems-e, s) -; InModule(info(m),name(m),ports(m),condense-mems(body(m))) -; -;defn condense-mems (c:Circuit) -> Circuit : -; Circuit{info(c),_,main(c)} $ -; for m in modules(c) map : -; match(m) : -; (m:ExModule) : m -; (m:InModule) : condense-mems(m) - -;============= Lower Types ================ -; -public defstruct LowerTypes <: Pass -public defmethod pass (b:LowerTypes) -> (Circuit -> Circuit) : lower-types -public defmethod name (b:LowerTypes) -> String : "Lower Types" -public defmethod short-name (b:LowerTypes) -> String : "lower-types" - -;------------- Utils --------------- -defn is-ground? (t:Type) -> True|False : - match(t) : - (t:UIntType|SIntType) : true - (t) : false -defn data? (ex:Expression) -> True|False : - match(kind(ex)) : - (k:MemKind) : match(ex) : - (ex:WRef|WSubIndex) : false - (ex:WSubField) : - var yes? = switch { _ == name(ex) } : - `wdata : true - `rdata : true - `data : true - `mask : true - else : false - yes? and match(exp(ex)) : - (e:WSubField) : - contains?(ports(kind(e) as MemKind),name(e)) and (exp(e) typeof WRef) - (e) : false - (ex) : false - (k) : false - -defn expand-name (e:Expression) -> List<Symbol> : - val names = Vector<Symbol>() - defn expand-name-e (e:Expression) -> Expression : - match(map(expand-name-e,e)) : - (e:WRef) : add(names,name(e)) - (e:WSubField) : add(names,name(e)) - (e:WSubIndex) : add(names,to-symbol(value(e))) - e - expand-name-e(e) - to-list(names) - - -defn lower-other-mem (e:Expression, dt:Type) -> List<Expression> : - val names = expand-name(e) - if length(names) < 3 : error("Shouldn't be here") - for x in fast-create-exps(names[0],dt) map : - var base = lowered-name(x) - for (x in names,i in 0 to false) do : - if i >= 3 : base = symbol-join([base `_ x]) - val m = WRef(base, UnknownType(), kind(e), UNKNOWN-GENDER) - val p = WSubField(m,to-symbol(names[1]),UnknownType(),UNKNOWN-GENDER) - WSubField(p,to-symbol(names[2]),UnknownType(),UNKNOWN-GENDER) - -defn lower-data-mem (e:Expression) -> Expression : - val names = expand-name(e) - if length(names) < 3 : error("Shouldn't be here") - else : - var base = names[0] - for (x in names,i in 0 to false) do : - if i >= 3 : base = symbol-join([base `_ x]) - val m = WRef(base, UnknownType(), kind(e), UNKNOWN-GENDER) - val p = WSubField(m,to-symbol(names[1]),UnknownType(),UNKNOWN-GENDER) - WSubField(p,to-symbol(names[2]),UnknownType(),UNKNOWN-GENDER) - -defn merge (a:Symbol,b:Symbol,x:Symbol) -> Symbol : symbol-join([a x b]) -defn lowered-name (e:Expression) -> Symbol : - match(e) : - (e:WRef) : name(e) - (e:WSubField) : merge(lowered-name(exp(e)),name(e),`_) - (e:WSubIndex) : merge(lowered-name(exp(e)),to-symbol(value(e)),`_) -defn root-ref (e:Expression) -> WRef : - match(e) : - (e:WRef) : e - (e:WSubField|WSubIndex|WSubAccess) : root-ref(exp(e)) - (e:WIndexer) : root-ref(exps(e)[0]) - -;------------- Pass ------------------ - -defn lower-types (m:Module) -> Module : - val mdt = HashTable<Symbol,Type>(symbol-hash) - defn lower-types (s:Stmt) -> Stmt : - defn lower-mem (e:Expression) -> List<Expression> : - val names = expand-name(e) - if contains?([`data `mask `rdata `wdata `wmask],names[2]) : - list(lower-data-mem(e)) - else : - lower-other-mem(e,mdt[name(root-ref(e))]) - defn lower-types-e (e:Expression) -> Expression : - match(e) : - (e:WRef|UIntValue|SIntValue) : e - (e:WSubField) : - match(kind(e)) : - (k:InstanceKind) : - val names = expand-name(e) - var n = names[1] - for (x in names,i in 0 to false) do : - if i > 1 : n = symbol-join([n `_ x]) - WSubField(root-ref(e),n,type(e),gender(e)) - (k:MemKind) : - if not gender(e) == FEMALE : - lower-mem(e)[0] - else : e - (k) : WRef(lowered-name(e),type(e),kind(e),gender(e)) - (e:WSubIndex) : WRef(lowered-name(e),type(e),kind(e),gender(e)) - (e:DoPrim) : map(lower-types-e,e) - match(map(lower-types-e,s)) : - (s:DefWire|DefPoison) : - if is-ground?(type(s)) : s - else : - val es = fast-create-exps(name(s),type(s)) - Begin $ for (e in es, i in 0 to false) map : - defn replace-type (t:Type) -> Type : type(e) - defn replace-name (n:Symbol) -> Symbol : lowered-name(e) - map{replace-name,_} $ map(replace-type,s) - (s:DefRegister) : - if is-ground?(type(s)) : s - else : - val es = fast-create-exps(name(s),type(s)) - Begin $ for (e in es, i in 0 to false) map : - val init = lower-types-e(fast-create-exps(init(s))[i]) - DefRegister(info(s),lowered-name(e),type(e),clock(s),reset(s),init) - (s:WDefInstance) : - val fields* = for f in fields(type(s) as BundleType) map-append : - val es = fast-create-exps(WRef(name(f),type(f),ExpKind(),flip(f) * MALE)) - for e in es map : - switch { _ == gender(e) } : - MALE : Field(lowered-name(e),DEFAULT,type(f)) - FEMALE : Field(lowered-name(e),REVERSE,type(f)) - WDefInstance(info(s),name(s),module(s),BundleType(fields*)) - (s:DefMemory) : - mdt[name(s)] = data-type(s) - if is-ground?(data-type(s)) : s - else : - val es = fast-create-exps(name(s),data-type(s)) - Begin $ for e in es map : - DefMemory(info(s),lowered-name(e),type(e),depth(s),write-latency(s),read-latency(s),readers(s),writers(s),readwriters(s)) - (s:Connect) : - if kind(loc(s)) typeof MemKind : - val es = lower-mem(loc(s)) - Begin $ for e in es map : - Connect(info(s),e,exp(s)) - else : s - (s) : map(lower-types,s) - - val ports* = - for p in ports(m) map-append : - val es = fast-create-exps(WRef(name(p),type(p),PortKind(),to-gender(direction(p)))) - for e in es map : - Port(info(p),lowered-name(e),to-dir(gender(e)),type(e)) - match(m) : - (m:ExModule) : ExModule(info(m),name(m),ports*) - (m:InModule) : InModule(info(m),name(m),ports*,lower-types(body(m))) - -defn lower-types (c:Circuit) -> Circuit : - Circuit{info(c),_,main(c)} $ - for m in modules(c) map : lower-types(m) - -;============ VERILOG ============== - -public defstruct Verilog <: Pass : - with-output: (() -> False) -> False -public defmethod pass (b:Verilog) -> (Circuit -> Circuit) : emit-verilog{with-output(b),_} -public defmethod name (b:Verilog) -> String : "To Verilog" -public defmethod short-name (b:Verilog) -> String : "To Verilog" - -;============ Utilz ============= -defstruct VIndent -defstruct VRandom -val tab = VIndent() -val ran = VRandom() -defn wref (n:Symbol,t:Type) : WRef(n,t,ExpKind(),UNKNOWN-GENDER) -defn escape (s:String) -> String : - val s* = Vector<String>() - add(s*,"\"");" - var percent = false - for c in s do : - if c == '\n' : - add(s*,"\\n") - else : - if c == 'x' and percent : - add(s*,"h") - else : add(s*,to-string(c)) - percent = c == '%' - add(s*,"\"");" - string-join(s*) -defn remove-root (ex:Expression) -> Expression : - match(exp(ex as WSubField)) : - (e:WSubField) : remove-root(e) - (e:WRef) : WRef(name(ex as WSubField),type(ex),InstanceKind(),UNKNOWN-GENDER) -defn !empty? (s:Vector) -> True|False : - if length(s) == 0 : false - else : true -defn long! (t:Type) -> Long : - match(t) : - (t:UIntType|SIntType) : width(width(t) as IntWidth) - (t:BundleType) : - var w = to-long(0) - for f in fields(t) do : - w = w + long!(type(f)) - w - (t:VectorType) : to-long(size(t)) * long!(type(t)) - -defn rand-string (t:Type) -> Streamable : - val w* = ((long!(t) + to-long(31)) / to-long(32)) - ["{" w* "{" ran "}};"] -defn emit (x:?) : emit(x,0) -defn emit (x:?, top:Int) : - match(x) : - (e:Expression) : - turn-off-debug(false) - match(e) : - (e:DoPrim) : emit(op-stream(e), top + 1) - (e:WRef) : print(e) - (e:WSubField) : print(lowered-name(e)) - (e:WSubAccess) : print-all([lowered-name(exp(e)) "[" lowered-name(index(e)) "]"]) - (e:WSubIndex) : print(e) - (e:UIntValue|SIntValue) : v-print(e) - turn-on-debug(false) - (t:Type) : - match(t) : - (t:UIntType|SIntType) : - val w = long!(t) - to-long(1) - if w > to-long(0) : print-all(["[" w ":0]"]) - else : print("");" - (t:ClockType) : print("");" - (t:VectorType) : - emit(type(t), top + 1) - print-all(["[" size(t) - 1 ":0]"]) - (t) : println(t) - - (p:Direction) : - switch {_ == p} : - INPUT : print("input") - OUTPUT : print("output") - (s:Symbol) : print(s) - (i:Int) : print(i) - (i:Long) : print(i) - (s:String) : print(s) - (t:VIndent) : print(" ") - (r:VRandom) : print("$random") - (s:Streamable) : - for x in s do : - emit(x, top + 1) - if top == 0 : print("\n") - -;------------- PASS ----------------- -defn v-print (e:UIntValue|SIntValue) : - val str = to-string(value(e)) - val out = substring(str,1,length(str) - 1) - print $ string-join $ match(e) : - (e:UIntValue) : [long!(type(e)) "'" out] - (e:SIntValue) : [long!(type(e)) "'s" out] -defn op-stream (doprim:DoPrim) -> Streamable : - defn cast-if (e:Expression) -> ? : - val signed? = for x in args(doprim) any? : type(x) typeof SIntType - if not signed? : e - else : match(type(e)) : - (t:SIntType) : ["$signed(" e ")"] - (t:UIntType) : ["$signed({1'b0," e "})"] - defn cast (e:Expression) -> ? : - match(type(doprim)) : - (t:UIntType) : e - (t:SIntType) : ["$signed(" e ")"] - defn a0 () -> Expression : args(doprim)[0] - defn a1 () -> Expression : args(doprim)[1] - defn a2 () -> Expression : args(doprim)[2] - defn c0 () -> Int : consts(doprim)[0] - defn c1 () -> Int : consts(doprim)[1] - - switch {_ == op(doprim)} : - ADD-OP : [cast-if(a0()) " + " cast-if(a1())] - SUB-OP : [cast-if(a0()) " - " cast-if(a1())] - MUL-OP : [cast-if(a0()) " * " cast-if(a1()) ] - DIV-OP : [cast-if(a0()) " / " cast-if(a1()) ] - MOD-OP : [cast-if(a0()) " % " cast-if(a1()) ] - QUO-OP : [cast-if(a0()) " / " cast-if(a1()) ] - REM-OP : [cast-if(a0()) " % " cast-if(a1()) ] - ADD-WRAP-OP : [cast-if(a0()), " + " cast-if(a1())] - SUB-WRAP-OP : [cast-if(a0()), " - " cast-if(a1())] - LESS-OP : [cast-if(a0()) " < " cast-if(a1())] - LESS-EQ-OP : [cast-if(a0()) " <= " cast-if(a1())] - GREATER-OP : [cast-if(a0()) " > " cast-if(a1())] - GREATER-EQ-OP : [cast-if(a0()) " >= " cast-if(a1())] - NEQUIV-OP : [cast-if(a0()) " != " cast-if(a1())] - EQUIV-OP : [cast-if(a0()) " == " cast-if(a1())] - NEQUAL-OP : [cast-if(a0()) " != " cast-if(a1())] - EQUAL-OP : [cast-if(a0()) " == " cast-if(a1())] - MUX-OP : [a0() " ? " cast(a1()) " : " cast(a2())] - PAD-OP : - val w = long!(type(a0())) - val diff = (to-long(c0()) - w) - if w == to-long(0) : [ a0() ] - else : match(type(doprim)) : - (t:SIntType) : ["{{" diff "{" a0() "[" w - to-long(1) "]}}, " a0() " }"] - (t) : ["{{" diff "'d0 }, " a0() " }"] - AS-UINT-OP : ["$unsigned(" a0() ")"] - AS-SINT-OP : ["$signed(" a0() ")"] - DYN-SHIFT-LEFT-OP : [cast(a0()) " << " a1()] - DYN-SHIFT-RIGHT-OP : - match(type(doprim)) : - (t:SIntType) : [cast(a0()) " >>> " a1()] - (t) : [cast(a0()) " >> " a1()] - SHIFT-LEFT-OP : [cast(a0()) " << " c0()] - SHIFT-RIGHT-OP : [cast(a0()) "[" long!(type(a0())) - to-long(1) ":" c0() "]"] - NEG-OP : ["-{" cast(a0()) "}"] - CONVERT-OP : - match(type(a0())) : - (t:UIntType) : ["{1'b0," cast(a0()) "}"] - (t:SIntType) : [cast(a0())] - BIT-NOT-OP : ["~ " cast(a0())] - BIT-AND-OP : [cast(a0()) " & " cast(a1())] - BIT-OR-OP : [cast(a0()) " | " cast(a1())] - BIT-XOR-OP : [cast(a0()) " ^ " cast(a1())] - CONCAT-OP : ["{" cast(a0()) "," cast(a1()) "}"] - BIT-SELECT-OP : [cast(a0()) "[" c0() "]"] - BITS-SELECT-OP : [cast(a0()) "[" c0() ":" c1() "]"] - BIT-AND-REDUCE-OP : - val v = Vector<Streamable>() - for b in 0 to to-int(long!(type(doprim))) do : - add(v,[cast(a0()) "[" b "]"]) - join(v," & ") - BIT-OR-REDUCE-OP : - val v = Vector<Streamable>() - for b in 0 to to-int(long!(type(doprim))) do : - add(v,[cast(a0() ) "[" b "]"]) - join(v," | ") - BIT-XOR-REDUCE-OP : - val v = Vector<Streamable>() - for b in 0 to to-int(long!(type(doprim))) do : - add(v,[cast(a0() ) "[" b "]"]) - join(v," ^ ") - -defn emit-verilog (m:InModule) -> Module : - val netlist = HashTable<Expression,Expression>(exp-hash) - val simlist = Vector<Stmt>() - val namehash = get-sym-hash(m,keys(v-keywords)) - defn build-netlist (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : netlist[loc(s)] = exp(s) - (s:Conditionally) : add(simlist,s) - (s:DefNode) : - val e = WRef(name(s),get-type(s),NodeKind(),MALE) - netlist[e] = value(s) - (s) : map(build-netlist,s) - s - - val portdefs = Vector<Streamable>() - val declares = Vector<Streamable>() - val assigns = Vector<Streamable>() - val at-clock = HashTable<Expression,Vector<Streamable>>(exp-hash) - val initials = Vector<Streamable>() - val simulates = Vector<Streamable>() - defn declare (b:Symbol,n:Symbol,t:Type) : - match(t) : - (t:VectorType) : add(declares,[b " " type(t) " " n " [0:" size(t) - 1 "];"]) - (t) : add(declares,[b " " t " " n ";"]) - defn assign (e:Expression,value:Expression) : - add(assigns,["assign " e " = " value]) - defn update-and-reset (e:Expression,clk:Expression,reset?:Expression,init:Expression) : - if not key?(at-clock,clk) : - at-clock[clk] = Vector<Streamable>() - add(at-clock[clk],["if(" reset? ") begin"]) - add(at-clock[clk],[tab e " <= " init]) - add(at-clock[clk],["end else"]) - add(at-clock[clk],[tab e " <= " netlist[e]]) - add(at-clock[clk],["end"]) - defn update (e:Expression,value:Expression,clk:Expression,en:Expression) : - if not key?(at-clock,clk) : - at-clock[clk] = Vector<Streamable>() - if en == one : - add(at-clock[clk],[e " <= " value]) - else : - add(at-clock[clk],["if(" en ") begin"]) - add(at-clock[clk],[tab e " <= " value]) - add(at-clock[clk],["end"]) - defn initialize (e:Expression) : - add(initials,[e " = " rand-string(type(e))]) - defn initialize-mem (n:Symbol,i:Int,t:Type) : - add(initials,["for (initvar = 0; initvar < " i "; initvar = initvar+1)"]) - val index = WRef(`initvar,UnknownType(),ExpKind(),UNKNOWN-GENDER) - add(initials,[tab WSubAccess(wref(n,t),index,UnknownType(),FEMALE), " = " rand-string(t)]) - defn instantiate (n:Symbol,m:Symbol,es:List<Expression>) : - add(declares,[m " " n " ("]) - for (e in es,i in 1 to false) do : - val s = [tab "." remove-root(e) "(" lowered-name(e) ")"] - if i == length(es) : add(declares,[s ","]) - else : add(declares,s) - add(declares,[");"]) - for e in es do : - declare(`wire,lowered-name(e),type(e)) - val e* = WRef(lowered-name(e),type(e),kind(e),gender(e)) - if (gender(e) == FEMALE) : assign(e*,netlist[e]) - defn simulate (clk:Expression,en:Expression,s:Streamable) : - if not key?(at-clock,clk) : - at-clock[clk] = Vector<Streamable>() - add(at-clock[clk],["`ifndef SYNTHESIS"]) - add(at-clock[clk],[tab "if(" en ") begin"]) - add(at-clock[clk],[tab tab s]) - add(at-clock[clk],[tab "end"]) - add(at-clock[clk],["`endif"]) - defn stop (ret:Int) -> Streamable : - ["$fdisplay(32/'h80000002," ret ");$finish;"] - defn printf (str:String,args:List<Expression>) -> Streamable : - val str* = join(List(escape(str),args),",") - ["$fdisplay(32/'h80000002," str* ");"] - defn delay (e:Expression, n:Int, clk:Expression) -> Expression : - var e* = e - for i in 0 to n do : - val name = firrtl-gensym(`GEN,namehash) - declare(`reg,name,type(e)) - val e** = WRef(name,type(e),ExpKind(),UNKNOWN-GENDER) - update(e**,e*,clk,one) - e* = e** - e* - defn build-ports () : - for (p in ports(m),i in 0 to false) do : - var end = ",\n" - if length(ports(m)) - 1 == i : - end = "\n);\n" - switch {_ == direction(p)} : - INPUT : - add(portdefs,[direction(p) " " type(p) " " name(p) ]) - OUTPUT : - add(portdefs,[direction(p) " " type(p) " " name(p) ]) - val e* = WRef(name(p),type(p),PortKind(),FEMALE) - assign(e*,netlist[e*]) - if length(ports(m)) == 0 : print(");\n") - defn build-streams (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : s - (s:DefWire) : - declare(`wire,name(s),type(s)) - val e = wref(name(s),type(s)) - assign(e,netlist[e]) - (s:DefRegister) : - declare(`reg,name(s),type(s)) - val e = wref(name(s),type(s)) - update-and-reset(e,clock(s),reset(s),init(s)) - initialize(e) - (s:DefPoison) : - declare(`reg,name(s),type(s)) - val e = wref(name(s),type(s)) - initialize(e) - (s:DefNode) : - declare(`wire,name(s),type(value(s))) - assign(WRef(name(s),type(value(s)),NodeKind(),MALE),value(s)) - (s:Stop) : simulate(clk(s),en(s),stop(ret(s))) - (s:Print) : simulate(clk(s),en(s),printf(string(s),args(s))) - (s:WDefInstance) : - val es = fast-create-exps(WRef(name(s),type(s),InstanceKind(),MALE)) - instantiate(name(s),module(s),es) - (s:DefMemory) : - val mem = WRef(name(s),get-type(s),MemKind(append-all([readers(s) writers(s) readwriters(s)])),UNKNOWN-GENDER) - defn mem-exp (p:Symbol,f:Symbol) : - val t1 = field-type(type(mem),p) - val t2 = field-type(t1,f) - WSubField{_,f,t2,UNKNOWN-GENDER} $ - WSubField{_,p,t1,UNKNOWN-GENDER} $ - mem - - declare(`reg,name(s),VectorType(data-type(s),depth(s))) - initialize-mem(name(s),depth(s),data-type(s)) - for r in readers(s) do : - val data = mem-exp(r,`data) - val addr = mem-exp(r,`addr) - val en = mem-exp(r,`en) - val clk = mem-exp(r,`clk) - - declare(`wire,lowered-name(data),type(data)) - declare(`wire,lowered-name(addr),type(addr)) - declare(`wire,lowered-name(en),type(en)) - declare(`wire,lowered-name(clk),type(clk)) - - ; Read port - assign(addr,netlist[addr]) ;Connects value to m.r.addr - assign(en,netlist[en]) ;Connects value to m.r.en - assign(clk,netlist[clk]) ;Connects value to m.r.clk - val addr* = delay(addr,read-latency(s),clk) - val en* = delay(en,read-latency(s),clk) - val mem-port = WSubAccess(mem,addr*,UnknownType(),UNKNOWN-GENDER) - update(data,mem-port,clk,en*) ; m.r.data <= m[addr*] - - for w in writers(s) do : - val data = mem-exp(w,`data) - val addr = mem-exp(w,`addr) - val mask = mem-exp(w,`mask) - val en = mem-exp(w,`en) - val clk = mem-exp(w,`clk) - - declare(`wire,lowered-name(data),type(data)) - declare(`wire,lowered-name(addr),type(addr)) - declare(`wire,lowered-name(mask),type(mask)) - declare(`wire,lowered-name(en),type(en)) - declare(`wire,lowered-name(clk),type(clk)) - - ; Write port - assign(data,netlist[data]) - assign(addr,netlist[addr]) - assign(mask,netlist[mask]) - assign(en,netlist[en]) - assign(clk,netlist[clk]) - - val data* = delay(data,write-latency(s) - 1,clk) - val addr* = delay(addr,write-latency(s) - 1,clk) - val mask* = delay(mask,write-latency(s) - 1,clk) - val en* = delay(en,write-latency(s) - 1,clk) - val mem-port = WSubAccess(mem,addr*,UnknownType(),UNKNOWN-GENDER) - update(mem-port,data*,clk,AND(en*,mask*)) - - for rw in readwriters(s) do : - val rdata = mem-exp(rw,`rdata) - val raddr = mem-exp(rw,`raddr) - val ren = mem-exp(rw,`ren) - val wdata = mem-exp(rw,`wdata) - val waddr = mem-exp(rw,`waddr) - val wmask = mem-exp(rw,`wmask) - val wen = mem-exp(rw,`wen) - val clk = mem-exp(rw,`clk) - - declare(`wire,lowered-name(rdata),type(rdata)) - declare(`wire,lowered-name(raddr),type(raddr)) - declare(`wire,lowered-name(ren),type(ren)) - declare(`wire,lowered-name(wdata),type(wdata)) - declare(`wire,lowered-name(waddr),type(waddr)) - declare(`wire,lowered-name(wmask),type(wmask)) - declare(`wire,lowered-name(wen),type(wen)) - declare(`wire,lowered-name(clk),type(clk)) - - ; Both - assign(clk,netlist[clk]) - - ; Read - assign(raddr,netlist[raddr]) - assign(ren,netlist[ren]) - val raddr* = delay(raddr,read-latency(s),clk) - val ren* = delay(ren,read-latency(s),clk) - val rmem-port = WSubAccess(mem,raddr*,UnknownType(),UNKNOWN-GENDER) - update(rdata,rmem-port,clk,ren*) - - ; Write - assign(wdata,netlist[wdata]) - assign(waddr,netlist[waddr]) - assign(wmask,netlist[wmask]) - assign(wen,netlist[wen]) - - val wdata* = delay(wdata,write-latency(s) - 1,clk) - val waddr* = delay(waddr,write-latency(s) - 1,clk) - val wmask* = delay(wmask,write-latency(s) - 1,clk) - val wen* = delay(wen,write-latency(s) - 1,clk) - val wmem-port = WSubAccess(mem,waddr*,UnknownType(),UNKNOWN-GENDER) - update(wmem-port,wdata*,clk,AND(wen*,wmask*)) - (s:Begin) : map(build-streams,s) - s - - defn emit-streams () : - emit(["module " name(m) "("]) - if !empty?(portdefs) : - for (x in portdefs, i in 0 to false) do : - if i != length(portdefs) : emit([tab x ","]) - else : emit([tab x]) - emit([");"]) - - if !empty?(declares) : - for x in declares do : emit([tab x]) - - if !empty?(assigns) : - for x in assigns do : emit([tab x]) - - if !empty?(initials) : - emit(["`ifndef SYNTHESIS"]) - emit([" integer initvar;"]) - emit([" initial begin"]) - emit([" #0.002;"]) - for x in initials do : - emit([tab x]) - emit([" end"]) - emit(["`endif"]) - - for clk-stream in at-clock do : - if !empty?(value(clk-stream)) : - emit([tab "always @(posedge " key(clk-stream) ") begin"]) - for x in value(clk-stream) do : - emit([tab tab x]) - emit([tab "end"]) - - emit(["endmodule"]) - - build-netlist(body(m)) - build-ports() - build-streams(body(m)) - emit-streams() - m - -defn emit-verilog (with-output:(() -> False) -> False, c:Circuit) : - with-output $ fn () : - for m in modules(c) do : - match(m) : - (m:InModule) : emit-verilog(m) - (m:ExModule) : false - c - - diff --git a/src/main/stanza/primop.stanza b/src/main/stanza/primop.stanza index 6c43c494..4b8d0cbc 100644 --- a/src/main/stanza/primop.stanza +++ b/src/main/stanza/primop.stanza @@ -95,11 +95,11 @@ public defn set-primop-type (e:DoPrim) -> DoPrim : NEQUAL-OP : DoPrim(o,a,c,BoolType()) EQUIV-OP : DoPrim(o,a,c,BoolType()) NEQUIV-OP : DoPrim(o,a,c,BoolType()) - MUX-OP : DoPrim{o,a,c,_} $ - match(t2(),t3()) : - (t2:UIntType, t3:UIntType) : UIntType(MAX(w2(),w3())) - (t2:SIntType, t3:SIntType) : SIntType(MAX(w2(),w3())) - (t2, t3) : UnknownType() + ;MUX-OP : DoPrim{o,a,c,_} $ + ; match(t2(),t3()) : + ; (t2:UIntType, t3:UIntType) : UIntType(MAX(w2(),w3())) + ; (t2:SIntType, t3:SIntType) : SIntType(MAX(w2(),w3())) + ; (t2, t3) : UnknownType() PAD-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(c1()) @@ -146,9 +146,21 @@ public defn set-primop-type (e:DoPrim) -> DoPrim : (t1:SIntType) : SIntType(w1()) (t1) : UnknownType() BIT-NOT-OP : DoPrim(o,a,c,t1()) - BIT-AND-OP : DoPrim(o,a,c,UIntType(MAX(w1(),w2()))) - BIT-OR-OP : DoPrim(o,a,c,UIntType(MAX(w1(),w2()))) - BIT-XOR-OP : DoPrim(o,a,c,UIntType(MAX(w1(),w2()))) + BIT-AND-OP : DoPrim{o,a,c,_} $ + match(t1()) : + (t1:UIntType) : UIntType(MAX(w1(),w2())) + (t1:SIntType) : SIntType(MAX(w1(),w2())) + (t1) : UnknownType() + BIT-OR-OP : DoPrim{o,a,c,_} $ + match(t1()) : + (t1:UIntType) : UIntType(MAX(w1(),w2())) + (t1:SIntType) : SIntType(MAX(w1(),w2())) + (t1) : UnknownType() + BIT-XOR-OP : DoPrim{o,a,c,_} $ + match(t1()) : + (t1:UIntType) : UIntType(MAX(w1(),w2())) + (t1:SIntType) : SIntType(MAX(w1(),w2())) + (t1) : UnknownType() BIT-AND-REDUCE-OP : DoPrim(o,a,c,BoolType()) BIT-OR-REDUCE-OP : DoPrim(o,a,c,BoolType()) BIT-XOR-REDUCE-OP : DoPrim(o,a,c,BoolType()) |
