aboutsummaryrefslogtreecommitdiff
path: root/src/main/stanza/errors.stanza
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/stanza/errors.stanza')
-rw-r--r--src/main/stanza/errors.stanza189
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
+
+