diff options
| author | azidar | 2015-07-21 11:42:06 -0700 |
|---|---|---|
| committer | azidar | 2015-07-21 11:42:06 -0700 |
| commit | d1c11b612201d1d167ece627350a35b303cf4e8b (patch) | |
| tree | fc7a634030d7b18c8db4e4a76f08271e6a9ac200 /src | |
| parent | c093b68df9c461fb44306a1845bba7dc40d3136c (diff) | |
| parent | c69a45738f40e234ffb82db0f6030f7d185dc305 (diff) | |
Merge branch 'new-low-firrtl' of github.com:ucb-bar/firrtl into new-low-firrtl
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/stanza/compilers.stanza | 24 | ||||
| -rw-r--r-- | src/main/stanza/errors.stanza | 97 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 8 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 7 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 14 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 334 | ||||
| -rw-r--r-- | src/main/stanza/verilog.stanza | 20 |
7 files changed, 362 insertions, 142 deletions
diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index d65e7718..64d4a7c4 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -65,6 +65,7 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> : RemoveSpecialChars() CheckHighForm() CheckLowForm() + CheckInitialization() Verilog(file(c)) ] @@ -76,16 +77,25 @@ public defn run-passes (c:Circuit,ls:List<Pass>) : println("Compiling!") if PRINT-CIRCUITS : println("Original Circuit") if PRINT-CIRCUITS : print(c) - val start-time = current-time-us() + ;val start-time = current-time-us() + val start-time = to-int(to-string(current-time-us() / to-long(1000))) var t = start-time - val tables = Vector<HashTable<Symbol,HashTable<Symbol,Symbol>>>() + val time-table = Vector<[String,Int]>() for p in ls do : + println-all(STANDARD-ERROR,["Starting " name(p)]) if PRINT-CIRCUITS : println(name(p)) c* = pass(p)(c*) if PRINT-CIRCUITS : print(c*) - val current-time = current-time-us() - println-all(["Finished " name(p) "\n"]) - println-all(["Time since start: " current-time - start-time]) - println-all(["Time for this pass: " current-time - t]) + val current-time = to-int(to-string(current-time-us() / to-long(1000))) + println-all(STANDARD-ERROR,["Finished " name(p)]) + println-all(STANDARD-ERROR,["Milliseconds since start: " current-time - start-time]) + println-all(STANDARD-ERROR,["Milliseconds for this pass: " current-time - t]) + println-all(STANDARD-ERROR,["\n"]) + add(time-table,[name(p), current-time - t]) t = current-time - println("Done!") + + println(STANDARD-ERROR,"===== Time Breakdown =====") + for x in time-table do : + println-all(STANDARD-ERROR,[x[0] " --- " to-float(x[1] as Int) / to-float(t - start-time) "%"]) + println(STANDARD-ERROR,"==========================") + println(STANDARD-ERROR,"Done!") diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index e36ec06d..d8969dd3 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -283,20 +283,26 @@ public defn check-high-form (c:Circuit) -> Circuit : map(check-high-form-t{info,_:Type},e) e - defn check-high-form-s (s:Stmt,names:HashTable<Symbol,True>) -> Stmt : + defn check-high-form-s (s:Stmt,names:HashTable<Symbol,True>,mnames:HashTable<Symbol,True>) -> Stmt : defn check-name (info:FileInfo,name:Symbol) -> False : if key?(names,name) : add(errors,NotUnique(info,name)) map(check-high-form-t{info(s),_:Type},s) - map{check-high-form-s{_,names},_} $ { - match(map(check-high-form-e{info(s),_,names},s)) : - (s:DefWire|DefRegister) : + map{check-high-form-s{_,names,mnames},_} $ { + match(s) : ;map(check-high-form-e{info(s),_,names},s)) : + (s:DefWire) : check-name(info(s),name(s)) names[name(s)] = true + (s:DefRegister) : + check-name(info(s),name(s)) + names[name(s)] = true + check-high-form-e(info(s),reset(s),names) + check-high-form-e(info(s),clock(s),names) (s:DefMemory) : check-name(info(s),name(s)) names[name(s)] = true if has-flip?(type(s)) : add(errors, MemWithFlip(info(s), name(s))) + check-high-form-e(info(s),clock(s),names) (s:DefInstance) : if not contains?(name(module(s) as Ref),map(name,modules(c))) : add(errors, ModuleNotDefined(info(s),name(module(s) as Ref))) @@ -304,21 +310,34 @@ public defn check-high-form (c:Circuit) -> Circuit : names[name(s)] = true (s:DefNode) : check-name(info(s),name(s)) + check-high-form-e(info(s),value(s),names) names[name(s)] = true (s:DefAccessor) : check-name(info(s),name(s)) + check-high-form-e(info(s),index(s),names) + check-high-form-e(info(s),source(s),names) names[name(s)] = true (s:Connect) : check-valid-loc(info(s),loc(s)) + check-high-form-e(info(s),loc(s),names) + check-high-form-e(info(s),exp(s),names) (s:BulkConnect) : check-valid-loc(info(s),loc(s)) + check-high-form-e(info(s),loc(s),names) + check-high-form-e(info(s),exp(s),names) + (s:OnReset) : + check-high-form-e(info(s),loc(s),names) + check-high-form-e(info(s),exp(s),names) + (s:Conditionally) : + check-high-form-e(info(s),pred(s),names) (s) : false s }() defn check-high-form-m (m:Module) -> False : val names = HashTable<Symbol,True>(symbol-hash) + val mnames = HashTable<Symbol,True>(symbol-hash) for m in modules(c) do : - names[name(m)] = true + mnames[name(m)] = true for p in ports(m) do : names[name(p)] = true ;if name(p) == `reset : @@ -335,7 +354,7 @@ public defn check-high-form (c:Circuit) -> Circuit : match(m) : (m:ExModule) : false - (m:InModule) : check-high-form-s(body(m),names) + (m:InModule) : check-high-form-s(body(m),names,mnames) ;match(any-prefixes?(names,to-string(sym),to-string(sym))) : ;(s:False) : false ;(s:String) : add(errors,IsPrefix(info,to-symbol(s))) @@ -827,3 +846,69 @@ public defn check-low-form (c:Circuit) -> Circuit : 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 ": 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) : + val init? = HashTable<Symbol,FileInfo|True>(symbol-hash) + defn get-name (e:Expression) -> Symbol : + match(e) : + (e:Ref) : name(e) + (e:Subfield) : symbol-join([get-name(exp(e)) `. name(e)]) + (e) : error("Shouldn't be here") + + defn check-init-s (s:Stmt) : + do(check-init-s,s) + match(s) : + (s:DefWire|DefRegister) : init?[name(s)] = info(s) + (s:DefAccessor) : + if acc-dir(s) == WRITE : init?[name(s)] = info(s) + (s:DefInstance) : + for f in fields(type(module(s)) as BundleType) do : + if flip(f) == REVERSE : + init?[symbol-join([name(s) `. name(f)])] = info(s) + (s:Connect) : + init?[get-name(loc(s))] = true + (s) : false + + for p in ports(m) do : + if direction(p) == OUTPUT : + init?[name(p)] = info(p) + + check-init-s(body(m)) + + for x in init? do : + match(value(x)) : + (v:FileInfo) : add(errors, RefNotInitialized(v,key(x))) + (v) : false + + for m in modules(c) do : + match(m) : + (m:InModule) : check-init-m(m) + (m) : false + + 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 e57c5f74..15666a9a 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -7,6 +7,7 @@ public defmethod info! (x:?) : FileInfo() public val vector-expand-delin = `$ public val bundle-expand-delin = `$ +public val module-expand-delin = `$ public val scope-delin = `% public val temp-delin = `! public val inline-delin = `^ @@ -29,6 +30,8 @@ public definterface Width public defstruct UnknownWidth <: Width public defstruct IntWidth <: Width : width: Int +public defstruct LongWidth <: Width : + width : Long public definterface PrimOp public val ADD-OP = new PrimOp @@ -174,15 +177,16 @@ public defstruct Port : public definterface Module public defmulti name (m:Module) -> Symbol public defmulti ports (m:Module) -> List<Port> +public defmulti info (m:Module) -> FileInfo public defstruct InModule <: Module : - info: FileInfo + info: FileInfo with: (as-method => true) name: Symbol with: (as-method => true) ports: List<Port> with: (as-method => true) body: Stmt public defstruct ExModule <: Module : - info: FileInfo + info: FileInfo with: (as-method => true) name: Symbol with: (as-method => true) ports: List<Port> with: (as-method => true) diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 96c50c3c..7e07eb8b 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -167,7 +167,7 @@ defsyntax firrtl : if not empty?(rest) : FPE(rest, "Expected a statement here.") InModule(first-info(form),name, ps, Begin(cs)) - module = (exmodule ?name:#id! #:! (?ps:#port ... ?rest ...)) : + module = (extmodule ?name:#id! #:! (?ps:#port ... ?rest ...)) : if not empty?(rest) : FPE(rest, "Expected a port here.") ExModule(first-info(form),name, ps) @@ -210,7 +210,10 @@ defsyntax firrtl : accdir = (rdwr) : RDWR defrule width : - width = (?x:#int) : IntWidth(x) + width = (?x:#intorlong) : + match(x) : + (x:Int) : IntWidth(x) + (x:Long) : LongWidth(x) width = (?) : UnknownWidth() ;Main Statement Productions diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index bd8a0fd6..0118c73b 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -117,6 +117,7 @@ defmethod print (o:OutputStream, w:Width) : match(w) : (w:UnknownWidth) : "?" (w:IntWidth) : width(w) + (w:LongWidth) : width(w) defmethod print (o:OutputStream, op:PrimOp) : print{o, _} $ @@ -251,7 +252,7 @@ defmethod print (o:OutputStream, m:InModule) : print(io,body(m)) defmethod print (o:OutputStream, m:ExModule) : - print-all(o, ["exmodule " name(m) " :"]) + print-all(o, ["extmodule " name(m) " :"]) print-debug(o,m) print(o,"\n") val io = IndentedStream(o, 3) @@ -451,13 +452,12 @@ public defn merge!<?K,?V> (a:HashTable<?K,?V>, b:HashTable<K,V>) : for e in b do : a[key(e)] = value(e) -public defn pow (x:Int,y:Int) -> Int : +public defn pow (x:Long,y:Long) -> Long : var x* = to-long(1) - var y* = to-long(y) + var y* = y while y* != to-long(0) : - x* = x* * to-long(x) - y* = y* - to-long(1) - if x* > to-long(2147483647) : error("Value too big for Int") - else : to-int $ to-string(x*) + x* = times(x*,x) + y* = minus(y*,to-long(1)) + x* diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index c03e2194..cfcbb36b 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -295,19 +295,19 @@ public defmethod short-name (b:RemoveSpecialChars) -> String : "rem-spec-chars" defn get-new-string (n:Char) -> String : switch {n == _} : ;'_' : "__" - '~' : "_A" - '!' : "_B" - '@' : "_C" - '#' : "_D" - ;'$' : "_E" - '%' : "_F" - '^' : "_G" - '*' : "_H" - '-' : "_I" - '+' : "_J" - '=' : "_K" - '?' : "_L" - '/' : "_M" + '~' : "$A" + '!' : "$B" + '@' : "$C" + '#' : "$D" + ;'$' : "$E" + '%' : "$F" + '^' : "$G" + '*' : "$H" + '-' : "$I" + '+' : "$J" + '=' : "$K" + '?' : "$L" + '/' : "$M" else : to-string(n) ;------------ Pass ------------------ @@ -319,25 +319,25 @@ defn remove-special-chars (c:Circuit) : add(n*,get-new-string(c)) symbol-join(n*) defn rename-t (t:Type) -> Type : - match(map(rename-t,t)) : + match(t) : (t:BundleType) : BundleType $ for f in fields(t) map : - Field(rename(name(f)),flip(f),type(f)) - (e) : e + Field(rename(name(f)),flip(f),rename-t(type(f))) + (e) : map(rename-t,e) defn rename-e (e:Expression) -> Expression : - map{rename-t,_} $ match(map(rename-e,e)) : - (e:Ref) : Ref(rename(name(e)),type(e)) - (e:Subfield) : Subfield(exp(e),rename(name(e)),type(e)) - (e) : e + match(e) : + (e:Ref) : Ref(rename(name(e)),rename-t(type(e))) + (e:Subfield) : Subfield(exp(e),rename(name(e)),rename-t(type(e))) + (e) : map(rename-t,map(rename-e,e)) defn rename-s (s:Stmt) -> Stmt : - map{rename-t,_} $ match(map(rename-e,s)) : - (s:DefWire) : DefWire(info(s),rename(name(s)),type(s)) - (s:DefRegister) : DefRegister(info(s),rename(name(s)),type(s),clock(s),reset(s)) + match(map(rename-e,s)) : + (s:DefWire) : DefWire(info(s),rename(name(s)),rename-t(type(s))) + (s:DefRegister) : DefRegister(info(s),rename(name(s)),rename-t(type(s)),clock(s),reset(s)) (s:DefInstance) : DefInstance(info(s),rename(name(s)),module(s)) - (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s),clock(s)) + (s:DefMemory) : DefMemory(info(s),rename(name(s)),rename-t(type(s)) as VectorType,seq?(s),clock(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(rename-s,s) + (s) : map(rename-t,map(rename-s,s)) Circuit(info(c),modules*, main(c)) where : val modules* = @@ -743,16 +743,14 @@ defn resolve-genders (c:Circuit) : genders[n] = g done? = false g - val entry = for kv in genders find : - key(kv) == n + val entry = get?(genders,n,false) match(entry) : - (e:KeyValue<Symbol,Gender>) : - val value = value(e) - if value == UNKNOWN-GENDER and g == UNKNOWN-GENDER : g - else if value != UNKNOWN-GENDER and g == UNKNOWN-GENDER : value - else if value == UNKNOWN-GENDER and g != UNKNOWN-GENDER : force-gender(n,g) - else : value - (e:False) : force-gender(n,g) + (g*:Gender) : + if g* == UNKNOWN-GENDER and g == UNKNOWN-GENDER : g + else if g* != UNKNOWN-GENDER and g == UNKNOWN-GENDER : g* + else if g* == UNKNOWN-GENDER and g != UNKNOWN-GENDER : force-gender(n,g) + else : g* + (g*:False) : force-gender(n,g) defn resolve-stmt (s:Stmt) -> Stmt : match(s) : @@ -1281,6 +1279,12 @@ defmethod print (o:OutputStream, sv:SymbolicValue) : (sv: SVMux) : print-all(o, ["(" pred(sv) " ? " conseq(sv) " : " alt(sv) ")"]) (sv: SVNul) : print(o, "SVNUL") +defn map (f: Expression -> Expression, sv:SymbolicValue) -> SymbolicValue : + match(sv) : + (sv:SVMux) : SVMux(f(pred(sv)),conseq(sv),alt(sv)) + (sv:SVExp) : SVExp(f(exp(sv))) + (sv:SVNul) : sv + defmulti map<?T> (f: SymbolicValue -> SymbolicValue, sv:?T&SymbolicValue) -> T defmethod map (f: SymbolicValue -> SymbolicValue, sv:SymbolicValue) -> SymbolicValue : match(sv) : @@ -1288,15 +1292,18 @@ defmethod map (f: SymbolicValue -> SymbolicValue, sv:SymbolicValue) -> SymbolicV (sv) : sv defn do (f:SymbolicValue -> ?, s:SymbolicValue) -> False : - for x in s map : - f(x) - x + defn f* (sv:SymbolicValue) -> SymbolicValue : + f(sv) + sv + map(f*,s) false + defn dor (f:SymbolicValue -> ?, e:SymbolicValue) -> False : do(f,e) - for x in e map : + defn f* (x:SymbolicValue) -> SymbolicValue : dor(f,x) x + map(f*,e) false defmethod equal? (a:SymbolicValue,b:SymbolicValue) -> True|False : @@ -1328,13 +1335,13 @@ defn deepcopy (t:HashTable<Symbol,SymbolicValue>) -> HashTable<Symbol,SymbolicVa val t0 = HashTable<Symbol,SymbolicValue>(symbol-hash) for x in t do : t0[key(x)] = value(x) -defn get-unique-keys (ts:List<HashTable<Symbol,SymbolicValue>>) -> Vector<Symbol> : - t0 where : - val t0 = Vector<Symbol>() - for v in ts do : - for t in v do : - val duplicate? = for x in t0 any? : x == key(t) - if not duplicate? : add(t0,key(t)) +defn get-unique-keys (ts:List<HashTable<Symbol,SymbolicValue>>) -> Streamable<Symbol> : + val h = HashTable<Symbol,True>(symbol-hash) + for v in ts do : + for t in v do : + h[key(t)] = true + keys(h) + defn has-nul? (sv:SymbolicValue) -> True|False : var has? = false if sv typeof SVNul : has? = true @@ -1378,16 +1385,6 @@ defn reduce-or (l:List<Expression>) -> Expression : ; kinds: Used to know the kind of reference, so we know whether we should error if it isn't initialized. We also know how we should declare the refernce. ; enables:Calculated off of assigns. -;----------------- Errors ------------------------ - -defn RefNotInitialized (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": Reference " name " is not fully initialized."] - -defn RefNotConnected (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": Reference " name " is never connected to."] - ;---------------- Helper Functions -------------- defn get-read-enable (sym:Symbol,table:HashTable<Symbol,SymbolicValue>) -> Expression : defn get-single-read-enable (sym:Symbol,sv:SymbolicValue) -> Expression : @@ -1494,28 +1491,55 @@ defn build-tables (s:Stmt, (s:Begin) : for s* in body(s) do: build-tables(s*,assign,resets,flattn,rsignals) (s:DefMemory|DefNode|EmptyStmt) : false + +defn mark-referenced (referenced?:HashTable<Symbol,True>, s:Stmt) -> False : + defn mark-referenced-e (e:Expression) -> Expression : + match(map(mark-referenced-e,e)) : + (e:Ref) : + referenced?[name(e)] = true + e + (e) : e + do(mark-referenced{referenced?,_:Stmt},s) + map(mark-referenced-e,s) + false + +defn mark-referenced (referenced?:HashTable<Symbol,True>, sv:SymbolicValue) -> False : + defn mark-referenced-e (e:Expression) -> Expression : + match(map(mark-referenced-e,e)) : + (e:Ref) : + referenced?[name(e)] = true + e + (e) : e + map(mark-referenced-e,sv) + false + +defn is-referenced? (referenced?:HashTable<Symbol,True>, s:Stmt) -> True|False : + match(s) : + (s:DefWire|DefRegister|DefAccessor|DefMemory|DefNode) : key?(referenced?,name(s)) + (s:DefInstance) : true + ;--------------- Expand Whens Pass ------------------- public defn expand-whens (c:Circuit) -> Circuit : - val errors = Vector<PassException>() defn expand-whens (ports:List<Port>, table:HashTable<Symbol,SymbolicValue>,cons:Vector<Stmt>) -> False : for p in ports do : if direction(p) == OUTPUT : val ref = WRef(name(p),type(p),PortKind(),FEMALE) - if has-nul?(table[name(p)]) : - add(errors,RefNotInitialized(info(p), name(p))) - else : add{cons,_} $ Connect(FileInfo(),ref,to-exp(table[name(p)]) as Expression) + if not has-nul?(table[name(p)]) : + add{cons,_} $ Connect(FileInfo(),ref,to-exp(table[name(p)]) as Expression) defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stmt>,cons:Vector<Stmt>) -> Stmt : match(map(expand-whens{_,table,decs,cons},s)) : - (s:DefNode|DefMemory) : add(decs,s) + (s:DefNode) : + add(decs,s) + (s:DefMemory) : + add(decs,s) (s:DefWire) : add(decs,s) val ref = WRef(name(s),type(s),NodeKind(),FEMALE) - if has-nul?(table[name(s)]) : - add(errors,RefNotInitialized(info(s), name(s))) - else : add{cons,_} $ Connect(info(s),ref,to-exp(table[name(s)]) as Expression) + if not has-nul?(table[name(s)]) : + add{cons,_} $ Connect(info(s),ref,to-exp(table[name(s)]) as Expression) (s:DefRegister) : add(decs,s) val e = to-exp(table[name(s)]) @@ -1527,8 +1551,7 @@ public defn expand-whens (c:Circuit) -> Circuit : add{cons,_} $ Connect(info(s),ref,e) else : add{cons,_} $ Conditionally(info(s),en,Connect(info(s),ref,e),EmptyStmt()) - (e:False) : - add(errors,RefNotConnected(info(s), name(s))) + (e:False) : false (s:DefAccessor) : add(decs,s) val t = type(type(source(s)) as VectorType) @@ -1543,8 +1566,7 @@ public defn expand-whens (c:Circuit) -> Circuit : add{cons,_} $ Connect(info(s),ref,e) else : add{cons,_} $ Conditionally(info(s),en,Connect(info(s),ref,e),EmptyStmt()) - (e:False) : - add(errors,RefNotConnected(info(s), n)) + (e:False) : false (s:DefInstance) : add(decs,s) for f in fields(type(module(s)) as BundleType) map : @@ -1554,9 +1576,8 @@ public defn expand-whens (c:Circuit) -> Circuit : val f = to-symbol(split(to-string(n),'.')[1]) val ref = WRef(x,type(module(s)),InstanceKind(),FEMALE) val sref = WSubfield(ref,f,bundle-field-type(type(module(s)),f),FEMALE) - if has-nul?(table[n]) : - add(errors,RefNotInitialized(info(s), n)) - else : add{cons,_} $ Connect(info(s),sref,to-exp(table[n]) as Expression) + if not has-nul?(table[n]) : + add{cons,_} $ Connect(info(s),sref,to-exp(table[n]) as Expression) (s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : false s @@ -1577,30 +1598,102 @@ public defn expand-whens (c:Circuit) -> Circuit : build-tables(body(m),assign,resets,flattn,rsignals) for x in assign do : assign[key(x)] = optimize(value(x)) for x in resets do : resets[key(x)] = optimize(value(x)) + ;val enables = get-enables(assign,kinds) ;for x in enables do : enables[key(x)] = optimize(value(x)) - println-debug("====== Assigns ======") - for x in assign do : println-debug(x) - println-debug("====== Resets ======") - for x in resets do : println-debug(x) + ;println-debug("====== Assigns ======") + ;for x in assign do : println-debug(x) + ;println-debug("====== Resets ======") + ;for x in resets do : println-debug(x) val table = merge-resets(assign,resets,rsignals) - println-debug("====== Table ======") - for x in table do : println-debug(x) + ;println-debug("====== Table ======") + ;for x in table do : println-debug(x) + val decs = Vector<Stmt>() val cons = Vector<Stmt>() expand-whens(ports(m),table,cons) expand-whens(body(m),table,decs,cons) - InModule(info(m),name(m),ports(m),Begin(append(to-list(decs),to-list(cons)))) + + val referenced? = HashTable<Symbol,True>(symbol-hash) + for x in table do : + mark-referenced(referenced?,value(x)) + for x in decs do : + mark-referenced(referenced?,x) + val decs* = Vector<Stmt>() + for x in decs do : + if is-referenced?(referenced?,x) : add(decs*,x) + + InModule(info(m),name(m),ports(m),Begin(to-list(append(decs*,to-list(cons))))) val c* = Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : expand-whens(m) - throw(PassExceptions(errors)) when not empty?(errors) + ;throw(PassExceptions(errors)) when not empty?(errors) 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:DefInstance) : DefInstance(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 @@ -1627,7 +1720,6 @@ 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 @@ -1667,6 +1759,9 @@ defmethod equal? (w1:Width,w2:Width) -> True|False : if not contains?(args(w2),w) : ret(false) ret(true) (w1:IntWidth,w2:IntWidth) : width(w1) == width(w2) + (w1:LongWidth,w2:IntWidth) : width(w1) == to-long $ width(w2) + (w1:IntWidth,w2:LongWidth) : to-long(width(w1)) == width(w2) + (w1:LongWidth,w2:LongWidth) : 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) : @@ -1703,14 +1798,21 @@ defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Width> : (w:PlusWidth) : match(arg1(w),arg2(w)) : (w1:IntWidth,w2:IntWidth) : IntWidth(width(w1) + width(w2)) + (w1:LongWidth,w2:IntWidth) : LongWidth(plus(width(w1),to-long $ width(w2))) + (w1:IntWidth,w2:LongWidth) : LongWidth(plus(to-long $ width(w1), width(w2))) + (w1:LongWidth,w2:LongWidth) : LongWidth(plus(width(w1),width(w2))) (w1,w2) : w (w:MinusWidth) : match(arg1(w),arg2(w)) : - (w1:IntWidth,w2:IntWidth) : IntWidth(width(w1) - width(w2)) + (w1:IntWidth,w2:IntWidth) : IntWidth(width(w1) + width(w2)) + (w1:LongWidth,w2:IntWidth) : LongWidth(minus(width(w1),to-long $ width(w2))) + (w1:IntWidth,w2:LongWidth) : LongWidth(minus(to-long $ width(w1), width(w2))) + (w1:LongWidth,w2:LongWidth) : LongWidth(minus(width(w1),width(w2))) (w1,w2) : w (w:ExpWidth) : match(arg1(w)) : - (w1:IntWidth) : IntWidth(pow(2,width(w1)) - 1) + (w1:IntWidth) : LongWidth(pow(to-long(2),to-long(width(w1) - 1))) + (w1:LongWidth) : LongWidth(pow(to-long(2),minus(width(w1), to-long(1)))) (w1) : w (w) : w defn substitute (w:Width,h:HashTable<Symbol,Width>) -> Width : @@ -1893,36 +1995,40 @@ defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTabl defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit : defn evaluate (w:Width) -> Width : - defn apply (a:Int|False,f:(Int) -> Int) -> Int|False : - if a typeof Int : f(a as Int) + defn apply (a:Long|False,f:(Long) -> Long) -> Long|False : + if a typeof Long : f(a as Long) else : false - defn apply (a:Int|False,b:Int|False, f: (Int,Int) -> Int) -> Int|False : - if a typeof Int and b typeof Int : f(a as Int, b as Int) + 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<Int|False>,f:(Int,Int) -> Int) -> Int|False : - if length(l) == 0 : 0 + 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:Int,b:Int) -> Int : + defn max (a:Long,b:Long) -> Long : if a >= b : a else : b - defn solve (w:Width) -> Int|False : + defn solve (w:Width) -> False|Long : match(w) : (w:VarWidth) : val w* = h[name(w)] if w* typeof VarWidth : false else : solve(w*) (w:MaxWidth) : apply-l(map(solve,args(w)),max) - (w:PlusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ + _}) - (w:MinusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ - _}) - (w:ExpWidth) : apply(2,solve(arg1(w)),{pow(_,_) - 1}) - (w:IntWidth) : width(w) + (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) : to-long(width(w)) + (w:LongWidth) : width(w) (w) : println(w) error("Shouldn't be here") val s = solve(w) - if s typeof Int : IntWidth(s as Int) - else : w + match(s) : + (s:Long) : + if s > to-long(2147483647) : LongWidth(s) + else : IntWidth(to-int $ to-string $ s) + (s) : w defn reduce-var-widths-w (w:Width) -> Width : println-all-debug(["REPLACE: " w]) @@ -2193,25 +2299,33 @@ public defstruct Pad <: Pass public defmethod pass (b:Pad) -> (Circuit -> Circuit) : pad-widths public defmethod name (b:Pad) -> String : "Pad Widths" -defn int-width! (t:Type) -> Int : +;------------ Helper Functions -------------- +defn int-width! (t:Type) -> Long : match(width!(t)) : - (w:IntWidth) : width(w) + (w:IntWidth) : to-long(width(w)) + (w:LongWidth) : width(w) (w) : error("Non-int width") -defn set-width (desired:Int,t:Type) -> Type : +defn set-width (desired:Long,t:Type) -> Type : match(t) : - (t:UIntType) : UIntType(IntWidth(desired)) - (t:SIntType) : SIntType(IntWidth(desired)) + (t:UIntType) : UIntType(LongWidth(desired)) + (t:SIntType) : SIntType(LongWidth(desired)) (t) : error("Non-ground type") -defn pad-widths-e (desired:Int,e:Expression) -> Expression : - defn trim (desired:Int, e:Expression) : +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(desired - 1, 0),set-width(desired,type(e))) - defn pad (desired:Int, e:Expression) : + 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(desired),set-width(desired,type(e))) - defn trim-pad (desired:Int, e:Expression) : + 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 @@ -2221,13 +2335,13 @@ defn pad-widths-e (desired:Int,e:Expression) -> Expression : ;; println-all(["PAD-E " desired " " e]) match(e) : (e:DoPrim) : - val new-desired = reduce(max, 0, map(int-width!{type(_)}, args(e))) + 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(1, args(e)[0]), pad-widths-e(new-desired, args(e)[1]), pad-widths-e(new-desired, args(e)[2])), consts(e), type(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*) @@ -2236,11 +2350,11 @@ defn pad-widths-e (desired:Int,e:Expression) -> Expression : (e:UIntValue) : val i = int-width!(type(e)) if i > desired : trim(desired, e) - else : UIntValue(value(e),IntWidth(desired)) + else : UIntValue(value(e),LongWidth(desired)) (e:SIntValue) : val i = int-width!(type(e)) if i > desired : trim(desired, e) - else : SIntValue(value(e),IntWidth(desired)) + else : SIntValue(value(e),LongWidth(desired)) (e) : error(to-string $ e) defn pad-widths-s (s:Stmt) -> Stmt : diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index 8d6bfecf..2921c964 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -13,12 +13,13 @@ public defmethod name (b:Verilog) -> String : "To Verilog" public defmethod short-name (b:Verilog) -> String : "To Verilog" ;============ Utilz ============= -defn width! (w:Width) -> Int : +defn width! (w:Width) -> Long : match(w) : - (w:IntWidth) : width(w) + (w:IntWidth) : to-long(width(w)) + (w:LongWidth) : width(w) (w) : error("Non-supported width type.") -defn width! (t:Type) -> Int : +defn width! (t:Type) -> Long : match(t) : (t:UIntType) : width!(width(t)) (t:SIntType) : width!(width(t)) @@ -29,6 +30,9 @@ defn emit (w:Width) -> String : (w:IntWidth) : if width(w) >= 1 : string-join $ ["[" width(w) - 1 ":0]"] ;TODO check if need to special case 0 or 1 width wires else : "" + (w:LongWidth) : + if width(w) >= to-long(1) : string-join $ ["[" width(w) - to-long(1) ":0]"] ;TODO check if need to special case 0 or 1 width wires + else : "" (w) : error("Non-supported width type.") @@ -41,7 +45,7 @@ defn get-width (t:Type) -> String : defn remove-subfield (e:Expression) -> Expression : match(map(remove-subfield,e)) : - (e:Subfield) : Ref(to-symbol $ string-join $ [emit(exp(e)) "_" name(e)],type(e)) + (e:Subfield) : Ref(to-symbol $ string-join $ [emit(exp(e)) bundle-expand-delin name(e)],type(e)) (e) : e ;============ Verilog Backend ============= @@ -90,10 +94,10 @@ defn emit (e:Expression) -> String : PAD-OP : val x = args(e)[0] val w = width!(type(x)) - val diff = consts(e)[0] - w - if w == 0 : [ emit(x) ] + val diff = (to-long(consts(e)[0]) - w) + if w == to-long(0) : [ emit(x) ] else : - if type(e) typeof SIntType : ["{{" diff "{" emit(x) "[" w - 1 "]}}, " emit(x) " }"] + if type(e) typeof SIntType : ["{{" diff "{" emit(x) "[" w - to-long(1) "]}}, " emit(x) " }"] else : ["{{" diff "'d0 }, " emit(x) " }"] AS-UINT-OP : ["$unsigned(" emit(args(e)[0]) ")"] @@ -207,7 +211,7 @@ defn emit-module (m:InModule) : inst-ports[sym] = Vector<Streamable>() insts[sym] = name(module(s) as Ref) for f in fields(type(module(s)) as BundleType) do : - val n* = to-symbol $ string-join $ [sym "_" name(f)] + val n* = to-symbol $ string-join $ [sym bundle-expand-delin name(f)] add(wires,["wire " get-width(type(f)) " " n* ";"]) add(inst-ports[sym], ["." name(f) "( " n* " )"]) if flip(f) == REVERSE : |
