diff options
| author | azidar | 2015-10-07 14:48:04 -0700 |
|---|---|---|
| committer | azidar | 2015-10-07 14:49:54 -0700 |
| commit | 4183c648b719eac9da26e2d9d34fa852ebdbfd20 (patch) | |
| tree | 87d216e61563d0498c29953b824848ab92a7ade9 | |
| parent | 9f2e1fd28f8526f7b68dc4b0ea030ceded720697 (diff) | |
Added Printf and Stop to firrtl. #23 #24.
| -rw-r--r-- | TODO | 1 | ||||
| -rw-r--r-- | src/main/stanza/errors.stanza | 58 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 8 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 2 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 24 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 99 | ||||
| -rw-r--r-- | src/main/stanza/verilog.stanza | 46 | ||||
| -rw-r--r-- | test/errors/high-form/Printf.fir | 15 | ||||
| -rw-r--r-- | test/features/Printf.fir | 19 | ||||
| -rw-r--r-- | test/features/Stop.fir | 20 |
10 files changed, 260 insertions, 32 deletions
@@ -3,6 +3,7 @@ Support ASIC backend Mem of vec, should just work? ASIC rams (pass to replace smem with black box) Readwrite Port +Add %s, %b, %e etc. to spec ================================================ ========== ADAM's BIG ARSE TODO LIST ============ diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index ad289ea0..b6a854af 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -109,6 +109,19 @@ defn IllegalUnknownWidth (info:FileInfo) : PassException $ string-join $ [info ": [module " mname "] Widths must be defined for memories and poison nodes."] +defn BadPrintf (info:FileInfo,x:Char) : + PassException $ string-join $ + [info ": [module " mname "] Bad printf format: \"%" x "\""];" + +defn BadPrintfTrailing (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Bad printf format: trailing \"%\""];" + +defn BadPrintfIncorrectNum (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Bad printf format: incorrect number of arguments"];" + + ;---------------- Helper Functions -------------- defn has-flip? (t:Type) -> True|False : var has? = false @@ -198,7 +211,7 @@ defn contains?<?T> (c:?T,cs:Streamable<?T>) -> True|False : ; (s:False) : false ; (s:String) : myret(string-join([char(trie) s])) ; false - + defn check-high-form-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) -> False : defn correct-num (ne:Int|False,nc:Int) -> False : if not (ne typeof False) : @@ -248,6 +261,20 @@ defn check-high-form-primop (e:DoPrim, errors:Vector<PassException>,info:FileInf public defn check-high-form (c:Circuit) -> Circuit : val errors = Vector<PassException>() + + defn check-fstring (info:FileInfo,s:String,i:Int) -> False : + val valid-formats = "bedxs" + var percent = false + var ret = true + var npercents = 0 + for x in s do : + if (not contains?(valid-formats,x)) and percent : + add(errors,BadPrintf(info,x)) + if x == '%' : npercents = npercents + 1 + percent = x == '%' + if percent : add(errors,BadPrintfTrailing(info)) + if npercents != i : add(errors,BadPrintfIncorrectNum(info)) + defn check-valid-loc (info:FileInfo,e:Expression) -> False : match(e) : (e:UIntValue|SIntValue|DoPrim) : @@ -337,6 +364,10 @@ public defn check-high-form (c:Circuit) -> Circuit : check-valid-loc(info(s),loc(s)) check-high-form-e(info(s),loc(s),names) check-high-form-e(info(s),exp(s),names) + (s:PrintfStmt) : + for x in args(s) do: + check-high-form-e(info(s),x,names) + check-fstring(info(s),string(s),length(args(s))) (s:BulkConnect) : check-valid-loc(info(s),loc(s)) check-high-form-e(info(s),loc(s),names) @@ -445,6 +476,9 @@ public defn check-kinds (c:Circuit) -> Circuit : println(type(source(s))) add(errors,AccessVecOrMem(info(s))) (s:Conditionally) : check-not-mem(info(s),pred(s)) + (s:PrintfStmt) : + for x in args(s) do : + check-not-mem(info(s),x) (s:Connect) : check-not-mem(info(s),loc(s)) check-not-mem(info(s),exp(s)) @@ -510,6 +544,10 @@ defn InvalidConnect (info:FileInfo) : PassException $ string-join $ [info ": [module " mname "] Type mismatch."] +defn PrintfArgNotGround (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Printf arguments must be either UIntType or SIntType."] + defn PredNotUInt (info:FileInfo) : PassException $ string-join $ [info ": [module " mname "] Predicate not a UIntType."] @@ -556,8 +594,8 @@ defmethod equal? (t1:Type,t2:Type) -> True|False : else : false (t1,t2) : false -defn u () -> UIntType : UIntType(UnknownWidth()) -defn s () -> SIntType : SIntType(UnknownWidth()) +defn ut () -> UIntType : UIntType(UnknownWidth()) +defn st () -> SIntType : SIntType(UnknownWidth()) defn check-types-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) -> False : defn all-same-type (ls:List<Expression>) -> False : @@ -676,8 +714,12 @@ public defn check-types (c:Circuit) -> Circuit : (s:OnReset) : if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s))) if has-flip?(type(loc(s))) : add(errors,OnResetIllegalFlips(info(s))) + (s:PrintfStmt) : + for x in args(s) do : + if type(x) != ut() and type(x) != st(): + add(errors,PrintfArgNotGround(info(s))) (s:Conditionally) : - if type(pred(s)) != u() : add(errors,PredNotUInt(info(s))) + if type(pred(s)) != ut() : add(errors,PredNotUInt(info(s))) (s:DefNode) : if has-flip?(type(value(s))) : add(errors,NodeIllegalFlips(info(s))) (s) : false @@ -808,6 +850,9 @@ public defn check-genders (c:Circuit) -> Circuit : (s:Connect) : check-gender(info(s),genders,loc(s),FEMALE) check-gender(info(s),genders,exp(s),MALE) + (s:PrintfStmt) : + for x in args(s) do : + check-gender(info(s),genders,x,MALE) (s:BulkConnect) : check-gender(info(s),genders,loc(s),FEMALE) check-gender(info(s),genders,exp(s),MALE) @@ -817,6 +862,7 @@ public defn check-genders (c:Circuit) -> Circuit : (s:Conditionally) : check-gender(info(s),genders,pred(s),MALE) (s:EmptyStmt) : false + (s:StopStmt) : false (s:Begin) : false @@ -1056,6 +1102,9 @@ public defn check-low-form (c:Circuit) -> Circuit : add(insts,name(s)) (s:DefNode) : check-correct-exp(info(s),value(s)) + (s:PrintfStmt) : + for x in args(s) do : + check-correct-exp(info(s),x) (s:DefRegister) : false (s:DefAccessor) : false (s:Conditionally) : @@ -1071,6 +1120,7 @@ public defn check-low-form (c:Circuit) -> Circuit : else : assigned?[to-symbol $ to-string $ e] = true (e) : check-correct-exp(info(s),e) (s:EmptyStmt) : false + (s:StopStmt) : false (s:Begin) : do(check-low-form-s,s) match(m) : diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index 0ed785c7..5bc1ea68 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -155,6 +155,14 @@ public defstruct Connect <: Stmt : ;LOW info: FileInfo with: (as-method => true) loc: Expression exp: Expression +public defstruct StopStmt <: Stmt : ;LOW + info: FileInfo with: (as-method => true) + ret: Int +public defstruct PrintfStmt <: Stmt : ;LOW + info: FileInfo with: (as-method => true) + string: String + args: List<Expression> + public defstruct EmptyStmt <: Stmt ;LOW public definterface Type diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index c2c7cfa5..a4ca89f7 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -246,6 +246,8 @@ defsyntax firrtl : stmt = (write accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s,i,WRITE) stmt = (infer accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s,i,INFER) stmt = (rdwr accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s, i,RDWR) + stmt = (stop(?ret:#int)) : StopStmt(first-info(form),ret) + stmt = (printf(?str:#string ?es:#exp ...)) : PrintfStmt(first-info(form),str,es) stmt = (?s:#stmt/when) : s stmt = (?x:#exp := ?y:#exp!) : Connect(first-info(form),x, y) diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index ffc9b39e..59c7c36a 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -110,6 +110,11 @@ public defmethod print (o:OutputStream, p:Pass) : ;============== Various Useful Functions ============== +public defn add-all (v1:Vector,v2:Vector) -> False : + for x in v2 do : + add(v1,x) + + public defn ceil-log2 (i:Long) -> Long : defn* loop (n:Long, l:Long) : if n < i : @@ -138,6 +143,17 @@ public defn req-num-bits (i: Int) -> Int : else : i ceil-log2(i* + 1) + 1 +defn escape (s:String) -> String : + val s* = Vector<String>() + add(s*,"\"");" + for c in s do : + if c == '\n' : + add(s*,"\\n") + else : add(s*,to-string(c)) + add(s*,"\"");" + string-join(s*) + ;" + ;============== PRINTERS =================================== defmethod print (o:OutputStream, d:Flip) : @@ -261,6 +277,13 @@ defmethod print (o:OutputStream, c:Stmt) : print-all(o, ["onreset " loc(c) " := " exp(c)]) (c:EmptyStmt) : print(o, "skip") + (c:StopStmt) : + print-all(o, ["stop(" ret(c) ")"]) + (c:PrintfStmt) : + print-all(o, ["printf("]) ;" + print-all(o, join(List(escape(string(c)),args(c)), ", ")) + print(o, ")") + if not c typeof Conditionally|Begin|EmptyStmt : print-debug(o,c) defmethod print (o:OutputStream, t:Type) : @@ -352,6 +375,7 @@ defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : (c:Connect) : Connect(info(c),f(loc(c)), f(exp(c))) (c:BulkConnect) : BulkConnect(info(c),f(loc(c)), f(exp(c))) (c:OnReset) : OnReset(info(c),f(loc(c)),f(exp(c))) + (c:PrintfStmt) : PrintfStmt(info(c),string(c),map(f,args(c))) (c) : c public defmulti map<?T> (f: Stmt -> Stmt, c:?T&Stmt) -> T diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index f0c4d242..f2931bc8 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -186,7 +186,7 @@ public var PRINT-GENDERS : True|False = false public var PRINT-CIRCUITS : True|False = false public var PRINT-DEBUG : True|False = false public var PRINT-INFO : True|False = false -;=== Printers === +;=== ThePrinters === public defn println-all-debug (l:?) -> False : if PRINT-DEBUG : println-all(l) @@ -358,6 +358,8 @@ defn remove-special-chars (c:Circuit) : (s:BulkConnect) : BulkConnect(info(s),rename-e(loc(s)),rename-e(exp(s))) (s:Connect) : Connect(info(s),rename-e(loc(s)),rename-e(exp(s))) (s:EmptyStmt) : s + (s:StopStmt) : s + (s:PrintfStmt) : PrintfStmt(info(s),string(s),map(rename-e,args(s))) Circuit(info(c),modules*, rename(main(c))) where : val modules* = @@ -693,7 +695,7 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue< val [s*,l*] = infer-types(conseq(s),l) val [s**,l**] = infer-types(alt(s),l) [Conditionally(info(s),pred(s),s*,s**),l] - (s:Connect|BulkConnect|OnReset|EmptyStmt) : [s,l] + (s:Connect|BulkConnect|OnReset|EmptyStmt|StopStmt|PrintfStmt) : [s,l] defn infer-types (m:Module, l:List<KeyValue<Symbol,Type>>) -> Module : val ptypes = @@ -812,6 +814,8 @@ defn resolve-genders (c:Circuit) : val conseq* = resolve-stmt(conseq(s)) val alt* = resolve-stmt(alt(s)) Conditionally(info(s),pred*,conseq*,alt*) + (s:PrintfStmt) : + PrintfStmt(info(s),string(s),map(resolve-expr{_,MALE},args(s))) (s) : map(resolve-stmt,s) defn resolve-expr (e:Expression,desired:Gender) -> Expression : @@ -1122,7 +1126,10 @@ defn lower (body:Stmt) -> Stmt : [MALE,FEMALE] : DecFromIndexer(info(s),index*,exps,name(ntf),type(ntf)) (s:Conditionally) : Conditionally(info(s),exp(head $ expand-expr(pred(s))),lower-stmt(conseq(s)),lower-stmt(alt(s))) - (s:Begin|EmptyStmt) : map(lower-stmt,s) + (s:PrintfStmt) : + val args* = for x in args(s) map : exp(head(expand-expr(x))) + PrintfStmt(info(s),string(s),args*) + (s:Begin|EmptyStmt|StopStmt) : map(lower-stmt,s) lower-stmt(body) @@ -1534,11 +1541,23 @@ defn merge-resets (assign:HashTable<Symbol,SymbolicValue>, resets:HashTable<Symb (a:False,r:False) : error("Shouldn't be here") table +defn mark (vs:Vector<[Stmt,Expression]>,pred:Expression) -> False : + for i in 0 to length(vs) do : + val [s,e] = vs[i] + vs[i] = [s, AND(e,pred)] + +; ------ Print Debug Info ------ +defn print-table (t:HashTable<Symbol,SymbolicValue>,s:String) : + println-debug(s) + for x in t do : println-debug(x) + + defn build-tables (s:Stmt, assign:HashTable<Symbol,SymbolicValue>, resets:HashTable<Symbol,SymbolicValue>, flattn:HashTable<Symbol,True|False>, rsignals:HashTable<Symbol,Expression>, + simuls:Vector<[Stmt,Expression]>, ) -> False : match(s) : (s:DefWire) : @@ -1580,26 +1599,28 @@ defn build-tables (s:Stmt, val assign-a = deepcopy(assign) val resets-c = deepcopy(resets) val resets-a = deepcopy(resets) - build-tables(conseq(s),assign-c,resets-c,flattn,rsignals) - build-tables(alt(s),assign-a,resets-a,flattn,rsignals) + val simuls-c = Vector<[Stmt,Expression]>() + val simuls-a = Vector<[Stmt,Expression]>() + build-tables(conseq(s),assign-c,resets-c,flattn,rsignals,simuls-c) + build-tables(alt(s),assign-a,resets-a,flattn,rsignals,simuls-a) for i in get-unique-keys(list(assign-c,assign-a)) do : assign[i] = combine(flattn,assign-c,assign-a,i) as SymbolicValue val r = combine(flattn,resets-c,resets-a,i) match(r) : (r:SymbolicValue) : resets[i] = r (r) : false - println-debug("TABLE-C") - for x in assign-c do : println-debug(x) - println-debug("TABLE-A") - for x in assign-a do : println-debug(x) - println-debug("TABLE") - for x in assign do : println-debug(x) - println-debug("RESET-C") - for x in resets-c do : println-debug(x) - println-debug("RESET-A") - for x in resets-a do : println-debug(x) - println-debug("RESET") - for x in resets do : println-debug(x) + + mark(simuls-c,pred(s)) + mark(simuls-a,DoPrim(BIT-NOT-OP,list(pred(s)),list(),UIntType(LongWidth(1)))) + add-all(simuls,simuls-c) + add-all(simuls,simuls-a) + + print-table(assign-c,"TABLE-C") + print-table(assign-a,"TABLE-A") + print-table(assign,"TABLE") + print-table(resets-c,"RESET-C") + print-table(resets-a,"RESET-A") + print-table(resets,"RESET") (s:Connect|OnReset) : val key* = match(loc(s)) : (e:WRef) : name(e) @@ -1607,7 +1628,9 @@ defn build-tables (s:Stmt, (e) : error("Shouldn't be here with ~" % [e]) 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:Begin) : for s* in body(s) do: build-tables(s*,assign,resets,flattn,rsignals,simuls) + (s:StopStmt|PrintfStmt) : + add(simuls,[s one]) (s:DefMemory|DefPoison|DefNode|EmptyStmt) : false @@ -1635,6 +1658,7 @@ defn is-referenced? (referenced?:HashTable<Symbol,True>, s:Stmt) -> True|False : match(s) : (s:DefPoison|DefWire|DefRegister|DefAccessor|DefMemory|DefNode) : key?(referenced?,name(s)) (s:DefInstance) : true + (s:PrintfStmt|StopStmt|Conditionally) : true ;--------------- Expand Whens Pass ------------------- @@ -1698,7 +1722,7 @@ public defn expand-whens (c:Circuit) -> Circuit : val sref = WSubfield(ref,f,bundle-field-type(type(module(s)),f),FEMALE) if not has-nul?(table[n]) : add{cons,_} $ Connect(info(s),sref,to-exp(table[n]) as Expression) - (s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : false + (s:Connect|Conditionally|OnReset|Begin|EmptyStmt|StopStmt|PrintfStmt) : false s defn expand-whens (m:Module) -> Module : @@ -1709,13 +1733,14 @@ public defn expand-whens (c:Circuit) -> Circuit : val resets = HashTable<Symbol,SymbolicValue>(symbol-hash) val flattn = HashTable<Symbol,True|False>(symbol-hash) val rsignals = HashTable<Symbol,Expression>(symbol-hash) + val simuls = Vector<[Stmt,Expression]>() for p in ports(m) do : if direction(p) == OUTPUT : assign[name(p)] = SVNul() flattn[name(p)] = false - build-tables(body(m),assign,resets,flattn,rsignals) + build-tables(body(m),assign,resets,flattn,rsignals,simuls) for x in assign do : assign[key(x)] = optimize(value(x)) for x in resets do : resets[key(x)] = optimize(value(x)) @@ -1736,6 +1761,11 @@ public defn expand-whens (c:Circuit) -> Circuit : expand-whens(ports(m),table,cons) expand-whens(body(m),table,decs,cons) + for se in simuls do : + val [s e] = se + if e == one : add(decs,s) + else : add(decs,Conditionally(info(s),e,s,EmptyStmt())) + val referenced? = HashTable<Symbol,True>(symbol-hash) for x in table do : mark-referenced(referenced?,value(x)) @@ -2052,6 +2082,8 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod val e = gen-constraints(exp(s)) add(v,WGeq(width!(type(l)),width!(type(e)))) Connect(info(s),l,e) + (s:PrintfStmt) : + PrintfStmt(info(s),string(s),map(gen-constraints,args(s))) (s:Conditionally) : val p = gen-constraints(pred(s)) add(v,WGeq(width!(type(p)),LongWidth(1))) @@ -2326,14 +2358,26 @@ defn split-exp (c:Circuit) : ;Predicate val pred* = map(split-exp-e{_,full-name(pred(s)),info(s)},pred(s)) - ;Connect - val c = conseq(s) as Connect - val exp* = map(split-exp-e{_,full-name(loc(c)),info(c)},exp(c)) - val conseq* = Connect(info(c),loc(c),exp*) - add(v,Conditionally(info(s),pred*,conseq*,alt(s))) + ;Connect TODO Broken for stop/printf + match(conseq(s)) : + (c:Connect) : + val exp* = map(split-exp-e{_,full-name(loc(c)),info(c)},exp(c)) + val conseq* = Connect(info(c),loc(c),exp*) + add(v,Conditionally(info(s),pred*,conseq*,alt(s))) + (c:PrintfStmt) : + val args* = for x in args(c) map : + map(split-exp-e{_,false,info(c)},x) + val conseq* = PrintfStmt(info(c),string(c),args*) + add(v,Conditionally(info(s),pred*,conseq*,alt(s))) + (c:StopStmt) : + add(v,Conditionally(info(s),pred*,c,alt(s))) (s:Connect) : val exp* = map(split-exp-e{_,full-name(loc(s)),info(s)},exp(s)) add(v,Connect(info(s),loc(s),exp*)) + (s:PrintfStmt) : + val args* = for x in args(s) map : + map(split-exp-e{_,false,info(s)},x) + add(v,PrintfStmt(info(s),string(s),args*)) (s:DefNode) : val exp* = map(split-exp-e{_,name(s),info(s)},value(s)) add(v,DefNode(info(s),name(s),exp*)) @@ -2488,6 +2532,11 @@ defn pad-widths-s (s:Stmt) -> Stmt : val loc* = pad-widths-e(i,loc(s)) val exp* = pad-widths-e(i,exp(s)) Connect(info(s),loc*,exp*) + (s:PrintfStmt) : + val args* = for x in args(s) map : + val i = int-width!(type(x)) + pad-widths-e(i,x) + PrintfStmt(info(s),string(s),args*) (s:DefNode) : val i = int-width!(type(value(s))) val exp* = pad-widths-e(i,value(s)) diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index ef78659a..5cf42323 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -54,6 +54,20 @@ defn get-name (e:Expression) -> Symbol : (e:Subfield) : error("Shouldn't be here") (e) : error("Shouldn't be here") +defn escape (s:String) -> String : + val s* = Vector<String>() + add(s*,"\"");" + var percent = false + for c in s do : + if c == '\n' : + add(s*,"\\n") + else : + if c == 'x' and percent : + add(s*,"h") + else : add(s*,to-string(c)) + percent = c == '%' + add(s*,"\"");" + string-join(s*) ;============ Verilog Backend ============= defn emit-as-type (e:Expression,t:Type) -> String : @@ -168,15 +182,32 @@ defn emit-module (m:InModule) : val decs = HashTable<Symbol,Stmt>(symbol-hash) ; all declarations, for fast lookups val cons = HashTable<Symbol,Expression>(symbol-hash) ; all connections val ens = HashTable<Symbol,Expression>(symbol-hash) ; all enables + val simuls = Vector<Streamable>() defn build-table (s:Stmt) -> False : match(s) : (s:DefWire|DefPoison|DefRegister|DefAccessor|DefMemory|DefNode|DefInstance) : add(vdecs,name(s) => s) decs[name(s)] = s (s:Conditionally) : - val n = get-name(loc(conseq(s) as Connect)) - ens[n] = pred(s) - cons[n] = exp(conseq(s) as Connect) + match(conseq(s)) : + (c:Connect) : + val n = get-name(loc(c)) + ens[n] = pred(s) + cons[n] = exp(conseq(s) as Connect) + (c:PrintfStmt) : + add(simuls,["if(" emit(pred(s)) ") begin"]) + add(simuls,[" $fdisplay(32/'h80000002," string-join(List(escape(string(c)),map(emit,args(c))), ", ") ");"]) + add(simuls,["end"]) + (c:StopStmt) : + add(simuls,["if(" emit(pred(s)) ") begin"]) + add(simuls,[" $fdisplay(32/'h80000002," ret(c) ");"]) + add(simuls,[" $finish;"]) + add(simuls,["end"]) + (s:PrintfStmt) : + add(simuls,["$fdisplay(32/'h80000002," string-join(List(escape(string(s)),map(emit,args(s))), ", ") ");"]) + (c:StopStmt) : + add(simuls,["$fdisplay(32/'h80000002," ret(c) ");"]) + add(simuls,["$finish;"]) (s:Connect) : val n = get-name(loc(s)) cons[n] = exp(s) @@ -321,6 +352,15 @@ defn emit-module (m:InModule) : print(" ") println-all(u) println(" end") + + if length(simuls) != 0 : + println("`ifndef SYNTHESIS") + println(" always @(*) begin") + for x in simuls do : + print(" ") + println-all(x) + println(" end") + println("`endif") println("endmodule") diff --git a/test/errors/high-form/Printf.fir b/test/errors/high-form/Printf.fir new file mode 100644 index 00000000..7f285d3e --- /dev/null +++ b/test/errors/high-form/Printf.fir @@ -0,0 +1,15 @@ +; RUN: firrtl -i %s -o %s.v -X verilog -p c 2>&1 | tee %s.out | FileCheck %s + +circuit Top : + module Top : + input x : {y : UInt<1>} + input p : UInt<1> + printf("Hello World%!\n",x) + printf("Hello World%") + printf("Hello World%d %s %h %x",x,x,x) + +;CHECK: Bad printf format: "%!" +;CHECK: Bad printf format: trailing "%" +;CHECK: Bad printf format: incorrect number of arguments +;CHECK: Bad printf format: "%h" +;CHECK: Bad printf format: incorrect number of arguments diff --git a/test/features/Printf.fir b/test/features/Printf.fir new file mode 100644 index 00000000..8449825f --- /dev/null +++ b/test/features/Printf.fir @@ -0,0 +1,19 @@ +; RUN: firrtl -i %s -o %s.v -X verilog -p c 2>&1 | tee %s.out | FileCheck %s + +;CHECK: Lower To Ground +circuit Top : + module Top : + input x : {y : UInt<1>} + input p : UInt<1> + printf("Hello World!\n") + printf("Hello World! %x\n", x.y) + when p : + printf("In consequence\n") + else : + printf("In alternate\n") + +;CHECK: printf("Hello World!\n") +;CHECK: printf("Hello World! %x\n", x$y) +;CHECK: when p : printf("In consequence\n") +;CHECK: when not(p) : printf("In alternate\n") +;CHECK: Done! diff --git a/test/features/Stop.fir b/test/features/Stop.fir new file mode 100644 index 00000000..fc8869fa --- /dev/null +++ b/test/features/Stop.fir @@ -0,0 +1,20 @@ +; RUN: firrtl -i %s -o %s.v -X verilog -p c 2>&1 | tee %s.out | FileCheck %s + +;CHECK: Lower To Ground + +circuit Top : + module Top : + input p : UInt<1> + input q : UInt<1> + when p : + stop(0) + when q : + stop(1) + stop(3) + +;CHECK: when p : stop(0) +;CHECK: when q : stop(1) +;CHECK: stop(3) + +;CHECK: Done! + |
