diff options
| author | Adam Izraelevitz | 2016-08-15 10:32:41 -0700 |
|---|---|---|
| committer | GitHub | 2016-08-15 10:32:41 -0700 |
| commit | bebd04c4c68c320b2b72325e348c726dc33beae6 (patch) | |
| tree | 69f6d4da577977cc7ff428b0545bb4735507aad0 /src/main/stanza/errors.stanza | |
| parent | cca37c46fc0848f5dbf5f95ba60755ed6d60712b (diff) | |
Remove stanza (#231)
* Removed stanza implementation/tests.
In the future we can move the stanza tests over, but for now they should
be deleted.
* Added back integration .fir files
* Added Makefile to give Travis hooks
* Added firrtl script (was ignored before)
Diffstat (limited to 'src/main/stanza/errors.stanza')
| -rw-r--r-- | src/main/stanza/errors.stanza | 1032 |
1 files changed, 0 insertions, 1032 deletions
diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza deleted file mode 100644 index 6d702e9b..00000000 --- a/src/main/stanza/errors.stanza +++ /dev/null @@ -1,1032 +0,0 @@ -;Copyright (c) 2014 - 2016 The Regents of the University of -;California (Regents). All Rights Reserved. Redistribution and use in -;source and binary forms, with or without modification, are permitted -;provided that the following conditions are met: -; * Redistributions of source code must retain the above -; copyright notice, this list of conditions and the following -; two paragraphs of disclaimer. -; * Redistributions in binary form must reproduce the above -; copyright notice, this list of conditions and the following -; two paragraphs of disclaimer in the documentation and/or other materials -; provided with the distribution. -; * Neither the name of the Regents nor the names of its contributors -; may be used to endorse or promote products derived from this -; software without specific prior written permission. -;IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, -;SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, -;ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF -;REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT -;LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -;A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF -;ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION -;TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -;MODIFICATIONS. -defpackage firrtl/errors : - import core - import verse - import firrtl/ir2 - import firrtl/ir-utils - import firrtl/primops - import firrtl/passes - import firrtl-main - import bigint2 - -; TODO -; make sure it compiles, write tests, look over code to make sure its right -;========== ALL CHECKS ================= -;PARSER CHECK -; * No nested modules <- parser -; * Only modules in circuit (no statements or expressions) <- parser -; * Module must be a reference in inst declaration - -;AFTER ?????? -; o No combinational loops - -;================= High Form Check ========================== -; * Subexps of Subfield and Index can only be subfields, index, or refs -; * Can only connect to a Ref or Subfield or Index or WritePort -; * A module has the same name as main of circuit -; * mems cannot be a bundle with flips -; * instance module must have the same name as a defined module -; * Unique names per module -; * No name can be a prefix of any other name. -; * all references are declared -; * UInt only has positive ints -; * Vector types has positive size -; * Width sizes are positive -; * Primops have the correct number of arguments - -public defstruct CheckHighForm <: Pass -public defmethod pass (b:CheckHighForm) -> (Circuit -> Circuit) : check-high-form -public defmethod name (b:CheckHighForm) -> String : "High Form Check" -public defmethod short-name (b:CheckHighForm) -> String : "high-form-check" - -var sinfo! = FileInfo() - -;----------------- Errors ------------------------ -defn NotUnique (name:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Reference " name " does not have a unique name."] - -defn IsPrefix (prefix:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Symbol " prefix " is a prefix."] - -defn InvalidLOC () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Invalid connect to an expression that is not a reference or a WritePort."] - -defn NegUInt () : - PassException $ string-join $ - [sinfo! ": [module " mname "] UIntValue cannot be negative."] - -defn UndeclaredReference (name:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Reference " name " is not declared."] - -defn PoisonWithFlip (name:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Poison " name " cannot be a bundle type with flips."] - -defn MemWithFlip (name:Symbol) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Memory " name " cannot be a bundle type with flips."] - -defn InvalidAccess () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Invalid access to non-reference."] - -defn NoTopModule (name:Symbol) : - PassException $ string-join $ - [sinfo! ": A single module must be named " name "."] - -defn ModuleNotDefined (name:Symbol) : - PassException $ string-join $ - [sinfo! ": Module " name " is not defined."] - -defn IncorrectNumArgs (op:Symbol, n:Int) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Primop " op " requires " n " expression arguments."] - -defn IncorrectNumConsts (op:Symbol, n:Int) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Primop " op " requires " n " integer arguments."] - -defn NegWidth () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Width cannot be negative or zero."] - -defn NegVecSize () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Vector type size cannot be negative."] - -defn NegMemSize () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Memory size cannot be negative or zero."] - -defn IllegalUnknownWidth () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Widths must be defined for memories and poison nodes."] - -defn BadPrintf (x:Char) : - PassException $ string-join $ - [sinfo! ": [module " mname "] Bad printf format: \"%" x "\""];" - -defn BadPrintfTrailing () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Bad printf format: trailing \"%\""];" - -defn BadPrintfIncorrectNum () : - PassException $ string-join $ - [sinfo! ": [module " mname "] Bad printf format: incorrect number of arguments"];" - - -;---------------- Helper Functions -------------- -defn has-flip? (t:Type) -> True|False : - var has? = false - defn find-flip (t:Type) -> Type : - match(t) : - (t:BundleType) : - for f in fields(t) do : - if flip(f) == REVERSE : has? = true - t - (t) : t - find-flip(t) - map(find-flip,t) - has? - -defn contains?<?T> (c:?T,cs:Streamable<?T>) -> True|False : - label<True|False> myret : - for x in cs do : - if x == c : myret(true) - false - -;--------------- Prefix Checker -------------------- - -defstruct Trie : - children : HashTable<Symbol,Trie> - end? : True|False with: (setter => set-end) - -defmethod print (o:OutputStream,t:Trie) : - print-all(o,["[end?:" end?(t) ",children:" children(t) "]"]) - -defn split (s:Symbol) -> List<Symbol> : - map(to-symbol,split(to-string(s),'$')) - -defn contains? (t:Trie,s:Symbol) -> True|False : - key?(children(t),s) - -defn empty? (t:Trie) -> True|False : - length(children(t)) == 0 - -defn add (t:Trie,ls:List<Symbol>) -> True|False : - var t*:Trie = t - var saw-end? = false - for x in ls do : - if end?(t*) : saw-end? = true - if contains?(t*,x) : t* = children(t*)[x] - else : - val temp = Trie(HashTable<Symbol,Trie>(symbol-hash),false) - children(t*)[x] = temp - t* = temp - set-end(t*,true) - saw-end? or not empty?(t*) - -defn contains? (t:Trie,ls:List<Symbol>) -> True|False : - var t*:Trie = t - label<True|False> myret : - for x in ls do : - if contains?(t*,x) : t* = children(t*)[x] - else : myret(false) - myret(end?(t*)) - -;--------------- Check High Form Pass ------------------- -public defn check-high-form (c:Circuit) -> Circuit : - val errors = Vector<PassException>() - defn check-high-form-primop (e:DoPrim) -> False : - defn correct-num (ne:Int|False,nc:Int) -> False : - if not (ne typeof False) : - if length(args(e)) != ne as Int : add(errors,IncorrectNumArgs(to-symbol(op(e)),ne as Int)) - if length(consts(e)) != nc : add(errors,IncorrectNumConsts(to-symbol $ op(e),nc)) - - switch {op(e) == _} : - ADD-OP : correct-num(2,0) - SUB-OP : correct-num(2,0) - MUL-OP : correct-num(2,0) - DIV-OP : correct-num(2,0) - REM-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) - PAD-OP : correct-num(1,1) - AS-UINT-OP : correct-num(1,0) - AS-SINT-OP : correct-num(1,0) - AS-CLOCK-OP : correct-num(1,0) - SHIFT-LEFT-OP : correct-num(1,1) - SHIFT-RIGHT-OP : correct-num(1,1) - DYN-SHIFT-LEFT-OP : correct-num(2,0) - DYN-SHIFT-RIGHT-OP : correct-num(2,0) - CONVERT-OP : correct-num(1,0) - NEG-OP : correct-num(1,0) - NOT-OP : correct-num(1,0) - AND-OP : correct-num(2,0) - OR-OP : correct-num(2,0) - XOR-OP : correct-num(2,0) - AND-REDUCE-OP : correct-num(false,0) - OR-REDUCE-OP : correct-num(false,0) - XOR-REDUCE-OP : correct-num(false,0) - CONCAT-OP : correct-num(2,0) - BITS-SELECT-OP : correct-num(1,2) - HEAD-OP : correct-num(1,1) - TAIL-OP : correct-num(1,1) - - defn check-fstring (s:String,i:Int) -> False : - val valid-formats = "bedxs" - var percent = false - var ret = true - var npercents = 0 - for x in s do : - if (not contains?(valid-formats,x)) and percent : - add(errors,BadPrintf(x)) - if x == '%' : npercents = npercents + 1 - percent = x == '%' - if percent : add(errors,BadPrintfTrailing()) - if npercents != i : add(errors,BadPrintfIncorrectNum()) - defn check-valid-loc (e:Expression) -> False : - match(e) : - (e:UIntValue|SIntValue|DoPrim) : - add(errors,InvalidLOC()) - (e) : false - defn check-high-form-w (w:Width) -> Width : - match(w) : - (w:IntWidth) : - if width(w) <= to-long(0) : - add(errors,NegWidth()) - w - (w) : w - defn check-high-form-t (t:Type) -> Type : - match(map(check-high-form-t,t)) : - (t:VectorType) : - if size(t) < 0 : add(errors,NegVecSize()) - (t) : false - map(check-high-form-w,t) - - defn check-high-form-m (m:Module) -> Module : - val names = HashTable<Symbol,True>(symbol-hash) - val mnames = HashTable<Symbol,True>(symbol-hash) - val tries = Trie(HashTable<Symbol,Trie>(symbol-hash),false) - defn check-high-form-e (e:Expression) -> Expression : - defn valid-subexp (e:Expression) -> Expression : - match(e) : - (e:WRef|WSubField|WSubIndex|WSubAccess|Mux|ValidIf) : false - (e) : add(errors,InvalidAccess()) - e - match(map(check-high-form-e,e)) : - (e:WRef) : - if not key?(names,name(e)) : - add(errors,UndeclaredReference(name(e))) - (e:DoPrim) : check-high-form-primop(e) - (e:Mux|ValidIf) : e - (e:UIntValue) : false - (e:WSubAccess) : - valid-subexp(exp(e)) - e - (e) : map(valid-subexp,e) - map(check-high-form-w,e) - map(check-high-form-t,e) - e - defn check-high-form-s (s:Stmt) -> Stmt : - defn check-name (name:Symbol) -> Symbol : - if key?(names,name) : add(errors,NotUnique(name)) - else : names[name] = true - val ls = split(name) - if add(tries,ls) : add(errors,IsPrefix(name)) - name - sinfo! = info(s) - map(check-name,s) - map(check-high-form-t,s) - map(check-high-form-e,s) - match(s) : - (s:DefWire|DefRegister|DefNode|Conditionally|Stop|Begin) : false - (s:DefPoison) : - if has-flip?(type(s)) : add(errors, PoisonWithFlip(name(s))) - check-high-form-t(type(s)) - (s:DefMemory) : - if has-flip?(data-type(s)) : add(errors, MemWithFlip(name(s))) - if depth(s) <= 0 : add(errors,NegMemSize()) - (s:WDefInstance) : - if not contains?(module(s),map(name,modules(c))) : - add(errors, ModuleNotDefined(module(s))) - (s:Connect) : check-valid-loc(loc(s)) - (s:Print) : check-fstring(string(s),length(args(s))) - (s:BulkConnect) : check-valid-loc(loc(s)) - (s) : false - - map(check-high-form-s,s) - - mname = name(m) - for m in modules(c) do : - mnames[name(m)] = true - for p in ports(m) do : - names[name(p)] = true - map(check-high-form-t,type(p)) - map(check-high-form-w,type(p)) - - match(m) : - (m:ExModule) : false - (m:InModule) : check-high-form-s(body(m)) - m - - var number-top-m = 0 - for m in modules(c) do : - if name(m) == main(c) : number-top-m = number-top-m + 1 - check-high-form-m(m) - sinfo! = info!(c) - if number-top-m != 1 : add(errors,NoTopModule(main(c))) - throw(PassExceptions(errors)) when not empty?(errors) - c - -;==================== CHECK TYPES ===================== -; o Subfields are only on bundles, before type inference <- need to not error, just do unknown-type -; o Indexes are only on vectors -; o pred in conditionally must be of type UInt -; o enable/index in read/writeports must be UInt -; o node's value cannot be a bundle with a flip in it -; o := has same types -; o 2nd arg in dshr/l must be UInt, in general do primops -; o clock must be ClockType -; o reset must be UInt<1> - -public defstruct CheckTypes <: Pass -public defmethod pass (b:CheckTypes) -> (Circuit -> Circuit) : check-types -public defmethod name (b:CheckTypes) -> String : "Check Types" -public defmethod short-name (b:CheckTypes) -> String : "check-types" - -;----------------- Errors --------------------- -defn SubfieldNotInBundle (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Subfield " name " is not in bundle."] - -defn SubfieldOnNonBundle (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Subfield " name " is accessed on a non-bundle."] - -defn IndexTooLarge (info:FileInfo, value:Int) : - PassException $ string-join $ - [info ": [module " mname "] Index with value " value " is too large."] - -defn IndexOnNonVector (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Index illegal on non-vector type."] - -defn AccessIndexNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Access index must be a UInt type."] - -defn IndexNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Index is not of UIntType."] - -defn EnableNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Enable is not of UIntType."] - -defn InvalidConnect (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Type mismatch."] - -defn PrintfArgNotGround (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Printf arguments must be either UIntType or SIntType."] - -defn ReqClk (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Requires a clock typed signal."] - -defn EnNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Enable must be a UIntType typed signal."] - -defn PredNotUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Predicate not a UIntType."] - -defn OpNotGround (info:FileInfo, op:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Primop " op " cannot operate on non-ground types."] - -defn OpNotUInt (info:FileInfo, op:Symbol,e:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Primop " op " requires argument " e " to be a UInt type."] - -defn OpNotAllUInt (info:FileInfo, op:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Primop " op " requires all arguments to be UInt type."] - -defn OpNotAllSameType (info:FileInfo, op:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Primop " op " requires all operands to have the same type."] - -defn NodePassiveType (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Node must be a passive type."] - -defn MuxSameType (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Must mux between equivalent types."] - -defn MuxPassiveTypes (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Must mux between passive types."] - -defn MuxCondUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] A mux condition must be of type UInt."] - -defn ValidIfPassiveTypes (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Must validif a passive type."] - -defn ValidIfCondUInt (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] A validif condition must be of type UInt."] - -;---------------- Helper Functions -------------- -defmethod equal? (t1:Type,t2:Type) -> True|False : - match(t1,t2) : - (t1:ClockType,t2:ClockType) : true - (t1:UIntType,t2:UIntType) : true - (t1:SIntType,t2:SIntType) : true - (t1:BundleType,t2:BundleType) : - var same? = true - for (f1 in fields(t1),f2 in fields(t2)) do : - if flip(f1) != flip(f2) : same? = false - if name(f1) != name(f2) : same? = false - if type(f1) != type(f2) : same? = false - same? - (t1:VectorType,t2:VectorType) : - if type(t1) == type(t2) and size(t1) == size(t2) : true - else : false - (t1,t2) : false - -defn ut () -> UIntType : UIntType(UnknownWidth()) -defn st () -> SIntType : SIntType(UnknownWidth()) - -defn check-types-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) -> False : - defn all-same-type (ls:List<Expression>) -> False : - var error? = false - for x in ls do : - if type(head(ls)) != type(x) : - error? = true - if error? : add(errors,OpNotAllSameType(info,to-symbol $ op(e))) - defn all-ground (ls:List<Expression>) -> False : - var error? = false - for x in ls do : - if not (type(x) typeof UIntType or type(x) typeof SIntType) : - error? = true - if error? : add(errors,OpNotGround(info,to-symbol $ op(e))) - defn all-uint (ls:List<Expression>) -> False : - var error? = false - for x in ls do : - if not (type(x) typeof UIntType) : - error? = true - if error? : add(errors,OpNotAllUInt(info,to-symbol $ op(e))) - defn is-uint (x:Expression) -> False : - var error? = false - if not (type(x) typeof UIntType) : - error? = true - if error? : add(errors,OpNotUInt(info,to-symbol $ op(e),to-symbol(x))) - - switch {op(e) == _} : - AS-UINT-OP : false - AS-SINT-OP : false - AS-CLOCK-OP : false - DYN-SHIFT-LEFT-OP : (is-uint(args(e)[1]) all-ground(args(e))) - DYN-SHIFT-RIGHT-OP : (is-uint(args(e)[1]) all-ground(args(e))) - ADD-OP : all-ground(args(e)) - SUB-OP : all-ground(args(e)) - MUL-OP : all-ground(args(e)) - DIV-OP : all-ground(args(e)) - REM-OP : all-ground(args(e)) - LESS-OP : all-ground(args(e)) - LESS-EQ-OP : all-ground(args(e)) - GREATER-OP : all-ground(args(e)) - GREATER-EQ-OP : all-ground(args(e)) - EQUAL-OP : all-ground(args(e)) - NEQUAL-OP : all-ground(args(e)) - PAD-OP : all-ground(args(e)) - SHIFT-LEFT-OP : all-ground(args(e)) - SHIFT-RIGHT-OP : all-ground(args(e)) - CONVERT-OP : all-ground(args(e)) - NEG-OP : all-ground(args(e)) - NOT-OP : all-ground(args(e)) - AND-OP : all-ground(args(e)) - OR-OP : all-ground(args(e)) - XOR-OP : all-ground(args(e)) - AND-REDUCE-OP : all-ground(args(e)) - OR-REDUCE-OP : all-ground(args(e)) - XOR-REDUCE-OP : all-ground(args(e)) - CONCAT-OP : all-ground(args(e)) - BITS-SELECT-OP : all-ground(args(e)) - HEAD-OP : all-ground(args(e)) - TAIL-OP : all-ground(args(e)) - -;----------------- Check Types Pass --------------------- -public defn check-types (c:Circuit) -> Circuit : - val errors = Vector<PassException>() - defn passive? (t:Type) -> True|False : - match(t) : - (t:UIntType|SIntType) : true - (t:VectorType) : passive?(type(t)) - (t:BundleType) : - var p? = true - for x in fields(t) do : - if (flip(x) == REVERSE) : p? = false - if not passive?(type(x)) : p? = false - p? - (t) : true - defn check-types-e (info:FileInfo,e:Expression) -> Expression : - match(map(check-types-e{info,_},e)) : - (e:WRef) : e - (e:WSubField) : - match(type(exp(e))) : - (t:BundleType) : - val ft = for p in fields(t) find : name(p) == name(e) - if ft == false : add(errors,SubfieldNotInBundle(info,name(e))) - (t) : add(errors,SubfieldOnNonBundle(info,name(e))) - (e:WSubIndex) : - match(type(exp(e))) : - (t:VectorType) : - if value(e) >= size(t) : add(errors,IndexTooLarge(info,value(e))) - (t) : add(errors,IndexOnNonVector(info)) - (e:WSubAccess) : - match(type(exp(e))) : - (t:VectorType) : false - (t) : add(errors,IndexOnNonVector(info)) - match(type(index(e))) : - (t:UIntType) : false - (t) : add(errors,AccessIndexNotUInt(info)) - (e:DoPrim) : check-types-primop(e,errors,info) - (e:Mux) : - if type(tval(e)) != type(fval(e)) : add(errors,MuxSameType(info)) - if not passive?(type(e)) : add(errors,MuxPassiveTypes(info)) - if not passive?(type(e)) : add(errors,MuxPassiveTypes(info)) - if not (type(cond(e)) typeof UIntType) : add(errors,MuxCondUInt(info)) - (e:ValidIf) : - if not passive?(type(e)) : add(errors,ValidIfPassiveTypes(info)) - if not (type(cond(e)) typeof UIntType) : add(errors,ValidIfCondUInt(info)) - (e:UIntValue|SIntValue) : false - e - - defn bulk-equals? (t1:Type,t2:Type) -> True|False : - match(t1,t2) : - (t1:BundleType,t2:BundleType) : - var same? = true - for (f1 in fields(t1),f2 in fields(t2)) do : - if name(f1) == name(f2) : - if flip(f1) != flip(f2) : same? = false - if not bulk-equals?(type(f1),type(f2)) : same? = false - same? - (t1:ClockType,t2:ClockType) : true - (t1:UIntType,t2:UIntType) : true - (t1:SIntType,t2:SIntType) : true - (t1:VectorType,t2:VectorType) : - if bulk-equals?(type(t1),type(t2)) : true - else : false - (t1,t2) : false - - defn check-types-s (s:Stmt) -> Stmt : - map{check-types-s,_} $ { - match(map(check-types-e{info(s),_},s)) : - (s:Connect) : - if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s))) - (s:BulkConnect) : - if not bulk-equals?(type(loc(s)),type(exp(s))) : - add(errors,InvalidConnect(info(s))) - (s:Stop) : - if type(clk(s)) != ClockType() : add(errors,ReqClk(info(s))) - if type(en(s)) != ut() : add(errors,EnNotUInt(info(s))) - (s:Print) : - for x in args(s) do : - if type(x) != ut() and type(x) != st(): - add(errors,PrintfArgNotGround(info(s))) - if type(clk(s)) != ClockType() : add(errors,ReqClk(info(s))) - if type(en(s)) != ut() : add(errors,EnNotUInt(info(s))) - (s:Conditionally) : - if type(pred(s)) != ut() : add(errors,PredNotUInt(info(s))) - (s:DefNode) : - if not passive?(type(value(s))) : - add(errors,NodePassiveType(info(s))) - (s) : false - s }() - - for m in modules(c) do : - mname = name(m) - match(m) : - (m:ExModule) : false - (m:InModule) : check-types-s(body(m)) - throw(PassExceptions(errors)) when not empty?(errors) - c - -;================= GENDER CHECK ========================== -; o Nodes always male -; o Accessors only have one gender, unless rdwr -; o output/input only one gender -; o correctly check for the base bundle - -public defstruct CheckGenders <: Pass -public defmethod pass (b:CheckGenders) -> (Circuit -> Circuit) : check-genders -public defmethod name (b:CheckGenders) -> String : "Check Genders" -public defmethod short-name (b:CheckGenders) -> String : "check-genders" - -;----------------- Errors --------------------- -defn WrongGender (info:FileInfo,expr:Symbol,wrong:Symbol,right:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Expression " expr " is used as a " wrong " but can only be used as a " right "."] - -;---------------- Helper Functions -------------- -defn dir-to-gender (d:Direction) -> Gender : - switch {_ == d} : - INPUT : MALE - OUTPUT : FEMALE ;BI-GENDER - -defn as-srcsnk (g:Gender) -> Symbol : - switch {_ == g} : - MALE : `source - FEMALE : `sink - UNKNOWN-GENDER : `unknown - BI-GENDER : `sourceOrSink - -;----------------- Check Genders Pass --------------------- - -public defn check-genders (c:Circuit) -> Circuit : - val errors = Vector<PassException>() - defn get-kind (e:Expression) -> Kind : - match(e) : - (e:WRef) : kind(e) - (e:WSubField) : get-kind(exp(e)) - (e:WSubIndex) : get-kind(exp(e)) - (e:WSubAccess) : get-kind(exp(e)) - (e) : NodeKind() - - defn check-gender (info:FileInfo,genders:HashTable<Symbol,Gender>,e:Expression,desired:Gender) -> False : - val gender = get-gender(e,genders) - val kind* = get-kind(e) - defn flip? (t:Type) -> True|False : - var f? = false - defn flip-rec (t:Type,f:Flip) -> Type : - match(t) : - (t:BundleType) : - for field in fields(t) do : - flip-rec(type(field),f * flip(field)) - (t:VectorType) : flip-rec(type(t),f) - (t) : if f == REVERSE : f? = true - t - flip-rec(t,DEFAULT) - f? - - val has-flip? = flip?(type(e)) - ;println(e) - ;println(gender) - ;println(desired) - ;println(kind*) - ;println(desired == gender) - ;if gender != desired and gender != BI-GENDER: - switch fn ([x,y]) : gender == x and desired == y : - [MALE, FEMALE] : - add(errors,WrongGender(info,to-symbol(e),as-srcsnk(desired),as-srcsnk(gender))) - [FEMALE, MALE] : - if (kind* == PortKind() or kind* == InstanceKind()) and has-flip? == false : - ; OK! - false - else : - ; Not Ok! - add(errors,WrongGender(info,to-symbol(e),as-srcsnk(desired),as-srcsnk(gender))) - else : false - - defn get-gender (e:Expression,genders:HashTable<Symbol,Gender>) -> Gender : - match(e) : - (e:WRef) : genders[name(e)] - (e:WSubField) : - val f = {_ as Field} $ for f in fields(type(exp(e)) as BundleType) find : name(f) == name(e) - get-gender(exp(e),genders) * flip(f) - (e:WSubIndex) : get-gender(exp(e),genders) - (e:WSubAccess) : get-gender(exp(e),genders) - (e:DoPrim) : MALE - (e:UIntValue) : MALE - (e:SIntValue) : MALE - (e:Mux) : MALE - (e:ValidIf) : MALE - - defn check-genders-e (info:FileInfo,e:Expression,genders:HashTable<Symbol,Gender>) -> False : - do(check-genders-e{info,_,genders},e) - match(e) : - (e:WRef) : false - (e:WSubField) : false - (e:WSubIndex) : false - (e:WSubAccess) : false - (e:DoPrim) : - for e in args(e) do : - check-gender(info,genders,e,MALE) - (e:Mux) : do(check-gender{info,genders,_,MALE},e) - (e:ValidIf) : do(check-gender{info,genders,_,MALE},e) - (e:UIntValue) : false - (e:SIntValue) : false - - defn check-genders-s (s:Stmt,genders:HashTable<Symbol,Gender>) -> False : - do(check-genders-e{info(s),_:Expression,genders},s) - do(check-genders-s{_:Stmt,genders},s) - match(s) : - (s:DefWire) : genders[name(s)] = BI-GENDER - (s:DefPoison) : genders[name(s)] = MALE - (s:DefRegister) : genders[name(s)] = BI-GENDER - (s:DefNode) : - check-gender(info(s),genders,value(s),MALE) - genders[name(s)] = MALE - (s:DefMemory) : genders[name(s)] = MALE - (s:WDefInstance) : genders[name(s)] = MALE - (s:Connect) : - check-gender(info(s),genders,loc(s),FEMALE) - check-gender(info(s),genders,exp(s),MALE) - (s:Print) : - for x in args(s) do : - check-gender(info(s),genders,x,MALE) - check-gender(info(s),genders,en(s),MALE) - check-gender(info(s),genders,clk(s),MALE) - (s:BulkConnect) : - check-gender(info(s),genders,loc(s),FEMALE) - check-gender(info(s),genders,exp(s),MALE) - (s:Conditionally) : - check-gender(info(s),genders,pred(s),MALE) - (s:Empty) : false - (s:Stop) : - check-gender(info(s),genders,en(s),MALE) - check-gender(info(s),genders,clk(s),MALE) - (s:Begin|IsInvalid) : false - - for m in modules(c) do : - mname = name(m) - val genders = HashTable<Symbol,Gender>(symbol-hash) - for p in ports(m) do : - genders[name(p)] = dir-to-gender(direction(p)) - match(m) : - (m:ExModule) : false - (m:InModule) : check-genders-s(body(m),genders) - throw(PassExceptions(errors)) when not empty?(errors) - c - -;================= Width Check ========================== -;AFTER WIDTH INFERENCE -; * No names -; * No Unknowns -; * All widths are positive -; * widths are large enough to contain value - - -public defstruct CheckWidths <: Pass -public defmethod pass (b:CheckWidths) -> (Circuit -> Circuit) : check-width -public defmethod name (b:CheckWidths) -> String : "Width Check" -public defmethod short-name (b:CheckWidths) -> String : "width-check" - -;----------------- Errors ------------------------ - -defn UninferredWidth (info:FileInfo) : - PassException $ string-join $ - [info ": [module " mname "] Uninferred width."] - -defn WidthTooSmall (info:FileInfo,v:String) : - PassException $ string-join $ - [info ": [module " mname "] Width too small for constant " v "."] - -;---------------- Helper Functions -------------- - -;--------------- Check Width Pass ------------------- -public defn check-width (c:Circuit) -> Circuit : - val errors = Vector<PassException>() - - defn check-width-m (m:Module) -> False : - defn check-width-w (info:FileInfo,w:Width) -> Width : - match(w) : - (w:IntWidth) : - if width(w) <= to-long(0) : add(errors,NegWidth()) - (w) : - add(errors,UninferredWidth(info)) - w - - defn check-width-e (info:FileInfo,e:Expression) -> Expression : - match(map(check-width-e{info,_},e)) : - (e:UIntValue) : - match(width(e)) : - (w:IntWidth) : - if max(to-long(1),to-long(req-num-bits(value(e)) - 1)) > width(w) : - add(errors,WidthTooSmall(info,to-string(value(e)))) - (w) : add(errors,UninferredWidth(info)) - check-width-w(info,width(e)) - (e:SIntValue) : - match(width(e)) : - (w:IntWidth) : - if to-long(req-num-bits(value(e))) > width(w) : - add(errors,WidthTooSmall(info,to-string(value(e)))) - (w) : add(errors,UninferredWidth(info)) - check-width-w(info,width(e)) - (e:DoPrim) : false - (e) : false - - ;mapr(check-width-w{info,_},type(map(check-width-e{info,_},e))) - e - - defn check-width-s (s:Stmt) -> Stmt : - sinfo! = info(s) - map(check-width-e{info(s),_},map(check-width-s,s)) - map(mapr{check-width-w{info(s),_},_:Type},s) - - for p in ports(m) do : - mapr(check-width-w{info(p),_},type(p)) - - match(m) : - (m:ExModule) : false - (m:InModule) : check-width-s(body(m)) - false - - for m in modules(c) do : - mname = name(m) - check-width-m(m) - throw(PassExceptions(errors)) when not empty?(errors) - c - - -;================ Initialization Check ================== -; Error on all componenents that are not connected to. - -public defstruct CheckInitialization <: Pass -public defmethod pass (b:CheckInitialization) -> (Circuit -> Circuit) : check-init -public defmethod name (b:CheckInitialization) -> String : "Check Initialization" -public defmethod short-name (b:CheckInitialization) -> String : "check-init" - -;----------------- Errors ------------------------ - -defn RefNotInitialized (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": [module " mname "] Reference " name " is not fully initialized."] - -;------------ Helper Functions ------------- - -;------------ Pass ------------------ - -public defn check-init (c:Circuit) : - val errors = Vector<PassException>() - - defn check-init-m (m:InModule) : - defn get-name (e:Expression) -> Symbol : - match(e) : - (e:WRef) : name(e) - (e:WSubField) : symbol-join([get-name(exp(e)) `. name(e)]) - (e:WSubIndex) : symbol-join([get-name(exp(e)) to-symbol("[") value(e) to-symbol("]")]) - (e) : error("Shouldn't be here") - defn has-void? (e:Expression) -> True|False : - var void? = false - defn has-void (e:Expression) -> Expression : - match(e) : - (e:WVoid) : - void? = true - e - (e) : map(has-void,e) - has-void(e) - void? - defn check-init-s (s:Stmt) -> Stmt : - match(s) : - (s:Connect) : - if has-void?(exp(s)) : add(errors,RefNotInitialized(info(s),get-name(loc(s)))) - s - (s) : map(check-init-s,s) - - check-init-s(body(m)) - - for m in modules(c) do : - mname = name(m) - match(m) : - (m:InModule) : check-init-m(m) - (m) : false - - throw(PassExceptions(errors)) when not empty?(errors) - c - -;;================= Low Form Check ========================== -;;AFTER LOWERING -;; o All things connect to once -;; o no reg -;; o no accessors -;; o only vecs are for memories -;; o no bundles (future, will have them for mems) -;; o only predicated conditional connects -; -;public defstruct CheckLowForm <: Pass -;public defmethod pass (b:CheckLowForm) -> (Circuit -> Circuit) : check-low-form -;public defmethod name (b:CheckLowForm) -> String : "Low Form Check" -;public defmethod short-name (b:CheckLowForm) -> String : "low-form-check" -; -;;----------------- Errors ------------------------ -;defn InvalidVec (info:FileInfo,name:Symbol) : -; PassException $ string-join $ -; [info ": [module " mname "] Expression " name " has an illegal vector type."] -; -;defn InvalidBundle (info:FileInfo,name:Symbol) : -; PassException $ string-join $ -; [info ": [module " mname "] Expression " name " has an illegal bundle type."] -; -;defn NoWhen (info:FileInfo) : -; PassException $ string-join $ -; [info ": [module " mname "] Illegal when statement. No when statements with multiple statements are allowed in low firrtl."] -; -;defn SingleAssignment (info:FileInfo,name:Symbol) : -; PassException $ string-join $ -; [info ": [module " mname "] Illegal assignment to " name ". Wires can only be assigned to once."] -; -;defn NoOnReset (info:FileInfo) : -; PassException $ string-join $ -; [info ": [module " mname "] Invalid use of on-reset. No on-resets are allowed in low firrtl."] -; -;defn NoBulkConnect (info:FileInfo) : -; PassException $ string-join $ -; [info ": [module " mname "] Invalid use of <>. No <>'s are allowed in low firrtl."] -; -;;---------------- Helper Functions -------------- -; -;;--------------- Check Low Form Pass ------------------- -;public defn check-low-form (c:Circuit) -> Circuit : -; val errors = Vector<PassException>() -; -; defn check-low-form-t (info:FileInfo,t:Type,name:Symbol) -> False : -; match(t) : -; (t:VectorType) : add(errors,InvalidVec(info,name)) -; (t:BundleType) : add(errors,InvalidBundle(info,name)) -; (t) : false -; -; defn check-low-form-m (m:Module) -> False : -; for p in ports(m) do : -; check-low-form-t(info(p),type(p),name(p)) -; -; val assigned? = HashTable<Symbol,True>(symbol-hash) -; val insts = Vector<Symbol>() -; val mems = Vector<Symbol>() -; defn check-correct-exp (info:FileInfo,e:Expression) -> False : -; do(check-correct-exp{info,_:Expression},e) -; match(e) : -; (e:Ref) : -; if contains?(insts,name(e)) : -; for f in fields(type(e) as BundleType) do : -; check-low-form-t(info,type(f),name(e)) -; if contains?(mems,name(e)) : -; check-low-form-t(info,type(type(e) as VectorType),name(e)) -; (e) : false ;check-low-form-t(info,type(e),to-symbol $ to-string(e)) -; defn check-low-form-s (s:Stmt) -> False : -; match(s) : -; (s:DefWire) : -; check-low-form-t(info(s),type(s),name(s)) -; (s:DefPoison) : -; check-low-form-t(info(s),type(s),name(s)) -; (s:DefMemory) : -; check-low-form-t(info(s),type(s),name(s)) -; add(mems,name(s)) -; (s:DefInstance) : -; for f in fields(type(module(s)) as BundleType) do : -; check-low-form-t(info(s),type(f),name(s)) -; add(insts,name(s)) -; (s:DefNode) : -; check-correct-exp(info(s),value(s)) -; (s:Print) : -; for x in args(s) do : -; check-correct-exp(info(s),x) -; (s:DefRegister) : false -; (s:DefAccessor) : false -; (s:Conditionally) : -; if (not alt(s) typeof Empty) or (conseq(s) typeof Begin) : add(errors,NoWhen(info(s))) -; (s:OnReset) : add(errors,NoOnReset(info(s))) -; (s:BulkConnect) : add(errors,NoBulkConnect(info(s))) -; (s:Connect) : -; check-correct-exp(info(s),exp(s)) -; match(loc(s)) : -; (e:Ref|Subfield) : -; val n* = to-symbol $ to-string $ e -; if key?(assigned?,n*) : add(errors,SingleAssignment(info(s),n*)) -; else : assigned?[to-symbol $ to-string $ e] = true -; (e) : check-correct-exp(info(s),e) -; (s:Empty) : false -; (s:Stop) : false -; (s:Begin) : do(check-low-form-s,s) -; -; match(m) : -; (m:ExModule) : false -; (m:InModule) : check-low-form-s(body(m)) -; false -; -; for m in modules(c) do : -; mname = name(m) -; check-low-form-m(m) -; throw(PassExceptions(errors)) when not empty?(errors) -; c -; |
