diff options
| author | azidar | 2015-08-25 14:13:00 -0700 |
|---|---|---|
| committer | azidar | 2015-08-25 14:13:13 -0700 |
| commit | eb1ab67b6cc3fd4a549da563bf643bd519d7562e (patch) | |
| tree | a21f0ca828398a33a68f38209429cc6beed86edc | |
| parent | 6cd96b6315c32bbf6c4ace28197ff1d4be86a129 (diff) | |
Added width check pass with tests. #22.
| -rw-r--r-- | src/main/stanza/compilers.stanza | 56 | ||||
| -rw-r--r-- | src/main/stanza/errors.stanza | 232 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 8 | ||||
| -rw-r--r-- | test/errors/high-form/NegWidth.fir | 2 | ||||
| -rw-r--r-- | test/errors/width/NegWidth.fir | 9 | ||||
| -rw-r--r-- | test/errors/width/SmallWidth.fir | 13 | ||||
| -rw-r--r-- | test/errors/width/UninferredWidth.fir | 12 |
7 files changed, 210 insertions, 122 deletions
diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index eb0a36c4..b9a3028a 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -32,6 +32,7 @@ public defmethod passes (c:StandardFlo) -> List<Pass> : Inline() SplitExp() ToRealIR() + CheckWidths() ;RemoveSpecialChars() CheckHighForm() CheckLowForm() @@ -42,34 +43,33 @@ public defstruct StandardVerilog <: Compiler : with-output : (() -> False) -> False with: (as-method => true) public defmethod passes (c:StandardVerilog) -> List<Pass> : to-list $ [ - RemoveSpecialChars() - RemoveScopes() - CheckHighForm() - TempElimination() - ToWorkingIR() - ;; MakeExplicitReset() - ResolveKinds() - CheckKinds() - InferTypes() - CheckTypes() - ResolveGenders() - CheckGenders() - ExpandAccessors() - LowerToGround() - ExpandIndexedConnects() - InferTypes() - CheckGenders() - ExpandWhens() - InferWidths() - ;Pad() - ConstProp() - SplitExp() - ToRealIR() - ;RemoveSpecialChars() - CheckHighForm() - CheckLowForm() - CheckInitialization() - Verilog(with-output(c)) + RemoveSpecialChars() ;R + RemoveScopes() ;R + CheckHighForm() ;R + TempElimination() ;R + ToWorkingIR() ;R -> W + ResolveKinds() ;W + CheckKinds() ;W + InferTypes() ;R + CheckTypes() ;R + ResolveGenders() ;W + CheckGenders() ;W + ExpandAccessors() ;W + LowerToGround() ;W + ExpandIndexedConnects() ;W + InferTypes() ;R + CheckGenders() ;W + ExpandWhens() ;W + InferWidths() ;R + Pad() ;R + ConstProp() ;R + SplitExp() ;R + ToRealIR() ;W -> R + CheckWidths() ;R + CheckHighForm() ;R + CheckLowForm() ;R + CheckInitialization() ;R + Verilog(with-output(c)) ;R ] diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index 77e48263..72535242 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -16,13 +16,6 @@ defpackage firrtl/errors : ; * Only modules in circuit (no statements or expressions) <- parser ; * Module must be a reference in inst declaration -;AFTER WIDTH INFERENCE -; o No names -; o No Unknowns -; o All widths are positive -; o pad's width is greater than value's width -; o widths are large enough to contain value - ;AFTER ?????? ; o No combinational loops @@ -92,10 +85,6 @@ defn ModuleNotDefined (info:FileInfo, name:Symbol) : PassException $ string-join $ [info ": Module " 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>."] - defn IncorrectNumArgs (info:FileInfo, op:Symbol, n:Int) : PassException $ string-join $ [info ": [module " mname "] Primop " op " requires " n " expression arguments."] @@ -106,7 +95,7 @@ defn IncorrectNumConsts (info:FileInfo, op:Symbol, n:Int) : defn NegWidth (info:FileInfo) : PassException $ string-join $ - [info ": [module " mname "] Width cannot be negative."] + [info ": [module " mname "] Width cannot be negative or zero."] defn NegVecSize (info:FileInfo) : PassException $ string-join $ @@ -264,7 +253,7 @@ public defn check-high-form (c:Circuit) -> Circuit : defn check-high-form-w (info:FileInfo,w:Width,unknown-ok?:True|False) -> Width : match(w) : (w:IntWidth) : - if width(w) < 0 : add(errors,NegWidth(info)) + if width(w) <= 0 : add(errors,NegWidth(info)) w (w:UnknownWidth) : if unknown-ok? == false : add(errors,IllegalUnknownWidth(info)) @@ -363,15 +352,6 @@ public defn check-high-form (c:Circuit) -> Circuit : mnames[name(m)] = true for p in ports(m) do : names[name(p)] = true - ;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))) map(check-high-form-t{info(p),_,true},type(p)) map(check-high-form-w{info(p),_,true},type(p)) @@ -466,7 +446,6 @@ public defn check-kinds (c:Circuit) -> Circuit : 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 @@ -833,6 +812,146 @@ public defn check-genders (c:Circuit) -> Circuit : 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) : + val init? = HashTable<Symbol,FileInfo|True>(symbol-hash) + defn get-name (e:Expression) -> Symbol : + match(e) : + (e:Ref) : name(e) + (e:Subfield) : symbol-join([get-name(exp(e)) `. name(e)]) + (e) : error("Shouldn't be here") + + defn check-init-s (s:Stmt) : + do(check-init-s,s) + match(s) : + (s:DefWire|DefRegister) : init?[name(s)] = info(s) + (s:DefAccessor) : + if acc-dir(s) == WRITE : init?[name(s)] = info(s) + (s:DefInstance) : + for f in fields(type(module(s)) as BundleType) do : + if flip(f) == REVERSE : + init?[symbol-join([name(s) `. name(f)])] = info(s) + (s:Connect) : + init?[get-name(loc(s))] = true + (s) : false + + for p in ports(m) do : + if direction(p) == OUTPUT : + init?[name(p)] = info(p) + + check-init-s(body(m)) + + for x in init? do : + match(value(x)) : + (v:FileInfo) : add(errors, RefNotInitialized(v,key(x))) + (v) : false + + 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 + +;================= 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) <= 0 : add(errors,NegWidth(info)) + (w:LongWidth) : + if width(w) <= to-long(0) : add(errors,NegWidth(info)) + (w) : + add(errors,UninferredWidth(info)) + w + + defn check-width-e (info:FileInfo,e:Expression) -> Expression : + match(map(check-width-e{info,_},e)) : + (e:UIntValue|SIntValue) : + match(width(e)) : + (w:IntWidth) : + if num-bits(value(e)) > width(w) : + add(errors,WidthTooSmall(info,to-string(value(e)))) + (w:LongWidth) : + if to-long(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 : + 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 + + ;================= Low Form Check ========================== ;AFTER LOWERING ; o All things connect to once @@ -944,70 +1063,3 @@ public defn check-low-form (c:Circuit) -> Circuit : 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) : - val init? = HashTable<Symbol,FileInfo|True>(symbol-hash) - defn get-name (e:Expression) -> Symbol : - match(e) : - (e:Ref) : name(e) - (e:Subfield) : symbol-join([get-name(exp(e)) `. name(e)]) - (e) : error("Shouldn't be here") - - defn check-init-s (s:Stmt) : - do(check-init-s,s) - match(s) : - (s:DefWire|DefRegister) : init?[name(s)] = info(s) - (s:DefAccessor) : - if acc-dir(s) == WRITE : init?[name(s)] = info(s) - (s:DefInstance) : - for f in fields(type(module(s)) as BundleType) do : - if flip(f) == REVERSE : - init?[symbol-join([name(s) `. name(f)])] = info(s) - (s:Connect) : - init?[get-name(loc(s))] = true - (s) : false - - for p in ports(m) do : - if direction(p) == OUTPUT : - init?[name(p)] = info(p) - - check-init-s(body(m)) - - for x in init? do : - match(value(x)) : - (v:FileInfo) : add(errors, RefNotInitialized(v,key(x))) - (v) : false - - 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 - - - - diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index bf2e27bf..5c09b034 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -2049,9 +2049,11 @@ defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit : defn solve (w:Width) -> False|Long : match(w) : (w:VarWidth) : - val w* = h[name(w)] - if w* typeof VarWidth : false - else : solve(w*) + val w* = get?(h,name(w),false) + match(w*) : + (w:VarWidth) : false + (w:False) : false + (w) : solve(w as Width) (w:MaxWidth) : apply-l(map(solve,args(w)),max) (w:PlusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{plus(_,_)}) (w:MinusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{minus(_,_)}) diff --git a/test/errors/high-form/NegWidth.fir b/test/errors/high-form/NegWidth.fir index 9b055228..1eb54a34 100644 --- a/test/errors/high-form/NegWidth.fir +++ b/test/errors/high-form/NegWidth.fir @@ -1,5 +1,5 @@ ; RUN: firrtl -i %s -o %s.v -X verilog -p c 2>&1 | tee %s.out | FileCheck %s -; CHECK: Width cannot be negative. +; CHECK: Width cannot be negative or zero. circuit Top : module Top : diff --git a/test/errors/width/NegWidth.fir b/test/errors/width/NegWidth.fir new file mode 100644 index 00000000..5d5bbf43 --- /dev/null +++ b/test/errors/width/NegWidth.fir @@ -0,0 +1,9 @@ +; RUN: firrtl -i %s -o %s.v -X verilog -p ciwT 2>&1 | tee %s.out | FileCheck %s +; CHECK: Width cannot be negative or zero. + +circuit Top : + module Top : + output y : UInt + + wire x : UInt<2> + y := shr(x,4) diff --git a/test/errors/width/SmallWidth.fir b/test/errors/width/SmallWidth.fir new file mode 100644 index 00000000..9e26699e --- /dev/null +++ b/test/errors/width/SmallWidth.fir @@ -0,0 +1,13 @@ +; RUN: firrtl -i %s -o %s.v -X verilog -p ciwT 2>&1 | tee %s.out | FileCheck %s +; CHECK: Width too small for constant "h121". +; CHECK: Width too small for constant "h13333". + +circuit Top : + module Top : + output z : UInt + + z := add(UInt<4>("h121"),UInt<3>("h13333")) + + + + diff --git a/test/errors/width/UninferredWidth.fir b/test/errors/width/UninferredWidth.fir new file mode 100644 index 00000000..d4cff841 --- /dev/null +++ b/test/errors/width/UninferredWidth.fir @@ -0,0 +1,12 @@ +; RUN: firrtl -i %s -o %s.v -X verilog -p ciwTd 2>&1 | tee %s.out | FileCheck %s +; CHECK: Uninferred width. + +circuit Top : + module Top : + input z : UInt + + + + + + |
