diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/stanza.zip | bin | 3716930 -> 3729434 bytes | |||
| -rw-r--r-- | src/main/stanza/compilers.stanza | 12 | ||||
| -rw-r--r-- | src/main/stanza/custom-compiler.stanza | 38 | ||||
| -rw-r--r-- | src/main/stanza/custom-passes.stanza | 106 | ||||
| -rw-r--r-- | src/main/stanza/errors.stanza | 263 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 25 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-test-main.stanza | 10 | ||||
| -rw-r--r-- | src/main/stanza/flo.stanza | 22 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 12 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 61 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 376 | ||||
| -rw-r--r-- | src/main/stanza/primop.stanza | 1 | ||||
| -rw-r--r-- | src/main/stanza/verilog.stanza | 90 |
13 files changed, 786 insertions, 230 deletions
diff --git a/src/lib/stanza.zip b/src/lib/stanza.zip Binary files differindex aed19c22..8dc3ea0a 100644 --- a/src/lib/stanza.zip +++ b/src/lib/stanza.zip diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index 8b84cc54..0c3978ab 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -12,7 +12,7 @@ public defstruct StandardFlo <: Compiler : file: String with: (as-method => true) public defmethod passes (c:StandardFlo) -> List<Pass> : to-list $ [ - CheckHighForm() + CheckHighForm(expand-delin) ;; TempElimination() ToWorkingIR() MakeExplicitReset() @@ -31,6 +31,9 @@ public defmethod passes (c:StandardFlo) -> List<Pass> : Inline() SplitExp() ToRealIR() + SpecialRename(`#,`_) + SpecialRename(`$,`::) + CheckHighForm(`::) Flo(file(c)) ] @@ -38,8 +41,13 @@ public defstruct StandardVerilog <: Compiler : file: String with: (as-method => true) public defmethod passes (c:StandardVerilog) -> List<Pass> : to-list $ [ +<<<<<<< HEAD CheckHighForm() ;; TempElimination() +======= + CheckHighForm(expand-delin) + TempElimination() +>>>>>>> upstream/master ToWorkingIR() MakeExplicitReset() ResolveKinds() @@ -53,9 +61,9 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> : ExpandIndexedConnects() ExpandWhens() InferWidths() - ;Inline() SplitExp() ToRealIR() + SpecialRename(`#,`_) Verilog(file(c)) ] diff --git a/src/main/stanza/custom-compiler.stanza b/src/main/stanza/custom-compiler.stanza new file mode 100644 index 00000000..1ca29bdd --- /dev/null +++ b/src/main/stanza/custom-compiler.stanza @@ -0,0 +1,38 @@ +defpackage firrtl/custom-compiler : + import core + import verse + import firrtl/ir-utils + import firrtl/ir2 + import firrtl/passes + import firrtl/errors + import firrtl/verilog + import firrtl/custom-passes + +public defstruct InstrumentedVerilog <: Compiler : + file: String with: (as-method => true) + args: List<String> +public defmethod passes (c:InstrumentedVerilog) -> List<Pass> : + to-list $ [ + WhenCoverage(args(c)[0],args(c)[1]) + CheckHighForm(expand-delin) + TempElimination() + ToWorkingIR() + MakeExplicitReset() + ResolveKinds() + CheckKinds() + InferTypes() + CheckTypes() + ResolveGenders() + CheckGenders() + ExpandAccessors() + LowerToGround() + ExpandIndexedConnects() + ExpandWhens() + InferWidths() + SplitExp() + ToRealIR() + SpecialRename(`#,`_) + Verilog(file(c)) + ] + + diff --git a/src/main/stanza/custom-passes.stanza b/src/main/stanza/custom-passes.stanza new file mode 100644 index 00000000..e4c3d9d3 --- /dev/null +++ b/src/main/stanza/custom-passes.stanza @@ -0,0 +1,106 @@ +defpackage firrtl/custom-passes : + import core + import verse + import firrtl/ir-utils + import firrtl/ir2 + +public defstruct WhenCoverage <: Pass : + port-name : String + reg-name : String +public defmethod pass (b:WhenCoverage) -> (Circuit -> Circuit) : when-coverage{port-name(b),reg-name(b),_} +public defmethod name (b:WhenCoverage) -> String : "When Coverage" +public defmethod short-name (b:WhenCoverage) -> String : "when-coverage" + +;============ Utilz ============= +defn concat-all (ls:List<Expression>) -> Expression : + if length(ls) == 0 : error("Shouldn't be here") + if length(ls) == 1 : head(ls) + else : DoPrim( CONCAT-OP, + list(head(ls),concat-all(tail(ls))), + list(), + UIntType(UnknownWidth())) + +;============ When Coverage Pass ============= +;port width = 1 bit per scope + portwidths of all instances + +defn needs-instrumentation (m:Module,ms:List<Module>,instrument?:HashTable<Symbol,True|False>) -> False : + defn needs-instrumentation-s (s:Stmt) -> False : + match(s) : + (s:Conditionally) :instrument?[name(m)] = true + (s:DefInstance) : + val module-of-inst = for x in ms find : name(x) == name(module(s) as Ref) + if module-of-inst != false : + needs-instrumentation(module-of-inst as Module,ms,instrument?) + instrument?[name(m)] = instrument?[name(module-of-inst as Module)] + (s) : false + do(needs-instrumentation-s,s) + + match(m) : + (m:InModule) : do(needs-instrumentation-s,body(m)) + (m:ExModule) : false + +defn when-coverage (port-name:Symbol, reg-name:Symbol, instrument?:HashTable<Symbol,True|False>, m:InModule) -> InModule : + val when-bits = Vector<Ref>() + val inst-bits = Vector<Ref>() + val sym = HashTable<Symbol,Int>(symbol-hash) + val w1 = IntWidth(1) + val t1 = UIntType(w1) + val u1 = UIntValue(1,w1) + defn when-coverage (s:Stmt) -> Stmt : + match(s) : + (s:Conditionally) : + val ref = Ref(firrtl-gensym(reg-name,sym),t1) + add(when-bits,ref) + val conseq* = Begin(list(Connect(FileInfo()ref,u1),conseq(s))) + map(when-coverage,Conditionally(info(s),pred(s),conseq*,alt(s))) + (s:DefInstance) : + if instrument?[name(module(s) as Ref)] : + val ref = Ref(firrtl-gensym(port-name,sym),UIntType(UnknownWidth())) + add(inst-bits,ref) + val sfld = Subfield(Ref(name(s),UnknownType()),port-name,UnknownType()) + Begin(list(s,Connect(FileInfo(),ref,sfld))) + else : s + (s) : map(when-coverage,s) + + val body* = when-coverage(body(m)) + val logic = Vector<Stmt>() + val port-ref = Ref(port-name,UIntType(UnknownWidth())) + + val w-ls = to-list $ when-bits + if length(w-ls) != 0 : + val reg-ref = Ref(reg-name,UIntType(IntWidth(length(w-ls)))) + add{logic,_} $ DefRegister(FileInfo(),name(reg-ref),type(reg-ref)) + add{logic,_} $ OnReset(FileInfo(),reg-ref,UIntValue(0,IntWidth(length(w-ls)))) + for (x in w-ls, i in 0 to false) do : + add{logic,_} $ DefWire(FileInfo(),name(x),type(x)) + add{logic,_} $ Connect(FileInfo(),x,DoPrim(BIT-SELECT-OP,list(reg-ref),list(i),UIntType(w1))) + add{logic,_} $ Connect(FileInfo(),reg-ref,concat-all(w-ls)) + + val i-ls = to-list $ inst-bits + if length(i-ls) != 0 : + for (x in i-ls, i in 0 to false) do : + add{logic,_} $ DefWire(FileInfo(),name(x),type(x)) + add{logic,_} $ Connect(FileInfo(),x,UIntValue(0,UnknownWidth())) + + if instrument?[name(m)] : add{logic,_} $ Connect(FileInfo(),port-ref,concat-all(append(w-ls,i-ls))) + + if length(logic) != 0 : + val ports* = List(Port(FileInfo(),port-name,OUTPUT,UIntType(UnknownWidth())),ports(m)) + val body** = Begin(list(Begin(to-list $ logic),body*)) + InModule(info(m),name(m),ports*,body**) + else : m + +public defn when-coverage (port-name:String, reg-name:String, c:Circuit) : + val instrument? = HashTable<Symbol,True|False>(symbol-hash) + for m in modules(c) do : + instrument?[name(m)] = false + val top = for m in modules(c) find : name(m) == main(c) + if top != false : needs-instrumentation(top as Module,modules(c),instrument?) + + val modules* = for m in modules(c) map : + match(m) : + (m:InModule) : + when-coverage(to-symbol $ port-name,to-symbol $ reg-name,instrument?,m) + (m:ExModule) : m + Circuit(info(c),modules*,main(c)) + diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index 8c5532b0..0795a2a9 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -19,7 +19,6 @@ defpackage firrtl/errors : ; o No names ; o No Unknowns ; o All widths are positive -; o Pad's width is greater than value's width ; o pad's width is greater than value's width ; o widths are large enough to contain value @@ -43,9 +42,13 @@ defpackage firrtl/errors : ; * 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 defstruct CheckHighForm <: Pass : + sym : Symbol +public defmethod pass (b:CheckHighForm) -> (Circuit -> Circuit) : check-high-form{_,sym(b)} public defmethod name (b:CheckHighForm) -> String : "High Form Check" public defmethod short-name (b:CheckHighForm) -> String : "high-form-check" @@ -94,6 +97,22 @@ defn WrongReset (info:FileInfo, name:Symbol) : PassException $ string-join $ [info ": Module " name " has a reset that is not of type UInt<1>."] +defn IncorrectNumArgs (info:FileInfo, op:Symbol, n:Int) : + PassException $ string-join $ + [info ": Primop " op " requires " n " expression arguments."] + +defn IncorrectNumConsts (info:FileInfo, op:Symbol, n:Int) : + PassException $ string-join $ + [info ": Primop " op " requires " n " integer arguments."] + +defn NegWidth (info:FileInfo) : + PassException $ string-join $ + [info ": Width cannot be negative."] + +defn NegVecSize (info:FileInfo) : + PassException $ string-join $ + [info ": Vector type size cannot be negative."] + ;---------------- Helper Functions -------------- defn has-flip? (t:Type) -> True|False : var has? = false @@ -114,28 +133,70 @@ defn contains?<?T> (c:?T,cs:Streamable<?T>) -> True|False : if x == c : myret(true) false -defn is-prefix? (s:Symbol,v:Vector<Symbol>) -> Symbol|False : +defn is-prefix? (s:Symbol,v:Vector<Symbol>,sym:Symbol) -> Symbol|False : + defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False : + var is? = true + val s1* = to-string(s1) + val s2* = to-string(s2) + for (x in s1*, y in s2*) do : + if x != y : is? = false + if length(s1*) > length(s2*) : + if s1*[length(s2*)] != to-string(sym)[0] : is? = false + if length(s1*) < length(s2*) : + if s2*[length(s1*)] != to-string(sym)[0] : is? = false + if length(s1*) == length(s2*) : + is? = false + is? label<Symbol|False> myret : for x in v do : if is-prefix?(x,s) : myret(x) false -defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False : - var is? = true - val s1* = to-string(s1) - val s2* = to-string(s2) - for (x in s1*, y in s2*) do : - if x != y : is? = false - if length(s1*) > length(s2*) : - if s1*[length(s2*)] != '$' : is? = false - if length(s1*) < length(s2*) : - if s2*[length(s1*)] != '$' : is? = false - if length(s1*) == length(s2*) : - is? = false - is? +defn check-high-form-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) -> 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(info,to-symbol(op(e)),ne as Int)) + if length(consts(e)) != nc : add(errors,IncorrectNumConsts(info,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) + 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) ;--------------- Check High Form Pass ------------------- -public defn check-high-form (c:Circuit) -> Circuit : +public defn check-high-form (c:Circuit,sym:Symbol) -> Circuit : val errors = Vector<PassException>() defn check-valid-loc (info:FileInfo,e:Expression) -> False : @@ -144,6 +205,20 @@ public defn check-high-form (c:Circuit) -> Circuit : add(errors,InvalidLOC(info)) (e) : false + defn check-high-form-w (info:FileInfo,w:Width) -> Width : + match(w) : + (w:IntWidth) : + if width(w) < 0 : add(errors,NegWidth(info)) + w + (w) : w + + defn check-high-form-t (info:FileInfo,t:Type) -> Type : + match(map(check-high-form-t{info,_},t)) : + (t:VectorType) : + if size(t) < 0 : add(errors,NegVecSize(info)) + (t) : false + map(check-high-form-w{info,_:Width},t) + defn check-high-form-e (info:FileInfo,e:Expression,names:Vector<Symbol>) -> Expression : match(map(check-high-form-e{info,_,names},e)) : (e:Ref) : @@ -157,18 +232,23 @@ public defn check-high-form (c:Circuit) -> Circuit : match(exp(e)) : (e:Ref|Subfield|Index) : false (e) : add(errors,InvalidIndex(info)) + (e:DoPrim) : check-high-form-primop(e,errors,info) ;; (e:UIntValue) : ;; if value(e) < 0 : ;; add(errors,NegUInt(info)) (e) : false + map(check-high-form-w{info,_:Width},e) + map(check-high-form-t{info,_:Type},e) e defn check-high-form-s (s:Stmt,names:Vector<Symbol>) -> Stmt : defn check-name (info:FileInfo,name:Symbol) -> False : if contains?(name,names) : add(errors,NotUnique(info,name)) - val prefix = is-prefix?(name,names) + val prefix = is-prefix?(name,names,sym) if prefix typeof Symbol : add(errors,IsPrefix(info,name,prefix as Symbol)) + map(check-high-form-t{info(s),_:Type},s) + map{check-high-form-s{_,names},_} $ { match(map(check-high-form-e{info(s),_,names},s)) : (s:DefWire|DefRegister) : @@ -191,6 +271,8 @@ public defn check-high-form (c:Circuit) -> Circuit : add(names,name(s)) (s:Connect) : check-valid-loc(info(s),loc(s)) + (s:BulkConnect) : + check-valid-loc(info(s),loc(s)) (s) : false s }() @@ -209,10 +291,15 @@ public defn check-high-form (c:Circuit) -> Circuit : add(errors,WrongReset(info!(m),name(m))) else : add(errors,WrongReset(info!(m),name(m))) + map(check-high-form-t{info(p),_},type(p)) + map(check-high-form-w{info(p),_},type(p)) + add(names,`reset) - check-high-form-s(body(m),names) + match(m) : + (m:ExModule) : false + (m:InModule) : check-high-form-s(body(m),names) false var number-top-m = 0 @@ -284,8 +371,6 @@ public defn check-kinds (c:Circuit) -> Circuit : check-is-mem(info,mem(e)) check-not-mem(info,index(e)) check-not-mem(info,enable(e)) - ;(e:Pad) : - ;check-not-mem(info,value(e)) (e) : do(check-not-mem{info,_},e) defn check-kinds-s (s:Stmt) -> False : do(check-kinds-e{info(s),_:Expression},s) @@ -296,6 +381,9 @@ public defn check-kinds (c:Circuit) -> Circuit : (s:Connect) : check-not-mem(info(s),loc(s)) check-not-mem(info(s),exp(s)) + (s:BulkConnect) : + check-not-mem(info(s),loc(s)) + check-not-mem(info(s),exp(s)) (s:OnReset) : check-is-reg(info(s),loc(s)) check-not-mem(info(s),exp(s)) @@ -303,13 +391,14 @@ public defn check-kinds (c:Circuit) -> Circuit : do(check-kinds-s,s) for m in modules(c) do : - check-kinds-s(body(m)) + match(m) : + (m:ExModule) : false + (m:InModule) : check-kinds-s(body(m)) throw(PassExceptions(errors)) when not empty?(errors) c ;==================== CHECK TYPES ===================== -; o expression in pad must be a ground type ; 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 @@ -348,10 +437,6 @@ defn EnableNotUInt (info:FileInfo) : PassException $ string-join $ [info ": Enable is not of UIntType."] -;defn PadNotGround (info:FileInfo) : - ;PassException $ string-join $ - ;[info ": Illegal Pad on non-ground type."] - defn InvalidConnect (info:FileInfo) : PassException $ string-join $ [info ": Type mismatch."] @@ -360,6 +445,27 @@ defn PredNotUInt (info:FileInfo) : PassException $ string-join $ [info ": Predicate not a UIntType."] +defn OpNotGround (info:FileInfo, op:Symbol) : + PassException $ string-join $ + [info ": Primop " op " cannot operate on non-ground types."] + +defn OpNotUInt (info:FileInfo, op:Symbol,e:Symbol) : + PassException $ string-join $ + [info ": Primop " op " requires argument " e " to be a UInt type."] + +defn OpNotAllUInt (info:FileInfo, op:Symbol) : + PassException $ string-join $ + [info ": Primop " op " requires all arguments to be UInt type."] + +defn OpNotAllSameType (info:FileInfo, op:Symbol) : + PassException $ string-join $ + [info ": Primop " op " requires all operands to have the same type."] + +defn NodeWithFlips (info:FileInfo) : + PassException $ string-join $ + [info ": Node cannot be a bundle type with flips."] + + ;---------------- Helper Functions -------------- defmethod equal? (t1:Type,t2:Type) -> True|False : match(t1,t2) : @@ -380,6 +486,64 @@ defmethod equal? (t1:Type,t2:Type) -> True|False : defn u () -> UIntType : UIntType(UnknownWidth()) defn s () -> SIntType : SIntType(UnknownWidth()) +defn check-types-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) -> False : + defn all-same-type (ls:List<Expression>) -> False : + for x in ls do : + if type(head(ls)) != type(x) : + add(errors,OpNotAllSameType(info,to-symbol $ op(e))) + defn all-ground (ls:List<Expression>) -> False : + for x in ls do : + if not (type(x) typeof UIntType or type(x) typeof SIntType) : + add(errors,OpNotGround(info,to-symbol $ op(e))) + defn all-uint (ls:List<Expression>) -> False : + for x in ls do : + if not (type(x) typeof UIntType) : + add(errors,OpNotAllUInt(info,to-symbol $ op(e))) + defn is-uint (x:Expression) -> False : + if not (type(x) typeof UIntType) : + 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 : all-same-type(args(e)) + NEQUAL-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-uint(args(e)) + BIT-AND-OP : all-uint(args(e)) + BIT-OR-OP : all-uint(args(e)) + BIT-XOR-OP : all-uint(args(e)) + 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-SELECT-OP : all-uint(args(e)) + BITS-SELECT-OP : all-uint(args(e)) + ;----------------- Check Types Pass --------------------- public defn check-types (c:Circuit) -> Circuit : val errors = Vector<PassException>() @@ -397,33 +561,32 @@ public defn check-types (c:Circuit) -> Circuit : (t:VectorType) : if value(e) >= size(t) : add(errors,IndexTooLarge(info,value(e))) (t) : add(errors,IndexOnNonVector(info)) - (e:DoPrim) : false ;check-types-primop(e) + (e:DoPrim) : check-types-primop(e,errors,info) (e:ReadPort|WritePort) : if type(index(e)) != u() : add(errors,IndexNotUInt(info)) if type(enable(e)) != u() : add(errors,EnableNotUInt(info)) (e:Register) : if type(enable(e)) != u() : add(errors,EnableNotUInt(info)) - ;(e:Pad) : - ;val t = type(value(e)) - ;if not (t == u() or t == s()) : add(errors,PadNotGround(info)) (e:UIntValue|SIntValue) : false e 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 - (s:OnReset) : - if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s))) - s - (s:Conditionally) : - if type(pred(s)) != u() : add(errors,PredNotUInt(info(s))) - s - (s) : s + 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:OnReset) : + if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s))) + (s:Conditionally) : + if type(pred(s)) != u() : add(errors,PredNotUInt(info(s))) + (s:DefNode) : + if has-flip?(type(value(s))) : add(errors,NodeWithFlips(info(s))) + (s) : false + s }() for m in modules(c) do : - check-types-s(body(m)) + match(m) : + (m:ExModule) : false + (m:InModule) : check-types-s(body(m)) throw(PassExceptions(errors)) when not empty?(errors) c @@ -469,7 +632,6 @@ public defn check-genders (c:Circuit) -> Circuit : 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:WIndex) : get-gender(exp(e),genders) - ;(e:Pad) : MALE (e:DoPrim) : MALE (e:UIntValue) : MALE (e:SIntValue) : MALE @@ -483,7 +645,6 @@ public defn check-genders (c:Circuit) -> Circuit : (e:WRef) : false (e:WSubfield) : false (e:WIndex) : false - ;(e:Pad) : check-gender(info,genders,value(e),MALE) (e:DoPrim) : for e in args(e) do : check-gender(info,genders,e,MALE) @@ -511,6 +672,9 @@ public defn check-genders (c:Circuit) -> Circuit : (s:Connect) : check-gender(info(s),genders,loc(s),FEMALE) check-gender(info(s),genders,exp(s),MALE) + (s:BulkConnect) : + check-gender(info(s),genders,loc(s),FEMALE) + check-gender(info(s),genders,exp(s),MALE) (s:OnReset) : check-gender(info(s),genders,loc(s),FEMALE) check-gender(info(s),genders,exp(s),MALE) @@ -524,6 +688,9 @@ public defn check-genders (c:Circuit) -> Circuit : val genders = HashTable<Symbol,Gender>(symbol-hash) for p in ports(m) do : genders[name(p)] = dir-to-gender(direction(p)) - check-genders-s(body(m),genders) + match(m) : + (m:ExModule) : false + (m:InModule) : check-genders-s(body(m),genders) 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 39538498..18e069b4 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -5,6 +5,9 @@ defpackage firrtl/ir2 : public defmulti info! (x:?) -> FileInfo public defmethod info! (x:?) : FileInfo() +public val expand-delin = `$ +public val gen-delin = `# + public definterface Direction public val INPUT = new Direction public val OUTPUT = new Direction @@ -114,6 +117,7 @@ public defstruct DefMemory <: Stmt : ;LOW info: FileInfo with: (as-method => true) name: Symbol type: VectorType + seq?: True|False public defstruct DefNode <: Stmt : ;LOW info: FileInfo with: (as-method => true) name: Symbol @@ -130,7 +134,11 @@ public defstruct Conditionally <: Stmt : alt: Stmt public defstruct Begin <: Stmt : ;LOW body: List<Stmt> -public defstruct OnReset <: Stmt : ;LOW +public defstruct OnReset <: Stmt : + info: FileInfo with: (as-method => true) + loc: Expression + exp: Expression +public defstruct BulkConnect <: Stmt : info: FileInfo with: (as-method => true) loc: Expression exp: Expression @@ -163,12 +171,21 @@ public defstruct Port : direction: Direction type: Type -public defstruct Module : +public definterface Module +public defmulti name (m:Module) -> Symbol +public defmulti ports (m:Module) -> List<Port> + +public defstruct InModule <: Module : info: FileInfo - name: Symbol - ports: List<Port> + name: Symbol with: (as-method => true) + ports: List<Port> with: (as-method => true) body: Stmt +public defstruct ExModule <: Module : + info: FileInfo + name: Symbol with: (as-method => true) + ports: List<Port> with: (as-method => true) + public defstruct Circuit : info: FileInfo modules: List<Module> diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza index 5a7e593d..071717bb 100644 --- a/src/main/stanza/firrtl-test-main.stanza +++ b/src/main/stanza/firrtl-test-main.stanza @@ -13,6 +13,10 @@ #include("flo.stanza") #include("verilog.stanza") +;Custom Packages +#include("custom-passes.stanza") +#include("custom-compiler.stanza") + defpackage firrtl-main : import core import verse @@ -22,6 +26,9 @@ defpackage firrtl-main : import stz/parser import firrtl/ir-utils import firrtl/compiler + ;Custom Packages + import firrtl/custom-passes + import firrtl/custom-compiler defn set-printvars! (p:List<Char>) : if contains(p,'t') : PRINT-TYPES = true @@ -47,6 +54,7 @@ defn main () : var output = false var compiler = false val pass-names = Vector<String>() + val pass-args = Vector<String>() var printvars = "" for (s in args, i in 0 to false) do : if s == "-i" : input = args[i + 1] @@ -54,6 +62,7 @@ defn main () : if s == "-x" : add(pass-names,args[i + 1]) if s == "-X" : compiler = args[i + 1] if s == "-p" : printvars = args[i + 1] + if s == "-s" : add(pass-args,args[i + 1]) if input == false : error("No input file provided. Use -i flag.") @@ -72,6 +81,7 @@ defn main () : switch {_ == compiler} : "flo" : run-passes(c,StandardFlo(output as String)) "verilog" : run-passes(c,StandardVerilog(output as String)) + "verilute" : run-passes(c,InstrumentedVerilog(output as String,to-list $ pass-args)) else : error("Invalid compiler flag") main() diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza index c75071cd..bb9365ae 100644 --- a/src/main/stanza/flo.stanza +++ b/src/main/stanza/flo.stanza @@ -24,9 +24,11 @@ defn set-width (desired:Int,t:Type) -> Type : defn pad-widths-e (desired:Int,e:Expression) -> Expression : defn trim (desired:Int, e:Expression) : - DoPrim(BITS-SELECT-OP,list(e),list(0,desired),set-width(desired,type(e))) + ;; println-all(["TRIM " desired " e " e]) + DoPrim(BITS-SELECT-OP,list(e),list(desired - 1, 0),set-width(desired,type(e))) defn pad (desired:Int, e:Expression) : - DoPrim(PAD-OP,list(e),list(),set-width(desired,type(e))) + ;; println-all(["PAD " desired " e " e]) + DoPrim(PAD-OP,list(e),list(desired),set-width(desired,type(e))) defn trim-pad (desired:Int, e:Expression) : val i = int-width!(type(e)) if i > desired : trim(desired, e) @@ -83,7 +85,9 @@ defn pad-widths-s (s:Stmt) -> Stmt : public defn pad-widths (c:Circuit) -> Circuit : Circuit{info(c),_,main(c)} $ for m in modules(c) map : - Module(info(m),name(m),ports(m),pad-widths-s(body(m))) + match(m) : + (m:ExModule) : error("Cannot use flo backend with external modules") + (m:InModule) : InModule(info(m),name(m),ports(m),pad-widths-s(body(m))) ;============= Flo Backend ================ @@ -217,7 +221,7 @@ defn maybe-mov (e:Expression) -> String : (e) : false if need-mov?: "mov " else: "" -defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol) : +defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol,sh:HashTable<Symbol,Int>) : match(s) : (s:DefWire) : "" (s:DefInstance) : error("Shouldn't be here") @@ -226,7 +230,7 @@ defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol) : emit-all([top "::" name(s) " = mem'" prim-width(type(vtype)) " " size(vtype) "\n"], top) (s:DefNode) : emit-all([top "::" name(s) " = " maybe-mov(value(s)) value(s) "\n"], top) - (s:Begin) : do(emit-s{_, v, top}, body(s)) + (s:Begin) : do(emit-s{_, v, top,sh}, body(s)) (s:Connect) : match(loc(s)) : (r:Ref) : @@ -236,14 +240,14 @@ defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol) : else : emit-all([top "::" n " = " maybe-mov(exp(s)) exp(s) "\n"], top) (w:WritePort) : - val n = firrtl-gensym(`F) + val n = firrtl-gensym(`F,sh) emit-all([top "::" n " = wr'" prim-width(type(w)) " " enable(w) " " mem(w) " " index(w) " " exp(s) "\n"], top) (o) : println-all(["CONNEcT LOC " loc(s)]) error("Unknown Connect") (s) : s -defn emit-module (m:Module) : +defn emit-module (m:InModule,sh:HashTable<Symbol,Int>) : val v = Vector<Symbol>() for port in ports(m) do : if name(port) ==`reset : @@ -251,10 +255,10 @@ defn emit-module (m:Module) : else : switch {_ == direction(port)} : INPUT : print-all([name(m) "::" name(port) " = " "in'" prim-width(type(port)) "\n"]) OUTPUT : add(v,name(port)) - emit-s(body(m), to-list(v), name(m)) + emit-s(body(m), to-list(v), name(m),sh) public defn emit-flo (file:String, c:Circuit) : with-output-file{file, _} $ fn () : - emit-module(modules(c)[0]) + emit-module(modules(c)[0] as InModule,get-sym-hash(modules(c)[0] as InModule)) false c diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 0833543f..cbfe106e 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -151,9 +151,15 @@ defsyntax firrtl : module = (module ?name:#id! #:! (?ps:#port ... ?cs:#stmt ... ?rest ...)) : if not empty?(rest) : FPE(rest, "Expected a statement here.") - Module(first-info(form),name, ps, Begin(cs)) + InModule(first-info(form),name, ps, Begin(cs)) + module = (exmodule ?name:#id! #:! (?ps:#port ... ?rest ...)) : + if not empty?(rest) : + FPE(rest, "Expected a port here.") + ExModule(first-info(form),name, ps) module != (module) : FPE(form, "Invalid syntax for module definition.") + module != (exmodule) : + FPE(form, "Invalid syntax for exmodule definition.") defrule port : port = (input ?name:#id! #:! ?type:#type!) : Port(first-info(form),name, INPUT, type) @@ -187,13 +193,15 @@ defsyntax firrtl : defrule statements : stmt = (wire ?name:#id! #:! ?t:#type!) : DefWire(first-info(form),name, t) stmt = (reg ?name:#id! #:! ?t:#type!) : DefRegister(first-info(form),name, t) - stmt = (mem ?name:#id! #:! ?t:#vectype!) : DefMemory(first-info(form),name, t) + stmt = (cmem ?name:#id! #:! ?t:#vectype!) : DefMemory(first-info(form),name, t, false) + stmt = (smem ?name:#id! #:! ?t:#vectype!) : DefMemory(first-info(form),name, t, true) stmt = (inst ?name:#id! #of! ?m:#ref!) : DefInstance(first-info(form),name, m) stmt = (node ?name:#id! #=! ?e:#exp!) : DefNode(first-info(form),name, e) stmt = (accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i) stmt = (?s:#stmt/when) : s stmt = (?x:#exp := ?y:#exp!) : Connect(first-info(form),x, y) + stmt = (?x:#exp <> ?y:#exp!) : BulkConnect(first-info(form),x, y) stmt = (on-reset ?x:#exp := ?y:#exp!) : OnReset(first-info(form),x, y) stmt = ((?s:#stmt ?ss:#stmt ... ?rest ...)) : diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index d2afca05..c39a1ad1 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -9,15 +9,42 @@ public defmulti print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|M ;============== GENSYM STUFF ====================== -val sym-hash = HashTable<Symbol,Int>(symbol-hash) -public defn firrtl-gensym (s:Symbol) -> Symbol : - val cur = get?(sym-hash,s,0) - val nxt = cur + 1 - sym-hash[s] = nxt - symbol-join([s cur]) + +public defn firrtl-gensym (s:Symbol) -> Symbol : firrtl-gensym(s,HashTable<Symbol,Int>(symbol-hash)) + +public defn firrtl-gensym (s:Symbol,sym-hash:HashTable<Symbol,Int>) -> Symbol : + defn get-new (s:Symbol, i:Int) -> Symbol : + val s* = symbol-join([s i]) + if contains?(keys(sym-hash),s*) : + get-new(s,i + 1) + else : + sym-hash[s] = i + sym-hash[s*] = 0 + s* + get-new(s,0) -public defn firrtl-gensym () -> Symbol : - firrtl-gensym(`gen) +public defn firrtl-gensym (sym-hash:HashTable<Symbol,Int>) -> Symbol : + firrtl-gensym(`gen,sym-hash) + +public defn get-sym-hash (m:InModule) -> HashTable<Symbol,Int> : + val sym-hash = HashTable<Symbol,Int>(symbol-hash) + defn add-name (s:Symbol) -> False : + sym-hash[s] = 0 + defn to-port (p:Port) -> False : add-name(name(p)) + defn to-stmt (s:Stmt) -> Stmt : + match(s) : + (s:DefWire) : add-name(name(s)) + (s:DefRegister) : add-name(name(s)) + (s:DefInstance) : add-name(name(s)) + (s:DefMemory) : add-name(name(s)) + (s:DefNode) : add-name(name(s)) + (s:DefAccessor) : add-name(name(s)) + (s) : false + map(to-stmt,s) + + to-stmt(body(m)) + map(to-port,ports(m)) + sym-hash ;============== Exceptions ===================== @@ -127,7 +154,8 @@ defmethod print (o:OutputStream, c:Stmt) : (c:DefRegister) : print-all(o,["reg " name(c) " : " type(c)]) (c:DefMemory) : - print-all(o,["mem " name(c) " : " type(c)]) + if seq?(c) : print-all(o,["smem " name(c) " : " type(c)]) + else : print-all(o,["cmem " name(c) " : " type(c)]) (c:DefInstance) : print-all(o,["inst " name(c) " of " module(c)]) (c:DefNode) : @@ -147,6 +175,8 @@ defmethod print (o:OutputStream, c:Stmt) : do(print{o,_}, join(body(c), "\n")) (c:Connect) : print-all(o, [loc(c) " := " exp(c)]) + (c:BulkConnect) : + print-all(o, [loc(c) " <> " exp(c)]) (c:OnReset) : print-all(o, ["on-reset " loc(c) " := " exp(c)]) (c:EmptyStmt) : @@ -181,7 +211,7 @@ defmethod print (o:OutputStream, p:Port) : print-all(o, [direction(p) " " name(p) " : " type(p)]) print-debug(o,p) -defmethod print (o:OutputStream, m:Module) : +defmethod print (o:OutputStream, m:InModule) : print-all(o, ["module " name(m) " :"]) print-debug(o,m) print(o,"\n") @@ -190,6 +220,14 @@ defmethod print (o:OutputStream, m:Module) : println(io,p) print(io,body(m)) +defmethod print (o:OutputStream, m:ExModule) : + print-all(o, ["exmodule " name(m) " :"]) + print-debug(o,m) + print(o,"\n") + val io = IndentedStream(o, 3) + for p in ports(m) do : + println(io,p) + defmethod print (o:OutputStream, c:Circuit) : print-all(o, ["circuit " main(c) " :"]) print-debug(o,c) @@ -231,6 +269,7 @@ defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : (c:DefInstance) : DefInstance(info(c),name(c), f(module(c))) (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:OnReset) : OnReset(info(c),f(loc(c)),f(exp(c))) (c) : c @@ -272,7 +311,7 @@ defmethod map (f: Type -> Type, c:Stmt) -> Stmt : match(c) : (c:DefWire) : DefWire(info(c),name(c),f(type(c))) (c:DefRegister) : DefRegister(info(c),name(c),f(type(c))) - (c:DefMemory) : DefMemory(info(c),name(c),f(type(c)) as VectorType) + (c:DefMemory) : DefMemory(info(c),name(c),f(type(c)) as VectorType,seq?(c)) (c) : c public defmulti mapr<?T> (f: Width -> Width, t:?T&Type) -> T diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index b6926a7b..80035325 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -9,7 +9,7 @@ defpackage firrtl/passes : ;============== Pass List ================ public val standard-passes = to-list $ [ - CheckHighForm() + CheckHighForm(expand-delin) TempElimination() ToWorkingIR() MakeExplicitReset() @@ -85,6 +85,11 @@ defstruct ConnectFromIndexed <: Stmt : ;================ WORKING IR UTILS ========================= +;defmethod equal? (f1:Flip, f2:Flip) -> True|False : +; switch fn ([x,y]) : f1 == x and f2 == y : +; [DEFAULT,DEFAULT] : true +; [REVERSE,REVERSE] : true +; else : false defn plus (g1:Gender,g2:Gender) -> Gender : switch fn ([x,y]) : g1 == x and g2 == y : @@ -304,7 +309,9 @@ defn temp-elimination (c:Circuit) : Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : - Module(info(m),name(m), ports(m), temp-elim-s(body(m))) + match(m) : + (m:InModule) : InModule(info(m),name(m), ports(m), temp-elim-s(body(m))) + (m:ExModule) : m ;================= Bring to Working IR ======================== ; Returns a new Circuit with Refs, Subfields, Indexes and DefAccessors @@ -330,7 +337,9 @@ defn to-working-ir (c:Circuit) : Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : - Module(info(m),name(m), ports(m), to-stmt(body(m))) + match(m) : + (m:InModule) : InModule(info(m),name(m), ports(m), to-stmt(body(m))) + (m:ExModule) : m ;=============== MAKE EXPLICIT RESET ======================= ; All modules have an implicit reset signal - however, the @@ -367,8 +376,11 @@ defn make-explicit-reset (c:Circuit) : var ports! = ports(m) if not contains?(explicit-reset,name(m)) : ports! = append(ports(m),list(Port(FileInfo(),`reset,INPUT,UIntType(IntWidth(1))))) - val body! = route-reset(body(m)) - Module(info(m),name(m),ports!,body!) + match(m) : + (m:InModule) : + val body! = route-reset(body(m)) + InModule(info(m),name(m),ports!,body!) + (m:ExModule) : ExModule(info(m),name(m),ports!) defn make-explicit-reset (m:Module, c:Circuit) -> Module : val explicit-reset = find-explicit(c) @@ -417,15 +429,20 @@ defn resolve-kinds (c:Circuit) : kinds[name(m)] = ModuleKind() for p in ports(m) do : kinds[name(p)] = PortKind() - find-stmt(body(m)) + 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) for m in modules(c) do : kinds[name(m)] = ModuleKind() find(m,kinds) - val body! = resolve(body(m),kinds) - Module(info(m),name(m),ports(m),body!) + 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* = @@ -504,15 +521,18 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue< val [s*,l*] = infer-types(conseq(s),l) val [s**,l**] = infer-types(alt(s),l) [Conditionally(info(s),pred(s),s*,s**),l] - (s:Connect|OnReset|EmptyStmt) : [s,l] + (s:Connect|BulkConnect|OnReset|EmptyStmt) : [s,l] defn infer-types (m:Module, l:List<KeyValue<Symbol,Type>>) -> Module : val ptypes = for p in ports(m) map : name(p) => type(p) println-all-debug(append(ptypes,l)) - val [s,l*] = infer-types(body(m),append(ptypes, l)) - Module(info(m),name(m),ports(m),s) + match(m) : + (m:InModule) : + val [s,l*] = infer-types(body(m),append(ptypes, l)) + InModule(info(m),name(m),ports(m),s) + (m:ExModule) : m defn infer-types (c:Circuit) -> Circuit : val l = @@ -565,8 +585,11 @@ defn resolve-genders (c:Circuit) : var done? = true defn resolve-iter (m:Module) -> Module : - val body* = resolve-stmt(body(m)) - Module(info(m),name(m),ports(m),body*) + match(m) : + (m:InModule) : + val body* = resolve-stmt(body(m)) + InModule(info(m),name(m),ports(m),body*) + (m:ExModule) : m defn get-gender (n:Symbol,g:Gender) -> Gender : defn force-gender (n:Symbol,g:Gender) -> Gender : @@ -607,6 +630,8 @@ defn resolve-genders (c:Circuit) : WDefAccessor(info(s),name(s),source*,index*,gender*) (s:Connect) : Connect(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) + (s:BulkConnect) : + BulkConnect(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) (s:OnReset) : OnReset(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) (s:Conditionally) : @@ -696,7 +721,9 @@ defn expand-accessors (c:Circuit) : Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : - Module(info(m),name(m),ports(m),expand-stmt(body(m))) + match(m) : + (m:InModule) : InModule(info(m),name(m),ports(m),expand-stmt(body(m))) + (m:ExModule) : m ;;=============== LOWERING TO GROUND TYPES ============================= ; All non-ground (elevated) types (Vectors, Bundles) are expanded out to @@ -742,9 +769,8 @@ defn index-of-elem (t:BundleType, s:Symbol) -> Int : else : sum = sum + num-elems(type(f)) error("Shouldn't be here") - defn generate-entry (n:Symbol,t:Type) -> List<NTF> : - defn uniquify (n*:Symbol) -> Symbol : symbol-join([n "_" n*]) + defn uniquify (n*:Symbol) -> Symbol : symbol-join([n expand-delin n*]) match(t) : (t:BundleType) : for f in fields(t) map-append : @@ -840,7 +866,7 @@ defn lower (body:Stmt) -> Stmt : DefNode(info(s),name(s),exp(x)) (s:DefMemory) : Begin $ for x in generate-entry(name(s),type(type(s))) map : - DefMemory(info(s),name(x),VectorType(type(x),size(s))) + DefMemory(info(s),name(x),VectorType(type(x),size(s)), seq?(s)) (s:WDefAccessor) : val ls = generate-entry(name(s),type(s)) val rs = generate-entry(name(source(s) as WRef),type(s)) @@ -863,6 +889,28 @@ defn lower (body:Stmt) -> Stmt : [MALE,FEMALE] : if s typeof Connect : Connect(info(s),r*,l*) else : OnReset(info(s),r*,l*) + (s:BulkConnect) : + val ls-fake = generate-entry(`null,type(loc(s))) + val rs-fake = generate-entry(`null,type(exp(s))) + val ls = expand-expr(loc(s)) + val rs = expand-expr(exp(s)) + val ls* = Vector<EF>() + val rs* = Vector<EF>() + for (l-fake in ls-fake,l in ls) do : + for (r-fake in rs-fake, r in rs) do : + if name(l-fake) == name(r-fake) and flip(l-fake) == flip(r-fake) and type(l-fake) == type(r-fake) : + add(ls*,l) + add(rs*,r) + Begin $ for (l in to-list(ls*), r in to-list(rs*)) map : + val lgender = FEMALE * flip(l) + val rgender = MALE * flip(r) + val l* = set-gender(exp(l),lgender,flip(l)) + val r* = set-gender(exp(r),rgender,flip(r)) + println-all-debug(["Left: " l " with Gender: " lgender]) + println-all-debug(["Right: " r " with Gender: " rgender]) + switch fn ([x,y]) : lgender == x and rgender == y : + [FEMALE,MALE] : Connect(info(s),l*,r*) + [MALE,FEMALE] : Connect(info(s),r*,l*) (s:ConnectFromIndexed) : Begin(ls) where : val ctable = HashTable<Symbol,Vector<EF>>(symbol-hash) for e in exps(s) do : @@ -908,9 +956,13 @@ defn lower (body:Stmt) -> Stmt : lower-stmt(body) defn lower-module (c:Circuit,m:Module) -> Module : - Module(info(m),name(m),ports*,body*) where : - val body* = lower(body(m)) - val ports* = lower-ports(ports(m)) + val ports* = lower-ports(ports(m)) + match(m) : + (m:InModule) : + val body* = lower(body(m)) + InModule(info(m),name(m),ports*,body*) + (m:ExModule) : + ExModule(info(m),name(m),ports*) defn lower-to-ground (c:Circuit) -> Circuit : Circuit(info(c),modules*, main(c)) where : @@ -928,20 +980,20 @@ public defmethod pass (b:ExpandIndexedConnects) -> (Circuit -> Circuit) : expand public defmethod name (b:ExpandIndexedConnects) -> String : "Expand Indexed Connects" public defmethod short-name (b:ExpandIndexedConnects) -> String : "expand-indexed-connects" -defn expand-connect-indexed-stmt (s: Stmt) -> Stmt : +defn expand-connect-indexed-stmt (s: Stmt,sh:HashTable<Symbol,Int>) -> Stmt : defn equality (e1:Expression,e2:Expression) -> Expression : DoPrim(EQUAL-OP,list(e1,e2),List(),UIntType(UnknownWidth())) defn get-name (e:Expression) -> Symbol : match(e) : - (e:WRef) : symbol-join([name(e) `__]) - (e:WSubfield) : symbol-join([get-name(exp(e)) `. name(e) `__]) - (e:WIndex) : symbol-join([get-name(exp(e)) `. to-symbol(value(e)) `__]) + (e:WRef) : symbol-join([name(e) gen-delin]) + (e:WSubfield) : symbol-join([get-name(exp(e)) `. name(e) gen-delin]) + (e:WIndex) : symbol-join([get-name(exp(e)) `. to-symbol(value(e)) gen-delin]) (e) : `T match(s) : (s:ConnectToIndexed) : Begin $ if length(locs(s)) == 0 : list(EmptyStmt()) else : - val ref = WRef(firrtl-gensym(get-name(exp(s))),type(index(s)),NodeKind(),UNKNOWN-GENDER) + val ref = WRef(firrtl-gensym(get-name(index(s)),sh),type(index(s)),NodeKind(),UNKNOWN-GENDER) append( list(DefNode(info(s),name(ref),index(s))) to-list $ @@ -955,7 +1007,7 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt : (s:ConnectFromIndexed) : Begin $ if length(exps(s)) == 0 : list(EmptyStmt()) else : - val ref = WRef(firrtl-gensym(get-name(loc(s))),type(index(s)),NodeKind(),UNKNOWN-GENDER) + val ref = WRef(firrtl-gensym(get-name(index(s)),sh),type(index(s)),NodeKind(),UNKNOWN-GENDER) append( list(Connect(info(s),loc(s),head(exps(s))),DefNode(info(s),name(ref),index(s))) to-list $ @@ -966,10 +1018,14 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt : EmptyStmt() ) ) - (s) : map(expand-connect-indexed-stmt,s) + (s) : map(expand-connect-indexed-stmt{_,sh},s) defn expand-connect-indexed (m: Module) -> Module : - Module(info(m),name(m),ports(m),expand-connect-indexed-stmt(body(m))) + match(m) : + (m:InModule) : + val sh = get-sym-hash(m) + InModule(info(m),name(m),ports(m),expand-connect-indexed-stmt(body(m),sh)) + (m:ExModule) : m defn expand-connect-indexed (c: Circuit) -> Circuit : Circuit(info(c),modules*, main(c)) where : @@ -1173,63 +1229,49 @@ defn expand-whens (ports:List<Port>, table:HashTable<Symbol,SymbolicValue>,cons: for p in ports do : if direction(p) == OUTPUT : val ref = WRef(name(p),type(p),PortKind(),FEMALE) - add{cons,_} $ - if has-nul?(table[name(p)]) : - println("Uninitialized: ~" % [to-string(name(p))]);TODO actually collect error - EmptyStmt() - else : Connect(FileInfo(),ref,to-exp(table[name(p)]) as Expression) + if has-nul?(table[name(p)]) : + println("Uninitialized: ~" % [to-string(name(p))]);TODO actually collect error + else : add{cons,_} $ Connect(FileInfo(),ref,to-exp(table[name(p)]) as Expression) defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stmt>,cons:Vector<Stmt>) -> Stmt : match(map(expand-whens{_,table,decs,cons},s)) : (s:DefNode|DefMemory) : add(decs,s) (s:DefWire) : add(decs,s) - add{cons,_} $ { - val ref = WRef(name(s),type(s),NodeKind(),FEMALE) - if has-nul?(table[name(s)]) : - println("Uninitialized: ~" % [to-string(name(s))]);TODO actually collect error - EmptyStmt() - else : Connect(info(s),ref,to-exp(table[name(s)]) as Expression) - }() + val ref = WRef(name(s),type(s),NodeKind(),FEMALE) + if has-nul?(table[name(s)]) : + println("Uninitialized: ~" % [to-string(name(s))]);TODO actually collect error + else : add{cons,_} $ Connect(info(s),ref,to-exp(table[name(s)]) as Expression) (s:DefRegister) : - ;add(decs,DefWire(info(s),name(s),type(s))) - ;add{cons,_} $ { - ; val ref = WRef(name(s),type(s),RegKind(),FEMALE) - ; val e = to-exp(table[name(s)]) - ; match(e) : - ; (e:False) : EmptyStmt() - ; (e:Expression) : Connect(info(s),ref,Register(type(s),e, to-exp(optimize $ get-write-enable(table[name(s)])) as Expression)) - ;}() val e = to-exp(table[name(s)]) - add{cons,_} $ { - match(e) : - (e:False) : EmptyStmt() - (e:Expression) : DefNode(info(s),name(s),Register(type(s),e,to-exp(optimize $ get-write-enable(table[name(s)])) as Expression)) - }() + match(e) : + (e:Expression) : + add{decs,_} $ DefWire(info(s),name(s),type(s)) + val ref = WRef(name(s),type(s),NodeKind(),FEMALE) + add{cons,_} $ Connect(info(s),ref,Register(type(s),e,to-exp(optimize $ get-write-enable(table[name(s)])) as Expression)) + (e:False) : false (s:WDefAccessor) : val t = type(type(source(s)) as VectorType) val n = name(s) - add{cons,_} $ { switch {_ == gender(s)} : MALE : - Begin $ list $ DefNode(info(s),n,ReadPort(source(s),index(s),t,get-read-enable(n,table))) + add{decs,_} $ DefWire(info(s),n,t) + val ref = WRef(n,t,WriteAccessorKind(),FEMALE) + add{cons,_} $ Connect(info(s),ref,ReadPort(source(s),index(s),t,get-read-enable(n,table))) FEMALE : add(decs,DefWire(info(s),n,t)) - val ref = WRef(n,t,WriteAccessorKind(),FEMALE) + val ref = WRef(n,t,WriteAccessorKind(),MALE) + val enable = (to-exp $ optimize $ get-write-enable(table[n])) as Expression + val wp = WritePort(source(s),index(s),t,enable as Expression) val e = to-exp(table[n]) - val s* = match(e) : + add{cons,_} $ Connect(info(s),wp,ref) + match(e) : (e:False) : println("Uninitialized: ~" % [to-string(n)]) ;TODO actually collect error - EmptyStmt() (e:Expression) : - Connect(info(s),ref,e) - val enable = (to-exp $ optimize $ get-write-enable(table[n])) as Expression - val wp = WritePort(source(s),index(s),t,enable as Expression) - Begin $ list(Connect(info(s),wp,ref),s*) - }() + add{cons,_} $ Connect(info(s),ref,e) (s:DefInstance) : add(decs,s) - add{cons,_} $ Begin $ for f in fields(type(module(s)) as BundleType) map : if flip(f) == REVERSE : val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs @@ -1239,9 +1281,7 @@ defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stm val sref = WSubfield(ref,f,bundle-field-type(type(module(s)),f),FEMALE) if has-nul?(table[n]) : println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error - EmptyStmt() - else : Connect(info(s),sref,to-exp(table[n]) as Expression) - else : EmptyStmt() + else : add{cons,_} $ Connect(info(s),sref,to-exp(table[n]) as Expression) (s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : false s @@ -1347,34 +1387,37 @@ defn build-tables (s:Stmt, (s:DefMemory|DefNode|EmptyStmt) : false defn expand-whens (m:Module) -> Module : - val assign = HashTable<Symbol,SymbolicValue>(symbol-hash) - val resets = HashTable<Symbol,SymbolicValue>(symbol-hash) - val flattn = HashTable<Symbol,True|False>(symbol-hash) - - for p in ports(m) do : - if direction(p) == OUTPUT : - assign[name(p)] = SVNul() - flattn[name(p)] = false - - build-tables(body(m),assign,resets,flattn) - for x in assign do : assign[key(x)] = optimize(value(x)) - for x in resets do : resets[key(x)] = optimize(value(x)) - ;val enables = get-enables(assign,kinds) - ;for x in enables do : enables[key(x)] = optimize(value(x)) - - println-debug("====== Assigns ======") - for x in assign do : println-debug(x) - println-debug("====== Resets ======") - for x in resets do : println-debug(x) - - val table = merge-resets(assign,resets) - println-debug("====== Table ======") - for x in table do : println-debug(x) - val decs = Vector<Stmt>() - val cons = Vector<Stmt>() - expand-whens(ports(m),table,cons) - expand-whens(body(m),table,decs,cons) - Module(info(m),name(m),ports(m),Begin(append(to-list(decs),to-list(cons)))) + match(m) : + (m:ExModule) : m + (m:InModule) : + val assign = HashTable<Symbol,SymbolicValue>(symbol-hash) + val resets = HashTable<Symbol,SymbolicValue>(symbol-hash) + val flattn = HashTable<Symbol,True|False>(symbol-hash) + + for p in ports(m) do : + if direction(p) == OUTPUT : + assign[name(p)] = SVNul() + flattn[name(p)] = false + + build-tables(body(m),assign,resets,flattn) + for x in assign do : assign[key(x)] = optimize(value(x)) + for x in resets do : resets[key(x)] = optimize(value(x)) + ;val enables = get-enables(assign,kinds) + ;for x in enables do : enables[key(x)] = optimize(value(x)) + + println-debug("====== Assigns ======") + for x in assign do : println-debug(x) + println-debug("====== Resets ======") + for x in resets do : println-debug(x) + + val table = merge-resets(assign,resets) + println-debug("====== Table ======") + for x in table do : println-debug(x) + val decs = Vector<Stmt>() + val cons = Vector<Stmt>() + expand-whens(ports(m),table,cons) + expand-whens(body(m),table,decs,cons) + InModule(info(m),name(m),ports(m),Begin(append(to-list(decs),to-list(cons)))) defn expand-whens (c:Circuit) -> Circuit : Circuit(info(c),modules*, main(c)) where : @@ -1409,6 +1452,8 @@ public defstruct MaxWidth <: 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) : @@ -1600,7 +1645,7 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod match(map(gen-constraints-s,s)) : (s:DefWire) : DefWire(info(s),name(s),h[name(s)]) (s:DefInstance) : DefInstance(info(s),name(s),gen-constraints(module(s))) - (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)] as VectorType) + (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)] as VectorType,seq?(s)) (s:DefNode) : val l = h[name(s)] val r = gen-constraints(value(s)) @@ -1636,14 +1681,14 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod (e:UIntValue) : match(width(e)) : (w:UnknownWidth) : - val w* = VarWidth(firrtl-gensym(`w)) + val w* = VarWidth(firrtl-gensym(`w,width-name-hash)) add(v,WGeq(w*,IntWidth(ceil-log2(value(e))))) UIntValue(value(e),w*) (w) : e (e:SIntValue) : match(width(e)) : (w:UnknownWidth) : - val w* = VarWidth(firrtl-gensym(`w)) + val w* = VarWidth(firrtl-gensym(`w,width-name-hash)) add(v,WGeq(w*,IntWidth(1 + ceil-log2(abs(value(e)))))) SIntValue(value(e),w*) (w) : e @@ -1652,7 +1697,9 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod val ports* = for p in ports(m) map : Port(info(p),name(p),direction(p),h[name(p)]) - Module(info(m),name(m),ports*,gen-constraints-s(body(m))) + match(m) : + (m:ExModule) : ExModule(info(m),name(m),ports*) + (m:InModule) : InModule(info(m),name(m),ports*,gen-constraints-s(body(m))) defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTable<Symbol,Type> : defn build-environment (s:Stmt) -> False : @@ -1665,7 +1712,10 @@ defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTabl do(build-environment,s) for p in ports(m) do : h[name(p)] = bundle-field-type(h[name(m)],name(p)) - build-environment(body(m)) + + match(m) : + (m:ExModule) : false + (m:InModule) : build-environment(body(m)) h defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit : @@ -1706,15 +1756,18 @@ defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit : w* val modules* = for m in modules(c) map : - Module{info(m),name(m),_,mapr(reduce-var-widths-w,body(m))} $ - for p in ports(m) map : - Port(info(p),name(p),direction(p),mapr(reduce-var-widths-w,type(p))) + 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 remove-unknowns-w (w:Width) -> Width : match(w) : - (w:UnknownWidth) : VarWidth(firrtl-gensym(`w)) + (w:UnknownWidth) : VarWidth(firrtl-gensym(`w,width-name-hash)) (w) : w defn remove-unknowns (t:Type) -> Type : mapr(remove-unknowns-w,t) @@ -1758,7 +1811,7 @@ 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,Module>(symbol-hash) + 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)) : @@ -1781,30 +1834,32 @@ defn inline-instances (c:Circuit) : (e:WSubfield) : match(kind(exp(e) as WRef)) : (k:InstanceKind) : - WRef(symbol-join([name(exp(e) as WRef) "_" name(e)]),type(e),k,gender(e)) + WRef(symbol-join([name(exp(e) as WRef) expand-delin name(e)]),type(e),k,gender(e)) (k:MemKind) : e (e) : e - defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n "_" ref]) + defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n expand-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) "_" name(e)]),type(e),k,gender(e)) + WRef(symbol-join([name(exp(e) as WRef) expand-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:DefInstance) : error("Shouldn't be here") - (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s)) + (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s)) (s:DefNode) : DefNode(info(s),rename(name(s),n),value(s)) (s) : s for m in modules(c) do : - h[name(m)] = m - val top = (for m in modules(c) find : name(m) == main(c)) as Module - Circuit(info(c),list(Module(info(top),name(top),ports(top),inline-inst(body(top)))),main(c)) + 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 ======================== @@ -1821,34 +1876,38 @@ defn full-name (e:Expression) -> Symbol : (e) : error("Non-supported expression.") defn split-exp (c:Circuit) : - defn split-exp-s (s:Stmt,v:Vector<Stmt>) -> False : + defn split-exp-s (s:Stmt,v:Vector<Stmt>,sh:HashTable<Symbol,Int>) -> False : + defn split-exp-e (e:Expression,n:Symbol|False,info:FileInfo) -> Expression : + match(map(split-exp-e{_,n,info},e)) : + (e:DoPrim) : + val n* = + if n typeof False : firrtl-gensym(`T,sh) + else : firrtl-gensym(symbol-join([n as Symbol gen-delin]),sh) + add(v,DefNode(info,n*,e)) + WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER) + (e) : e match(s) : (s:Begin) : - defn f (s:Stmt) -> False: split-exp-s(s,v) + defn f (s:Stmt) -> False: split-exp-s(s,v,sh) do(f,s) (s:Conditionally) : error("Shouldn't be here") (s:Connect) : match(loc(s)) : - (e:WritePort) : add(v,map(split-exp-e{_,v,full-name(exp(s)),info(s)},s)) - (e) : add(v,map(split-exp-e{_,v,full-name(loc(s)),info(s)},s)) - (s:DefNode) : add(v,map(split-exp-e{_,v,name(s),info(s)},s)) - (s) : add(v,map(split-exp-e{_,v,false,info(s)},s)) + (e:WritePort) : add(v,map(split-exp-e{_,full-name(exp(s)),info(s)},s)) + (e) : add(v,map(split-exp-e{_,full-name(loc(s)),info(s)},s)) + (s:DefNode) : add(v,map(split-exp-e{_,name(s),info(s)},s)) + (s) : add(v,map(split-exp-e{_,false,info(s)},s)) false - defn split-exp-e (e:Expression,v:Vector<Stmt>,n:Symbol|False,info:FileInfo) -> Expression : - match(map(split-exp-e{_,v,n,info},e)): - (e:DoPrim) : - val n* = - if n typeof False : firrtl-gensym(`T) - else : firrtl-gensym(symbol-join([n as Symbol `__])) - add(v,DefNode(info,n*,e)) - WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER) - (e) : e Circuit{info(c),_,main(c)} $ for m in modules(c) map : - val v = Vector<Stmt>() - split-exp-s(body(m),v) - Module(info(m),name(m),ports(m),Begin(to-list(v))) + match(m) : + (m:InModule) : + val v = Vector<Stmt>() + val sh = get-sym-hash(m) + split-exp-s(body(m),v,sh) + InModule(info(m),name(m),ports(m),Begin(to-list(v))) + (m:ExModule) : m ;================= Bring to Real IR ======================== ; Returns a new Circuit with only real IR nodes. @@ -1874,5 +1933,60 @@ defn to-real-ir (c:Circuit) : Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : - Module(info(m),name(m), ports(m), to-stmt(body(m))) + match(m) : + (m:InModule) : InModule(info(m),name(m), ports(m), to-stmt(body(m))) + (m:ExModule) : m + +;================= 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) + 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-exp (e:Expression) -> Expression : + 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 : + match(map(to-exp,s)) : + (s:DefWire) : DefWire(info(s),rename(name(s)),type(s)) + (s:DefRegister) : DefRegister(info(s),rename(name(s)),type(s)) + (s:DefInstance) : DefInstance(info(s),rename(name(s)),module(s)) + (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s)) + (s:DefNode) : DefNode(info(s),rename(name(s)),value(s)) + (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),source(s),index(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 + diff --git a/src/main/stanza/primop.stanza b/src/main/stanza/primop.stanza index 34ede86c..0e343d74 100644 --- a/src/main/stanza/primop.stanza +++ b/src/main/stanza/primop.stanza @@ -5,6 +5,7 @@ defpackage firrtl/primops : import firrtl/ir-utils import firrtl/passes + public defn lower-and-type-primop (e:DoPrim) -> DoPrim : defn u () : UIntType(UnknownWidth()) defn s () : SIntType(UnknownWidth()) diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index 19472573..bee10177 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -38,6 +38,11 @@ defn remove-subfield (e:Expression) -> Expression : (e:Subfield) : Ref(to-symbol $ string-join $ [emit(exp(e)) "_" name(e)],type(e)) (e) : e +definterface VKind +defstruct WireKind <: VKind +defstruct RegKind <: VKind +defstruct SeqMemKind <: VKind +defstruct ComMemKind <: VKind ;============ Verilog Backend ============= @@ -109,7 +114,24 @@ defn emit (e:Expression) -> String : v = concat(v, [" ^ " emit(x)]) v -defn emit-module (m:Module) : +defn emit-module (m:InModule) : + val h = HashTable<Symbol,VKind>(symbol-hash) + defn build-table (m:InModule) : + defn build-table (s:Stmt) -> Stmt : + match(map(build-table,s)) : + (s:DefWire) : h[name(s)] = WireKind() + (s:DefMemory) : + if seq?(s) : h[name(s)] = SeqMemKind() + else : h[name(s)] = ComMemKind() + (s:Connect) : + match(exp(s)) : + (e:Register) : h[name(loc(s) as Ref)] = RegKind() + (e) : false + (s) : false + s + build-table(body(m)) + build-table(m) + val wires = Vector<Streamable>() val regs = Vector<Streamable>() val inits = Vector<Streamable>() @@ -117,39 +139,36 @@ defn emit-module (m:Module) : val updates = Vector<Streamable>() val insts = HashTable<Symbol,Symbol>(symbol-hash) ; inst -> module val inst-ports = HashTable<Symbol,Vector<Streamable>>(symbol-hash) + + val sh = get-sym-hash(m) defn emit-s (s:Stmt) : match(map(remove-subfield,s)) : - (s:DefWire) : add(wires,["wire " get-width(type(s)) " " name(s) ";"]) + (s:DefWire) : + if h[name(s)] == RegKind() : + add(regs,["reg " get-width(type(s)) " " name(s) ";"]) + else : + add(wires,["wire " get-width(type(s)) " " name(s) ";"]) (s:DefInstance) : inst-ports[name(s)] = Vector<Streamable>() insts[name(s)] = name(module(s) as Ref) for f in fields(type(module(s)) as BundleType) do : - ;val sf = value(s) as Subfield - ;val e = exp(sf) as Ref val n* = to-symbol $ string-join $ [name(s) "_" name(f)] add(wires,["wire " get-width(type(f)) " " n* ";"]) add(inst-ports[name(s)], ["." name(f) "( " n* " )"]) (s:DefMemory) : val vtype = type(s) as VectorType - val innerwidth = - add(regs,["reg " get-width(type(vtype)) " " name(s) " [0:" size(vtype) "];"]) - add(inits,["for (initvar = 0; initvar < " size(vtype) "; initvar = initvar+1)"]) - add(inits,[name(s) " = {" width!(type(vtype)) "{$random}};"]) - (s:DefNode) : - if value(s) typeof Register : - val reg = value(s) as Register - add(regs,["reg " get-width(type(reg)) " " name(s) ";"]) - add(inits,[name(s) " = {" width!(type(reg)) "{$random}};"]) - add(updates,["if(" emit(enable(reg)) ") begin"]) - add(updates,[" " name(s) " <= " emit(value(reg)) ";"]) - add(updates,["end"]) - else if value(s) typeof ReadPort : - val rp = value(s) as ReadPort - add(assigns,["assign " name(s) " = " emit(mem(rp)) "[" emit(index(rp)) "];"]) + if seq?(s) : + add(regs,["reg " get-width(type(vtype)) " " name(s) " [0:" size(vtype) "];"]) + add(inits,["for (initvar = 0; initvar < " size(vtype) "; initvar = initvar+1)"]) + add(inits,[name(s) " = {" width!(type(vtype)) "{$random}};"]) else : - add(wires,["wire " get-width(type(value(s))) " " name(s) ";"]) - add(assigns,["assign " name(s) " = " emit(value(s)) ";"]) + add(regs,["reg " get-width(type(vtype)) " " name(s) " [0:" size(vtype) "];"]) + add(inits,["for (initvar = 0; initvar < " size(vtype) "; initvar = initvar+1)"]) + add(inits,[name(s) " = {" width!(type(vtype)) "{$random}};"]) + (s:DefNode) : + add(wires,["wire " get-width(type(value(s))) " " name(s) ";"]) + add(assigns,["assign " name(s) " = " emit(value(s)) ";"]) (s:Begin) : do(emit-s, body(s)) (s:Connect) : if loc(s) typeof WritePort : @@ -158,7 +177,29 @@ defn emit-module (m:Module) : add(updates,[" " emit(mem(wp)) "[" emit(index(wp)) "] <= " emit(exp(s)) ";"]) add(updates,["end"]) else : - add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"]) + if exp(s) typeof Register : + val n = name(loc(s) as Ref) + val reg = exp(s) as Register + add(inits,[n " = {" width!(type(reg)) "{$random}};"]) + add(updates,["if(" emit(enable(reg)) ") begin"]) + add(updates,[" " n " <= " emit(value(reg)) ";"]) + add(updates,["end"]) + else if exp(s) typeof ReadPort : + val n = name(loc(s) as Ref) + val rp = exp(s) as ReadPort + match(h[name(mem(rp) as Ref)]) : + (k:SeqMemKind) : + val index* = Ref(firrtl-gensym(name(index(rp) as Ref),sh),type(index(rp))) + add(regs,[ "reg " get-width(type(index*)) " " name(index*) ";"]) + add(inits,[name(index*) " = {" width!(type(index*)) "{$random}};"]) + add(updates,["if(" emit(enable(rp)) ") begin"]) + add(updates,[" " name(index*) " <= " emit(index(rp)) ";"]) + add(updates,["end"]) + add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index*) "];"]) + (k:ComMemKind) : + add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index(rp)) "];"]) + else : + add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"]) (s) : s emit-s(body(m)) @@ -219,5 +260,8 @@ defn emit-module (m:Module) : public defn emit-verilog (file:String, c:Circuit) : with-output-file{file, _} $ fn () : for m in modules(c) do : - emit-module(m) + match(m) : + (m:InModule) : emit-module(m) + (m:ExModule) : false + c |
