diff options
Diffstat (limited to 'src')
| -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 |
6 files changed, 380 insertions, 65 deletions
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") |
