diff options
| author | jackbackrack | 2015-05-14 13:39:56 -0700 |
|---|---|---|
| committer | jackbackrack | 2015-05-14 13:39:56 -0700 |
| commit | 369a6d9ee974f7ca825174e053742e0d4f440575 (patch) | |
| tree | 1fa3fc4a103505d4b5eac777d320bc825dd90de5 /src | |
| parent | 54c33b61ff2c6da7fcd717885316604ecc559c25 (diff) | |
| parent | 521a4277bfc1d764dc9ee771c604200525e871cb (diff) | |
merge
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/stanza/errors.stanza | 504 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 20 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-test-main.stanza | 1 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 30 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 38 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 324 |
6 files changed, 649 insertions, 268 deletions
diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index b0dbca68..30414afd 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -7,100 +7,95 @@ defpackage firrtl/errors : import firrtl/passes import firrtl-main +; TODO +; make sure it compiles, write tests, look over code to make sure its right ;========== ALL CHECKS ================= -;CAUGHT IN PARSER -; No nested modules <- parser -; Only modules in circuit (no statements or expressions) <- parser - -;CAUGHT in HIGH FORM CHECK -; Unique names per module -; No name can be a prefix of any other name. -; Can only connect to a Ref or Subfield or Index -; UInt only has positive ints -; all references are declared -; mems cannot be a bundle with flips -; cannot connect to Register or ReadPort - -;AFTER KIND RESOLUTION -; Cannot connect directly to a mem ever -; onreset can only handle a register - -;AFTER TYPE INFERENCE -; expression in pad must be a ground type -; Subfields are only on bundles, before type inference <- need to not error, just do unknown-type -; node's value cannot be a bundle with a flip in it -; 2nd arg in dshr/l must be UInt -; pred in conditionally must be of type UInt -; Type checking +;PARSER CHECK +; * No nested modules <- parser +; * Only modules in circuit (no statements or expressions) <- parser +; * Module must be a reference in inst declaration + +;AFTER GENDER INFERENCE +; o Nodes always male +; o Accessors only have one gender, unless rdwr +; o output/input only one gender +; o correctly check for the base bundle ;AFTER WIDTH INFERENCE -; No names -; No Unknowns -; All widths are positive -; Pad's width is greater than value's width -; pad's width is greater than value's width +; 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 ;AFTER LOWERING -; All things connect to once - -; ?? -; No combinational loops -; cannot connect to a pad, or a register. only connct to a reference +; o All things connect to once +; o no reg +; o no accessors -definterface HighFormException <: Exception -defn HighFormException (s:String) : - new HighFormException : - defmethod print (o:OutputStream, this) : - print(o, s) +;AFTER ?????? +; o No combinational loops +; o cannot connect to a pad, or a register. only connct to a reference -defn HighFormExceptions (xs:Streamable<HighFormException>) : - HighFormException(string-join(xs, "\n")) +;================= High Form Check ========================== +; * Subexps of Subfield and Index can only be subfields, index, or refs +; * Can only connect to a Ref or Subfield or Index or WritePort +; * A module has the same name as main of circuit +; * mems cannot be a bundle with flips +; * instance module must have the same name as a defined module +; * reset must be UInt<1> +; * Unique names per module +; * No name can be a prefix of any other name. +; * all references are declared +; * UInt only has positive ints -defn NotUnique (info:FileInfo|False, name:Symbol) : - HighFormException $ string-join $ +;----------------- Errors ------------------------ +defn NotUnique (info:FileInfo, name:Symbol) : + PassException $ string-join $ [info ": Reference " name " does not have a unique name."] -defn IsPrefix (info:FileInfo|False, name1:Symbol, name2:Symbol) : - HighFormException $ string-join $ +defn IsPrefix (info:FileInfo, name1:Symbol, name2:Symbol) : + PassException $ string-join $ [info ": Reference " name1 " and " name2 " share a prefix."] -defn InvalidLOC (info:FileInfo|False) : - HighFormException $ string-join $ +defn InvalidLOC (info:FileInfo) : + PassException $ string-join $ [info ": Invalid connect to an expression that is not a reference or a WritePort."] -defn NegUInt (info:FileInfo|False) : - HighFormException $ string-join $ - [info ": UInt has a negative value."] +defn NegUInt (info:FileInfo) : + PassException $ string-join $ + [info ": UIntValue cannot be negative."] -defn UndeclaredReference (info:FileInfo|False, name:Symbol) : - HighFormException $ string-join $ +defn UndeclaredReference (info:FileInfo, name:Symbol) : + PassException $ string-join $ [info ": Reference " name " is not declared."] -defn MemWithFlip (info:FileInfo|False, name:Symbol) : - HighFormException $ string-join $ +defn MemWithFlip (info:FileInfo, name:Symbol) : + PassException $ string-join $ [info ": Memory " name " cannot be a bundle type with flips."] -defn InvalidSubfield (info:FileInfo|False, name:Symbol) : - HighFormException $ string-join $ +defn InvalidSubfield (info:FileInfo) : + PassException $ string-join $ [info ": Invalid subfield access to non-reference."] -defn InvalidIndex (info:FileInfo|False, name:Symbol) : - HighFormException $ string-join $ +defn InvalidIndex (info:FileInfo) : + PassException $ string-join $ [info ": Invalid index access to non-reference."] -defn NoTopModule (info:FileInfo|False, name:Symbol) : - HighFormException $ string-join $ +defn NoTopModule (info:FileInfo, name:Symbol) : + PassException $ string-join $ [info ": A single module must be named " name "."] -defn InstNotModule (info:FileInfo|False, name:Symbol) : - HighFormException $ string-join $ - [info ": The referenced module in the instance declaration, " name ", is not a reference."] +defn ModuleNotDefined (info:FileInfo, name:Symbol) : + PassException $ string-join $ + [info ": Module " name " is not defined."] -defn ModuleNotDefined (info:FileInfo|False, name:Symbol) : - HighFormException $ string-join $ - [info ": The referenced module in the instance declaration, " name ", is not defined."] +defn WrongReset (info:FileInfo, name:Symbol) : + PassException $ string-join $ + [info ": Module " name " has a reset that is not of type UInt<1>."] -;================ Check Helper Functions ============== +;---------------- Helper Functions -------------- defn has-flip? (t:Type) -> True|False : var has? = false defn find-flip (t:Type) -> Type : @@ -136,46 +131,85 @@ defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False : 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? -;================= High Form Check ========================== -;CAUGHT in HIGH FORM CHECK -; o Unique names per module -; o No name can be a prefix of any other name. -; o Can only connect to a Ref or Subfield or Index -; o UInt only has positive ints -; o all references are declared -; o cannot connect to Register or ReadPort -; * A module has the same name as main of circuit -; * mems cannot be a bundle with flips -; o instance module must be a reference with same name as defined module -; o reset must be UInt<1> - +;--------------- Check High Form Pass ------------------- public defn check-high-form (c:Circuit) -> Circuit : - val errors = Vector<HighFormException>() + val errors = Vector<PassException>() + + defn check-valid-loc (info:FileInfo,e:Expression) -> False : + match(e) : + (e:UIntValue|SIntValue|DoPrim|ReadPort|Register|Pad) : + add(errors,InvalidLOC(info)) + (e) : false + + defn check-high-form-e (info:FileInfo,e:Expression,names:Vector<Symbol>) -> Expression : + match(map(check-high-form-e{info,_,names},e)) : + (e:Ref) : + if not contains?(name(e),names) : + add(errors,UndeclaredReference(info,name(e))) + (e:Subfield) : + match(exp(e)) : + (e:Ref|Subfield|Index) : false + (e) : add(errors,InvalidSubfield(info)) + (e:Index) : + match(exp(e)) : + (e:Ref|Subfield|Index) : false + (e) : add(errors,InvalidIndex(info)) + (e:UIntValue) : + if value(e) < 0 : + add(errors,NegUInt(info)) + (e) : false + e defn check-high-form-s (s:Stmt,names:Vector<Symbol>) -> Stmt : - defn check-name (info:FileInfo|False,name:Symbol) -> False : + defn check-name (info:FileInfo,name:Symbol) -> False : if contains?(name,names) : add(errors,NotUnique(info,name)) val prefix = is-prefix?(name,names) if prefix typeof Symbol : add(errors,IsPrefix(info,name,prefix as Symbol)) map{check-high-form-s{_,names},_} $ { - match(s) : - (s:DefWire|DefRegister) : check-name(info!(s),name(s)) + match(map(check-high-form-e{info(s),_,names},s)) : + (s:DefWire|DefRegister) : + check-name(info(s),name(s)) + add(names,name(s)) (s:DefMemory) : - check-name(info!(s),name(s)) - if has-flip?(type(s)) : add(errors, MemWithFlip(info!(s), name(s))) + check-name(info(s),name(s)) + add(names,name(s)) + if has-flip?(type(s)) : add(errors, MemWithFlip(info(s), name(s))) (s:DefInstance) : - if not (module(s) typeof Ref) : add(errors, InstNotModule(info!(s),name(s))) - else : - if not contains?(name(module(s) as Ref),map(name,modules(c))) : - add(errors, ModuleNotDefined(info!(s),name(s))) + if not contains?(name(module(s) as Ref),map(name,modules(c))) : + add(errors, ModuleNotDefined(info(s),name(module(s) as Ref))) + add(names,name(s)) + (s:DefNode) : + add(names,name(s)) + (s:DefAccessor) : + add(names,name(s)) + (s:Connect) : + check-valid-loc(info(s),loc(s)) (s) : false s }() defn check-high-form-m (m:Module) -> False : val names = Vector<Symbol>() + for m in modules(c) do : + add(names,name(m)) + for p in ports(m) do : + add(names,name(p)) + if name(p) == `reset : + if direction(p) == OUTPUT : + add(errors,WrongReset(info!(m),name(m))) + else : + if type(p) typeof UIntType : + if width(type(p) as UIntType) != IntWidth(1) : + add(errors,WrongReset(info!(m),name(m))) + else : + add(errors,WrongReset(info!(m),name(m))) + + + add(names,`reset) check-high-form-s(body(m),names) false @@ -184,7 +218,295 @@ public defn check-high-form (c:Circuit) -> Circuit : if name(m) == main(c) : number-top-m = number-top-m + 1 check-high-form-m(m) if number-top-m != 1 : add(errors,NoTopModule(info!(c),main(c))) - throw(HighFormExceptions(errors)) when not empty?(errors) + throw(PassExceptions(errors)) when not empty?(errors) + c + +;================= KIND CHECK ========================== +; o Cannot connect directly to a mem ever +; o onreset can only handle a register +; o Cannot use a mem in anything except an accessor, Readport, or Writeport + +;----------------- Errors --------------------- +defn NotMem (info:FileInfo, name:Symbol) : + PassException $ string-join $ + [info ": Reference " name " must be a mem."] + +defn IsMem (info:FileInfo, name:Symbol) : + PassException $ string-join $ + [info ": Reference " name " cannot be a mem."] + +defn OnResetNotReg (info:FileInfo, name:Symbol) : + PassException $ string-join $ + [info ": Illegal on-reset to non-reg reference " name "."] + +;----------------- Check Kinds Pass --------------------- +; I may have been overeager in looking for places where mems can't be, as mems are guaranteed to have a vector +; type, and this will get caught in the type check pass +public defn check-kinds (c:Circuit) -> Circuit : + val errors = Vector<PassException>() + defn check-not-mem (info:FileInfo,e:Expression) -> False : + do(check-not-mem{info,_},e) + match(e) : + (e:WRef) : if kind(e) == MemKind() : add(errors,IsMem(info,name(e))) + (e:WSubfield) : check-not-mem(info,exp(e)) + (e:WIndex) : check-not-mem(info,exp(e)) + (e) : false + defn check-is-reg (info:FileInfo,e:Expression) -> False : + do(check-is-reg{info,_},e) + match(e) : + (e:WRef) : if kind(e) != RegKind() : add(errors,OnResetNotReg(info,name(e))) + (e:WSubfield) : check-is-reg(info,exp(e)) + (e:WIndex) : check-is-reg(info,exp(e)) + (e) : false + defn check-is-mem (info:FileInfo,e:Expression) -> False : + do(check-is-mem{info,_},e) + match(e) : + (e:WRef) : if kind(e) != MemKind() : add(errors,NotMem(info,name(e))) + (e:WSubfield) : check-is-mem(info,exp(e)) + (e:WIndex) : check-is-mem(info,exp(e)) + (e) : false + + defn check-kinds-e (info:FileInfo,e:Expression) -> False : + do(check-kinds-e{info,_},e) + match(e) : + (e:ReadPort) : + check-is-mem(info,mem(e)) + check-not-mem(info,index(e)) + check-not-mem(info,enable(e)) + (e:WritePort) : + 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) + match(s) : + (s:DefNode) : check-not-mem(info(s),value(s)) + (s:DefAccessor) : check-not-mem(info(s),index(s)) + (s:Conditionally) : check-not-mem(info(s),pred(s)) + (s:Connect) : + 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)) + (s) : false + do(check-kinds-s,s) + + for m in modules(c) do : + 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 +; o enable/index in read/writeports must be UInt +; o node's value cannot be a bundle with a flip in it +; o := has same types +; o 2nd arg in dshr/l must be UInt, in general do primops + +;----------------- Errors --------------------- +defn SubfieldNotInBundle (info:FileInfo, name:Symbol) : + PassException $ string-join $ + [info ": Subfield " name " is not in bundle."] + +defn SubfieldOnNonBundle (info:FileInfo, name:Symbol) : + PassException $ string-join $ + [info ": Subfield " name " is accessed on a non-bundle."] + +defn IndexTooLarge (info:FileInfo, value:Int) : + PassException $ string-join $ + [info ": Index with value " value " is too large."] + +defn IndexOnNonVector (info:FileInfo) : + PassException $ string-join $ + [info ": Index illegal on non-vector type."] + +defn IndexNotUInt (info:FileInfo) : + PassException $ string-join $ + [info ": Index is not of UIntType."] + +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."] + +defn PredNotUInt (info:FileInfo) : + PassException $ string-join $ + [info ": Predicate not a UIntType."] + +;---------------- Helper Functions -------------- +defmethod equal? (t1:Type,t2:Type) -> True|False : + match(t1,t2) : + (t1:UIntType,t2:UIntType) : true + (t1:SIntType,t2:SIntType) : true + (t1:BundleType,t2:BundleType) : + var same? = true + for (f1 in fields(t1),f2 in fields(t2)) do : + if flip(f1) != flip(f2) : same? = false + if name(f1) != name(f2) : same? = false + if type(f1) != type(f2) : same? = false + same? + (t1:VectorType,t2:VectorType) : + if type(t1) == type(t2) and size(t1) == size(t2) : true + else : false + (t1,t2) : false + +defn u () -> UIntType : UIntType(UnknownWidth()) +defn s () -> SIntType : SIntType(UnknownWidth()) + +;----------------- Check Types Pass --------------------- +public defn check-types (c:Circuit) -> Circuit : + val errors = Vector<PassException>() + defn check-types-e (info:FileInfo,e:Expression) -> Expression : + match(map(check-types-e{info,_},e)) : + (e:WRef) : e + (e:WSubfield) : + match(type(exp(e))) : + (t:BundleType) : + val ft = for p in fields(t) find : name(p) == name(e) + if ft == false : add(errors,SubfieldNotInBundle(info,name(e))) + (t) : add(errors,SubfieldOnNonBundle(info,name(e))) + (e:WIndex) : + match(type(exp(e))) : + (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: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 + + for m in modules(c) do : + check-types-s(body(m)) + throw(PassExceptions(errors)) when not empty?(errors) + c + +;================= GENDER CHECK ========================== +; o Nodes always male +; o Accessors only have one gender, unless rdwr +; o output/input only one gender +; o correctly check for the base bundle + +;----------------- Errors --------------------- +defn WrongGender (info:FileInfo,expr:Symbol,wrong:Symbol,right:Symbol) : + PassException $ string-join $ + [info ": Expression " expr "has gender " wrong " but requires gender " right "."] + +defn UnknownGenders (info:FileInfo,name:Symbol) : + PassException $ string-join $ + [info ": Accessor " name " has an unknown gender."] + +;---------------- Helper Functions -------------- +defn dir-to-gender (d:Direction) -> Gender : + switch {_ == d} : + INPUT : MALE + OUTPUT : FEMALE + +;----------------- Check Genders Pass --------------------- + +public defn check-genders (c:Circuit) -> Circuit : + val errors = Vector<PassException>() + defn check-gender (info:FileInfo,genders:HashTable<Symbol,Gender>,e:Expression,right:Gender) -> False : + val gender = get-gender(e,genders) + if gender != right and gender != BI-GENDER: + add(errors,WrongGender(info,to-symbol(e),to-symbol(gender),to-symbol(right))) + + defn get-gender (e:Expression,genders:HashTable<Symbol,Gender>) -> Gender : + match(e) : + (e:WRef) : genders[name(e)] + (e:WSubfield) : + val f = {_ as Field} $ for f in fields(type(exp(e)) as BundleType) find : name(f) == name(e) + get-gender(exp(e),genders) * flip(f) + (e:WIndex) : get-gender(exp(e),genders) + (e:Pad) : MALE + (e:DoPrim) : MALE + (e:UIntValue) : MALE + (e:SIntValue) : MALE + (e:ReadPort) : MALE + (e:WritePort) : FEMALE + (e:Register) : MALE + + defn check-genders-e (info:FileInfo,e:Expression,genders:HashTable<Symbol,Gender>) -> False : + do(check-genders-e{info,_,genders},e) + match(e) : + (e:WRef) : false + (e:WSubfield) : false + (e: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) + (e:UIntValue) : false + (e:SIntValue) : false + (e:ReadPort) : do(check-gender{info,genders,_,MALE},e) + (e:WritePort) : do(check-gender{info,genders,_,MALE},e) + (e:Register) : do(check-gender{info,genders,_,MALE},e) + + defn check-genders-s (s:Stmt,genders:HashTable<Symbol,Gender>) -> False : + do(check-genders-e{info(s),_:Expression,genders},s) + match(s) : + (s:DefWire) : genders[name(s)] = BI-GENDER + (s:DefRegister) : genders[name(s)] = BI-GENDER + (s:DefNode) : + check-gender(info(s),genders,value(s),MALE) + genders[name(s)] = MALE + (s:DefMemory) : genders[name(s)] = BI-GENDER + (s:DefInstance) : genders[name(s)] = MALE + (s:WDefAccessor) : + if gender(s) == UNKNOWN-GENDER : add(errors,UnknownGenders(info(s),name(s))) + check-gender(info(s),genders,index(s),MALE) + check-gender(info(s),genders,source(s),gender(s)) + genders[name(s)] = gender(s) + (s:Connect) : + 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) + (s:Conditionally) : + check-gender(info(s),genders,pred(s),MALE) + (s:EmptyStmt) : false + (s:Begin) : false + + + for m in modules(c) do : + 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) + 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 67d2c2d9..02145678 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -2,8 +2,8 @@ defpackage firrtl/ir2 : import core import verse -public defmulti info! (x:?) -> False -public defmethod info! (x:?) : false +public defmulti info! (x:?) -> FileInfo +public defmethod info! (x:?) : FileInfo() public definterface Direction public val INPUT = new Direction @@ -176,35 +176,46 @@ public defstruct Pad <: Expression : type: Type with: (as-method => true) public definterface Stmt +public defmulti info (s:Stmt) -> FileInfo + public defstruct DefWire <: Stmt : ;LOW + info: FileInfo with: (as-method => true) name: Symbol type: Type public defstruct DefRegister <: Stmt : + info: FileInfo with: (as-method => true) name: Symbol type: Type public defstruct DefInstance <: Stmt : ;LOW + info: FileInfo with: (as-method => true) name: Symbol module: Expression public defstruct DefMemory <: Stmt : ;LOW + info: FileInfo with: (as-method => true) name: Symbol type: VectorType public defstruct DefNode <: Stmt : ;LOW + info: FileInfo with: (as-method => true) name: Symbol value: Expression public defstruct DefAccessor <: Stmt : + info: FileInfo with: (as-method => true) name: Symbol source: Expression index: Expression public defstruct Conditionally <: Stmt : + info: FileInfo with: (as-method => true) pred: Expression conseq: Stmt alt: Stmt public defstruct Begin <: Stmt : ;LOW body: List<Stmt> public defstruct OnReset <: 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 exp: Expression public defstruct EmptyStmt <: Stmt ;LOW @@ -227,17 +238,18 @@ public defstruct Field : type: Type public defstruct Port : + info: FileInfo name: Symbol direction: Direction type: Type public defstruct Module : + info: FileInfo name: Symbol ports: List<Port> body: Stmt public defstruct Circuit : + info: FileInfo modules: List<Module> main: Symbol - - diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza index ca9bfa33..0f977ebe 100644 --- a/src/main/stanza/firrtl-test-main.stanza +++ b/src/main/stanza/firrtl-test-main.stanza @@ -27,6 +27,7 @@ defn set-printvars! (p:List<Char>) : if contains(p,'g') : PRINT-GENDERS = true if contains(p,'c') : PRINT-CIRCUITS = true if contains(p,'d') : PRINT-DEBUG = true + if contains(p,'i') : PRINT-INFO = true ;firrtl -i gcd.fir -o gcd.flo -x qabcefghipjklmno -p c defn main () : diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 0e339cf3..15cc497a 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -218,7 +218,7 @@ defsyntax firrtl : circuit = (circuit ?name:#id! #:! (?ms:#module ... ?rest ...)) : if not empty?(rest) : FPE(rest, "Expected a module declaration here.") - Circuit(ms, name) + Circuit(first-info(form),ms, name) circuit != (circuit) : FPE(form, "Invalid syntax for circuit definition.") @@ -227,13 +227,13 @@ defsyntax firrtl : module = (module ?name:#id! #:! (?ps:#port ... ?cs:#stmt ... ?rest ...)) : if not empty?(rest) : FPE(rest, "Expected a statement here.") - Module(name, ps, Begin(cs)) + Module(first-info(form),name, ps, Begin(cs)) module != (module) : FPE(form, "Invalid syntax for module definition.") defrule port : - port = (input ?name:#id! #:! ?type:#type!) : Port(name, INPUT, type) - port = (output ?name:#id! #:! ?type:#type!) : Port(name, OUTPUT, type) + port = (input ?name:#id! #:! ?type:#type!) : Port(first-info(form),name, INPUT, type) + port = (output ?name:#id! #:! ?type:#type!) : Port(first-info(form),name, OUTPUT, type) ;Main Type Productions defrule type : @@ -261,16 +261,16 @@ defsyntax firrtl : ;Main Statement Productions defrule statements : - stmt = (wire ?name:#id! #:! ?t:#type!) : DefWire(name, t) - stmt = (reg ?name:#id! #:! ?t:#type!) : DefRegister(name, t) - stmt = (mem ?name:#id! #:! ?t:#vectype!) : DefMemory(name, t) - stmt = (inst ?name:#id! #of! ?m:#ref!) : DefInstance(name, m) - stmt = (node ?name:#id! #=! ?e:#exp!) : DefNode(name, e) - stmt = (accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(name, s, i) + 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 = (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(x, y) - stmt = (on-reset ?x:#exp := ?y:#exp!) : OnReset(x, y) + stmt = (?x:#exp := ?y:#exp!) : Connect(first-info(form),x, y) + stmt = (on-reset ?x:#exp := ?y:#exp!) : OnReset(first-info(form),x, y) stmt = ((?s:#stmt ?ss:#stmt ... ?rest ...)) : if not empty?(rest) : @@ -281,11 +281,11 @@ defsyntax firrtl : defrule stmt/when : stmt/when = (when ?pred:#exp! #:! ?conseq:#stmt! else ?alt:#stmt/when) : - Conditionally(pred, conseq, alt) + Conditionally(first-info(form),pred, conseq, alt) stmt/when = (when ?pred:#exp! #:! ?conseq:#stmt! else #:! ?alt:#stmt!) : - Conditionally(pred, conseq, alt) + Conditionally(first-info(form),pred, conseq, alt) stmt/when = (when ?pred:#exp! #:! ?conseq:#stmt!) : - Conditionally(pred, conseq, EmptyStmt()) + Conditionally(first-info(form),pred, conseq, EmptyStmt()) ;Main Expressions defrule exp : diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 6754a8bd..190ad09a 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -5,7 +5,7 @@ defpackage firrtl/ir-utils : ;============== DEBUG STUFF ============================= -public defmulti print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field) -> False +public defmulti print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|Module|Circuit) -> False ;============== PRINTERS =================================== @@ -171,11 +171,13 @@ defmethod print (o:OutputStream, c:Stmt) : (c:DefInstance) : print-all(o,["inst " name(c) " of " module(c)]) (c:DefNode) : - print-all(o,["node " name(c) " = " value(c)]) + print-all(o,["node " name(c) " = " value(c)]) (c:DefAccessor) : print-all(o,["accessor " name(c) " = " source(c) "[" index(c) "]"]) (c:Conditionally) : - println-all(o, ["when " pred(c) " :"]) + print-all(o, ["when " pred(c) " :"]) + print-debug(o,c) + print(o,"\n") print(io,conseq(c)) if alt(c) not-typeof EmptyStmt : print(o, "\nelse :") @@ -189,7 +191,7 @@ defmethod print (o:OutputStream, c:Stmt) : print-all(o, ["on-reset " loc(c) " := " exp(c)]) (c:EmptyStmt) : print(o, "skip") - print-debug(o,c) + if not c typeof Conditionally|Begin|EmptyStmt : print-debug(o,c) defmethod print (o:OutputStream, t:Type) : match(t) : @@ -220,14 +222,18 @@ defmethod print (o:OutputStream, p:Port) : print-debug(o,p) defmethod print (o:OutputStream, m:Module) : - println-all(o, ["module " name(m) " :"]) + print-all(o, ["module " name(m) " :"]) + print-debug(o,m) + print(o,"\n") val io = IndentedStream(o, 3) for p in ports(m) do : println(io,p) print(io,body(m)) defmethod print (o:OutputStream, c:Circuit) : - println-all(o, ["circuit " main(c) " :"]) + print-all(o, ["circuit " main(c) " :"]) + print-debug(o,c) + print(o,"\n") val io = IndentedStream(o, 3) for m in modules(c) do : println(io, m) @@ -261,18 +267,18 @@ defmethod map (f: Expression -> Expression, e:Expression) -> Expression : public defmulti map<?T> (f: Expression -> Expression, c:?T&Stmt) -> T defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : match(c) : - (c:DefAccessor) : DefAccessor(name(c), f(source(c)), f(index(c))) - (c:DefNode) : DefNode(name(c), f(value(c))) - (c:DefInstance) : DefInstance(name(c), f(module(c))) - (c:Conditionally) : Conditionally(f(pred(c)), conseq(c), alt(c)) - (c:Connect) : Connect(f(loc(c)), f(exp(c))) - (c:OnReset) : OnReset(f(loc(c)),f(exp(c))) + (c:DefAccessor) : DefAccessor(info(c),name(c), f(source(c)), f(index(c))) + (c:DefNode) : DefNode(info(c),name(c), f(value(c))) + (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:OnReset) : OnReset(info(c),f(loc(c)),f(exp(c))) (c) : c public defmulti map<?T> (f: Stmt -> Stmt, c:?T&Stmt) -> T defmethod map (f: Stmt -> Stmt, c:Stmt) -> Stmt : match(c) : - (c:Conditionally) : Conditionally(pred(c), f(conseq(c)), f(alt(c))) + (c:Conditionally) : Conditionally(info(c),pred(c), f(conseq(c)), f(alt(c))) (c:Begin) : Begin(map(f, body(c))) (c) : c @@ -307,9 +313,9 @@ defmethod map (f: Type -> Type, c:Expression) -> Expression : public defmulti map<?T> (f: Type -> Type, c:?T&Stmt) -> T defmethod map (f: Type -> Type, c:Stmt) -> Stmt : match(c) : - (c:DefWire) : DefWire(name(c),f(type(c))) - (c:DefRegister) : DefRegister(name(c),f(type(c))) - (c:DefMemory) : DefMemory(name(c),f(type(c)) as VectorType) + (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) : 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 d04f7366..131f0a7b 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -7,27 +7,28 @@ defpackage firrtl/passes : import firrtl-main import firrtl/errors -;============== EXCEPTIONS ================================= -defclass PassException <: Exception -defn PassException (msg:String) : - new PassException : - defmethod print (o:OutputStream, this) : - print(o, msg) +;============== Exceptions ===================== +public definterface PassException <: Exception +public defn PassException (s:String) : + new PassException : + defmethod print (o:OutputStream, this) : + print(o, s) + +public defn PassExceptions (xs:Streamable<PassException>) : + PassException(string-join(xs, "\n")) ;=============== WORKING IR ================================ -definterface Kind -defstruct WireKind <: Kind -defstruct RegKind <: Kind -defstruct InstanceKind <: Kind -defstruct ReadAccessorKind <: Kind -defstruct WriteAccessorKind <: Kind -defstruct PortKind <: Kind -defstruct NodeKind <: Kind ; All elems except structural memory, wires - -defstruct MemKind <: Kind -defstruct ModuleKind <: Kind -defstruct StructuralMemKind <: Kind ; Separate kind because need special treatment -defstruct AccessorKind <: Kind +public definterface Kind +public defstruct WireKind <: Kind +public defstruct RegKind <: Kind +public defstruct InstanceKind <: Kind +public defstruct ReadAccessorKind <: Kind +public defstruct WriteAccessorKind <: Kind +public defstruct PortKind <: Kind +public defstruct NodeKind <: Kind ; All elems except structural memory, wires +public defstruct MemKind <: Kind +public defstruct ModuleKind <: Kind +public defstruct AccessorKind <: Kind public definterface Gender public val MALE = new Gender @@ -35,36 +36,39 @@ public val FEMALE = new Gender public val UNKNOWN-GENDER = new Gender public val BI-GENDER = new Gender -defstruct WRef <: Expression : +public defstruct WRef <: Expression : name: Symbol type: Type with: (as-method => true) kind: Kind gender: Gender with: (as-method => true) -defstruct WSubfield <: Expression : +public defstruct WSubfield <: Expression : exp: Expression name: Symbol type: Type with: (as-method => true) gender: Gender with: (as-method => true) -defstruct WIndex <: Expression : +public defstruct WIndex <: Expression : exp: Expression value: Int type: Type with: (as-method => true) gender: Gender with: (as-method => true) -defstruct WDefAccessor <: Stmt : +public defstruct WDefAccessor <: Stmt : + info: FileInfo with: (as-method => true) name: Symbol source: Expression index: Expression gender: Gender defstruct ConnectToIndexed <: Stmt : + info: FileInfo with: (as-method => true) index: Expression locs: List<Expression> exp: Expression defstruct ConnectFromIndexed <: Stmt : + info: FileInfo with: (as-method => true) index: Expression loc: Expression exps: List<Expression> @@ -100,19 +104,19 @@ defn swap (d:Direction) -> Direction : OUTPUT : INPUT INPUT : OUTPUT -defn times (flip:Flip,d:Direction) -> Direction : flip * d -defn times (d:Direction,flip:Flip) -> Direction : +public defn times (flip:Flip,d:Direction) -> Direction : flip * d +public defn times (d:Direction,flip:Flip) -> Direction : switch {_ == flip} : DEFAULT : d REVERSE : swap(d) -defn times (g:Gender,flip:Flip) -> Gender : flip * g -defn times (flip:Flip,g:Gender) -> Gender : +public defn times (g:Gender,flip:Flip) -> Gender : flip * g +public defn times (flip:Flip,g:Gender) -> Gender : switch {_ == flip} : DEFAULT : g REVERSE : swap(g) -defn times (f1:Flip,f2:Flip) -> Flip : +public defn times (f1:Flip,f2:Flip) -> Flip : switch {_ == f2} : DEFAULT : f1 REVERSE : swap(f1) @@ -139,6 +143,9 @@ defmethod print (o:OutputStream, g:Gender) : BI-GENDER : "b" UNKNOWN-GENDER: "u" +defmethod info (stmt:Begin) -> FileInfo : FileInfo() +defmethod info (stmt:EmptyStmt) -> FileInfo : FileInfo() + defmethod type (exp:UIntValue) -> Type : UIntType(width(exp)) defmethod type (exp:SIntValue) -> Type : SIntType(width(exp)) @@ -162,6 +169,7 @@ public var PRINT-TWIDTHS : True|False = false public var PRINT-GENDERS : True|False = false public var PRINT-CIRCUITS : True|False = false public var PRINT-DEBUG : True|False = false +public var PRINT-INFO : True|False = false ;=== Printers === public defn println-all-debug (l:?) -> False : @@ -183,31 +191,34 @@ defmethod print (o:OutputStream, k:Kind) : (k:NodeKind) : "n" (k:ModuleKind) : "module" (k:InstanceKind) : "inst" - (k:StructuralMemKind) : "smem" (k:ReadAccessorKind) : "racc" (k:WriteAccessorKind) : "wacc" -defn hasGender (e:Expression|Stmt|Type|Port|Field) : +defn hasGender (e:?) : e typeof WRef|WSubfield|WIndex|WDefAccessor -defn hasWidth (e:Expression|Stmt|Type|Port|Field) : +defn hasWidth (e:?) : e typeof UIntType|SIntType|UIntValue|SIntValue|Pad -defn hasType (e:Expression|Stmt|Type|Port|Field) : +defn hasType (e:?) : e typeof Ref|Subfield|Index|DoPrim|WritePort|ReadPort|WRef|WSubfield |WIndex|DefWire|DefRegister|DefMemory|Register |VectorType|Port|Field|Pad -defn hasKind (e:Expression|Stmt|Type|Port|Field) : +defn hasKind (e:?) : e typeof WRef -defn any-debug? (e:Expression|Stmt|Type|Port|Field) : +defn hasInfo (e:?) : + e typeof Stmt|Port|Circuit|Module + +defn any-debug? (e:?) : (hasGender(e) and PRINT-GENDERS) or (hasType(e) and PRINT-TYPES) or (hasWidth(e) and PRINT-WIDTHS) or - (hasKind(e) and PRINT-KINDS) + (hasKind(e) and PRINT-KINDS) or + (hasInfo(e) and PRINT-INFO) -defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field) : +defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|Module|Circuit) : defn wipe-width (t:Type) -> Type : match(t) : (t:UIntType) : UIntType(UnknownWidth()) @@ -220,6 +231,7 @@ defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field) : if PRINT-TWIDTHS and hasType(e): print-all(o,["<t:" type(e as ?) ">"]) if PRINT-WIDTHS and hasWidth(e): print-all(o,["<w:" width(e as ?) ">"]) if PRINT-GENDERS and hasGender(e): print-all(o,["<g:" gender(e as ?) ">"]) + if PRINT-INFO and hasInfo(e): print-all(o,["<i:" info(e as ?) ">"]) defmethod print (o:OutputStream, e:WRef) : print(o,name(e)) @@ -234,15 +246,15 @@ defmethod print (o:OutputStream, e:WIndex) : print-debug(o,e as ?) defmethod print (o:OutputStream, s:WDefAccessor) : - print-all(o,["accessor " name(s) " = " source(s) "[" index(s) "]"]) + print-all(o,["accessor " name(s) " = " source(s) "[" index(s) "] @[" info(s) "]"]) print-debug(o,s) defmethod print (o:OutputStream, c:ConnectToIndexed) : - print-all(o, [locs(c) "[" index(c) "] := " exp(c)]) + print-all(o, [locs(c) "[" index(c) "] := " exp(c) " @[" info(c) "]"]) print-debug(o,c as ?) defmethod print (o:OutputStream, c:ConnectFromIndexed) : - print-all(o, [loc(c) " := " exps(c) "[" index(c) "]"]) + print-all(o, [loc(c) " := " exps(c) "[" index(c) "] @[" info(c) "]"]) print-debug(o,c as ?) defmethod map (f: Expression -> Expression, e: WSubfield) : @@ -251,11 +263,11 @@ defmethod map (f: Expression -> Expression, e: WIndex) : WIndex(f(exp(e)), value(e), type(e), gender(e)) defmethod map (f: Expression -> Expression, c:WDefAccessor) : - WDefAccessor(name(c), f(source(c)), f(index(c)), gender(c)) + WDefAccessor(info(c),name(c), f(source(c)), f(index(c)), gender(c)) defmethod map (f: Expression -> Expression, c:ConnectToIndexed) : - ConnectToIndexed(f(index(c)), map(f, locs(c)), f(exp(c))) + ConnectToIndexed(info(c),f(index(c)), map(f, locs(c)), f(exp(c))) defmethod map (f: Expression -> Expression, c:ConnectFromIndexed) : - ConnectFromIndexed(f(index(c)), f(loc(c)), map(f, exps(c))) + ConnectFromIndexed(info(c),f(index(c)), f(loc(c)), map(f, exps(c))) defmethod map (f: Type -> Type, e: WRef) : WRef(name(e), f(type(e)), kind(e), gender(e)) @@ -287,10 +299,10 @@ defn temp-elimination (c:Circuit) : else : s (s) : map(temp-elim-s,s) - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : - Module(name(m), ports(m), temp-elim-s(body(m))) + Module(info(m),name(m), ports(m), temp-elim-s(body(m))) ;================= Bring to Working IR ======================== ; Returns a new Circuit with Refs, Subfields, Indexes and DefAccessors @@ -306,13 +318,13 @@ defn to-working-ir (c:Circuit) : (e) : e defn to-stmt (s:Stmt) : match(map(to-exp,s)) : - (s:DefAccessor) : WDefAccessor(name(s),source(s),index(s), UNKNOWN-GENDER) + (s:DefAccessor) : WDefAccessor(info(s),name(s),source(s),index(s), UNKNOWN-GENDER) (s) : map(to-stmt,s) - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : - Module(name(m), ports(m), to-stmt(body(m))) + Module(info(m),name(m), ports(m), to-stmt(body(m))) ;=============== MAKE EXPLICIT RESET ======================= ; All modules have an implicit reset signal - however, the @@ -339,20 +351,20 @@ defn make-explicit-reset (c:Circuit) : (s:DefInstance) : val iref = WSubfield(WRef(name(s), UnknownType(), InstanceKind(), UNKNOWN-GENDER),`reset,UnknownType(),UNKNOWN-GENDER) val pref = WRef(`reset, UnknownType(), PortKind(), MALE) - Begin(to-list([s,Connect(iref,pref)])) + Begin(to-list([s,Connect(info(s),iref,pref)])) (s) : map(route-reset,s) var ports! = ports(m) if not contains?(explicit-reset,name(m)) : - ports! = append(ports(m),list(Port(`reset,INPUT,UIntType(IntWidth(1))))) + ports! = append(ports(m),list(Port(FileInfo(),`reset,INPUT,UIntType(IntWidth(1))))) val body! = route-reset(body(m)) - Module(name(m),ports!,body!) + Module(info(m),name(m),ports!,body!) defn make-explicit-reset (m:Module, c:Circuit) -> Module : val explicit-reset = find-explicit(c) make-explicit(m,explicit-reset) - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : make-explicit-reset(m,c) @@ -399,9 +411,9 @@ defn resolve-kinds (c:Circuit) : kinds[name(m)] = ModuleKind() find(m,kinds) val body! = resolve(body(m),kinds) - Module(name(m),ports(m),body!) + Module(info(m),name(m),ports(m),body!) - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : resolve-kinds(m,c) @@ -434,7 +446,7 @@ defn bundle-field-type (v:Type,s:Symbol) -> Type : val ft = for p in fields(v) find : name(p) == s if ft != false : type(ft as Field) else : UnknownType() - (v) : error(string-join(["Accessing subfield " s " on a non-Bundle type."])) + (v) : UnknownType() defn get-vector-subtype (v:Type) -> Type : match(v) : @@ -474,7 +486,7 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue< (s:Conditionally) : val [s*,l*] = infer-types(conseq(s),l) val [s**,l**] = infer-types(alt(s),l) - [Conditionally(pred(s),s*,s**),l] + [Conditionally(info(s),pred(s),s*,s**),l] (s:Connect|OnReset|EmptyStmt) : [s,l] defn infer-types (m:Module, l:List<KeyValue<Symbol,Type>>) -> Module : @@ -483,14 +495,14 @@ defn infer-types (m:Module, l:List<KeyValue<Symbol,Type>>) -> Module : name(p) => type(p) println-all-debug(append(ptypes,l)) val [s,l*] = infer-types(body(m),append(ptypes, l)) - Module(name(m),ports(m),s) + Module(info(m),name(m),ports(m),s) defn infer-types (c:Circuit) -> Circuit : val l = for m in modules(c) map : name(m) => BundleType(map(to-field,ports(m))) println-all-debug(l) - Circuit{ _, main(c) } $ + Circuit{info(c), _, main(c) } $ for m in modules(c) map : infer-types(m,l) @@ -506,6 +518,18 @@ defn infer-types (c:Circuit) -> Circuit : ; Because accessor gender is not known during declaration, ; this pass requires iterating until a fixed point is reached. +; Notes +; Is there a case where an incorrect gender would cause a weird result in resolving an accessor gender, such that a following gender check is wrong/right which it shouldn't be? + +; I don't think so, because there is no way for resolving an accessor gender to change something from wrong -> right, so it will always fail in the gender check. +; As such, it doesn't matter what the accessor gender gets resolved to, as it will fail anyways + +; In the example below, FIRRTL will say accessor gender could not be resolved. Once this is fixed, then we will error "Cannot connect from an output, out" +; output out : UInt +; accessor x = m[i] +; x := out +; out := x + defn bundle-field-flip (n:Symbol,t:Type) -> Flip : match(t) : (b:BundleType) : @@ -521,7 +545,7 @@ defn resolve-genders (c:Circuit) : defn resolve-iter (m:Module) -> Module : val body* = resolve-stmt(body(m)) - Module(name(m),ports(m),body*) + Module(info(m),name(m),ports(m),body*) defn get-gender (n:Symbol,g:Gender) -> Gender : defn force-gender (n:Symbol,g:Gender) -> Gender : @@ -551,24 +575,24 @@ defn resolve-genders (c:Circuit) : get-gender(name(s),BI-GENDER) s (s:DefNode) : - DefNode(name(s),resolve-expr(value(s),get-gender(name(s),MALE))) + DefNode(info(s),name(s),resolve-expr(value(s),get-gender(name(s),MALE))) (s:DefInstance) : get-gender(name(s),MALE) - DefInstance(name(s),resolve-expr(module(s),MALE)) + DefInstance(info(s),name(s),resolve-expr(module(s),MALE)) (s:WDefAccessor) : val gender* = get-gender(name(s),UNKNOWN-GENDER) val index* = resolve-expr(index(s),MALE) val source* = resolve-expr(source(s),gender*) - WDefAccessor(name(s),source*,index*,gender*) + WDefAccessor(info(s),name(s),source*,index*,gender*) (s:Connect) : - Connect(resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) + Connect(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) (s:OnReset) : - OnReset(resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) + OnReset(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE)) (s:Conditionally) : val pred* = resolve-expr(pred(s),MALE) val conseq* = resolve-stmt(conseq(s)) val alt* = resolve-stmt(alt(s)) - Conditionally(pred*,conseq*,alt*) + Conditionally(info(s),pred*,conseq*,alt*) (s) : map(resolve-stmt,s) defn resolve-expr (e:Expression,desired:Gender) -> Expression : @@ -601,7 +625,7 @@ defn resolve-genders (c:Circuit) : val genders = HashTable<Symbol,Gender>(symbol-hash) resolve-module(m,genders) - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : resolve-genders(m,c) @@ -629,23 +653,25 @@ defn expand-stmt (s:Stmt) -> Stmt : if mem? : s else : val vtype = type(type(source(s)) as VectorType) - val wire = DefWire(name(s),vtype) + val wire = DefWire(info(s),name(s),vtype) switch {gender(s) == _} : MALE : Begin{list(wire,_)} $ ConnectFromIndexed( + info(s), index(s), WRef(name(wire),vtype,NodeKind(),FEMALE), expand-vector(source(s))) FEMALE: Begin{list(wire,_)} $ ConnectToIndexed( + info(s), index(s), expand-vector(source(s)), WRef(name(wire),vtype,NodeKind(),MALE)) (s) : map(expand-stmt,s) defn expand-accessors (c:Circuit) : - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : - Module(name(m),ports(m),expand-stmt(body(m))) + Module(info(m),name(m),ports(m),expand-stmt(body(m))) ;;=============== LOWERING TO GROUND TYPES ============================= ; All non-ground (elevated) types (Vectors, Bundles) are expanded out to @@ -718,18 +744,18 @@ defn expand-expr (e:Expression) -> List<EF> : for x in generate-entry(name(e),type(e)) map : EF(WRef(name(x),type(x),kind(e),gender(e)), flip(x)) (e:WSubfield) : + val f = {_ as Field} $ + for f in fields(type(exp(e)) as BundleType) find : name(f) == name(e) if inst?(exp(e)) : - val i = exp(e) - val f = {_ as Field} $ - for f in fields(type(i) as BundleType) find : name(f) == name(e) + println-all(["here with " exp(e)]) for x in generate-entry(name(f),type(f)) map : - EF(WSubfield(i,name(x),type(x),gender(e)),flip(x)) + EF(WSubfield(exp(e),name(x),type(x),gender(e)),flip(x)) else : val exps = expand-expr(exp(e)) val begin = index-of-elem(type(exp(e)) as BundleType,name(e)) val len = num-elems(type(e)) val ret = headn(tailn(exps,begin),len) - for r in ret map : EF(exp(r),DEFAULT) + for r in ret map : EF(exp(r),flip(r) * flip(f)) (e:WIndex) : val exps = expand-expr(exp(e)) val len = num-elems(type(e)) @@ -745,7 +771,7 @@ defn expand-expr (e:Expression) -> List<EF> : defn lower-ports (ports:List<Port>) -> List<Port> : for p in ports map-append : for x in generate-entry(name(p),type(p)) map : - Port(name(x),direction(p) * flip(x),type(x)) + Port(info(p),name(x),direction(p) * flip(x),type(x)) defn type (s:WDefAccessor) -> Type : type(type(source(s)) as VectorType) defn size (s:DefMemory) -> Int : size(type(s)) @@ -768,10 +794,10 @@ defn lower (body:Stmt) -> Stmt : match(s) : (s:DefWire) : Begin $ for x in generate-entry(name(s),type(s)) map : - DefWire(name(x),type(x)) + DefWire(info(s),name(x),type(x)) (s:DefRegister) : Begin{_} $ for x in generate-entry(name(s),type(s)) map : - DefRegister(name(x),type(x)) + DefRegister(info(s),name(x),type(x)) (s:DefInstance) : val fields = for f in fields(type(module(s)) as BundleType) map-append : @@ -779,20 +805,20 @@ defn lower (body:Stmt) -> Stmt : for etf in etfs map : Field(name(etf),flip(etf) * flip(f),type(etf)) val m = module(s) as WRef - DefInstance(name(s),WRef(name(m),BundleType(fields),kind(m),gender(m))) + DefInstance(info(s),name(s),WRef(name(m),BundleType(fields),kind(m),gender(m))) (s:DefNode) : Begin $ for x in expand-expr(value(s)) map : - DefNode(name(s),exp(x)) + DefNode(info(s),name(s),exp(x)) (s:DefMemory) : Begin $ for x in generate-entry(name(s),type(type(s))) map : - DefMemory(name(x),VectorType(type(x),size(s))) + DefMemory(info(s),name(x),VectorType(type(x),size(s))) (s:WDefAccessor) : val ls = generate-entry(name(s),type(s)) val rs = generate-entry(name(source(s) as WRef),type(s)) Begin $ for (l in ls, r in rs) map: if flip(r) == REVERSE : error("Shouldn't be here") val memref = WRef(name(r),VectorType(type(r),size(s)),MemKind(),gender(s)) - WDefAccessor(name(l),memref,index(s),gender(s)) + WDefAccessor(info(s),name(l),memref,index(s),gender(s)) (s:OnReset|Connect) : Begin $ for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map : val lgender = FEMALE * flip(l) @@ -803,11 +829,11 @@ defn lower (body:Stmt) -> Stmt : println-all-debug(["Right: " r " with Gender: " rgender]) switch fn ([x,y]) : lgender == x and rgender == y : [FEMALE,MALE] : - if s typeof Connect : Connect(l*,r*) - else : OnReset(l*,r*) + if s typeof Connect : Connect(info(s),l*,r*) + else : OnReset(info(s),l*,r*) [MALE,FEMALE] : - if s typeof Connect : Connect(r*,l*) - else : OnReset(r*,l*) + if s typeof Connect : Connect(info(s),r*,l*) + else : OnReset(info(s),r*,l*) (s:ConnectFromIndexed) : Begin(ls) where : val ctable = HashTable<Symbol,Vector<EF>>(symbol-hash) for e in exps(s) do : @@ -825,8 +851,8 @@ defn lower (body:Stmt) -> Stmt : val l* = set-gender(exp(l),lgender,flip(l)) val exps = to-list $ for e in ctable[n] map : set-gender(exp(e),rgender,flip(e)) switch fn ([x,y]) : lgender == x and rgender == y : - [FEMALE,MALE] : ConnectFromIndexed(index(s),l*,exps) - [MALE,FEMALE] : ConnectToIndexed(index(s),exps,l*) + [FEMALE,MALE] : ConnectFromIndexed(info(s),index(s),l*,exps) + [MALE,FEMALE] : ConnectToIndexed(info(s),index(s),exps,l*) (s:ConnectToIndexed) : Begin(ls) where : val ctable = HashTable<Symbol,Vector<EF>>(symbol-hash) for e in locs(s) do : @@ -844,21 +870,21 @@ defn lower (body:Stmt) -> Stmt : val r* = set-gender(exp(r),rgender,flip(r)) val locs = to-list $ for e in ctable[n] map : set-gender(exp(e),lgender,flip(e)) switch fn ([x,y]) : lgender == x and rgender == y : - [FEMALE,MALE] : ConnectToIndexed(index(s),locs,r*) - [MALE,FEMALE] : ConnectFromIndexed(index(s),r*,locs) + [FEMALE,MALE] : ConnectToIndexed(info(s),index(s),locs,r*) + [MALE,FEMALE] : ConnectFromIndexed(info(s),index(s),r*,locs) (s:Conditionally) : - Conditionally(exp(head $ expand-expr(pred(s))),lower-stmt(conseq(s)),lower-stmt(alt(s))) + Conditionally(info(s),exp(head $ expand-expr(pred(s))),lower-stmt(conseq(s)),lower-stmt(alt(s))) (s:Begin|EmptyStmt) : map(lower-stmt,s) lower-stmt(body) defn lower-module (c:Circuit,m:Module) -> Module : - Module(name(m),ports*,body*) where : + Module(info(m),name(m),ports*,body*) where : val body* = lower(body(m)) val ports* = lower-ports(ports(m)) defn lower-to-ground (c:Circuit) -> Circuit : - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : lower-module(c,m) @@ -884,11 +910,12 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt : else : val ref = WRef(firrtl-gensym(get-name(exp(s))),type(index(s)),NodeKind(),UNKNOWN-GENDER) append( - list(Connect(head(locs(s)),exp(s)),DefNode(name(ref),index(s))) + list(Connect(info(s),head(locs(s)),exp(s)),DefNode(info(s),name(ref),index(s))) to-list $ for (i in 1 to false, l in tail(locs(s))) stream : Conditionally( + info(s), equality(ref,UIntValue(i,UnknownWidth())), - Connect(l,exp(s)), + Connect(info(s),l,exp(s)), EmptyStmt() ) ) @@ -897,21 +924,22 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt : else : val ref = WRef(firrtl-gensym(get-name(loc(s))),type(index(s)),NodeKind(),UNKNOWN-GENDER) append( - list(Connect(loc(s),head(exps(s))),DefNode(name(ref),index(s))) + list(Connect(info(s),loc(s),head(exps(s))),DefNode(info(s),name(ref),index(s))) to-list $ for (i in 1 to false, e in tail(exps(s))) stream : Conditionally( + info(s), equality(ref,UIntValue(i,UnknownWidth())), - Connect(loc(s),e), + Connect(info(s),loc(s),e), EmptyStmt() ) ) (s) : map(expand-connect-indexed-stmt,s) defn expand-connect-indexed (m: Module) -> Module : - Module(name(m),ports(m),expand-connect-indexed-stmt(body(m))) + Module(info(m),name(m),ports(m),expand-connect-indexed-stmt(body(m))) defn expand-connect-indexed (c: Circuit) -> Circuit : - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : expand-connect-indexed(m) @@ -1113,7 +1141,7 @@ defn expand-whens (ports:List<Port>, table:HashTable<Symbol,SymbolicValue>,cons: if has-nul?(table[name(p)]) : println("Uninitialized: ~" % [to-string(name(p))]);TODO actually collect error EmptyStmt() - else : Connect(ref,to-exp(table[name(p)]) as Expression) + else : 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)) : @@ -1125,26 +1153,26 @@ defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stm if has-nul?(table[name(s)]) : println("Uninitialized: ~" % [to-string(name(s))]);TODO actually collect error EmptyStmt() - else : Connect(ref,to-exp(table[name(s)]) as Expression) + else : Connect(info(s),ref,to-exp(table[name(s)]) as Expression) }() (s:DefRegister) : - add(decs,DefWire(name(s),type(s))) + 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(ref,Register(type(s),e, to-exp(optimize $ get-write-enable(table[name(s)])) as Expression)) + (e:Expression) : Connect(info(s),ref,Register(type(s),e, to-exp(optimize $ get-write-enable(table[name(s)])) as Expression)) }() (s:WDefAccessor) : val t = type(type(source(s)) as VectorType) val n = name(s) - add(decs,DefWire(n,t)) + add(decs,DefWire(info(s),n,t)) add{cons,_} $ { switch {_ == gender(s)} : MALE : val ref = WRef(n,t,ReadAccessorKind(),FEMALE) - Begin $ list $ Connect(ref,ReadPort(source(s),index(s),t,get-read-enable(n,table))) + Begin $ list $ Connect(info(s),ref,ReadPort(source(s),index(s),t,get-read-enable(n,table))) FEMALE : val ref = WRef(n,t,WriteAccessorKind(),FEMALE) val e = to-exp(table[n]) @@ -1153,10 +1181,10 @@ defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stm println("Uninitialized: ~" % [to-string(n)]) ;TODO actually collect error EmptyStmt() (e:Expression) : - Connect(ref,e) + 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(wp,ref),s*) + Begin $ list(Connect(info(s),wp,ref),s*) }() (s:DefInstance) : add(decs,s) @@ -1171,7 +1199,7 @@ defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stm if has-nul?(table[n]) : println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error EmptyStmt() - else : Connect(sref,to-exp(table[n]) as Expression) + else : Connect(info(s),sref,to-exp(table[n]) as Expression) else : EmptyStmt() (s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : false s @@ -1305,10 +1333,10 @@ defn expand-whens (m:Module) -> Module : val cons = Vector<Stmt>() expand-whens(ports(m),table,cons) expand-whens(body(m),table,decs,cons) - Module(name(m),ports(m),Begin(append(to-list(decs),to-list(cons)))) + Module(info(m),name(m),ports(m),Begin(append(to-list(decs),to-list(cons)))) defn expand-whens (c:Circuit) -> Circuit : - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : expand-whens(m) @@ -1560,21 +1588,21 @@ public defn width! (e:Expression) -> Width : width!(type(e)) defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Module: defn gen-constraints-s (s:Stmt) -> Stmt : match(map(gen-constraints-s,s)) : - (s:DefWire) : DefWire(name(s),h[name(s)]) - (s:DefInstance) : DefInstance(name(s),gen-constraints(module(s))) - (s:DefMemory) : DefMemory(name(s),h[name(s)] as VectorType) + (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:DefNode) : val l = h[name(s)] val r = gen-constraints(value(s)) add(v,WGeq(width!(l),width!(type(r)))) add(v,WGeq(width!(type(r)),width!(l))) - DefNode(name(s),r) + DefNode(info(s),name(s),r) (s:Connect) : val l = gen-constraints(loc(s)) val e = gen-constraints(exp(s)) add(v,WGeq(width!(type(l)),width!(type(e)))) add(v,WGeq(width!(type(e)),width!(type(l)))) - Connect(l,e) + Connect(info(s),l,e) (s) : s defn gen-constraints (e:Expression) -> Expression : @@ -1612,9 +1640,9 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod (e) : e val ports* = - for p in ports(m) map : Port(name(p),direction(p),h[name(p)]) + for p in ports(m) map : Port(info(p),name(p),direction(p),h[name(p)]) - Module(name(m),ports*,gen-constraints-s(body(m))) + Module(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 : @@ -1642,11 +1670,11 @@ defn replace-var-widths (c:Circuit,h:HashTable<Symbol,Int>) -> Circuit : w* val modules* = for m in modules(c) map : - Module{name(m),_,mapr(replace-var-widths-w,body(m))} $ + Module{info(m),name(m),_,mapr(replace-var-widths-w,body(m))} $ for p in ports(m) map : - Port(name(p),direction(p),mapr(replace-var-widths-w,type(p))) + Port(info(p),name(p),direction(p),mapr(replace-var-widths-w,type(p))) - Circuit(modules*,main(c)) + Circuit(info(c),modules*,main(c)) defn remove-unknowns-w (w:Width) -> Width : match(w) : @@ -1682,7 +1710,7 @@ defn infer-widths (c:Circuit) -> Circuit : println-debug("======== SOLVED CONSTRAINTS ========") for x in h do : println-debug(x) println-debug("====================================") - replace-var-widths(Circuit(modules*,main(c)),h) + replace-var-widths(Circuit(info(c),modules*,main(c)),h) ;================= Inline Instances ======================== @@ -1702,7 +1730,7 @@ defn inline-instances (c:Circuit) : else : val v = Vector<Stmt>() for p in ports(m) do : - add(v,DefWire(name(p),type(p))) + add(v,DefWire(info(s),name(p),type(p))) add(v,inline-inst(body(m))) Begin(to-list(v)) h-s[n] = body* @@ -1728,15 +1756,15 @@ defn inline-instances (c:Circuit) : (e) : e defn rename-s (s:Stmt,n:Symbol) -> Stmt : map{rename-e{_,n},_} $ match(map(rename-s{_,n},s)) : - (s:DefWire) : DefWire(rename(name(s),n),type(s)) + (s:DefWire) : DefWire(info(s),rename(name(s),n),type(s)) (s:DefInstance) : error("Shouldn't be here") - (s:DefMemory) : DefMemory(rename(name(s),n),type(s)) - (s:DefNode) : DefNode(rename(name(s),n),value(s)) + (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(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(list(Module(name(top),ports(top),inline-inst(body(top)))),main(c)) + Circuit(info(c),list(Module(info(top),name(top),ports(top),inline-inst(body(top)))),main(c)) ;================= Split Expressions ======================== @@ -1751,27 +1779,27 @@ defn split-exp (c:Circuit) : (s:Conditionally) : error("Shouldn't be here") (s:Connect) : match(loc(s)) : - (e:WritePort) : add(v,map(split-exp-e{_,v,name(exp(s) as WRef)},s)) - (e) : add(v,map(split-exp-e{_,v,name(loc(s) as WRef)},s)) - (s:DefNode) : add(v,map(split-exp-e{_,v,name(s)},s)) - (s) : add(v,map(split-exp-e{_,v,false},s)) + (e:WritePort) : add(v,map(split-exp-e{_,v,name(exp(s) as WRef),info(s)},s)) + (e) : add(v,map(split-exp-e{_,v,name(loc(s) as WRef),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)) false - defn split-exp-e (e:Expression,v:Vector<Stmt>,n:Symbol|False) -> Expression : - match(map(split-exp-e{_,v,n},e)): + 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:Subfield|DoPrim|Pad|ReadPort|Register|WritePort) : val n* = if n typeof False : firrtl-gensym(`T) else : firrtl-gensym(symbol-join([n as Symbol `#])) ;to-symbol $ string-join $ [n as Symbol firrtl-gensym(`#)] - add(v,DefNode(n*,e)) + add(v,DefNode(info,n*,e)) WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER) (e) : e - Circuit{_,main(c)} $ + Circuit{info(c),_,main(c)} $ for m in modules(c) map : val v = Vector<Stmt>() split-exp-s(body(m),v) - Module(name(m),ports(m),Begin(to-list(v))) + Module(info(m),name(m),ports(m),Begin(to-list(v))) ;================= Bring to Real IR ======================== ; Returns a new Circuit with only real IR nodes. @@ -1790,10 +1818,10 @@ defn to-real-ir (c:Circuit) : (e:ConnectFromIndexed) : error("Shouldn't be here") (e) : map(to-stmt,e) - Circuit(modules*, main(c)) where : + Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : - Module(name(m), ports(m), to-stmt(body(m))) + Module(info(m),name(m), ports(m), to-stmt(body(m))) ;============= FLO PRINTER ====================================== ; Emit @@ -2024,22 +2052,34 @@ public defn run-passes (c: Circuit, p: List<Char>,file:String) : if PRINT-CIRCUITS : print(c*) if PRINT-CIRCUITS : println-all(["Finished " name "\n"]) - ; Early passes: - ; If modules have a reset defined, must be an INPUT and UInt(1) if contains(p,'X') or contains(p,'A') : do-stage("High Form Check", check-high-form) if contains(p,'X') or contains(p,'a') : do-stage("Temp Elimination", temp-elimination) if contains(p,'X') or contains(p,'b') : do-stage("Working IR", to-working-ir) + if contains(p,'X') or contains(p,'c') : do-stage("Make Explicit Reset", make-explicit-reset) + if contains(p,'X') or contains(p,'d') : do-stage("Resolve Kinds", resolve-kinds) + if contains(p,'X') or contains(p,'D') : do-stage("Check Kinds", check-kinds) + if contains(p,'X') or contains(p,'e') : do-stage("Infer Types", infer-types) + if contains(p,'X') or contains(p,'E') : do-stage("Check Types", check-types) + if contains(p,'X') or contains(p,'f') : do-stage("Resolve Genders", resolve-genders) - if contains(p,'X') or contains(p,'g') : do-stage("Expand Accessors", expand-accessors) - if contains(p,'X') or contains(p,'h') : do-stage("Lower To Ground", lower-to-ground) + if contains(p,'X') or contains(p,'F') : do-stage("Check Genders", check-genders) + + if contains(p,'X') or contains(p,'g') : do-stage("Expand Accessors", expand-accessors) ;mem kind + if contains(p,'X') or contains(p,'h') : do-stage("Lower To Ground", lower-to-ground) ;inst kind if contains(p,'X') or contains(p,'i') : do-stage("Expand Indexed Connects", expand-connect-indexed) - if contains(p,'X') or contains(p,'k') : do-stage("Expand Whens", expand-whens) - if contains(p,'X') or contains(p,'l') : do-stage("Infer Widths", infer-widths) - if contains(p,'X') or contains(p,'m') : do-stage("Inline Instances", inline-instances) + +; make sure no bundle types + if contains(p,'X') or contains(p,'k') : do-stage("Expand Whens", expand-whens) ; requires types, lowering + + if contains(p,'X') or contains(p,'l') : do-stage("Infer Widths", infer-widths) ; requires lowering, expand whens + + if contains(p,'X') or contains(p,'m') : do-stage("Inline Instances", inline-instances) ;inst kind + if contains(p,'X') or contains(p,'n') : do-stage("Split Expressions", split-exp) + if contains(p,'X') or contains(p,'o') : do-stage("Real IR", to-real-ir) if contains(p,'X') or contains(p,'F') : do-stage("To Flo", emit-flo{file,_}) println("Done!") |
