diff options
| author | azidar | 2015-12-03 15:12:02 -0800 |
|---|---|---|
| committer | azidar | 2016-01-16 14:28:17 -0800 |
| commit | c427b31a1ef8361b643d5f7435aeb42472dfe626 (patch) | |
| tree | 6ae504ba1b37b9d0fef281b491cf932ac6826c7b | |
| parent | ece8ec00868c182e141e8d1ac75bfb60bfaa87ec (diff) | |
WIP. Compiles and almost done with verilog backend. Need to think about emitting ports (and the assignments to them)
| -rw-r--r-- | src/main/stanza/compilers.stanza | 5 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 98 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 8 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 65 | ||||
| -rw-r--r-- | test/errors/high-form/Flip-Mem.fir | 8 | ||||
| -rw-r--r-- | test/passes/to-verilog/gcd.fir | 32 | ||||
| -rw-r--r-- | test/passes/to-verilog/mem.fir | 2 | ||||
| -rw-r--r-- | test/passes/to-verilog/rd-mem.fir | 4 | ||||
| -rw-r--r-- | test/passes/to-verilog/rdwr-mem.fir | 4 | ||||
| -rw-r--r-- | test/passes/to-verilog/shr.fir | 10 | ||||
| -rw-r--r-- | test/passes/to-verilog/wr-mem.fir | 2 |
11 files changed, 146 insertions, 92 deletions
diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index 9dda33fe..cfe5bbaf 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -58,6 +58,8 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> : ;CheckTypes() ;R ExpandAccesses() ;W ExpandConnects() ;W + ResolveKinds() ;W + InferTypes() ;R ResolveGenders() ;W ;LowerToGround() ;W ;ExpandIndexedConnects() ;W @@ -65,6 +67,9 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> : ;InferTypes() ;R ;CheckGenders() ;W ExpandWhens() ;W + ResolveKinds() ;W + InferTypes() ;R + ResolveGenders() ;W InferWidths() ;R ;ToRealIR() ;W -> R ;CheckWidths() ;R diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index fe8af96f..e8dd3306 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -8,21 +8,21 @@ defpackage firrtl/parser : import firrtl/ir-utils ;======= Convenience Types =========== -;definterface MStat -;defstruct Reader <: MStat : -; value: Symbol -;defstruct Writer <: MStat : -; value: Symbol -;defstruct ReadWriter <: MStat : -; value: Symbol -;defstruct ReadLatency <: MStat : -; value: Int -;defstruct WriteLatency <: MStat : -; value: Int -;defstruct DataType <: MStat : -; value: Type -;defstruct Depth <: MStat : -; value: Int +definterface MStat +defstruct Reader <: MStat : + value: Symbol +defstruct Writer <: MStat : + value: Symbol +defstruct ReadWriter <: MStat : + value: Symbol +defstruct ReadLatency <: MStat : + value: Int +defstruct WriteLatency <: MStat : + value: Int +defstruct DataType <: MStat : + value: Type +defstruct Depth <: MStat : + value: Int ;======= Convenience Functions ======== defn first-info? (form) -> FileInfo|False : match(form) : @@ -127,6 +127,10 @@ defsyntax firrtl : id! = (?x:#id) : x id! != () : FPE(form, "Expected an identifier here.") + ;Error if not => + =>! = (=>) : (`=>) + =>! != () : FPE(form, "Expected => here.") + ;Error if not a colon :! = (:) : (`:) :! != () : FPE(form, "Expected a colon here.") @@ -143,6 +147,10 @@ defsyntax firrtl : int$ = (?i:#int ?rest ...) when empty?(rest) : i int$ != () : FPE(form, "Expected a single integer literal here.") + ;Error if not an integer + int! = (?i:#int) : i + int! != () : FPE(form, "Expected an integer literal here.") + ;Error if not a single long integer long$ = (?i:#intorlong ?rest ...) when empty?(rest) : match(i) : @@ -238,41 +246,35 @@ defsyntax firrtl : width = (?) : UnknownWidth() ;Main Statement Productions - ;defrule mstat : - ; mstat = (reader ?name:#id!) : Reader(name) - ; mstat = (writer ?name:#id!) : Writer(name) - ; mstat = (read-writer ?name:#id!) : ReadWriter(name) - ; mstat = (read-latency #:! ?i:#int!) : ReadLatency(i) - ; mstat = (write-latency #:! ?i:#int!) : WriteLatency(i) - ; mstat = (data-type #:! ?t:#type!) : DataType(t) - ; mstat = (depth #:! ?i:#int!) : Depth(i) + defrule mstat : + mstat = (reader #=>! ?name:#id!) : Reader(name) + mstat = (writer #=>! ?name:#id!) : Writer(name) + mstat = (read-writer #=>! ?name:#id!) : ReadWriter(name) + mstat = (read-latency #=>! ?i:#int!) : ReadLatency(i) + mstat = (write-latency #=>! ?i:#int!) : WriteLatency(i) + mstat = (data-type #=>! ?t:#type!) : DataType(t) + mstat = (depth #=>! ?i:#int!) : Depth(i) defrule statements : stmt = (skip) : Empty() stmt = (wire ?name:#id! #:! ?t:#type!) : DefWire(first-info(form),name, t) stmt = (reg ?name:#id! #:! ?t:#type! ?clk:#exp! ?reset:#exp! ?init:#exp!) : DefRegister(first-info(form),name, t,clk,reset,init) - stmt = (mem ?name:#id! #:! ?data-type:#type! ?depth:#int ?writers:#id! ... ?wl:#int ?readers:#id! ... ?rl:#int ?readwriters:#id! ...) : - DefMemory(first-info(form),name,data-type,depth,wl,rl,readers,writers,readwriters) - ;val rl = Vector<Int>() - ;var wl = Vector<Int>() - ;var de = Vector<Int>() - ;var dt = Vector<Type>() - ;val rs = Vector<Symbol>() - ;val ws = Vector<Symbol>() - ;val rws = Vector<Symbol>() - ;for x in stats do : - ; match(x as MStat) : - ; (x:Reader) : add(rs,value(x)) - ; (x:Writer) : add(ws,value(x)) - ; (x:ReadWriter) : add(rws,value(x)) - ; (x:ReadLatency) : add(rl,value(x)) - ; (x:WriteLatency) : add(wl,value(x)) - ; (x:DataType) : add(dt,value(x)) - ; (x:Depth) : add(de,value(x)) - ;if length(rl) != 1 : FPE(stats, "Can only specify one read-latency.") - ;if length(wl) != 1 : FPE(stats, "Can only specify one write-latency.") - ;if length(de) != 1 : FPE(stats, "Can only specify one depth.") - ;if length(dt) != 1 : FPE(stats, "Can only specify one data-type.") - ;DefMemory(first-info(form),name,dt[0],de[0],wl[0],rl[0],to-list(rs),to-list(ws),to-list(rws)) + ;stmt = (mem ?name:#id! #:! ?data-type:#type! ?depth:#int ?writers:#id! ... ?wl:#int ?readers:#id! ... ?rl:#int ?readwriters:#id! ...) : + ; DefMemory(first-info(form),name,data-type,depth,wl,rl,readers,writers,readwriters) + stmt = (mem ?name:#id! #:! (?ms:#mstat ...)) : + defn grab (f:MStat -> True|False) : + map(value,to-list(filter(f,ms))) as List + defn grab1 (f:MStat -> True|False,s:String) : + val ls = grab(f) + if length(ls) != 1 : FPE(form,"Must declare one ~." << [s]) + head(ls) + val readers = grab({_ typeof Reader}) + val writers = grab({_ typeof Writer}) + val readwriters = grab({_ typeof ReadWriter}) + val write-latency = grab1({_ typeof WriteLatency},"write-latency") + val read-latency = grab1({_ typeof ReadLatency},"read-latency") + val depth = grab1({_ typeof Depth},"depth") + val data-type = grab1({_ typeof DataType},"data type") + DefMemory(first-info(form),name,data-type,depth,write-latency,read-latency,readers,writers,readwriters) stmt = (inst ?name:#id! #of! ?m:#id!) : 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) @@ -280,8 +282,8 @@ defsyntax firrtl : stmt = (printf(?clk:#exp ?str:#string ?es:#exp ...)) : Print(first-info(form),str,es,clk) stmt = (?s:#stmt/when) : s - stmt = (?x:#exp := ?y:#exp!) : Connect(first-info(form),x, y) - stmt = (?x:#exp <> ?y:#exp!) : BulkConnect(first-info(form),x, y) + stmt = (?x:#exp <= ?y:#exp!) : Connect(first-info(form),x, y) ;> + stmt = (?x:#exp <- ?y:#exp!) : BulkConnect(first-info(form),x, y);> ;stmt = ((?s:#stmt ?rest ...)) : ; Begin(List(s, parse-stmts(rest))) diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index ba0e2423..4b70175a 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -9,9 +9,9 @@ defpackage firrtl/ir-utils : public defmulti print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|Module|Circuit) -> False public defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|Module|Circuit) -> False : false public defmulti turn-off-debug (x:False) -> False -public defmethod turn-off-debug (x:False) : false +;public defmethod turn-off-debug (x:False) : false public defmulti turn-on-debug (x:False) -public defmethod turn-on-debug (x:False) : false +;public defmethod turn-on-debug (x:False) : false ;============== GENSYM STUFF ====================== @@ -314,9 +314,9 @@ defmethod print (o:OutputStream, c:Stmt) : (c:Begin) : do(print{o,_}, join(body(c), "\n")) (c:Connect) : - print-all(o, [loc(c) " := " exp(c)]) + print-all(o, [loc(c) " <= " exp(c)]) (c:BulkConnect) : - print-all(o, [loc(c) " <> " exp(c)]) + print-all(o, [loc(c) " <- " exp(c)]) (c:Empty) : print(o, "skip") (c:Stop) : diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 4dbd55d8..2621b408 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -96,7 +96,17 @@ defn get-gender (s:Stmt|Port) -> Gender : OUTPUT : FEMALE defmulti kind (e:Expression) -> Kind -defmethod kind (e:Expression) : ExpKind() +defmethod kind (e:Expression) : + match(e) : + (e:WRef) : kind(e) + (e:WSubField) : kind(exp(e)) + (e:WSubIndex) : kind(exp(e)) + (e:WIndexer) : + val k = kind(exps(e)[0]) + for x in exps(e) do : + if k != kind(x) : error("All kinds of exps of WIndexer must be the same") + k + (e) : ExpKind() defmethod info (stmt:Begin) -> FileInfo : FileInfo() defmethod info (stmt:Empty) -> FileInfo : FileInfo() @@ -213,6 +223,15 @@ defmethod turn-off-debug (x:False) : old-PRINT-CIRCUITS = PRINT-CIRCUITS old-PRINT-DEBUG = PRINT-DEBUG old-PRINT-INFO = PRINT-INFO + + PRINT-TYPES = false + PRINT-KINDS = false + PRINT-WIDTHS = false + PRINT-TWIDTHS = false + PRINT-GENDERS = false + PRINT-CIRCUITS = false + PRINT-DEBUG = false + PRINT-INFO = false defmethod turn-on-debug (x:False) : PRINT-TYPES = old-PRINT-TYPES PRINT-KINDS = old-PRINT-KINDS @@ -713,7 +732,9 @@ defn infer-types (c:Circuit) -> Circuit : (e:DoPrim) : set-primop-type(e) (e:UIntValue|SIntValue) : e defn infer-types-s (s:Stmt) -> Stmt : - match(map(infer-types-e,s)) : + map{infer-types-e,_} $ map(infer-types-s,s) + defn build-types (s:Stmt) -> Stmt : + match(s) : (s:DefWire|DefPoison|DefRegister|DefMemory|DefNode) : val t = remove-unknowns(get-type(s)) types[name(s)] = t @@ -721,13 +742,13 @@ defn infer-types (c:Circuit) -> Circuit : (s:WDefInstance) : types[name(s)] = module-types[module(s)] WDefInstance(info(s),name(s),module(s),module-types[module(s)]) - (s) : map(infer-types-s,s) + (s) : map(build-types,s) for p in ports(m) do : types[name(p)] = type(p) match(m) : (m:InModule) : - val s* = infer-types-s(body(m)) - InModule(info(m),name(m),ports(m),s*) + val s* = build-types(body(m)) + InModule(info(m),name(m),ports(m),infer-types-s(s*)) (m:ExModule) : m ; MAIN @@ -1965,7 +1986,11 @@ defn split-exp (m:InModule) -> InModule : if i > 0 : split(e) else : e (e) : e - map{split-exp-e{_,0},_} $ map(split-exp-s,s) + match(s) : + (s:Begin) : map(split-exp-s,s) + (s) : + add(v,map{split-exp-e{_,0},_} $ map(split-exp-s,s)) + s split-exp-s(body(m)) InModule(info(m),name(m),ports(m),Begin(to-list(v))) @@ -2391,7 +2416,7 @@ defn lowered-name (e:Expression) -> Symbol : defn root-ref (e:Expression) -> Expression : match(e) : (e:WRef) : e - (e:WSubField|WSubIndex) : root-ref(e) + (e:WSubField|WSubIndex) : root-ref(exp(e)) ;------------- Pass ------------------ @@ -2500,7 +2525,7 @@ defn emit (x:?, top:Int) : match(e) : (e:DoPrim) : op-print(e) (e:WRef) : print(e) - ;(e:WSubField) : print-all([exp(e) `_ name(f)]) + (e:WSubField) : print(lowered-name(e)) (e:WSubAccess) : print(e) (e:WSubIndex) : print(e) (e:UIntValue|SIntValue) : v-print(e) @@ -2513,6 +2538,7 @@ defn emit (x:?, top:Int) : else : "" (s:Symbol) : print(s) (i:Int) : print(i) + (i:Long) : print(i) (s:String) : print(s) (t:VIndent) : print(" ") (r:VRandom) : print("$random") @@ -2623,20 +2649,25 @@ defn emit-verilog (m:InModule) -> Module : s val declares = Vector<Streamable>() + val assigns = Vector<Streamable>() val at-clock = HashTable<Expression,Vector<Streamable>>(exp-hash) val initials = Vector<Streamable>() val simulates = Vector<Streamable>() defn declare (b:Symbol,n:Symbol,t:Type) : add(declares,[b t n ";"]) defn assign (e:Expression,value:Expression) : - add(declares,["assign " e " = " value]) + add(assigns,["assign " e " = " value]) defn update-reset (e:Expression,clk:Expression,reset?:Expression,init:Expression) : + if not key?(at-clock,clk) : + at-clock[clk] = Vector<Streamable>() add(at-clock[clk],["if(" reset? ") begin"]) add(at-clock[clk],[tab e " <= " init]) add(at-clock[clk],["end else"]) add(at-clock[clk],[tab e " <= " netlist[e]]) add(at-clock[clk],["end"]) defn update (e:Expression,clk:Expression,en:Expression) : + if not key?(at-clock,clk) : + at-clock[clk] = Vector<Streamable>() add(at-clock[clk],["if(" en ") begin"]) add(at-clock[clk],[tab e " <= " netlist[e]]) add(at-clock[clk],["end"]) @@ -2649,11 +2680,16 @@ defn emit-verilog (m:InModule) -> Module : defn instantiate (n:Symbol,m:Symbol,es:List<Expression>) : add(declares,[m " " n " ("]) for (e in es,i in 1 to false) do : - val s = [tab "." remove-root(e) "(" netlist[e] ")"] + val s = [tab "." remove-root(e) "(" lowered-name(e) ")"] if i == length(es) : add(declares,[s ","]) else : add(declares,s) add(declares,[");"]) + for e in es do : + val e* = WRef(lowered-name(e),type(e),kind(e),gender(e)) + if (gender(e) == FEMALE) : assign(e*,netlist[e]) defn simulate (clk:Expression,en:Expression,s:Streamable) : + if not key?(at-clock,clk) : + at-clock[clk] = Vector<Streamable>() add(at-clock[clk],["`ifndef SYNTHESIS"]) add(at-clock[clk],[tab "if(" en ") begin"]) add(at-clock[clk],[tab tab s]) @@ -2676,6 +2712,7 @@ defn emit-verilog (m:InModule) -> Module : defn build-streams (s:Stmt) -> Stmt : match(s) : + (s:Connect) : s (s:DefWire) : val es = create-exps(WRef(name(s),type(s),WireKind(),BI-GENDER)) for e in es do : @@ -2690,7 +2727,7 @@ defn emit-verilog (m:InModule) -> Module : (s:DefPoison) : val es = create-exps(WRef(name(s),type(s),PoisonKind(),MALE)) for e in es do : - declare(`wire,lowered-name(e),type(e)) + declare(`reg,lowered-name(e),type(e)) initialize(e) (s:DefNode) : declare(`wire,name(s),type(value(s))) @@ -2748,9 +2785,14 @@ defn emit-verilog (m:InModule) -> Module : s defn emit-streams () : + emit(["module " name(m) "("]) if !empty?(declares) : for x in declares do : emit(x) + + if !empty?(assigns) : + for x in assigns do : + emit(x) if !empty?(initials) : emit(["`ifndef SYNTHESIS"]) @@ -2768,6 +2810,7 @@ defn emit-verilog (m:InModule) -> Module : for x in value(clk-stream) do : emit([tab x]) emit(["end"]) + emit(["endmodule"]) build-netlist(body(m)) build-streams(body(m)) diff --git a/test/errors/high-form/Flip-Mem.fir b/test/errors/high-form/Flip-Mem.fir index 38935b57..ebc3ddbf 100644 --- a/test/errors/high-form/Flip-Mem.fir +++ b/test/errors/high-form/Flip-Mem.fir @@ -5,5 +5,9 @@ circuit Flip-Mem : module Flip-Mem : input clk : Clock - cmem mc : {x : UInt<3>, flip y : UInt<5>}[10], clk - smem ms : {x : UInt<3>, flip y : UInt<5>}[10], clk + mem mc : + depth => 10 + data-type => {x : UInt<3>, flip y : UInt<5>} + write-latency => 1 + read-latency => 0 + ;smem ms : {x : UInt<3>, flip y : UInt<5>}[10], clk diff --git a/test/passes/to-verilog/gcd.fir b/test/passes/to-verilog/gcd.fir index c79cc92e..cadd9ec8 100644 --- a/test/passes/to-verilog/gcd.fir +++ b/test/passes/to-verilog/gcd.fir @@ -6,7 +6,7 @@ circuit top : input x : UInt input y : UInt output q : UInt - q := subw(x, y) + q <= subw(x, y) module gcd : input clk : Clock input reset : UInt<1> @@ -18,18 +18,18 @@ circuit top : reg y : UInt,clk,reset,UInt(42) when gt(x, y) : inst s of subtracter - s.x := x - s.y := y - x := s.q + s.x <= x + s.y <= y + x <= s.q else : inst s2 of subtracter - s2.x := x - s2.y := y - y := s2.q + s2.x <= x + s2.y <= y + y <= s2.q when e : - x := a - y := b - z := x + x <= a + y <= b + z <= x module top : input a : UInt<16> input b : UInt<16> @@ -37,12 +37,12 @@ circuit top : input reset : UInt<1> output z : UInt inst i of gcd - i.clk := clk - i.reset := reset - i.a := a - i.b := b - i.e := UInt(1) - z := i.z + i.clk <= clk + i.reset <= reset + i.a <= a + i.b <= b + i.e <= UInt(1) + z <= i.z diff --git a/test/passes/to-verilog/mem.fir b/test/passes/to-verilog/mem.fir index 0d0e0e5f..5d1c60f0 100644 --- a/test/passes/to-verilog/mem.fir +++ b/test/passes/to-verilog/mem.fir @@ -7,6 +7,6 @@ circuit top : output read : UInt<30> cmem m : UInt<30>[128], clk read accessor x = m[UInt(0)] - read := x + read <= x diff --git a/test/passes/to-verilog/rd-mem.fir b/test/passes/to-verilog/rd-mem.fir index c21cd1c6..0bb86851 100644 --- a/test/passes/to-verilog/rd-mem.fir +++ b/test/passes/to-verilog/rd-mem.fir @@ -9,9 +9,9 @@ circuit top : smem m : UInt<32>[4],clk read accessor c = m[index] - rdata := UInt(0) + rdata <= UInt(0) when ren : - rdata := c + rdata <= c : CHECK: module top( : CHECK: output [31:0] rdata, diff --git a/test/passes/to-verilog/rdwr-mem.fir b/test/passes/to-verilog/rdwr-mem.fir index 667d831f..d056ecf6 100644 --- a/test/passes/to-verilog/rdwr-mem.fir +++ b/test/passes/to-verilog/rdwr-mem.fir @@ -12,9 +12,9 @@ circuit top : smem m : UInt<32>[4],clk rdwr accessor c = m[index] when ren : - rdata := c + rdata <= c when wen : - c := wdata + c <= wdata ; CHECK: module top( diff --git a/test/passes/to-verilog/shr.fir b/test/passes/to-verilog/shr.fir index c4b4e4d2..1b8db9e0 100644 --- a/test/passes/to-verilog/shr.fir +++ b/test/passes/to-verilog/shr.fir @@ -7,7 +7,7 @@ circuit HellaCache : module TLB_60 : output resp : {ppn : UInt<20>} - resp.ppn := UInt<1>("h00") + resp.ppn <= UInt<1>("h00") module HellaCache : input clock : Clock @@ -21,10 +21,10 @@ circuit HellaCache : node T_928 = bits(s1_req.addr, 11, 0) node s1_addr = cat(dtlb.resp.ppn, T_928) when s1_clk_en : - s2_req.addr := s1_addr + s2_req.addr <= s1_addr - s1_req.addr := UInt<?>(0) - s1_clk_en := UInt<?>(0) + s1_req.addr <= UInt<?>(0) + s1_clk_en <= UInt<?>(0) wire foo : UInt<28> - foo := shr(s1_addr, 3) + foo <= shr(s1_addr, 3) diff --git a/test/passes/to-verilog/wr-mem.fir b/test/passes/to-verilog/wr-mem.fir index 7641e894..b21491aa 100644 --- a/test/passes/to-verilog/wr-mem.fir +++ b/test/passes/to-verilog/wr-mem.fir @@ -10,7 +10,7 @@ circuit top : smem m : UInt<32>[4],clk write accessor c = m[index] when wen : - c := wdata + c <= wdata ; CHECK: module top( ; CHECK: input [31:0] wdata, |
