diff options
Diffstat (limited to 'src/main/stanza/errors.stanza')
| -rw-r--r-- | src/main/stanza/errors.stanza | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza new file mode 100644 index 00000000..3e1d2cb4 --- /dev/null +++ b/src/main/stanza/errors.stanza @@ -0,0 +1,189 @@ +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>) : + 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?<?T> (c:?T,cs:Streamable<?T>) -> True|False : + label<True|False> myret : + for x in cs do : + if x == c : myret(true) + false + +defn is-prefix? (s:Symbol,v:Vector<Symbol>) -> Symbol|False : + label<Symbol|False> myret : + for x in v do : + if is-prefix?(x,s) : myret(x) + false + +defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False : + var is? = true + val s1* = to-string(s1) + val s2* = to-string(s2) + for (x in s1*, y in s2*) do : + if x != y : is? = false + if length(s1*) > length(s2*) : + if s1*[length(s2*)] != '$' : is? = false + if length(s1*) < length(s2*) : + if s2*[length(s1*)] != '$' : is? = false + 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 + +public defn check-high-form (c:Circuit) -> Circuit : + val errors = Vector<HighFormException>() + + defn check-high-form-s (s:Stmt,names:Vector<Symbol>) -> 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<Symbol>() + 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 + + |
