aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/stanza/chirrtl.stanza323
-rw-r--r--src/main/stanza/compilers.stanza9
-rw-r--r--src/main/stanza/errors.stanza227
-rw-r--r--src/main/stanza/errorstemp.stanza994
-rw-r--r--src/main/stanza/firrtl-ir.stanza33
-rw-r--r--src/main/stanza/ir-parser.stanza20
-rw-r--r--src/main/stanza/ir-utils.stanza154
-rw-r--r--src/main/stanza/passes.stanza650
-rw-r--r--src/main/stanza/passes.stanza22662
-rw-r--r--src/main/stanza/passes.stanza32687
-rw-r--r--src/main/stanza/primop.stanza28
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())