defpackage firrtl/errors : import core import verse import firrtl/ir2 import firrtl/ir-utils import firrtl/primops import firrtl/passes import firrtl-main ;========== 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 ;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 ;AFTER LOWERING ; All things connect to once ; ?? ; No combinational loops ; cannot connect to a pad, or a register. only connct to a reference definterface HighFormException <: Exception defn HighFormException (s:String) : new HighFormException : defmethod print (o:OutputStream, this) : print(o, s) defn HighFormExceptions (xs:Streamable) : HighFormException(string-join(xs, "\n")) defn NotUnique (info:FileInfo|False, name:Symbol) : HighFormException $ string-join $ [info ": Reference " name " does not have a unique name."] defn IsPrefix (info:FileInfo|False, name1:Symbol, name2:Symbol) : HighFormException $ string-join $ [info ": Reference " name1 " and " name2 " share a prefix."] defn InvalidLOC (info:FileInfo|False) : HighFormException $ 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 UndeclaredReference (info:FileInfo|False, name:Symbol) : HighFormException $ string-join $ [info ": Reference " name " is not declared."] defn MemWithFlip (info:FileInfo|False, name:Symbol) : HighFormException $ string-join $ [info ": Memory " name " cannot be a bundle type with flips."] defn InvalidSubfield (info:FileInfo|False, name:Symbol) : HighFormException $ string-join $ [info ": Invalid subfield access to non-reference."] defn InvalidIndex (info:FileInfo|False, name:Symbol) : HighFormException $ string-join $ [info ": Invalid index access to non-reference."] defn NoTopModule (info:FileInfo|False, name:Symbol) : HighFormException $ 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|False, name:Symbol) : HighFormException $ string-join $ [info ": The referenced module in the instance declaration, " name ", is not defined."] ;================ Check 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? (c:?T,cs:Streamable) -> True|False : label myret : for x in cs do : if x == c : myret(true) false defn is-prefix? (s:Symbol,v:Vector) -> Symbol|False : label myret : for x in v do : if is-prefix?(x,s) : myret(x) false defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False : var is? = true val s1* = to-string(s1) val s2* = to-string(s2) for (x in s1*, y in s2*) do : if x != y : is? = false if length(s1*) > length(s2*) : if s1*[length(s2*)] != '$' : is? = false if length(s1*) < length(s2*) : if s2*[length(s1*)] != '$' : is? = false 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> public defn check-high-form (c:Circuit) -> Circuit : val errors = Vector() defn check-high-form-s (s:Stmt,names:Vector) -> Stmt : defn check-name (info:FileInfo|False,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)) (s:DefMemory) : check-name(info!(s),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))) (s) : false s }() defn check-high-form-m (m:Module) -> False : val names = Vector() check-high-form-s(body(m),names) false 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) if number-top-m != 1 : add(errors,NoTopModule(info!(c),main(c))) throw(HighFormExceptions(errors)) when not empty?(errors) c