From cf80ff9c83c2fedd42ec186a3e342520c89f91ab Mon Sep 17 00:00:00 2001 From: azidar Date: Tue, 26 May 2015 17:33:40 -0700 Subject: Added <>. Added additional checks for primops. Added new chisel3 files. --- src/main/stanza/errors.stanza | 210 ++++++++++++++++++++++++++++++++++----- src/main/stanza/firrtl-ir.stanza | 4 + src/main/stanza/ir-parser.stanza | 1 + src/main/stanza/ir-utils.stanza | 3 + src/main/stanza/passes.stanza | 32 +++++- src/main/stanza/primop.stanza | 1 + 6 files changed, 223 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index 8c5532b0..e8b00087 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,6 +42,9 @@ 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 @@ -94,6 +96,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 @@ -134,6 +152,49 @@ defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False : is? = false is? +defn check-high-form-primop (e:DoPrim, errors:Vector,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 : val errors = Vector() @@ -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) -> Expression : match(map(check-high-form-e{info,_,names},e)) : (e:Ref) : @@ -157,10 +232,13 @@ 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) -> Stmt : @@ -169,6 +247,8 @@ public defn check-high-form (c:Circuit) -> Circuit : val prefix = is-prefix?(name,names) 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,6 +291,9 @@ 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) @@ -284,8 +369,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 +379,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)) @@ -309,7 +395,6 @@ public defn check-kinds (c:Circuit) -> Circuit : ;==================== 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 +433,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 +441,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 +482,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,info:FileInfo) -> False : + defn all-same-type (ls:List) -> 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) -> 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) -> 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() @@ -397,30 +557,27 @@ 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)) @@ -469,7 +626,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 +639,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 +666,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) diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index 39538498..e13e7655 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -134,6 +134,10 @@ public defstruct OnReset <: Stmt : ;LOW info: FileInfo with: (as-method => true) loc: Expression exp: Expression +public defstruct BulkConnect <: Stmt : ;LOW + info: FileInfo with: (as-method => true) + loc: Expression + exp: Expression public defstruct Connect <: Stmt : ;LOW info: FileInfo with: (as-method => true) loc: Expression diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 0833543f..2f7b3771 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -194,6 +194,7 @@ defsyntax firrtl : 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..28cdd136 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -147,6 +147,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) : @@ -231,6 +233,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 diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index b6926a7b..96225064 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -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 : @@ -504,7 +509,7 @@ defn infer-types (s:Stmt, l:List>) -> [Stmt List>) -> Module : val ptypes = @@ -607,6 +612,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) : @@ -742,7 +749,6 @@ 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 : defn uniquify (n*:Symbol) -> Symbol : symbol-join([n "_" n*]) match(t) : @@ -863,6 +869,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() + val rs* = Vector() + 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-hash) for e in exps(s) do : diff --git a/src/main/stanza/primop.stanza b/src/main/stanza/primop.stanza index 023723b8..7abfa94e 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()) -- cgit v1.2.3 From a2a48576534f87b28566504bb1e0c7faa493f463 Mon Sep 17 00:00:00 2001 From: azidar Date: Wed, 27 May 2015 15:43:15 -0700 Subject: Added external modules. Switched lower firrtl back to wire r; r := Register, instead of using nodes. Added a renaming pass for different backends. This will likely get deprecated, as a more robust name mangling scheme could be needed --- src/main/stanza/compilers.stanza | 9 +- src/main/stanza/errors.stanza | 55 +++++--- src/main/stanza/firrtl-ir.stanza | 18 ++- src/main/stanza/flo.stanza | 14 +- src/main/stanza/ir-parser.stanza | 8 +- src/main/stanza/ir-utils.stanza | 14 +- src/main/stanza/passes.stanza | 295 +++++++++++++++++++++++++-------------- src/main/stanza/verilog.stanza | 53 ++++--- 8 files changed, 305 insertions(+), 161 deletions(-) (limited to 'src') diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index 762ed9a8..efa8c992 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 : to-list $ [ - CheckHighForm() + CheckHighForm(expand-delin) TempElimination() ToWorkingIR() MakeExplicitReset() @@ -31,6 +31,9 @@ public defmethod passes (c:StandardFlo) -> List : Inline() SplitExp() ToRealIR() + SpecialRename(`#,`_) + SpecialRename(`$,`::) + CheckHighForm(`::) Flo(file(c)) ] @@ -38,7 +41,7 @@ public defstruct StandardVerilog <: Compiler : file: String with: (as-method => true) public defmethod passes (c:StandardVerilog) -> List : to-list $ [ - CheckHighForm() + CheckHighForm(expand-delin) TempElimination() ToWorkingIR() MakeExplicitReset() @@ -53,9 +56,9 @@ public defmethod passes (c:StandardVerilog) -> List : ExpandIndexedConnects() ExpandWhens() InferWidths() - ;Inline() SplitExp() ToRealIR() + SpecialRename(`#,`_) Verilog(file(c)) ] diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index e8b00087..0795a2a9 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -46,8 +46,9 @@ defpackage firrtl/errors : ; * 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" @@ -132,26 +133,25 @@ defn contains? (c:?T,cs:Streamable) -> True|False : if x == c : myret(true) false -defn is-prefix? (s:Symbol,v:Vector) -> Symbol|False : +defn is-prefix? (s:Symbol,v:Vector,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 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,info:FileInfo) -> False : defn correct-num (ne:Int|False,nc:Int) -> False : if not (ne typeof False) : @@ -196,7 +196,7 @@ defn check-high-form-primop (e:DoPrim, errors:Vector,info:FileInf 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() defn check-valid-loc (info:FileInfo,e:Expression) -> False : @@ -244,7 +244,7 @@ public defn check-high-form (c:Circuit) -> Circuit : defn check-high-form-s (s:Stmt,names:Vector) -> 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) @@ -297,7 +297,9 @@ public defn check-high-form (c:Circuit) -> Circuit : 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 @@ -389,7 +391,9 @@ 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 @@ -580,7 +584,9 @@ public defn check-types (c:Circuit) -> Circuit : 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 @@ -682,6 +688,9 @@ public defn check-genders (c:Circuit) -> Circuit : val genders = HashTable(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 e13e7655..eef48b11 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 @@ -167,12 +170,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 + +public defstruct InModule <: Module : info: FileInfo - name: Symbol - ports: List + name: Symbol with: (as-method => true) + ports: List with: (as-method => true) body: Stmt +public defstruct ExModule <: Module : + info: FileInfo + name: Symbol with: (as-method => true) + ports: List with: (as-method => true) + public defstruct Circuit : info: FileInfo modules: List diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza index e870d7ed..0f1f4eeb 100644 --- a/src/main/stanza/flo.stanza +++ b/src/main/stanza/flo.stanza @@ -32,15 +32,15 @@ defn pad-widths-e (desired:Int,e:Expression) -> Expression : if i > desired : DoPrim(BITS-SELECT-OP,list(e),list(0,desired),set-width(desired,type(e))) else if i == desired : e* - else : DoPrim(PAD-OP,list(e*),list(),set-width(desired,type(e*))) + else : DoPrim(PAD-OP,list(e*),list(desired),set-width(desired,type(e*))) else : e - (e:WRef|WSubfield|WIndex) : + (e:WRef|WSubfield|WIndex|Register|ReadPort) : println(e) val i = int-width!(type(e)) if i > desired : DoPrim(BITS-SELECT-OP,list(e),list(0,desired),set-width(desired,type(e))) else if i == desired : e - else : DoPrim(PAD-OP,list(e),list(),set-width(desired,type(e))) + else : DoPrim(PAD-OP,list(e),list(desired),set-width(desired,type(e))) (e:UIntValue) : val i = int-width!(type(e)) if i > desired : @@ -64,7 +64,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 ================ @@ -224,7 +226,7 @@ defn emit-s (s:Stmt, v:List, top:Symbol) : error("Unknown Connect") (s) : s -defn emit-module (m:Module) : +defn emit-module (m:InModule) : val v = Vector() for port in ports(m) do : if name(port) ==`reset : @@ -236,6 +238,6 @@ defn emit-module (m:Module) : 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) false c diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 2f7b3771..db3324e4 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) diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 28cdd136..4271edca 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -18,6 +18,10 @@ public defn firrtl-gensym (s:Symbol) -> Symbol : public defn firrtl-gensym () -> Symbol : firrtl-gensym(`gen) + +;public defn get-sym-hash (m:Circuit) -> HashTable : + ;public defn get-sym-hash (c:Circuit) -> HashTable : + ;============== Exceptions ===================== @@ -183,7 +187,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") @@ -192,6 +196,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) diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 96225064..3e2a058b 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() @@ -309,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 @@ -335,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 @@ -372,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) @@ -422,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-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* = @@ -516,8 +528,11 @@ defn infer-types (m:Module, l:List>) -> Module : 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 = @@ -570,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 : @@ -703,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 @@ -750,7 +770,7 @@ defn index-of-elem (t:BundleType, s:Symbol) -> Int : error("Shouldn't be here") defn generate-entry (n:Symbol,t:Type) -> List : - 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 : @@ -936,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 : @@ -961,15 +985,15 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt : 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))),type(index(s)),NodeKind(),UNKNOWN-GENDER) append( list(DefNode(info(s),name(ref),index(s))) to-list $ @@ -983,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))),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 $ @@ -997,7 +1021,9 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt : (s) : map(expand-connect-indexed-stmt,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) : InModule(info(m),name(m),ports(m),expand-connect-indexed-stmt(body(m))) + (m:ExModule) : m defn expand-connect-indexed (c: Circuit) -> Circuit : Circuit(info(c),modules*, main(c)) where : @@ -1201,63 +1227,49 @@ defn expand-whens (ports:List, table:HashTable,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,decs:Vector,cons:Vector) -> 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 @@ -1267,9 +1279,7 @@ defn expand-whens (s:Stmt, table:HashTable,decs:Vector Module : - val assign = HashTable(symbol-hash) - val resets = HashTable(symbol-hash) - val flattn = HashTable(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() - val cons = Vector() - 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-hash) + val resets = HashTable(symbol-hash) + val flattn = HashTable(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() + val cons = Vector() + 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 : @@ -1680,7 +1693,9 @@ defn gen-constraints (m:Module, h:HashTable, v:Vector) -> 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) -> HashTable : defn build-environment (s:Stmt) -> False : @@ -1693,7 +1708,10 @@ defn build-environment (c:Circuit,m:Module,h:HashTable) -> 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) -> Circuit : @@ -1734,9 +1752,12 @@ defn reduce-var-widths (c:Circuit,h:HashTable) -> 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)) @@ -1786,7 +1807,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-hash) + val h = HashTable(symbol-hash) val h-s = HashTable(symbol-hash) defn inline-inst (s:Stmt) -> Stmt : match(map(inline-inst,s)) : @@ -1809,17 +1830,17 @@ 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 : @@ -1830,9 +1851,11 @@ defn inline-instances (c:Circuit) : (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 ======================== @@ -1867,16 +1890,19 @@ defn split-exp (c:Circuit) : (e:DoPrim) : val n* = if n typeof False : firrtl-gensym(`T) - else : firrtl-gensym(symbol-join([n as Symbol `__])) + else : firrtl-gensym(symbol-join([n as Symbol gen-delin])) 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() - split-exp-s(body(m),v) - Module(info(m),name(m),ports(m),Begin(to-list(v))) + match(m) : + (m:InModule) : + val v = Vector() + split-exp-s(body(m),v) + 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. @@ -1902,5 +1928,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() + 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)) + (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/verilog.stanza b/src/main/stanza/verilog.stanza index 19472573..79bccefb 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -109,7 +109,20 @@ defn emit (e:Expression) -> String : v = concat(v, [" ^ " emit(x)]) v -defn emit-module (m:Module) : +defn emit-module (m:InModule) : + val h = Vector() + defn build-table (m:InModule) : + defn build-table (s:Stmt) -> Stmt : + match(map(build-table,s)) : + (s:Connect) : + match(exp(s)) : + (e:Register) : add(h,name(loc(s) as Ref)) + (e) : false + (s) : false + s + build-table(body(m)) + build-table(m) + val wires = Vector() val regs = Vector() val inits = Vector() @@ -120,13 +133,15 @@ defn emit-module (m:Module) : defn emit-s (s:Stmt) : match(map(remove-subfield,s)) : - (s:DefWire) : add(wires,["wire " get-width(type(s)) " " name(s) ";"]) + (s:DefWire) : + if contains?(to-list $ h, name(s)) : + 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() 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* " )"]) @@ -137,17 +152,6 @@ defn emit-module (m:Module) : 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)) "];"]) - else : 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)) @@ -158,7 +162,19 @@ 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 + 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 +235,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 -- cgit v1.2.3 From b44b49e6a6589add30b5b1d89d85f2e20432a515 Mon Sep 17 00:00:00 2001 From: azidar Date: Wed, 27 May 2015 17:15:44 -0700 Subject: Added sequential memories. mem no longer exists, must declare either cmem or smem. Added firrtl-gensym utility to generate a hashmap of names --- src/main/stanza/firrtl-ir.stanza | 1 + src/main/stanza/flo.stanza | 12 ++++---- src/main/stanza/ir-parser.stanza | 3 +- src/main/stanza/ir-utils.stanza | 50 +++++++++++++++++++++++--------- src/main/stanza/passes.stanza | 61 ++++++++++++++++++++++------------------ src/main/stanza/verilog.stanza | 45 ++++++++++++++++++++++------- 6 files changed, 114 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index eef48b11..e92f4854 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -117,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 diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza index 0f1f4eeb..41de8f82 100644 --- a/src/main/stanza/flo.stanza +++ b/src/main/stanza/flo.stanza @@ -200,7 +200,7 @@ defn maybe-mov (e:Expression) -> String : (e) : false if need-mov?: "mov " else: "" -defn emit-s (s:Stmt, v:List, top:Symbol) : +defn emit-s (s:Stmt, v:List, top:Symbol,sh:HashTable) : match(s) : (s:DefWire) : "" (s:DefInstance) : error("Shouldn't be here") @@ -209,7 +209,7 @@ defn emit-s (s:Stmt, v:List, 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) : @@ -219,14 +219,14 @@ defn emit-s (s:Stmt, v:List, 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:InModule) : +defn emit-module (m:InModule,sh:HashTable) : val v = Vector() for port in ports(m) do : if name(port) ==`reset : @@ -234,10 +234,10 @@ defn emit-module (m:InModule) : 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] as InModule) + 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 db3324e4..cbfe106e 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -193,7 +193,8 @@ 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) diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 4271edca..c39a1ad1 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -9,19 +9,42 @@ public defmulti print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|M ;============== GENSYM STUFF ====================== -val sym-hash = HashTable(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 () -> Symbol : - firrtl-gensym(`gen) -;public defn get-sym-hash (m:Circuit) -> HashTable : - ;public defn get-sym-hash (c:Circuit) -> HashTable : +public defn firrtl-gensym (s:Symbol) -> Symbol : firrtl-gensym(s,HashTable(symbol-hash)) + +public defn firrtl-gensym (s:Symbol,sym-hash:HashTable) -> 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 (sym-hash:HashTable) -> Symbol : + firrtl-gensym(`gen,sym-hash) + +public defn get-sym-hash (m:InModule) -> HashTable : + val sym-hash = HashTable(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 ===================== @@ -131,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) : @@ -287,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 (f: Width -> Width, t:?T&Type) -> T diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 3e2a058b..80035325 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -866,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)) @@ -980,7 +980,7 @@ 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) -> Stmt : defn equality (e1:Expression,e2:Expression) -> Expression : DoPrim(EQUAL-OP,list(e1,e2),List(),UIntType(UnknownWidth())) defn get-name (e:Expression) -> Symbol : @@ -993,7 +993,7 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt : (s:ConnectToIndexed) : Begin $ if length(locs(s)) == 0 : list(EmptyStmt()) else : - val ref = WRef(firrtl-gensym(get-name(index(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 $ @@ -1007,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(index(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 $ @@ -1018,11 +1018,13 @@ 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 : match(m) : - (m:InModule) : InModule(info(m),name(m),ports(m),expand-connect-indexed-stmt(body(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 : @@ -1450,6 +1452,8 @@ public defstruct MaxWidth <: Width : public defstruct ExpWidth <: Width : arg1 : Width +val width-name-hash = HashTable(symbol-hash) + public defmulti map (f: Width -> Width, w:?T&Width) -> T defmethod map (f: Width -> Width, w:Width) -> Width : match(w) : @@ -1641,7 +1645,7 @@ defn gen-constraints (m:Module, h:HashTable, v:Vector) -> 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)) @@ -1677,14 +1681,14 @@ defn gen-constraints (m:Module, h:HashTable, v:Vector) -> 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 @@ -1763,7 +1767,7 @@ defn reduce-var-widths (c:Circuit,h:HashTable) -> Circuit : 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) @@ -1847,7 +1851,7 @@ defn inline-instances (c:Circuit) : 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 : @@ -1872,35 +1876,36 @@ defn full-name (e:Expression) -> Symbol : (e) : error("Non-supported expression.") defn split-exp (c:Circuit) : - defn split-exp-s (s:Stmt,v:Vector) -> False : + defn split-exp-s (s:Stmt,v:Vector,sh:HashTable) -> 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,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 gen-delin])) - 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 : match(m) : (m:InModule) : val v = Vector() - split-exp-s(body(m),v) + 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 @@ -1970,7 +1975,7 @@ public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) : (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)) + (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) diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index 79bccefb..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 ============= @@ -110,13 +115,17 @@ defn emit (e:Expression) -> String : v defn emit-module (m:InModule) : - val h = Vector() + val h = HashTable(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) : add(h,name(loc(s) as Ref)) + (e:Register) : h[name(loc(s) as Ref)] = RegKind() (e) : false (s) : false s @@ -130,11 +139,13 @@ defn emit-module (m:InModule) : val updates = Vector() val insts = HashTable(symbol-hash) ; inst -> module val inst-ports = HashTable>(symbol-hash) + + val sh = get-sym-hash(m) defn emit-s (s:Stmt) : match(map(remove-subfield,s)) : (s:DefWire) : - if contains?(to-list $ h, name(s)) : + if h[name(s)] == RegKind() : add(regs,["reg " get-width(type(s)) " " name(s) ";"]) else : add(wires,["wire " get-width(type(s)) " " name(s) ";"]) @@ -147,13 +158,17 @@ defn emit-module (m:InModule) : 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}};"]) + 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(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)) ";"]) + 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 : @@ -172,7 +187,17 @@ defn emit-module (m:InModule) : else if exp(s) typeof ReadPort : val n = name(loc(s) as Ref) val rp = exp(s) as ReadPort - add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index(rp)) "];"]) + 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 -- cgit v1.2.3 From ca49cb05f9e2fbeac1d0c722eb7d342f74508b7e Mon Sep 17 00:00:00 2001 From: azidar Date: Fri, 29 May 2015 11:34:51 -0700 Subject: Added custom pass. Does not correctly run, stanza just spins. Requires debugging. --- src/main/stanza/custom-compiler.stanza | 38 ++++++++++++++++ src/main/stanza/custom-passes.stanza | 81 +++++++++++++++++++++++++++++++++ src/main/stanza/firrtl-ir.stanza | 4 +- src/main/stanza/firrtl-test-main.stanza | 13 ++++++ 4 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/main/stanza/custom-compiler.stanza create mode 100644 src/main/stanza/custom-passes.stanza (limited to 'src') 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 +public defmethod passes (c:InstrumentedVerilog) -> List : + 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..d47f6661 --- /dev/null +++ b/src/main/stanza/custom-passes.stanza @@ -0,0 +1,81 @@ +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 : + 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 when-coverage (port-name:Symbol, reg-name:Symbol, m:InModule) -> InModule : + val when-bits = Vector() + val inst-bits = Vector() + val sym = HashTable(symbol-hash) + val w1 = IntWidth(1) + val t1 = UIntType(w1) + val u1 = UIntValue(1,w1) + defn when-coverage (s:Stmt) -> Stmt : + map{when-coverage,_} $ 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))) + Conditionally(info(s),pred(s),conseq*,alt(s)) + (s:DefInstance) : + val ref = Ref(firrtl-gensym(port-name,sym),t1) + add(inst-bits,ref) + val sfld = Subfield(Ref(name(s),UnknownType()),port-name,UnknownType()) + Begin(list(s,Connect(FileInfo(),ref,sfld))) + (s) : s + + val body* = when-coverage(body(m)) + val logic = Vector() + + 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 : + val port-ref = Ref(port-name,UIntType(UnknownWidth())) + 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())) + 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 modules* = for m in modules(c) map : + match(m) : + (m:InModule) : + when-coverage(to-symbol $ port-name,to-symbol $ reg-name,m) + (m:ExModule) : m + Circuit(info(c),modules*,main(c)) + diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index e92f4854..18e069b4 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -134,11 +134,11 @@ public defstruct Conditionally <: Stmt : alt: Stmt public defstruct Begin <: Stmt : ;LOW body: List -public defstruct OnReset <: Stmt : ;LOW +public defstruct OnReset <: Stmt : info: FileInfo with: (as-method => true) loc: Expression exp: Expression -public defstruct BulkConnect <: Stmt : ;LOW +public defstruct BulkConnect <: Stmt : info: FileInfo with: (as-method => true) loc: Expression exp: Expression diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza index 5a7e593d..1a8f6780 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) : if contains(p,'t') : PRINT-TYPES = true @@ -42,11 +49,13 @@ defn get-passes (pass-names:List) -> List : p as Pass defn main () : + println("HERE") val args = commandline-arguments() var input = false var output = false var compiler = false val pass-names = Vector() + val pass-args = Vector() var printvars = "" for (s in args, i in 0 to false) do : if s == "-i" : input = args[i + 1] @@ -54,7 +63,9 @@ 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]) + println("THERE") if input == false : error("No input file provided. Use -i flag.") if output == false : @@ -66,12 +77,14 @@ defn main () : val c = parse-firrtl(lexed) set-printvars!(to-list(printvars)) + println("EVERYWHERE") if compiler == false : run-passes(c,get-passes(to-list(pass-names))) else : 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() -- cgit v1.2.3 From f21ddd8d016b8e8a098f19ad2fa76060408c4f25 Mon Sep 17 00:00:00 2001 From: azidar Date: Fri, 29 May 2015 12:22:59 -0700 Subject: Added new stanza --- src/lib/stanza.zip | Bin 3716930 -> 3729434 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'src') diff --git a/src/lib/stanza.zip b/src/lib/stanza.zip index aed19c22..8dc3ea0a 100644 Binary files a/src/lib/stanza.zip and b/src/lib/stanza.zip differ -- cgit v1.2.3 From 8fc826a2770f46d63d8d7b1bccf14d2bf6e6b7cd Mon Sep 17 00:00:00 2001 From: azidar Date: Fri, 29 May 2015 12:23:45 -0700 Subject: Fixed bugs in when-coverage pass. Works but has not been thoroughly tested --- src/main/stanza/custom-passes.stanza | 47 +++++++++++++++++++++++++-------- src/main/stanza/firrtl-test-main.stanza | 3 --- 2 files changed, 36 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/main/stanza/custom-passes.stanza b/src/main/stanza/custom-passes.stanza index d47f6661..e4c3d9d3 100644 --- a/src/main/stanza/custom-passes.stanza +++ b/src/main/stanza/custom-passes.stanza @@ -23,7 +23,23 @@ defn concat-all (ls:List) -> Expression : ;============ When Coverage Pass ============= ;port width = 1 bit per scope + portwidths of all instances -defn when-coverage (port-name:Symbol, reg-name:Symbol, m:InModule) -> InModule : +defn needs-instrumentation (m:Module,ms:List,instrument?:HashTable) -> 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, m:InModule) -> InModule : val when-bits = Vector() val inst-bits = Vector() val sym = HashTable(symbol-hash) @@ -31,21 +47,24 @@ defn when-coverage (port-name:Symbol, reg-name:Symbol, m:InModule) -> InModule : val t1 = UIntType(w1) val u1 = UIntValue(1,w1) defn when-coverage (s:Stmt) -> Stmt : - map{when-coverage,_} $ match(s) : + 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))) - Conditionally(info(s),pred(s),conseq*,alt(s)) + map(when-coverage,Conditionally(info(s),pred(s),conseq*,alt(s))) (s:DefInstance) : - val ref = Ref(firrtl-gensym(port-name,sym),t1) - add(inst-bits,ref) - val sfld = Subfield(Ref(name(s),UnknownType()),port-name,UnknownType()) - Begin(list(s,Connect(FileInfo(),ref,sfld))) - (s) : s + 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() + val port-ref = Ref(port-name,UIntType(UnknownWidth())) val w-ls = to-list $ when-bits if length(w-ls) != 0 : @@ -59,11 +78,11 @@ defn when-coverage (port-name:Symbol, reg-name:Symbol, m:InModule) -> InModule : val i-ls = to-list $ inst-bits if length(i-ls) != 0 : - val port-ref = Ref(port-name,UIntType(UnknownWidth())) 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())) - add{logic,_} $ Connect(FileInfo(),port-ref,concat-all(append(w-ls,i-ls))) + + 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)) @@ -72,10 +91,16 @@ defn when-coverage (port-name:Symbol, reg-name:Symbol, m:InModule) -> InModule : else : m public defn when-coverage (port-name:String, reg-name:String, c:Circuit) : + val instrument? = HashTable(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,m) + 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/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza index 1a8f6780..071717bb 100644 --- a/src/main/stanza/firrtl-test-main.stanza +++ b/src/main/stanza/firrtl-test-main.stanza @@ -49,7 +49,6 @@ defn get-passes (pass-names:List) -> List : p as Pass defn main () : - println("HERE") val args = commandline-arguments() var input = false var output = false @@ -65,7 +64,6 @@ defn main () : if s == "-p" : printvars = args[i + 1] if s == "-s" : add(pass-args,args[i + 1]) - println("THERE") if input == false : error("No input file provided. Use -i flag.") if output == false : @@ -77,7 +75,6 @@ defn main () : val c = parse-firrtl(lexed) set-printvars!(to-list(printvars)) - println("EVERYWHERE") if compiler == false : run-passes(c,get-passes(to-list(pass-names))) else : -- cgit v1.2.3