diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | README.md | 44 | ||||
| -rw-r--r-- | TODO | 1 | ||||
| -rw-r--r-- | spec/spec.pdf | bin | 246075 -> 247435 bytes | |||
| -rw-r--r-- | spec/spec.tex | 2 | ||||
| -rw-r--r-- | src/main/stanza/errors.stanza | 82 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 11 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 6 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 155 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 134 | ||||
| -rw-r--r-- | src/main/stanza/verilog.stanza | 57 | ||||
| -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 | ||||
| -rwxr-xr-x | utils/bin/FileCheck_linux | bin | 0 -> 388783 bytes |
15 files changed, 474 insertions, 76 deletions
@@ -31,7 +31,7 @@ build-fast: cd $(firrtl_dir) && stanza -i firrtl-test-main.stanza -o $(root_dir)/utils/bin/firrtl-stanza -flags OPTIMIZE make set-stanza -check: +check: cd $(test_dir) && lit -v . --path=$(root_dir)/utils/bin/ regress: @@ -63,7 +63,7 @@ $(units): % : firrtl -X verilog -i test/chisel3/$*.fir -o test/chisel3/$*.fir.v -p c > test/chisel3/$*.fir.out #scp test/chisel3/$*.fir.v adamiz@a5:/scratch/adamiz/firrtl-all/riscv-mini/generated-src/$*.v -done: build check +done: build-fast check regress say "done" fail: @@ -10,14 +10,42 @@ 4. As a favor, its useful to develop in stanza to give Patrick some language tips :) The hardest part to port will likely be the parser, but we hope to use an existing scala-based general-purpose parser for the port. -#### Installation instructions (for Mac): -*Disclaimer*: This project is going through development stages so there is no guarantee anything works. - `git clone https://github.com/ucb-bar/firrtl # Clone repository` - `make install-mac # Stanza installation` - `pip install lit # Install lit (this assumes you have pip installed)` - `make build # Build firrtl` - `make check # Run tests` - `make # Build & test` +#### Installation Instructions +*Disclaimer*: This project is going through development stages so there is no guarantee anything works. + +##### For Linux: + 1. Clone the repository: + `git clone https://github.com/ucb-bar/firrtl` + 1. Install Stanza: + `make install-linux` + 1. Install lit (you need to have pip installed first): + `pip install lit` + 1. Build firrtl: + `make build` + 1. Add `firrtl/utils/bin` to your `PATH`, so that the compiled firrtl will be + available anywhere. This also makes FileCheck available for the tests. + 1. Rename `FileCheck_linux` in `firrtl/utils/bin` to `FileCheck`. The original + `FileCheck` is a compiled Mac version and will not run on Linux. + *Note: This compiled binary may not run on all platforms. You may need to build + Clang/LLVM from source to extract the compiled FileCheck utility.* + 1. Run tests: + `make check` + 1. Build and test: + `make` + +##### For Mac: + 1. Clone the repository: + `git clone https://github.com/ucb-bar/firrtl` + 1. Install Stanza: + `make install-mac` + 1. Install lit (you need to have pip installed first): + `pip install lit` + 1. Build firrtl: + `make build` + 1. Run tests: + `make check` + 1. Build and test: + `make` #### Scala implementation The Scala FIRRTL implementation relies upon sbt 0.13.6. It uses sbt-assembly to create a fat JAR. @@ -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/spec/spec.pdf b/spec/spec.pdf Binary files differindex 4d8f94d5..a22c8d4b 100644 --- a/spec/spec.pdf +++ b/spec/spec.pdf diff --git a/spec/spec.tex b/spec/spec.tex index 163ec64c..4f146552 100644 --- a/spec/spec.tex +++ b/spec/spec.tex @@ -704,7 +704,7 @@ Section \ref{primitives} will describe the format and semantics of each operatio All primitive operations expression operands must be ground types. In addition, some operations allow all permutations of operand ground types, while others on allow subsets. -When well defined, input arguments are allowed to be differing widths. +When well defined, input arguments are allowed to be differing widths, with the semantics of sign-extending the input arguments prior to executing the operation. \subsection{Add Operation} \[ diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index 8b8c86fb..b6a854af 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -101,10 +101,27 @@ defn NegVecSize (info:FileInfo) : PassException $ string-join $ [info ": [module " mname "] Vector type size cannot be negative."] +defn NegMemSize (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Memory size cannot be negative or zero."] + 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 @@ -194,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) : @@ -244,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) : @@ -312,6 +343,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))) + if size(s) <= 0 : add(errors,NegMemSize(info(s))) check-high-form-t(info(s),type(s),false) check-high-form-e(info(s),clock(s),names) (s:DefInstance) : @@ -332,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) @@ -394,11 +430,20 @@ defn OnResetNotReg (info:FileInfo, name:Symbol) : PassException $ string-join $ [info ": [module " mname "] Illegal on-reset to non-reg reference " name "."] +defn AccessVecOrMem (info:FileInfo) : + PassException $ string-join $ + [info ": [module " mname "] Accessors can only access vector-typed components or memories."] + ;----------------- Check Kinds Pass --------------------- ; I may have been overeager in looking for places where mems can't be, as mems are guaranteed to have a vector ; type, and this will get caught in the type check pass public defn check-kinds (c:Circuit) -> Circuit : val errors = Vector<PassException>() + defn get-kind (e:Expression) -> Kind : + match(e) : + (e:WRef) : kind(e) + (e:WSubfield) : get-kind(exp(e)) + (e:WIndex) : get-kind(exp(e)) defn check-not-mem (info:FileInfo,e:Expression) -> False : do(check-not-mem{info,_},e) match(e) : @@ -424,8 +469,16 @@ public defn check-kinds (c:Circuit) -> Circuit : defn check-kinds-s (s:Stmt) -> False : match(s) : (s:DefNode) : check-not-mem(info(s),value(s)) - (s:DefAccessor) : check-not-mem(info(s),index(s)) + (s:DefAccessor) : + check-not-mem(info(s),index(s)) + if (get-kind(source(s)) != MemKind()) and (not type(source(s)) typeof VectorType) : + println(get-kind(source(s))) + 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)) @@ -491,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."] @@ -519,7 +576,6 @@ defn OnResetIllegalFlips (info:FileInfo) : PassException $ string-join $ [info ": [module " mname "] The register in onreset cannot be a bundle type with flips."] - ;---------------- Helper Functions -------------- defmethod equal? (t1:Type,t2:Type) -> True|False : match(t1,t2) : @@ -538,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 : @@ -658,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 @@ -790,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) @@ -799,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 @@ -1030,7 +1094,7 @@ public defn check-low-form (c:Circuit) -> Circuit : (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)) + check-low-form-t(info(s),type(s),name(s)) add(mems,name(s)) (s:DefInstance) : for f in fields(type(module(s)) as BundleType) do : @@ -1038,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) : @@ -1053,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 b0db73b2..5bc1ea68 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -118,9 +118,10 @@ public defstruct DefInstance <: Stmt : ;LOW public defstruct DefMemory <: Stmt : ;LOW info: FileInfo with: (as-method => true) name: Symbol - type: VectorType + type: Type seq?: True|False clock: Expression + size: Int public defstruct DefNode <: Stmt : ;LOW info: FileInfo with: (as-method => true) name: Symbol @@ -154,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 f81777f5..a4ca89f7 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -236,8 +236,8 @@ defsyntax firrtl : stmt = (skip) : EmptyStmt() stmt = (wire ?name:#id! #:! ?t:#type!) : DefWire(first-info(form),name, t) stmt = (reg ?name:#id! #:! ?t:#type! ?clk:#exp! ?reset:#exp!) : DefRegister(first-info(form),name, t,clk,reset) - stmt = (cmem ?name:#id! #:! ?t:#vectype! ?clk:#exp!) : DefMemory(first-info(form),name, t, false, clk) - stmt = (smem ?name:#id! #:! ?t:#vectype! ?clk:#exp!) : DefMemory(first-info(form),name, t, true, clk) + stmt = (cmem ?name:#id! #:! ?t:#vectype! ?clk:#exp!) : DefMemory(first-info(form),name, type(t), false, clk, size(t)) + stmt = (smem ?name:#id! #:! ?t:#vectype! ?clk:#exp!) : DefMemory(first-info(form),name, type(t), true, clk, size(t)) 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) @@ -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 27acedb3..3fd96882 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) : @@ -230,8 +246,8 @@ defmethod print (o:OutputStream, c:Stmt) : (c:DefRegister) : print-all(o,["reg " name(c) " : " type(c) ", " clock(c) ", " reset(c)]) (c:DefMemory) : - if seq?(c) : print-all(o,["smem " name(c) " : " type(c) ", " clock(c)]) - else : print-all(o,["cmem " name(c) " : " type(c) ", " clock(c)]) + if seq?(c) : print-all(o,["smem " name(c) " : " VectorType(type(c),size(c)) ", " clock(c)]) + else : print-all(o,["cmem " name(c) " : " VectorType(type(c),size(c)) ", " clock(c)]) (c:DefInstance) : print-all(o,["inst " name(c) " of " module(c)]) (c:DefNode) : @@ -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) : @@ -345,13 +368,14 @@ defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : match(c) : (c:DefAccessor) : DefAccessor(info(c),name(c), f(source(c)), f(index(c)),acc-dir(c)) (c:DefRegister) : DefRegister(info(c),name(c), type(c), f(clock(c)), f(reset(c))) - (c:DefMemory) : DefMemory(info(c),name(c), type(c), seq?(c), f(clock(c))) + (c:DefMemory) : DefMemory(info(c),name(c), type(c), seq?(c), f(clock(c)), size(c)) (c:DefNode) : DefNode(info(c),name(c), f(value(c))) (c:DefInstance) : DefInstance(info(c),name(c), f(module(c))) (c:Conditionally) : Conditionally(info(c),f(pred(c)), conseq(c), alt(c)) (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 @@ -390,7 +414,7 @@ defmethod map (f: Type -> Type, c:Stmt) -> Stmt : (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)) + (c:DefMemory) : DefMemory(info(c),name(c),f(type(c)),seq?(c),clock(c),size(c)) (c) : c public defmulti mapr<?T> (f: Width -> Width, t:?T&Type) -> T @@ -524,94 +548,199 @@ public defn pow (x:Long,y:Long) -> Long : ;=================== VERILOG KEYWORDS ======================= public val v-keywords = HashTable<Symbol,True>(symbol-hash) +v-keywords[`alias] = true v-keywords[`always] = true +v-keywords[`always_comb] = true +v-keywords[`always_ff] = true +v-keywords[`always_latch] = true v-keywords[`and] = true +v-keywords[`assert] = true v-keywords[`assign] = true +v-keywords[`assume] = true v-keywords[`attribute] = true +v-keywords[`automatic] = true +v-keywords[`before] = true v-keywords[`begin] = true +v-keywords[`bind] = true +v-keywords[`bins] = true +v-keywords[`binsof] = true +v-keywords[`bit] = true +v-keywords[`break] = true v-keywords[`buf] = true v-keywords[`bufif0] = true v-keywords[`bufif1] = true +v-keywords[`byte] = true v-keywords[`case] = true v-keywords[`casex] = true v-keywords[`casez] = true +v-keywords[`cell] = true +v-keywords[`chandle] = true +v-keywords[`class] = true +v-keywords[`clocking] = true v-keywords[`cmos] = true +v-keywords[`config] = true +v-keywords[`const] = true +v-keywords[`constraint] = true +v-keywords[`context] = true +v-keywords[`continue] = true +v-keywords[`cover] = true +v-keywords[`covergroup] = true +v-keywords[`coverpoint] = true +v-keywords[`cross] = true v-keywords[`deassign] = true v-keywords[`default] = true v-keywords[`defparam] = true +v-keywords[`design] = true v-keywords[`disable] = true +v-keywords[`dist] = true +v-keywords[`do] = true v-keywords[`edge] = true v-keywords[`else] = true v-keywords[`end] = true v-keywords[`endattribute] = true v-keywords[`endcase] = true +v-keywords[`endclass] = true +v-keywords[`endclocking] = true +v-keywords[`endconfig] = true v-keywords[`endfunction] = true +v-keywords[`endgenerate] = true +v-keywords[`endgroup] = true +v-keywords[`endinterface] = true v-keywords[`endmodule] = true +v-keywords[`endpackage] = true v-keywords[`endprimitive] = true +v-keywords[`endprogram] = true +v-keywords[`endproperty] = true v-keywords[`endspecify] = true +v-keywords[`endsequence] = true v-keywords[`endtable] = true v-keywords[`endtask] = true +v-keywords[`enum] = true v-keywords[`event] = true +v-keywords[`expect] = true +v-keywords[`export] = true +v-keywords[`extends] = true +v-keywords[`extern] = true +v-keywords[`final] = true +v-keywords[`first_match] = true v-keywords[`for] = true v-keywords[`force] = true +v-keywords[`foreach] = true v-keywords[`forever] = true v-keywords[`fork] = true +v-keywords[`forkjoin] = true v-keywords[`function] = true +v-keywords[`generate] = true +v-keywords[`genvar] = true v-keywords[`highz0] = true v-keywords[`highz1] = true v-keywords[`if] = true +v-keywords[`iff] = true v-keywords[`ifnone] = true +v-keywords[`ignore_bins] = true +v-keywords[`illegal_bins] = true +v-keywords[`import] = true +v-keywords[`incdir] = true +v-keywords[`include] = true v-keywords[`initial] = true +v-keywords[`initvar] = true v-keywords[`inout] = true v-keywords[`input] = true +v-keywords[`inside] = true +v-keywords[`instance] = true +v-keywords[`int] = true v-keywords[`integer] = true -v-keywords[`initvar] = true +v-keywords[`interconnect] = true +v-keywords[`interface] = true +v-keywords[`intersect] = true v-keywords[`join] = true -v-keywords[`medium] = true -v-keywords[`module] = true +v-keywords[`join_any] = true +v-keywords[`join_none] = true v-keywords[`large] = true +v-keywords[`liblist] = true +v-keywords[`library] = true +v-keywords[`local] = true +v-keywords[`localparam] = true +v-keywords[`logic] = true +v-keywords[`longint] = true v-keywords[`macromodule] = true +v-keywords[`matches] = true +v-keywords[`medium] = true +v-keywords[`modport] = true +v-keywords[`module] = true v-keywords[`nand] = true v-keywords[`negedge] = true +v-keywords[`new] = true v-keywords[`nmos] = true v-keywords[`nor] = true +v-keywords[`noshowcancelled] = true v-keywords[`not] = true v-keywords[`notif0] = true v-keywords[`notif1] = true +v-keywords[`null] = true v-keywords[`or] = true v-keywords[`output] = true +v-keywords[`package] = true +v-keywords[`packed] = true v-keywords[`parameter] = true v-keywords[`pmos] = true v-keywords[`posedge] = true v-keywords[`primitive] = true +v-keywords[`priority] = true +v-keywords[`program] = true +v-keywords[`property] = true +v-keywords[`protected] = true v-keywords[`pull0] = true v-keywords[`pull1] = true v-keywords[`pulldown] = true v-keywords[`pullup] = true +v-keywords[`pulsestyle_onevent] = true +v-keywords[`pulsestyle_ondetect] = true +v-keywords[`pure] = true +v-keywords[`rand] = true +v-keywords[`randc] = true +v-keywords[`randcase] = true +v-keywords[`randsequence] = true v-keywords[`rcmos] = true v-keywords[`real] = true v-keywords[`realtime] = true +v-keywords[`ref] = true v-keywords[`reg] = true v-keywords[`release] = true v-keywords[`repeat] = true +v-keywords[`return] = true v-keywords[`rnmos] = true v-keywords[`rpmos] = true v-keywords[`rtran] = true v-keywords[`rtranif0] = true v-keywords[`rtranif1] = true v-keywords[`scalared] = true +v-keywords[`sequence] = true +v-keywords[`shortint] = true +v-keywords[`shortreal] = true +v-keywords[`showcancelled] = true v-keywords[`signed] = true v-keywords[`small] = true +v-keywords[`solve] = true v-keywords[`specify] = true v-keywords[`specparam] = true +v-keywords[`static] = true v-keywords[`strength] = true +v-keywords[`string] = true v-keywords[`strong0] = true v-keywords[`strong1] = true +v-keywords[`struct] = true +v-keywords[`super] = true v-keywords[`supply0] = true v-keywords[`supply1] = true v-keywords[`table] = true +v-keywords[`tagged] = true v-keywords[`task] = true +v-keywords[`this] = true +v-keywords[`throughout] = true v-keywords[`time] = true +v-keywords[`timeprecision] = true +v-keywords[`timeunit] = true v-keywords[`tran] = true v-keywords[`tranif0] = true v-keywords[`tranif1] = true @@ -621,14 +750,26 @@ v-keywords[`tri1] = true v-keywords[`triand] = true v-keywords[`trior] = true v-keywords[`trireg] = true +v-keywords[`type] = true +v-keywords[`typedef] = true +v-keywords[`union] = true +v-keywords[`unique] = true v-keywords[`unsigned] = true +v-keywords[`use] = true +v-keywords[`var] = true v-keywords[`vectored] = true +v-keywords[`virtual] = true +v-keywords[`void] = true v-keywords[`wait] = true +v-keywords[`wait_order] = true v-keywords[`wand] = true v-keywords[`weak0] = true v-keywords[`weak1] = true v-keywords[`while] = true +v-keywords[`wildcard] = true v-keywords[`wire] = true +v-keywords[`with] = true +v-keywords[`within] = true v-keywords[`wor] = true v-keywords[`xnor] = true v-keywords[`xor] = true diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 0c812535..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) @@ -349,7 +349,7 @@ defn remove-special-chars (c:Circuit) : (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))) + (s:DefMemory) : DefMemory(info(s),rename(name(s)),rename-t(type(s)),seq?(s),rename-e(clock(s)),size(s)) (s:DefNode) : DefNode(info(s),rename(name(s)),rename-e(value(s))) (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),rename-e(source(s)),rename-e(index(s)),acc-dir(s)) (s:Conditionally) : Conditionally(info(s),rename-e(pred(s)),rename-s(conseq(s)),rename-s(alt(s))) @@ -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* = @@ -415,7 +417,7 @@ defn remove-scopes (c:Circuit) : (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)) + (s:DefMemory) : DefMemory(info(s),rename(name(s),env),type(s),seq?(s),clock(s),size(s)) (s:DefNode) : DefNode(info(s),rename(name(s),env),value(s)) (s:DefAccessor) : DefAccessor(info(s),rename(name(s),env),source(s),index(s),acc-dir(s)) (s:Conditionally) : @@ -688,12 +690,12 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue< (s:DefMemory) : [s,List(name(s) => type(s),l)] (s:DefInstance) : [s, List(name(s) => type(module(s)),l)] (s:DefNode) : [s, List(name(s) => type(value(s)),l)] - (s:DefAccessor) : [s, List(name(s) => get-vector-subtype(type(source(s))),l)] + (s:DefAccessor) : [s, List(name(s) => type(s),l)] (s:Conditionally) : 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 : @@ -1001,9 +1005,16 @@ defn lower-ports (ports:List<Port>) -> List<Port> : for x in generate-entry(name(p),type(p)) map : Port(info(p),name(x),direction(p) * flip(x),type(x)) -defn type (s:DefAccessor) -> Type : type(type(source(s)) as VectorType) -defn size (s:DefMemory) -> Int : size(type(s)) -defn size (s:DefAccessor) -> Int : size(type(source(s)) as VectorType) +defn get-kind (e:Expression) -> Kind : + match(e) : + (e:WRef) : kind(e) + (e:WSubfield) : get-kind(exp(e)) + (e:WIndex) : get-kind(exp(e)) + +defn type (s:DefAccessor) -> Type : + if get-kind(source(s)) == MemKind() : type(source(s)) + else : type(type(source(s)) as VectorType) + defn base-name (e:Expression) -> Symbol : match(e) : (e:WRef) : name(e) @@ -1041,15 +1052,15 @@ defn lower (body:Stmt) -> Stmt : for x in expand-expr(value(s)) map : DefNode(info(s),name(s),exp(x)) (s:DefMemory) : Begin $ - for x in generate-entry(name(s),type(type(s))) map : - DefMemory(info(s),name(x),VectorType(type(x),size(s)),seq?(s),clock(s)) + for x in generate-entry(name(s),type(s)) map : + DefMemory(info(s),name(x),type(x),seq?(s),clock(s),size(s)) (s:DefAccessor) : val ls = generate-entry(name(s),type(s)) val rs = generate-entry(name(source(s) as WRef),type(s)) val index* = exp(head $ expand-expr(index(s))) Begin $ for (l in ls, r in rs) map: if flip(r) == REVERSE : error("Shouldn't be here") - val memref = WRef(name(r),VectorType(type(r),size(s)),MemKind(),gender(s)) + val memref = WRef(name(r),type(r),MemKind(),gender(s)) DefAccessor(info(s),name(l),memref,index*,to-acc-dir(gender(s))) (s:OnReset|Connect) : Begin $ for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map : @@ -1115,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) @@ -1527,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) : @@ -1573,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) @@ -1600,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 @@ -1628,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 ------------------- @@ -1667,7 +1698,7 @@ public defn expand-whens (c:Circuit) -> Circuit : (e:False) : false (s:DefAccessor) : add(decs,s) - val t = type(type(source(s)) as VectorType) + val t = type(s) val n = name(s) if gender(s) == FEMALE : val ref = WRef(n,t,WriteAccessorKind(),FEMALE) @@ -1691,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 : @@ -1702,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)) @@ -1729,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)) @@ -2034,7 +2071,7 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod (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))) - (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)] as VectorType,seq?(s),gen-constraints(clock(s))) + (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)],seq?(s),gen-constraints(clock(s)),size(s)) (s:DefNode) : val l = h[name(s)] val r = gen-constraints(value(s)) @@ -2045,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))) @@ -2089,7 +2128,7 @@ defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTabl (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)) - (s:DefAccessor) : h[name(s)] = remove-unknowns(type(type(source(s)) as VectorType)) + (s:DefAccessor) : h[name(s)] = remove-unknowns(type(s)) (s:DefNode) : h[name(s)] = remove-unknowns(type(value(s))) (s) : false do(build-environment,s) @@ -2241,7 +2280,7 @@ defn inline-instances (c:Circuit) : (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)) + (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s),clock(s),size(s)) (s:DefNode) : DefNode(info(s),rename(name(s),n),value(s)) (s) : s for m in modules(c) do : @@ -2319,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*)) @@ -2395,7 +2446,7 @@ public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) : (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)) + (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s),clock(s),size(s)) (s:DefNode) : DefNode(info(s),rename(name(s)),value(s)) (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),source(s),index(s),acc-dir(s)) (s) : map(to-stmt,s) @@ -2481,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 1a495835..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) @@ -221,10 +252,9 @@ defn emit-module (m:InModule) : val w = width!(type(s)) add(inits,[sym " = " rand-string(w)]) (s:DefMemory) : - val vtype = type(s) as VectorType - add(regs,["reg " get-width(type(vtype)) " " sym " [0:" size(vtype) - 1 "];"]) - add(inits,["for (initvar = 0; initvar < " size(vtype) "; initvar = initvar+1)"]) - add(inits,[" " sym "[initvar] = " rand-string(width!(type(vtype))) ]) + add(regs,["reg " get-width(type(s)) " " sym " [0:" size(s) - 1 "];"]) + add(inits,["for (initvar = 0; initvar < " size(s) "; initvar = initvar+1)"]) + add(inits,[" " sym "[initvar] = " rand-string(width!(type(s))) ]) (s:DefNode) : add(wires,["wire " get-width(type(value(s))) " " sym ";"]) add(assigns,["assign " sym " = " emit(value(s)) ";"]) @@ -252,11 +282,11 @@ defn emit-module (m:InModule) : updates[get-name(clock(mem-declaration))] = my-clk-update ; emit read accessor - add(wires,["wire " get-width(type(type(source(s)) as VectorType)) " " sym ";"]) + add(wires,["wire " get-width(type(source(s))) " " sym ";"]) add(assigns,["assign " sym " = " emit(source(s)) "[" emit(index*) "];"]) else : ; emit read accessor - add(wires,["wire " get-width(type(type(source(s)) as VectorType)) " " sym ";"]) + add(wires,["wire " get-width(type(source(s))) " " sym ";"]) add(assigns,["assign " sym " = " emit(source(s)) "[" emit(index(s)) "];"]) WRITE : val my-clk-update = get?(updates,get-name(clock(mem-declaration)),Vector<Streamable>()) @@ -322,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! + diff --git a/utils/bin/FileCheck_linux b/utils/bin/FileCheck_linux Binary files differnew file mode 100755 index 00000000..1bb70b6d --- /dev/null +++ b/utils/bin/FileCheck_linux |
