diff options
| -rw-r--r-- | src/main/stanza/errors.stanza | 38 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 4 | ||||
| -rw-r--r-- | src/main/stanza/flo.stanza | 1 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 1 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 4 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 26 | ||||
| -rw-r--r-- | src/main/stanza/verilog.stanza | 5 | ||||
| -rw-r--r-- | test/errors/high-form/Flip-Poison.fir | 8 | ||||
| -rw-r--r-- | test/features/Poison.fir | 18 |
9 files changed, 91 insertions, 14 deletions
diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index 5c77c2a4..321349d6 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -68,6 +68,10 @@ defn UndeclaredReference (info:FileInfo, name:Symbol) : PassException $ string-join $ [info ": [module " mname "] Reference " name " is not declared."] +defn PoisonWithFlip (info:FileInfo, name:Symbol) : + PassException $ string-join $ + [info ": [module " mname "] Poison " name " cannot be a bundle type with flips."] + defn MemWithFlip (info:FileInfo, name:Symbol) : PassException $ string-join $ [info ": [module " mname "] Memory " name " cannot be a bundle type with flips."] @@ -108,6 +112,10 @@ defn NegVecSize (info:FileInfo) : PassException $ string-join $ [info ": [module " mname "] Vector type size cannot be negative."] +defn IllegalUnknownWidth (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Widths must be defined for memories and poison nodes."] + ;---------------- Helper Functions -------------- defn has-flip? (t:Type) -> True|False : var has? = false @@ -253,19 +261,22 @@ public defn check-high-form (c:Circuit) -> Circuit : add(errors,InvalidLOC(info)) (e) : false - defn check-high-form-w (info:FileInfo,w:Width) -> Width : + 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)) w + (w:UnknownWidth) : + if unknown-ok? == false : add(errors,IllegalUnknownWidth(info)) + w (w) : w - defn check-high-form-t (info:FileInfo,t:Type) -> Type : - match(map(check-high-form-t{info,_},t)) : + defn check-high-form-t (info:FileInfo,t:Type,unknown-ok?:True|False) -> Type : + match(map(check-high-form-t{info,_,true},t)) : (t:VectorType) : if size(t) < 0 : add(errors,NegVecSize(info)) (t) : false - map(check-high-form-w{info,_:Width},t) + map(check-high-form-w{info,_:Width,unknown-ok?},t) defn check-high-form-e (info:FileInfo,e:Expression,names:HashTable<Symbol,True>) -> Expression : match(map(check-high-form-e{info,_,names},e)) : @@ -284,20 +295,25 @@ public defn check-high-form (c:Circuit) -> Circuit : (e:UIntValue) : false ;if neg?(value(e)) : add(errors,NegUInt(info)) (e) : false - map(check-high-form-w{info,_:Width},e) - map(check-high-form-t{info,_:Type},e) + map(check-high-form-w{info,_:Width,true},e) + map(check-high-form-t{info,_:Type,true},e) e defn check-high-form-s (s:Stmt,names:HashTable<Symbol,True>,mnames:HashTable<Symbol,True>) -> Stmt : defn check-name (info:FileInfo,name:Symbol) -> False : if key?(names,name) : add(errors,NotUnique(info,name)) - map(check-high-form-t{info(s),_:Type},s) + map(check-high-form-t{info(s),_:Type,true},s) map{check-high-form-s{_,names,mnames},_} $ { match(s) : ;map(check-high-form-e{info(s),_,names},s)) : (s:DefWire) : check-name(info(s),name(s)) names[name(s)] = true + (s:DefPoison) : + check-name(info(s),name(s)) + if has-flip?(type(s)) : add(errors, PoisonWithFlip(info(s), name(s))) + names[name(s)] = true + check-high-form-t(info(s),type(s),false) (s:DefRegister) : check-name(info(s),name(s)) names[name(s)] = true @@ -307,6 +323,7 @@ public defn check-high-form (c:Circuit) -> Circuit : check-name(info(s),name(s)) names[name(s)] = true if has-flip?(type(s)) : add(errors, MemWithFlip(info(s), name(s))) + check-high-form-t(info(s),type(s),false) check-high-form-e(info(s),clock(s),names) (s:DefInstance) : if not contains?(name(module(s) as Ref),map(name,modules(c))) : @@ -355,8 +372,8 @@ public defn check-high-form (c:Circuit) -> Circuit : ; add(errors,WrongReset(info!(m),name(m))) ; else : ; add(errors,WrongReset(info!(m),name(m))) - map(check-high-form-t{info(p),_},type(p)) - map(check-high-form-w{info(p),_},type(p)) + map(check-high-form-t{info(p),_,true},type(p)) + map(check-high-form-w{info(p),_,true},type(p)) match(m) : (m:ExModule) : false @@ -773,6 +790,7 @@ public defn check-genders (c:Circuit) -> Circuit : 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) @@ -882,6 +900,8 @@ public defn check-low-form (c:Circuit) -> Circuit : 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(type(s)),name(s)) add(mems,name(s)) diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index fbe22463..de9b6cb3 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -132,6 +132,10 @@ public defstruct DefAccessor <: Stmt : source: Expression index: Expression acc-dir: AccDirection +public defstruct DefPoison <: Stmt : ;LOW + info: FileInfo with: (as-method => true) + name: Symbol + type: Type public defstruct Conditionally <: Stmt : info: FileInfo with: (as-method => true) pred: Expression diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza index 16360543..b34af613 100644 --- a/src/main/stanza/flo.stanza +++ b/src/main/stanza/flo.stanza @@ -162,6 +162,7 @@ defn emit-s (s:Stmt, flokinds:HashTable<Symbol,FloKind>, top:Symbol,sh:HashTable error("Unknown Connect") match(s) : (s:DefWire) : "" + (s:DefPoison) : "" (s:DefInstance) : error("Shouldn't be here") (e:DefAccessor) : if acc-dir == READ : diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 13b23906..adffc62d 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -239,6 +239,7 @@ defsyntax firrtl : stmt = (smem ?name:#id! #:! ?t:#vectype! ?clk:#exp!) : DefMemory(first-info(form),name, t, true, clk) stmt = (inst ?name:#id! #of! ?m:#ref!) : DefInstance(first-info(form),name,m) stmt = (node ?name:#id! #=! ?e:#exp!) : DefNode(first-info(form),name,e) + stmt = (poison ?name:#id! #:! ?t:#type!) : DefPoison(first-info(form),name, t) stmt = (onreset ?x:#exp := ?y:#exp!) : OnReset(first-info(form),x,y) stmt = (read accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s,i,READ) stmt = (write accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s,i,WRITE) diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 8f260e8c..3e375e81 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -71,6 +71,7 @@ public defn get-sym-hash (m:InModule,keywords:Streamable<Symbol>) -> HashTable<S (s:DefInstance) : add-name(name(s)) (s:DefMemory) : add-name(name(s)) (s:DefNode) : add-name(name(s)) + (s:DefPoison) : add-name(name(s)) (s:DefAccessor) : add-name(name(s)) (s) : false map(to-stmt,s) @@ -219,6 +220,8 @@ defmethod print (o:OutputStream, e:Expression) : defmethod print (o:OutputStream, c:Stmt) : val io = IndentedStream(o, 3) match(c) : + (c:DefPoison) : + print-all(o,["poison " name(c) " : " type(c)]) (c:DefWire) : print-all(o,["wire " name(c) " : " type(c)]) (c:DefRegister) : @@ -381,6 +384,7 @@ defmethod map (f: Type -> Type, c:Expression) -> Expression : public defmulti map<?T> (f: Type -> Type, c:?T&Stmt) -> T defmethod map (f: Type -> Type, c:Stmt) -> Stmt : match(c) : + (c:DefPoison) : DefPoison(info(c),name(c),f(type(c))) (c:DefWire) : DefWire(info(c),name(c),f(type(c))) (c:DefRegister) : DefRegister(info(c),name(c),f(type(c)),clock(c),reset(c)) (c:DefMemory) : DefMemory(info(c),name(c),f(type(c)) as VectorType,seq?(c),clock(c)) diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index a6239baa..bf2e27bf 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -32,6 +32,7 @@ public val standard-passes = to-list $ [ ;=============== WORKING IR ================================ public definterface Kind public defstruct WireKind <: Kind +public defstruct PoisonKind <: Kind public defstruct RegKind <: Kind public defstruct InstanceKind <: Kind public defstruct ReadAccessorKind <: Kind @@ -196,6 +197,7 @@ defmethod print (o:OutputStream, k:Kind) : print{o, _} $ match(k) : (k:WireKind) : "wire" + (k:PoisonKind) : "poison" (k:RegKind) : "reg" (k:AccessorKind) : "accessor" (k:PortKind) : "port" @@ -214,7 +216,7 @@ defn hasWidth (e:?) : defn hasType (e:?) : e typeof Ref|Subfield|Index|DoPrim|WRef|WSubfield - |WIndex|DefWire|DefRegister|DefMemory + |WIndex|DefWire|DefRegister|DefMemory|DefPoison |VectorType|Port|Field|UIntValue|SIntValue defn hasKind (e:?) : @@ -341,6 +343,7 @@ defn remove-special-chars (c:Circuit) : defn rename-s (s:Stmt) -> Stmt : match(s) : (s:DefWire) : DefWire(info(s),rename(name(s)),rename-t(type(s))) + (s:DefPoison) : DefPoison(info(s),rename(name(s)),rename-t(type(s))) (s:DefRegister) : DefRegister(info(s),rename(name(s)),rename-t(type(s)),rename-e(clock(s)),rename-e(reset(s))) (s:DefInstance) : DefInstance(info(s),rename(name(s)),rename-e(module(s))) (s:DefMemory) : DefMemory(info(s),rename(name(s)),rename-t(type(s)) as VectorType,seq?(s),rename-e(clock(s))) @@ -396,7 +399,7 @@ defn remove-scopes (c:Circuit) : else : n defn build-s (s:Stmt) : match(s) : - (s:DefWire|DefRegister|DefInstance|DefMemory|DefNode|DefAccessor) : + (s:DefWire|DefRegister|DefInstance|DefMemory|DefNode|DefAccessor|DefPoison) : occurrences[name(s)] = get?(occurrences,name(s),0) + 1 (s) : do(build-s,s) defn remove-scopes-e (e:Expression,env:Vector<HashTable<Symbol,Int>>) : @@ -406,6 +409,7 @@ defn remove-scopes (c:Circuit) : defn remove-scopes-s (s:Stmt,env:Vector<HashTable<Symbol,Int>>) -> Stmt : match(map(remove-scopes-e{_,env},s)) : (s:DefWire) : DefWire(info(s),rename(name(s),env),type(s)) + (s:DefPoison) : DefPoison(info(s),rename(name(s),env),type(s)) (s:DefRegister) : DefRegister(info(s),rename(name(s),env),type(s),clock(s),reset(s)) (s:DefInstance) : DefInstance(info(s),rename(name(s),env),module(s)) (s:DefMemory) : DefMemory(info(s),rename(name(s),env),type(s),seq?(s),clock(s)) @@ -584,6 +588,7 @@ defn resolve-kinds (c:Circuit) : defn find-stmt (s:Stmt) -> Stmt : match(s) : (s:DefWire) : kinds[name(s)] = NodeKind() + (s:DefPoison) : kinds[name(s)] = PoisonKind() (s:DefNode) : kinds[name(s)] = NodeKind() (s:DefRegister) : kinds[name(s)] = RegKind() (s:DefInstance) : kinds[name(s)] = InstanceKind() @@ -676,6 +681,7 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue< s* [Begin(body*),env] (s:DefWire) : [s,List(name(s) => type(s),l)] + (s:DefPoison) : [s,List(name(s) => type(s),l)] (s:DefRegister) : [s,List(name(s) => type(s),l)] (s:DefMemory) : [s,List(name(s) => type(s),l)] (s:DefInstance) : [s, List(name(s) => type(module(s)),l)] @@ -771,6 +777,9 @@ defn resolve-genders (c:Circuit) : defn resolve-stmt (s:Stmt) -> Stmt : match(s) : + (s:DefPoison) : + get-gender(name(s),MALE) + s (s:DefWire) : get-gender(name(s),BI-GENDER) s @@ -1015,6 +1024,9 @@ defn lower (body:Stmt) -> Stmt : defn lower-stmt (s:Stmt) -> Stmt : ;; println(s) match(s) : + (s:DefPoison) : Begin $ + for x in generate-entry(name(s),type(s)) map : + DefPoison(info(s),name(x),type(x)) (s:DefWire) : Begin $ for x in generate-entry(name(s),type(s)) map : DefWire(info(s),name(x),type(x)) @@ -1510,7 +1522,7 @@ defn build-tables (s:Stmt, if s typeof Connect : assign[key*] = SVExp(exp(s)) if s typeof OnReset : resets[key*] = SVExp(exp(s)) (s:Begin) : for s* in body(s) do: build-tables(s*,assign,resets,flattn,rsignals) - (s:DefMemory|DefNode|EmptyStmt) : false + (s:DefMemory|DefPoison|DefNode|EmptyStmt) : false defn mark-referenced (referenced?:HashTable<Symbol,True>, s:Stmt) -> False : @@ -1535,7 +1547,7 @@ defn mark-referenced (referenced?:HashTable<Symbol,True>, sv:SymbolicValue) -> S defn is-referenced? (referenced?:HashTable<Symbol,True>, s:Stmt) -> True|False : match(s) : - (s:DefWire|DefRegister|DefAccessor|DefMemory|DefNode) : key?(referenced?,name(s)) + (s:DefPoison|DefWire|DefRegister|DefAccessor|DefMemory|DefNode) : key?(referenced?,name(s)) (s:DefInstance) : true ;--------------- Expand Whens Pass ------------------- @@ -1555,6 +1567,8 @@ public defn expand-whens (c:Circuit) -> Circuit : add(decs,s) (s:DefMemory) : add(decs,s) + (s:DefPoison) : + add(decs,s) (s:DefWire) : add(decs,s) val ref = WRef(name(s),type(s),NodeKind(),FEMALE) @@ -1947,6 +1961,7 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod defn gen-constraints-s (s:Stmt) -> Stmt : match(map(gen-constraints-s,s)) : (s:DefWire) : DefWire(info(s),name(s),h[name(s)]) + (s:DefPoison) : DefPoison(info(s),name(s),h[name(s)]) (s:DefRegister) : DefRegister(info(s),name(s),h[name(s)],gen-constraints(clock(s)),gen-constraints(reset(s))) (s:DefAccessor) : DefAccessor(info(s),name(s),gen-constraints(source(s)),gen-constraints(index(s)), acc-dir(s)) (s:DefInstance) : DefInstance(info(s),name(s),gen-constraints(module(s))) @@ -2001,6 +2016,7 @@ defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTabl defn build-environment (s:Stmt) -> False : match(s) : (s:DefWire) : h[name(s)] = remove-unknowns(type(s)) + (s:DefPoison) : h[name(s)] = remove-unknowns(type(s)) (s:DefRegister) : h[name(s)] = remove-unknowns(type(s)) (s:DefInstance) : h[name(s)] = h[name(module(s) as WRef)] (s:DefMemory) : h[name(s)] = remove-unknowns(type(s)) @@ -2154,6 +2170,7 @@ defn inline-instances (c:Circuit) : defn rename-s (s:Stmt,n:Symbol) -> Stmt : map{rename-e{_,n},_} $ match(map(rename-s{_,n},s)) : (s:DefWire) : DefWire(info(s),rename(name(s),n),type(s)) + (s:DefPoison) : DefPoison(info(s),rename(name(s),n),type(s)) (s:DefRegister) : DefRegister(info(s),rename(name(s),n),type(s),clock(s),reset(s)) (s:DefInstance) : error("Shouldn't be here") (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s),clock(s)) @@ -2302,6 +2319,7 @@ public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) : defn to-stmt (s:Stmt) -> Stmt : map{to-type,_} $ match(map(to-exp,s)) : (s:DefWire) : DefWire(info(s),rename(name(s)),type(s)) + (s:DefPoison) : DefPoison(info(s),rename(name(s)),type(s)) (s:DefRegister) : DefRegister(info(s),rename(name(s)),type(s),clock(s),reset(s)) (s:DefInstance) : DefInstance(info(s),rename(name(s)),module(s)) (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s),clock(s)) diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index d4b360f0..053b78e7 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -165,7 +165,7 @@ defn emit-module (m:InModule) : defn build-table (m:InModule) : defn build-table (s:Stmt) -> Stmt : match(map(build-table,map(remove-subfield,s))) : - (s:DefWire|DefRegister|DefAccessor|DefMemory|DefNode|DefInstance) : + (s:DefWire|DefPoison|DefRegister|DefAccessor|DefMemory|DefNode|DefInstance) : add(vdecs,name(s) => s) decs[name(s)] = s (s:Conditionally) : @@ -195,6 +195,9 @@ defn emit-module (m:InModule) : for x in vdecs do : val sym = key(x) match(value(x)) : + (s:DefPoison) : + add(regs,["reg " get-width(type(s)) " " sym ";"]) + add(inits,[sym " = " rand-string(width!(type(s)))]) (s:DefWire) : add(wires,["wire " get-width(type(s)) " " sym ";"]) add(assigns,["assign " sym " = " emit(cons[sym]) ";"]) diff --git a/test/errors/high-form/Flip-Poison.fir b/test/errors/high-form/Flip-Poison.fir new file mode 100644 index 00000000..95a8c471 --- /dev/null +++ b/test/errors/high-form/Flip-Poison.fir @@ -0,0 +1,8 @@ +; RUN: firrtl -i %s -o %s.flo -X flo -p c | tee %s.out | FileCheck %s +; CHECK: Poison p cannot be a bundle type with flips. + +circuit Flip-Poison : + module Flip-Poison : + input clk : Clock + poison p : {x : UInt<10>, flip y : UInt<10>} + diff --git a/test/features/Poison.fir b/test/features/Poison.fir new file mode 100644 index 00000000..d8aa4411 --- /dev/null +++ b/test/features/Poison.fir @@ -0,0 +1,18 @@ +; RUN: firrtl -i %s -o %s.v -X verilog -p c 2>&1 | tee %s.out | FileCheck %s +; CHECK: Done! +circuit Poison : + module Poison : + input clk : Clock + input reset : UInt<1> + input index : UInt<7> + input p : UInt<1> + output out : {x : UInt<10>, y : UInt<10>} + + poison q : {x : UInt<10>, y : UInt<10>} + smem m : {x : UInt<10>, y : UInt<10>}[128],clk + infer accessor r = m[index] + when p : + out := r + else : + out := q + |
