diff options
| author | azidar | 2015-12-09 18:31:45 -0800 |
|---|---|---|
| committer | azidar | 2016-01-16 14:28:17 -0800 |
| commit | be78d49aa01c097978f69a3b022acb2047fdf438 (patch) | |
| tree | 76dc4b32b5e6861938404ebb4d124ca5b87d13a5 /src | |
| parent | c427b31a1ef8361b643d5f7435aeb42472dfe626 (diff) | |
New memory works with verilog. Slowly changing tests and fixing bugs.
Decided to not have Conditionally in low firrtl - instead, Print and
Stop have enables
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/stanza/compilers.stanza | 3 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 3 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 16 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 23 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 983 |
5 files changed, 361 insertions, 667 deletions
diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index cfe5bbaf..1598be21 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -77,6 +77,9 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> : ConstProp() ;R SplitExp() ;R LowerTypes() ;R + ResolveKinds() ;W + InferTypes() ;R + ResolveGenders() ;W ;CheckWidths() ;R ;CheckHighForm() ;R ;CheckLowForm() ;R diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index ec53465e..7ac72922 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -151,12 +151,13 @@ public defstruct Stop <: Stmt : ;LOW info: FileInfo with: (as-method => true) ret: Int clk: Expression + en: Expression public defstruct Print <: Stmt : ;LOW info: FileInfo with: (as-method => true) string: String args: List<Expression> clk: Expression - + en: Expression public defstruct Empty <: Stmt ;LOW public definterface Type diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index e8dd3306..896eed6f 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -273,13 +273,15 @@ defsyntax firrtl : 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) + val dt = grab1({_ typeof DataType},"data type") + println("Parser!") + println(dt) + DefMemory(first-info(form),name,dt,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) - stmt = (stop(?clk:#exp,?ret:#int)) : Stop(first-info(form),ret,clk) - stmt = (printf(?clk:#exp ?str:#string ?es:#exp ...)) : Print(first-info(form),str,es,clk) + stmt = (stop(?clk:#exp, ?en:#exp, ?ret:#int)) : Stop(first-info(form),ret,clk,en) + stmt = (printf(?clk:#exp ?en:#exp ?str:#string ?es:#exp ...)) : Print(first-info(form),str,es,clk,en) stmt = (?s:#stmt/when) : s stmt = (?x:#exp <= ?y:#exp!) : Connect(first-info(form),x, y) ;> @@ -317,11 +319,13 @@ defsyntax firrtl : (t:UIntType) : match(width(t)) : (w:IntWidth) : - if to-long(max(1,(req-num-bits(b) - 1))) > width(w) : + if to-long(req-num-bits(b)) > width(w) : FPE(form, "Width too small for UIntValue.") UIntValue(b, w) (w) : - UIntValue(b, w) + ;UIntValue(b, w) + val num-bits = req-num-bits(b) + UIntValue(b,IntWidth(max(1,num-bits))) (t:SIntType) : match(width(t)) : (w:IntWidth) : diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 4b70175a..fdd22acb 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -286,14 +286,13 @@ defmethod print (o:OutputStream, c:Stmt) : (c:DefMemory) : print-all(o,["mem " name(c) " : "]) print-debug(o,c) - print(o,"\n") - print-all(io,["data-type: " data-type(c) "\n"]) - print-all(io,["depth: " depth(c) "\n"]) - print-all(io,["write-latency: " write-latency(c) "\n"]) - print-all(io,["read-latency: " read-latency(c) "\n"]) - print-all(io,["readers: " readers(c) "\n"]) - print-all(io,["writers: " writers(c) "\n"]) - print-all(io,["readwriters: " readwriters(c) "\n"]) + print-all(io,["\ndata-type: " data-type(c)]) + print-all(io,["\ndepth: " depth(c)]) + print-all(io,["\nwrite-latency: " write-latency(c)]) + print-all(io,["\nread-latency: " read-latency(c)]) + for r in readers(c) do : print-all(io,["\nreader: " r]) + for w in writers(c) do : print-all(io,["\nwriter: " w]) + for rw in readwriters(c) do : print-all(io,["\nread-writer: " rw]) (c:DefInstance) : print-all(o,["inst " name(c) " of " module(c)]) (c:DefNode) : @@ -320,9 +319,9 @@ defmethod print (o:OutputStream, c:Stmt) : (c:Empty) : print(o, "skip") (c:Stop) : - print-all(o, ["stop(" ret(c) ", " clk(c) ")"]) + print-all(o, ["stop(" ret(c) ", " clk(c) ", " en(c) ")"]) (c:Print) : - print-all(o, ["printf(" clk(c) ", "]) ;" + print-all(o, ["printf(" clk(c) ", " en(c) ", "]) ;" print-all(o, join(List(escape(string(c)),args(c)), ", ")) print(o, ")") @@ -426,8 +425,8 @@ defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : (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:Stop) : Stop(info(c),ret(c),f(clk(c))) - (c:Print) : Print(info(c),string(c),map(f,args(c)),f(clk(c))) + (c:Stop) : Stop(info(c),ret(c),f(clk(c)),f(en(c))) + (c:Print) : Print(info(c),string(c),map(f,args(c)),f(clk(c)),f(en(c))) (c) : c public defmulti map<?T> (f: Stmt -> Stmt, c:?T&Stmt) -> T diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 2621b408..4f219def 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -90,6 +90,7 @@ defn get-gender (s:Stmt|Port) -> Gender : (s:DefWire|DefRegister) : BI-GENDER (s:WDefInstance|DefNode|DefInstance|DefPoison) : MALE (s:Begin|Connect|BulkConnect|Stop|Print|Empty) : UNKNOWN-GENDER + (s:DefMemory) : FEMALE (p:Port) : switch { _ == direction(p) } : INPUT : MALE @@ -119,27 +120,32 @@ defn get-type (s:Stmt) -> Type : (s:DefWire|DefPoison|DefRegister|WDefInstance) : type(s) (s:DefNode) : type(value(s)) (s:DefMemory) : - val data-type = data-type(s) + defn create-mask (n:Symbol) -> Field : + Field{n,DEFAULT,_} $ match(data-type(s)) : + (t:VectorType) : VectorType(BoolType(),size(t)) + (t:BundleType) : + val fields* = for f in fields(t) map : + Field(name(f),flip(f),BoolType()) + BundleType(fields*) + (t:UIntType|SIntType) : BoolType() val depth = depth(s) ; Fields val addr = Field(`addr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) val en = Field(`en,DEFAULT,BoolType()) val clk = Field(`clk,DEFAULT,ClockType()) - val rdata = Field(`data,REVERSE,data-type) - val wdata = Field(`data,DEFAULT,data-type) - val wmask = match(data-type) : - (t:VectorType) : Field(`mask,DEFAULT,VectorType(BoolType(),size(t))) - (t:BundleType) : - val fields* = for f in fields(t) map : - Field(name(f),flip(f),BoolType()) - Field(`mask, DEFAULT, BundleType(fields*)) + val def-data = Field(`data,DEFAULT,data-type(s)) + val rev-data = Field(`data,REVERSE,data-type(s)) + val rdata = Field(`rdata,REVERSE,data-type(s)) + val wdata = Field(`wdata,DEFAULT,data-type(s)) + val mask = create-mask(`mask) + val wmask = create-mask(`wmask) val ren = Field(`ren,DEFAULT,UIntType(IntWidth(1))) val wen = Field(`wen,DEFAULT,UIntType(IntWidth(1))) val raddr = Field(`raddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) val waddr = Field(`waddr,DEFAULT,UIntType(IntWidth(ceil-log2(depth)))) - val read-type = BundleType(to-list([rdata,addr,en,clk])) - val write-type = BundleType(to-list([wdata,wmask,addr,en,clk])) + val read-type = BundleType(to-list([rev-data,addr,en,clk])) + val write-type = BundleType(to-list([def-data,mask,addr,en,clk])) val readwrite-type = BundleType(to-list([wdata,wmask,waddr,wen,rdata,raddr,ren,clk])) val mem-fields = Vector<Field>() @@ -690,17 +696,6 @@ defn resolve-kinds (c:Circuit) : resolve-kinds(m,c) ;============== INFER TYPES ================================ -; This pass infers the type field in all IR nodes by updating -; and passing an environment to all statements in pre-order -; traversal, and resolving types in expressions in post- -; order traversal. -; Type propagation for primary ops are defined here. -; Notable cases: LetRec requires updating environment before -; resolving the subexpressions in its elements. -; Type errors are not checked in this pass, as this is -; postponed for a later/earlier pass. - - ; ------------------ Utils ------------------------- @@ -735,10 +730,15 @@ defn infer-types (c:Circuit) -> Circuit : map{infer-types-e,_} $ map(infer-types-s,s) defn build-types (s:Stmt) -> Stmt : match(s) : - (s:DefWire|DefPoison|DefRegister|DefMemory|DefNode) : + (s:DefWire|DefPoison|DefRegister|DefNode) : val t = remove-unknowns(get-type(s)) types[name(s)] = t set-type(s,t) + (s:DefMemory) : + val t = remove-unknowns(get-type(s)) + types[name(s)] = t + val dt = remove-unknowns(data-type(s)) + set-type(s,dt) (s:WDefInstance) : types[name(s)] = module-types[module(s)] WDefInstance(info(s),name(s),module(s),module-types[module(s)]) @@ -903,13 +903,14 @@ defn get-point (e:Expression) -> Int : match(e) : (e:WRef) : 0 (e:WSubField) : - var i = -1 + var i = 0 for f in fields(type(exp(e)) as BundleType) find : - i = i + 1 - name(f) == name(e) + val b = name(f) == name(e) + if not b : i = i + get-size(type(f)) + b get-point(exp(e)) + i (e:WSubIndex) : - get-point(exp(e)) + value(e) + get-point(exp(e)) + value(e) * get-size(e) (e:WIndexer) : get-point(exps(e)[0]) defn get-valid-points (t1:Type,t2:Type,flip1:Flip,flip2:Flip) -> List<[Int,Int]> : @@ -922,6 +923,8 @@ defn get-valid-points (t1:Type,t2:Type,flip1:Flip,flip2:Flip) -> List<[Int,Int]> else: list() (t1:BundleType,t2:BundleType) : val points = Vector<[Int,Int]>() + var ilen = 0 + var jlen = 0 for i in 0 to length(fields(t1)) do : for j in 0 to length(fields(t2)) do : val f1 = fields(t1)[i] @@ -930,14 +933,20 @@ defn get-valid-points (t1:Type,t2:Type,flip1:Flip,flip2:Flip) -> List<[Int,Int]> val ls = get-valid-points(type(f1),type(f2),flip1 * flip(f1), flip2 * flip(f2)) for x in ls do : - add(points,[x[0] + i, x[1] + j]) + add(points,[x[0] + ilen, x[1] + jlen]) + ilen = ilen + get-size(type(fields(t1)[i])) + jlen = jlen + get-size(type(fields(t2)[j])) to-list(points) (t1:VectorType,t2:VectorType) : val points = Vector<[Int,Int]>() + var ilen = 0 + var jlen = 0 for i in 0 to min(size(t1),size(t2)) do : val ls = get-valid-points(type(t1),type(t2),flip1,flip2) for x in ls do : - add(points,[x[0] + i, x[1] + i]) + add(points,[x[0] + ilen, x[1] + jlen]) + ilen = ilen + get-size(type(t1)) + jlen = jlen + get-size(type(t2)) to-list(points) defn create-exps (n:Symbol, t:Type) -> List<Expression> : create-exps(WRef(n,t,ExpKind(),UNKNOWN-GENDER)) @@ -958,22 +967,22 @@ defn expand-connects (c:Circuit) -> Circuit : val exp-lib = HashTable<Symbol,List<Expression>>(symbol-hash) defn create-lib (s:Stmt) -> Stmt : match(s) : - (s:DefWire|DefRegister|WDefInstance|DefNode|DefPoison) : ;TODO Memories? + (s:DefWire|DefRegister|WDefInstance|DefNode|DefPoison|DefMemory) : ;TODO Memories? exp-lib[name(s)] = create-exps(name(s),get-type(s)) + println(get-type(s)) s (s) : map(create-lib,s) defn expand-e (e:Expression, point:Int) -> Expression : - defn lookup-exp (e:Expression, point:Int) -> Expression : - match(e) : - (e:WRef) : exp-lib[name(e)][point] - (e:WSubField|WSubIndex) : lookup-exp(exp(e), point + get-point(e)) - (e) : error("Shouldn't be here") + println-all(["Expression: " e]) + println-all(["point: " point]) match(e) : - (e:WRef|WSubField|WSubIndex) : lookup-exp(e,point) + (e:WRef|WSubField|WSubIndex) : + println-all(["lib: " exp-lib[name(root-ref(e))]]) + println-all(["get-point: " get-point(e)]) + exp-lib[name(root-ref(e))][get-point(e) + point] (e:WIndexer) : - val exps* = - for e* in exps(e) map : - expand-e(e*,point) + val exps* = for e* in exps(e) map : + expand-e(e*,point) WIndexer(exps*,index(e),type(exps*[0]),gender(exps*[0])) (e:DoPrim) : e (e) : e @@ -1056,22 +1065,6 @@ public defn replace-indexer (c:Circuit) -> Circuit : ;;================ EXPAND WHENS ============================= ; This pass does three things: remove last connect semantics, ; remove conditional blocks, and eliminate concept of scoping. -; First, we scan the circuit to build a table mapping references -; to the final assigned value, represented with SymbolicValues. -; Within a scope, we remove the last connect symantics to get -; the final value. When leaving a scope, the resulting table -; is merged with the parent scope by using the SVMux. -; We also collect the kind of reference to know how to declare -; it in a following stage. -; Second, we use the table to declare each reference, then -; assign to each once. This is relatively straightforward -; except calculating the WritePort/ReadPort enables. -; Finally, we scan the table to remove redundant values -; The WritePort enable is calculated by returning 1 for all conditions -; for which the corresponding symbolic value is not SVNul. -; The ReadPort enable is calcuated by scanning all entries in -; the table for when this is referenced (a read). All conditions -; are accumulated and OR'ed together. public defstruct ExpandWhens <: Pass public defmethod pass (b:ExpandWhens) -> (Circuit -> Circuit) : expand-whens @@ -1146,12 +1139,21 @@ defn expand-whens (c:Circuit) -> Circuit : netlist[lvalue] = MUX(pred(s),c-netlist[lvalue],value) (value:False) : netlist[lvalue] = c-netlist[lvalue] - (s:Print|Stop) : add(simlist,Conditionally(info(s),p,s,Empty())) + (s:Print) : + if p == one : add(simlist,s) + else : add(simlist,Print(info(s),string(s),args(s),clk(s),AND(p,en(s)))) + (s:Stop) : + if p == one : add(simlist,s) + else : add(simlist,Stop(info(s),ret(s),clk(s),AND(p,en(s)))) (s) : map(expand-whens{_,netlist,p},s) s val netlist = HashTable<Expression,Expression>(exp-hash) expand-whens(body(m),netlist,one) + println("Netlist:") + println(netlist) + println("Simlist:") + println(simlist) [ netlist simlist ] defn create-module (netlist:HashTable<Expression,Expression>,simlist:Vector<Stmt>,m:InModule) -> InModule : @@ -1165,11 +1167,12 @@ defn expand-whens (c:Circuit) -> Circuit : (s:DefWire|DefRegister|WDefInstance|DefMemory) : add(stmts,s) for e in get-female-refs(name(s),get-type(s),get-gender(s)) do : + println(e) val rvalue = if s typeof DefRegister : replace-void(e,netlist[e]) else : netlist[e] add(stmts,Connect(info(s),e,rvalue)) - (s:DefPoison|DefNode|Stop|Print) : + (s:DefPoison|DefNode) : add(stmts,s) (s) : map(create,s) s @@ -1197,349 +1200,6 @@ defn expand-whens (c:Circuit) -> Circuit : create-module(netlist,simlist,m) Circuit(info(c),modules*,main(c)) - -;defn has-nul? (sv:SymbolicValue) -> True|False : -; var has? = false -; if sv typeof SVNul : has? = true -; for x in sv dor : -; if x typeof SVNul : has? = true -; has? -;defn remove-nul (sv:SymbolicValue) -> SymbolicValue : -; match(map(remove-nul,sv)) : -; (sv:SVMux) : -; match(conseq(sv),alt(sv)) : -; (c,a:SVNul) : c -; (c:SVNul,a) : a -; (c,a) : sv -; (sv) : sv -;defn to-exp (sv:SymbolicValue) -> Expression|False : -; match(remove-nul(sv)) : -; (sv:SVMux) : -; DoPrim(MUX-OP, -; list(pred(sv),to-exp(conseq(sv)) as Expression,to-exp(alt(sv)) as Expression), -; list(), -; UIntType(IntWidth(1))) -; (sv:SVExp) : exp(sv) -; (sv:SVNul) : false -;defn reduce-or (l:List<True|False>) -> True|False : -; if length(l) == 0 : false -; else : head(l) or reduce-or(tail(l)) -;defn reduce-or (l:List<Expression>) -> Expression : -; if length(l) == 0 : zero -; else : OR(head(l) reduce-or(tail(l))) - -; ========= Expand When Pass =========== - - - -;Can either check initialization here or in separate pass -;defn expand-whens (c:Circuit) -; -; Circuit(info(c),modules*, main(c)) where : -; val modules* = -; for m in modules(c) map : -; expand-whens(m) - - - - - -; TODO: replace stmt with wr (WRefs). The KIND of wref will help figure out what to emit as far as -; declarations, especially with not declaring anything for ports. We need WRefs, and not just Kinds, -; because we need the name of the symbolic expression. I think? Or maybe we can use the key? - -; 1) Build Table, Build Declaration List - -; assign: holds the symbolic value of a wref. -; resets: holds the symbolic value of connections under reset -; stmts: Used to hold the orignal type, as well as the mem/index for Write/ReadPorts -; kinds: Used to know the kind of reference, so we know whether we should error if it isn't initialized. We also know how we should declare the refernce. -; enables:Calculated off of assigns. - -;---------------- Helper Functions -------------- -;defn get-read-enable (sym:Symbol,table:HashTable<Symbol,SymbolicValue>) -> Expression : -; defn get-single-read-enable (sym:Symbol,sv:SymbolicValue) -> Expression : -; defn active (e:Expression) -> True|False : -; match(e) : -; (e:WRef) : name(e) == sym -; (e) : reduce-or{_} $ map(active,children(e)) -; (e) : false -; match(sv) : -; (sv: SVNul) : zero -; (sv: SVExp) : -; if active(exp(sv)) : one -; else : zero -; (sv: SVMux) : -; val e0 = get-single-read-enable(sym,SVExp(pred(sv))) -; val e1 = get-single-read-enable(sym,conseq(sv)) -; val e2 = get-single-read-enable(sym,alt(sv)) -; if e1 == e2 : OR(e0,e1) -; else : OR(e0,OR(AND(pred(sv),e1),AND(NOT(pred(sv)),e2))) -; reduce-or $ to-list $ for y in table stream : get-single-read-enable(sym,value(y)) -; -;defn get-write-enable (sv:SymbolicValue) -> SymbolicValue : -; match(map(get-write-enable,sv)) : -; (sv: SVExp) : SVExp(one) -; (sv: SVNul) : SVExp(zero) -; (sv) : sv -; -;defn merge-resets (assign:HashTable<Symbol,SymbolicValue>, resets:HashTable<Symbol,SymbolicValue>, rsignals:HashTable<Symbol,Expression>) -> HashTable<Symbol,SymbolicValue> : -; val table = HashTable<Symbol,SymbolicValue>(symbol-hash) -; for i in get-unique-keys(list(assign,resets)) do : -; table[i] = match(get?(assign,i,false),get?(resets,i,false)) : -; (a:SymbolicValue,r:SymbolicValue) : -; if r typeof SVNul : a -; else : SVMux(rsignals[i],r,a) -; (a:SymbolicValue,r:False) : a -; (a:False,r:SymbolicValue) : SVMux(rsignals[i],r,SVNul()) -; (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) : -; assign[name(s)] = SVNul() -; flattn[name(s)] = true -; (s:DefRegister) : -; assign[name(s)] = SVNul() -; flattn[name(s)] = true -; rsignals[name(s)] = reset(s) -; resets[name(s)] = SVNul() -; (s:DefAccessor) : -; assign[name(s)] = SVNul() -; flattn[name(s)] = false -; (s:WDefInstance) : ;TODO only add instance input ports. This probably involves correcting instance genders -; for f in fields(type(module(s)) as BundleType) do : -; if flip(f) == REVERSE : -; println-all-debug(["Instance: " s " has input " f]) -; val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs -; assign[n] = SVNul() -; flattn[n] = true -; (s:Conditionally) : -; defn combine (flattn:HashTable<Symbol,True|False>, -; table-c:HashTable<Symbol,SymbolicValue>, -; table-a:HashTable<Symbol,SymbolicValue>, -; i:Symbol) -> SymbolicValue|False : -; match(get?(table-c,i,false),get?(table-a,i,false)) : -; (c:SymbolicValue,a:SymbolicValue) : -; if c == a : c -; else : SVMux(pred(s),c,a) -; (c:SymbolicValue,a:False) : -; if flattn[i] : c -; else : SVMux(pred(s),c,SVNul()) -; (c:False,a:SymbolicValue) : -; if flattn[i] : a -; else : SVMux(pred(s),SVNul(),a) -; (c:False,a:False) : false -; -; val assign-c = deepcopy(assign) -; val assign-a = deepcopy(assign) -; val resets-c = deepcopy(resets) -; val resets-a = deepcopy(resets) -; 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 -; -; mark(simuls-c,pred(s)) -; mark(simuls-a,DoPrim(BIT-NOT-OP,list(pred(s)),list(),UIntType(IntWidth(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) -; (e:WSubField) : symbol-join([name(exp(e) as ?) `. name(e)]) -; (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,simuls) -; (s:StopStmt|PrintfStmt) : -; add(simuls,[s one]) -; (s:DefMemory|DefPoison|DefNode|EmptyStmt) : false -; -; -;defn mark-referenced (referenced?:HashTable<Symbol,True>, s:Stmt) -> False : -; defn mark-referenced-e (e:Expression) -> Expression : -; match(map(mark-referenced-e,e)) : -; (e:WRef) : -; referenced?[name(e)] = true -; e -; (e) : e -; do(mark-referenced{referenced?,_:Stmt},s) -; map(mark-referenced-e,s) -; false -; -;defn mark-referenced (referenced?:HashTable<Symbol,True>, sv:SymbolicValue) -> SymbolicValue : -; defn mark-referenced-e (e:Expression) -> Expression : -; match(map(mark-referenced-e,e)) : -; (e:WRef) : -; referenced?[name(e)] = true -; e -; (e) : e -; map{mark-referenced-e,_} $ map(mark-referenced{referenced?,_:SymbolicValue},sv) -; -;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:WDefInstance) : true -; (s:PrintfStmt|StopStmt|Conditionally) : true -; -;;--------------- Expand Whens Pass ------------------- -; -;public defn expand-whens (c:Circuit) -> Circuit : -; -; defn expand-whens (ports:List<Port>, table:HashTable<Symbol,SymbolicValue>,cons:Vector<Stmt>) -> False : -; for p in ports do : -; if direction(p) == OUTPUT : -; val ref = WRef(name(p),type(p),PortKind(),FEMALE) -; if not has-nul?(table[name(p)]) : -; add{cons,_} $ Connect(FileInfo(),ref,to-exp(table[name(p)]) as Expression) -; -; defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stmt>,cons:Vector<Stmt>) -> Stmt : -; match(map(expand-whens{_,table,decs,cons},s)) : -; (s:DefNode) : -; add(decs,s) -; (s:DefMemory) : -; add(decs,s) -; (s:DefPoison) : -; add(decs,s) -; (s:DefWire) : -; add(decs,s) -; val ref = WRef(name(s),type(s),NodeKind(),FEMALE) -; if not has-nul?(table[name(s)]) : -; add{cons,_} $ Connect(info(s),ref,to-exp(table[name(s)]) as Expression) -; (s:DefRegister) : -; add(decs,s) -; val e = to-exp(table[name(s)]) -; match(e) : -; (e:Expression) : -; val ref = WRef(name(s),type(s),NodeKind(),FEMALE) -; val en = to-exp(optimize $ get-write-enable(table[name(s)])) as Expression -; if en == one : -; add{cons,_} $ Connect(info(s),ref,e) -; else : -; add{cons,_} $ Conditionally(info(s),en,Connect(info(s),ref,e),EmptyStmt()) -; (e:False) : false -; (s:DefAccessor) : -; add(decs,s) -; val t = type(s) -; val n = name(s) -; if gender(s) == FEMALE : -; val ref = WRef(n,t,WriteAccessorKind(),FEMALE) -; val e = to-exp(table[n]) -; match(e) : -; (e:Expression) : -; val en = (to-exp $ optimize $ get-write-enable(table[n])) as Expression -; if en == one : -; add{cons,_} $ Connect(info(s),ref,e) -; else : -; add{cons,_} $ Conditionally(info(s),en,Connect(info(s),ref,e),EmptyStmt()) -; (e:False) : false -; (s:WDefInstance) : -; add(decs,s) -; for f in fields(type(module(s)) as BundleType) map : -; if flip(f) == REVERSE : -; val n = to-symbol("~.~" % [name(s),name(f)]) ; only on inputs -; val x = to-symbol(split(to-string(n),'.')[0]) -; val f = to-symbol(split(to-string(n),'.')[1]) -; val ref = WRef(x,type(module(s)),InstanceKind(),FEMALE) -; 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|StopStmt|PrintfStmt) : false -; s -; -; defn expand-whens (m:Module) -> Module : -; match(m) : -; (m:ExModule) : m -; (m:InModule) : -; val assign = HashTable<Symbol,SymbolicValue>(symbol-hash) -; 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,simuls) -; for x in assign do : assign[key(x)] = optimize(value(x)) -; for x in resets do : resets[key(x)] = optimize(value(x)) -; -; ;val enables = get-enables(assign,kinds) -; ;for x in enables do : enables[key(x)] = optimize(value(x)) -; -; ;println-debug("====== Assigns ======") -; ;for x in assign do : println-debug(x) -; ;println-debug("====== Resets ======") -; ;for x in resets do : println-debug(x) -; -; val table = merge-resets(assign,resets,rsignals) -; ;println-debug("====== Table ======") -; ;for x in table do : println-debug(x) -; -; val decs = Vector<Stmt>() -; val cons = Vector<Stmt>() -; 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)) -; if value(x) != SVNul() : -; referenced?[key(x)] = true -; for x in decs do : -; mark-referenced(referenced?,x) -; val decs* = Vector<Stmt>() -; for x in decs do : -; if is-referenced?(referenced?,x) : add(decs*,x) -; -; InModule(info(m),name(m),ports(m),Begin(to-list(append(decs*,to-list(cons))))) -; -; val c* = Circuit(info(c),modules*, main(c)) where : -; val modules* = -; for m in modules(c) map : -; expand-whens(m) -; ;throw(PassExceptions(errors)) when not empty?(errors) -; c* - ;;================ Module Duplication ================== ; Duplicates modules so that no module is instantiated ; more than once. @@ -1869,8 +1529,8 @@ defn infer-widths (c:Circuit) -> Circuit : for x in h do : println-debug(x) println-debug("====================================") reduce-var-widths(Circuit(info(c),modules(c),main(c)),h) -; -; + + ;;================= Inline Instances ======================== ;; Inlines instances. Assumes module with same name as the ;; Circuit is the top level module @@ -1931,35 +1591,7 @@ defn infer-widths (c:Circuit) -> Circuit : ; (m:InModule) : h[name(m)] = m ; val top = (for m in modules(c) find : name(m) == main(c)) as InModule ; Circuit(info(c),list(InModule(info(top),name(top),ports(top),inline-inst(body(top)))),main(c)) -; -;;================= Bring to Real IR ======================== -;; Returns a new Circuit with only real IR nodes. -;public defstruct ToRealIR <: Pass -;public defmethod pass (b:ToRealIR) -> (Circuit -> Circuit) : to-real-ir -;public defmethod name (b:ToRealIR) -> String : "Real IR" -;public defmethod short-name (b:ToRealIR) -> String : "real-ir" -; -;defn to-real-ir (c:Circuit) : -; defn to-exp (e:Expression) : -; match(map(to-exp,e)) : -; (e:WRef) : Ref(name(e), type(e)) -; (e:WSubField) : Subfield(exp(e),name(e),type(e)) -; (e:WSubIndex) : error("Shouldn't be here") -; (e) : e -; defn to-stmt (s:Stmt) : -; match(map(to-exp,s)) : -; (e:DecFromIndexer) : error("Shouldn't be here") -; (e:DecToIndexer) : error("Shouldn't be here") -; (e) : map(to-stmt,e) -; -; Circuit(info(c),modules*, main(c)) where : -; val modules* = -; for m in modules(c) map : -; match(m) : -; (m:InModule) : InModule(info(m),name(m), ports(m), to-stmt(body(m))) -; (m:ExModule) : m -; -; + ;;================= Split Expressions ======================== ;; Intended to only work on low firrtl public defstruct SplitExp <: Pass @@ -1989,7 +1621,7 @@ defn split-exp (m:InModule) -> InModule : match(s) : (s:Begin) : map(split-exp-s,s) (s) : - add(v,map{split-exp-e{_,0},_} $ map(split-exp-s,s)) + add(v,s) s split-exp-s(body(m)) InModule(info(m),name(m),ports(m),Begin(to-list(v))) @@ -2001,76 +1633,7 @@ defn split-exp (c:Circuit) -> Circuit : (m:ExModule) : m Circuit(info(c),modules*,main(c)) -;defn split-exp (c:Circuit) : -; defn split-exp-s (s:Stmt,v:Vector<Stmt>,sh:HashTable<Symbol,Int>) -> False : -; defn split-exp-e (e:Expression,n:Symbol|False,info:FileInfo) -> Expression : -; match(e) : -; (e:DoPrim) : -; ;var all-same-type? = true -; ;for x in args(e) do : -; ; if type(x) != type(e) : all-same-type? = false -; ;all-same-type? = false -; ;if not all-same-type? : -; ;val n* = -; ; if n typeof False : firrtl-gensym(`F,sh) -; ; else : firrtl-gensym(symbol-join([n as Symbol temp-delin]),sh) -; val n* = -; if n typeof False : firrtl-gensym(`F,sh) -; else : firrtl-gensym(n as Symbol,sh) -; add(v,DefNode(info,n*,map(split-exp-e{_,n,info},e))) -; Ref(n*,type(e)) -; ;else : e -; (e) : map(split-exp-e{_,n,info},e) -; defn f (s:Stmt) -> False: split-exp-s(s,v,sh) -; match(s) : -; (s:Begin) : -; do(f,s) -; (s:Conditionally) : -; ;Predicate -; val pred* = map(split-exp-e{_,full-name(pred(s)),info(s)},pred(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*)) -; (s) : add(v,map(split-exp-e{_,false,info(s)},s)) -; false -; -; ;val start-time = current-time-us() -; Circuit{info(c),_,main(c)} $ -; for m in modules(c) map : -; match(m) : -; (m:InModule) : -; val v = Vector<Stmt>() -; val sh = get-sym-hash(m,keys(v-keywords)) -; ;val before = current-time-us() - start-time -; ;println-all(["Before split: " before]) -; split-exp-s(body(m),v,sh) -; ;val now = current-time-us() - start-time -; ;println-all(["After split: " now]) -; ;println-all(["Diff: " now - before]) -; InModule(info(m),name(m),ports(m),Begin(to-list(v))) -; (m:ExModule) : m -; + ;;================= Special Rename ======================== ;; Returns a new Circuit with only real IR nodes. ;public defstruct SpecialRename <: Pass : @@ -2373,7 +1936,7 @@ defn is-ground? (t:Type) -> True|False : match(t) : (t:UIntType|SIntType) : true (t) : false -defn mport? (ex:Expression) -> True|False : +defn data? (ex:Expression) -> True|False : match(kind(ex)) : (k:MemKind) : match(ex) : (ex:WRef|WSubIndex) : false @@ -2382,7 +1945,7 @@ defn mport? (ex:Expression) -> True|False : `wdata : true `rdata : true `data : true - `wmask : true + `mask : true else : false yes? and match(exp(ex)) : (e:WSubField) : @@ -2390,22 +1953,40 @@ defn mport? (ex:Expression) -> True|False : (e) : false (ex) : false (k) : false -defn substitute (e:Expression, s:Symbol) -> Expression : - match(e) : - (e:WRef) : WRef(merge(name(e),s,`_),UnknownType(),kind(e),gender(e)) - (e) : map(substitute{_,s},e) -defn collect (e:Expression, s:Symbol) -> Expression : - match(e) : - (e:WSubField) : - if mport?(exp(e)) : substitute(e,s) - else : collect(e,merge(name(e),s,`_)) - (e:WSubIndex) : collect(e,merge(to-symbol(value(e)),s,`_)) - (e) : e -defn lower-mem (e:Expression) -> Expression : - match(e) : - (e:WSubField) : collect(exp(e),name(e)) - (e:WSubIndex) : collect(exp(e),to-symbol(value(e))) - (e) : e + +defn expand-name (e:Expression) -> List<Symbol> : + val names = Vector<Symbol>() + defn expand-name-e (e:Expression) -> Expression : + match(map(expand-name-e,e)) : + (e:WRef) : add(names,name(e)) + (e:WSubField) : add(names,name(e)) + (e:WSubIndex) : add(names,to-symbol(value(e))) + e + expand-name-e(e) + to-list(names) + + +defn lower-other-mem (e:Expression, dt:Type) -> List<Expression> : + val names = expand-name(e) + if length(names) < 3 : error("Shouldn't be here") + for x in create-exps(names[0],dt) map : + var base = lowered-name(x) + for (x in names,i in 0 to false) do : + if i >= 3 : base = symbol-join([base `_ x]) + val m = WRef(base, UnknownType(), kind(e), UNKNOWN-GENDER) + val p = WSubField(m,to-symbol(names[1]),UnknownType(),UNKNOWN-GENDER) + WSubField(p,to-symbol(names[2]),UnknownType(),UNKNOWN-GENDER) + +defn lower-data-mem (e:Expression) -> Expression : + val names = expand-name(e) + if length(names) < 3 : error("Shouldn't be here") + else : + var base = names[0] + for (x in names,i in 0 to false) do : + if i >= 3 : base = symbol-join([base `_ x]) + val m = WRef(base, UnknownType(), kind(e), UNKNOWN-GENDER) + val p = WSubField(m,to-symbol(names[1]),UnknownType(),UNKNOWN-GENDER) + WSubField(p,to-symbol(names[2]),UnknownType(),UNKNOWN-GENDER) defn merge (a:Symbol,b:Symbol,x:Symbol) -> Symbol : symbol-join([a x b]) defn lowered-name (e:Expression) -> Symbol : @@ -2413,62 +1994,81 @@ defn lowered-name (e:Expression) -> Symbol : (e:WRef) : name(e) (e:WSubField) : merge(lowered-name(exp(e)),name(e),`_) (e:WSubIndex) : merge(lowered-name(exp(e)),to-symbol(value(e)),`_) -defn root-ref (e:Expression) -> Expression : +defn root-ref (e:Expression) -> WRef : match(e) : (e:WRef) : e (e:WSubField|WSubIndex) : root-ref(exp(e)) ;------------- Pass ------------------ -defn lower-types (s:Stmt) -> Stmt : - defn lower-types-e (e:Expression) -> Expression : - match(e) : - (e:WRef|UIntValue|SIntValue) : e - (e:WSubField) : - match(kind(e)) : - (k:InstanceKind) : - val temp = lowered-name(WRef(name(e),UnknownType(),InstanceKind(),MALE)) - WSubField(root-ref(e),temp,type(e),gender(e)) - (k:MemKind) : lower-mem(e) - (k) : WRef(lowered-name(e),type(e),kind(e),gender(e)) - (e:WSubIndex) : WRef(lowered-name(e),type(e),kind(e),gender(e)) - (e:DoPrim) : map(lower-types-e,e) - match(map(lower-types-e,s)) : - (s:DefWire|DefRegister|DefPoison) : - if is-ground?(type(s)) : s +defn lower-types (m:Module) -> Module : + val mdt = HashTable<Symbol,Type>(symbol-hash) + defn lower-types (s:Stmt) -> Stmt : + defn lower-mem (e:Expression) -> List<Expression> : + val names = expand-name(e) + if contains?([`data `mask `rdata `wdata `wmask],names[2]) : + list(lower-data-mem(e)) else : - val es = create-exps(name(s),type(s)) - Begin $ for e in es map : - defn replace-type (t:Type) -> Type : type(e) - defn replace-name (n:Symbol) -> Symbol : lowered-name(e) - map{replace-name,_} $ map(replace-type,s) - (s:WDefInstance) : - val fields* = for f in fields(type(s) as BundleType) map-append : - val es = create-exps(WRef(name(f),type(f),ExpKind(),flip(f) * MALE)) - for e in es map : - switch { _ == gender(e) } : - MALE : Field(lowered-name(e),DEFAULT,type(f)) - FEMALE : Field(lowered-name(e),REVERSE,type(f)) - WDefInstance(info(s),name(s),module(s),BundleType(fields*)) - (s:DefMemory) : - if is-ground?(data-type(s)) : s - else : - val es = create-exps(name(s),data-type(s)) - Begin $ for e in es map : - DefMemory(info(s),merge(name(s),lowered-name(e),`_),type(e),depth(s),write-latency(s),read-latency(s),readers(s),writers(s),readwriters(s)) - (s) : map(lower-types,s) + lower-other-mem(e,mdt[name(root-ref(e))]) + defn lower-types-e (e:Expression) -> Expression : + match(e) : + (e:WRef|UIntValue|SIntValue) : e + (e:WSubField) : + match(kind(e)) : + (k:InstanceKind) : + val temp = lowered-name(WRef(name(e),UnknownType(),InstanceKind(),MALE)) + WSubField(root-ref(e),temp,type(e),gender(e)) + (k:MemKind) : + if not gender(e) == FEMALE : + lower-mem(e)[0] + else : e + (k) : WRef(lowered-name(e),type(e),kind(e),gender(e)) + (e:WSubIndex) : WRef(lowered-name(e),type(e),kind(e),gender(e)) + (e:DoPrim) : map(lower-types-e,e) + match(map(lower-types-e,s)) : + (s:DefWire|DefRegister|DefPoison) : + if is-ground?(type(s)) : s + else : + val es = create-exps(name(s),type(s)) + Begin $ for e in es map : + defn replace-type (t:Type) -> Type : type(e) + defn replace-name (n:Symbol) -> Symbol : lowered-name(e) + map{replace-name,_} $ map(replace-type,s) + (s:WDefInstance) : + val fields* = for f in fields(type(s) as BundleType) map-append : + val es = create-exps(WRef(name(f),type(f),ExpKind(),flip(f) * MALE)) + for e in es map : + switch { _ == gender(e) } : + MALE : Field(lowered-name(e),DEFAULT,type(f)) + FEMALE : Field(lowered-name(e),REVERSE,type(f)) + WDefInstance(info(s),name(s),module(s),BundleType(fields*)) + (s:DefMemory) : + mdt[name(s)] = data-type(s) + if is-ground?(data-type(s)) : s + else : + val es = create-exps(name(s),data-type(s)) + Begin $ for e in es map : + DefMemory(info(s),lowered-name(e),type(e),depth(s),write-latency(s),read-latency(s),readers(s),writers(s),readwriters(s)) + (s:Connect) : + if kind(loc(s)) typeof MemKind : + val es = lower-mem(loc(s)) + Begin $ for e in es map : + Connect(info(s),e,exp(s)) + else : s + (s) : map(lower-types,s) + + val ports* = + for p in ports(m) map-append : + val es = create-exps(WRef(name(p),type(p),PortKind(),to-gender(direction(p)))) + for e in es map : + Port(info(p),lowered-name(e),to-dir(gender(e)),type(e)) + match(m) : + (m:ExModule) : ExModule(info(m),name(m),ports*) + (m:InModule) : InModule(info(m),name(m),ports*,lower-types(body(m))) defn lower-types (c:Circuit) -> Circuit : Circuit{info(c),_,main(c)} $ - for m in modules(c) map : - val ports* = - for p in ports(m) map-append : - val es = create-exps(WRef(name(p),type(p),PortKind(),to-gender(direction(p)))) - for e in es map : - Port(info(p),lowered-name(e),to-dir(gender(e)),type(e)) - match(m) : - (m:ExModule) : ExModule(info(m),name(m),ports*) - (m:InModule) : InModule(info(m),name(m),ports*,lower-types(body(m))) + for m in modules(c) map : lower-types(m) ;============ VERILOG ============== @@ -2483,6 +2083,7 @@ defstruct VIndent defstruct VRandom val tab = VIndent() val ran = VRandom() +defn wref (n:Symbol,t:Type) : WRef(n,t,ExpKind(),UNKNOWN-GENDER) defn escape (s:String) -> String : val s* = Vector<String>() add(s*,"\"");" @@ -2523,10 +2124,10 @@ defn emit (x:?, top:Int) : (e:Expression) : turn-off-debug(false) match(e) : - (e:DoPrim) : op-print(e) + (e:DoPrim) : emit(op-stream(e), top + 1) (e:WRef) : print(e) (e:WSubField) : print(lowered-name(e)) - (e:WSubAccess) : print(e) + (e:WSubAccess) : print-all([lowered-name(exp(e)) "[" lowered-name(index(e)) "]"]) (e:WSubIndex) : print(e) (e:UIntValue|SIntValue) : v-print(e) turn-on-debug(false) @@ -2534,8 +2135,18 @@ defn emit (x:?, top:Int) : match(t) : (t:UIntType|SIntType) : val w = long!(t) - to-long(1) - if w >= to-long(0) : print-all(["[" w ":0]"]) - else : "" + if w > to-long(0) : print-all(["[" w ":0]"]) + else : print("");" + (t:ClockType) : print("");" + (t:VectorType) : + emit(type(t), top + 1) + print-all(["[" size(t) - 1 ":0]"]) + (t) : println(t) + + (p:Direction) : + switch {_ == p} : + INPUT : print("input") + OUTPUT : print("output") (s:Symbol) : print(s) (i:Int) : print(i) (i:Long) : print(i) @@ -2554,7 +2165,7 @@ defn v-print (e:UIntValue|SIntValue) : print $ string-join $ match(e) : (e:UIntValue) : [long!(type(e)) "'" out] (e:SIntValue) : [long!(type(e)) "'s" out] -defn op-print (doprim:DoPrim) : +defn op-stream (doprim:DoPrim) -> Streamable : defn cast-if (e:Expression) -> ? : val signed? = for x in args(doprim) any? : type(x) typeof SIntType if not signed? : e @@ -2571,7 +2182,7 @@ defn op-print (doprim:DoPrim) : defn c0 () -> Int : consts(doprim)[0] defn c1 () -> Int : consts(doprim)[1] - print $ string-join $ switch {_ == op(doprim)} : + switch {_ == op(doprim)} : ADD-OP : [cast-if(a0()) " + " cast-if(a1())] SUB-OP : [cast-if(a0()) " - " cast-if(a1())] MUL-OP : [cast-if(a0()) " * " cast-if(a1()) ] @@ -2597,9 +2208,9 @@ defn op-print (doprim:DoPrim) : else : match(type(doprim)) : (t:SIntType) : ["{{" diff "{" a0() "[" w - to-long(1) "]}}, " a0() " }"] (t) : ["{{" diff "'d0 }, " a0() " }"] - AS-UINT-OP : ["$unsigned(" emit(a0()) ")"] - AS-SINT-OP : ["$signed(" emit(a0()) ")"] - DYN-SHIFT-LEFT-OP : [cast(a0()) " << " emit(a1())] + AS-UINT-OP : ["$unsigned(" a0() ")"] + AS-SINT-OP : ["$signed(" a0() ")"] + DYN-SHIFT-LEFT-OP : [cast(a0()) " << " a1()] DYN-SHIFT-RIGHT-OP : match(type(doprim)) : (t:SIntType) : [cast(a0()) " >>> " a1()] @@ -2648,16 +2259,17 @@ defn emit-verilog (m:InModule) -> Module : (s) : map(build-netlist,s) s + val portdefs = Vector<Streamable>() 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 ";"]) + add(declares,[b " " t " " n ";"]) defn assign (e:Expression,value:Expression) : add(assigns,["assign " e " = " value]) - defn update-reset (e:Expression,clk:Expression,reset?:Expression,init:Expression) : + defn update-and-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"]) @@ -2665,18 +2277,21 @@ defn emit-verilog (m:InModule) -> Module : 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) : + defn update (e:Expression,value: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"]) + if en == one : + add(at-clock[clk],[e " <= " value]) + else : + add(at-clock[clk],["if(" en ") begin"]) + add(at-clock[clk],[tab e " <= " value]) + add(at-clock[clk],["end"]) defn initialize (e:Expression) : add(initials,[e " = " rand-string(type(e))]) - defn initialize-mem (e:Expression,i:Int) : + defn initialize-mem (n:Symbol,i:Int,t:Type) : add(initials,["for (initvar = 0; initvar < " i "; initvar = initvar+1)"]) val index = WRef(`initvar,UnknownType(),ExpKind(),UNKNOWN-GENDER) - add(initials,[tab WSubAccess(e,index,UnknownType(),FEMALE), " = " rand-string(type(e))]) + add(initials,[tab WSubAccess(wref(n,t),index,UnknownType(),FEMALE), " = " rand-string(t)]) defn instantiate (n:Symbol,m:Symbol,es:List<Expression>) : add(declares,[m " " n " ("]) for (e in es,i in 1 to false) do : @@ -2685,6 +2300,7 @@ defn emit-verilog (m:InModule) -> Module : else : add(declares,s) add(declares,[");"]) for e in es do : + declare(`wire,lowered-name(e),type(e)) 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) : @@ -2700,99 +2316,168 @@ defn emit-verilog (m:InModule) -> Module : defn printf (str:String,args:List<Expression>) -> Streamable : val str* = join(List(escape(str),args),",") ["$fdisplay(32/'h80000002," str* ");"] - defn delay (e:Expression, n:Int) -> Expression : + defn delay (e:Expression, n:Int, clk:Expression) -> Expression : var e* = e for i in 0 to n do : - val name = firrtl-gensym(lowered-name(e),namehash) + val name = firrtl-gensym(`GEN,namehash) declare(`reg,name,type(e)) val e** = WRef(name,type(e),ExpKind(),UNKNOWN-GENDER) - assign(e**,e*) + update(e**,e*,clk,one) e* = e** e* - + defn build-ports () : + for (p in ports(m),i in 0 to false) do : + var end = ",\n" + if length(ports(m)) - 1 == i : + end = "\n);\n" + switch {_ == direction(p)} : + INPUT : + add(portdefs,[direction(p) " " type(p) " " name(p) ]) + OUTPUT : + add(portdefs,[direction(p) " " type(p) " " name(p) ]) + val e* = WRef(name(p),type(p),PortKind(),FEMALE) + assign(e*,netlist[e*]) + if length(ports(m)) == 0 : print(");\n") 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 : - declare(`wire,lowered-name(e),type(e)) - assign(e,netlist[e]) + declare(`wire,name(s),type(s)) + val e = wref(name(s),type(s)) + assign(e,netlist[e]) (s:DefRegister) : - val es = create-exps(WRef(name(s),type(s),RegKind(),BI-GENDER)) - for e in es do : - declare(`reg,lowered-name(e),type(e)) - update-reset(e,clock(s),reset(s),init(s)) - initialize(e) + declare(`reg,name(s),type(s)) + val e = wref(name(s),type(s)) + update-and-reset(e,clock(s),reset(s),init(s)) + initialize(e) (s:DefPoison) : - val es = create-exps(WRef(name(s),type(s),PoisonKind(),MALE)) - for e in es do : - declare(`reg,lowered-name(e),type(e)) - initialize(e) + declare(`reg,name(s),type(s)) + val e = wref(name(s),type(s)) + initialize(e) (s:DefNode) : declare(`wire,name(s),type(value(s))) assign(WRef(name(s),type(value(s)),NodeKind(),MALE),value(s)) - (s:Conditionally) : - match(conseq(s)) : - (c:Stop) : simulate(clk(c),pred(s),stop(ret(c))) - (c:Print) : simulate(clk(c),pred(s),printf(string(c),args(c))) - (s:Stop) : simulate(clk(s),one,stop(ret(s))) - (s:Print) : simulate(clk(s),one,printf(string(s),args(s))) + (s:Stop) : simulate(clk(s),en(s),stop(ret(s))) + (s:Print) : simulate(clk(s),en(s),printf(string(s),args(s))) (s:WDefInstance) : - val es = create-exps(WRef(name(s),type(s),InstanceKind(),BI-GENDER)) + val es = create-exps(WRef(name(s),type(s),InstanceKind(),MALE)) instantiate(name(s),module(s),es) - (s:DefMemory) : ;TODO expand bundle in declaration, lots of thinking todo + (s:DefMemory) : + val mem = WRef(name(s),get-type(s),MemKind(append-all([readers(s) writers(s) readwriters(s)])),UNKNOWN-GENDER) + defn mem-exp (p:Symbol,f:Symbol) : + val t1 = field-type(type(mem),p) + val t2 = field-type(t1,f) + WSubField{_,f,t2,UNKNOWN-GENDER} $ + WSubField{_,p,t1,UNKNOWN-GENDER} $ + mem + declare(`reg,name(s),VectorType(data-type(s),depth(s))) - val mem = WRef(name(s),get-type(s),MemKind(append-all([readers(s) writers(s) readwriters(s)])),BI-GENDER) - initialize-mem(mem,depth(s)) - + initialize-mem(name(s),depth(s),data-type(s)) for r in readers(s) do : - val port = HashTable<Symbol,Expression>(symbol-hash) - for f in fields(get-type(s) as BundleType) do : - port[name(f)] = WSubField(mem,name(f),type(f),UNKNOWN-GENDER) - val addr* = delay(port[`addr],read-latency(s)) - val en* = delay(port[`en],read-latency(s)) - val e = port[`rdata] - netlist[e] = WSubAccess(mem,addr*,type(port[`rdata]),FEMALE) - update(e,port[`clk],en*) + val data = mem-exp(r,`data) + val addr = mem-exp(r,`addr) + val en = mem-exp(r,`en) + val clk = mem-exp(r,`clk) + + declare(`wire,lowered-name(data),type(data)) + declare(`wire,lowered-name(addr),type(addr)) + declare(`wire,lowered-name(en),type(en)) + declare(`wire,lowered-name(clk),type(clk)) + + ; Read port + assign(addr,netlist[addr]) ;Connects value to m.r.addr + assign(en,netlist[en]) ;Connects value to m.r.en + assign(clk,netlist[clk]) ;Connects value to m.r.clk + val addr* = delay(addr,read-latency(s),clk) + val en* = delay(en,read-latency(s),clk) + val mem-port = WSubAccess(mem,addr*,UnknownType(),UNKNOWN-GENDER) + update(data,mem-port,clk,en*) ; m.r.data <= m[addr*] for w in writers(s) do : - val port = HashTable<Symbol,Expression>(symbol-hash) - for f in fields(get-type(s) as BundleType) do : - port[name(f)] = WSubField(mem,name(f),type(f),UNKNOWN-GENDER) - val addr* = delay(port[`addr],write-latency(s) - 1) - val en* = delay(port[`en],write-latency(s) - 1) - val wmask* = delay(port[`wmask],write-latency(s) - 1) - val e = WSubAccess(port[`wdata],addr*,type(port[`wdata]),FEMALE) - update(e,port[`clk],AND(en*,wmask*)) + val data = mem-exp(w,`data) + val addr = mem-exp(w,`addr) + val mask = mem-exp(w,`mask) + val en = mem-exp(w,`en) + val clk = mem-exp(w,`clk) + + declare(`wire,lowered-name(data),type(data)) + declare(`wire,lowered-name(addr),type(addr)) + declare(`wire,lowered-name(mask),type(mask)) + declare(`wire,lowered-name(en),type(en)) + declare(`wire,lowered-name(clk),type(clk)) + + ; Write port + assign(data,netlist[data]) + assign(addr,netlist[addr]) + assign(mask,netlist[mask]) + assign(en,netlist[en]) + assign(clk,netlist[clk]) + + val data* = delay(data,write-latency(s) - 1,clk) + val addr* = delay(addr,write-latency(s) - 1,clk) + val mask* = delay(mask,write-latency(s) - 1,clk) + val en* = delay(en,write-latency(s) - 1,clk) + val mem-port = WSubAccess(mem,addr*,UnknownType(),UNKNOWN-GENDER) + update(mem-port,data*,clk,AND(en*,mask*)) for rw in readwriters(s) do : - val port = HashTable<Symbol,Expression>(symbol-hash) - for f in fields(get-type(s) as BundleType) do : - port[name(f)] = WSubField(mem,name(f),type(f),UNKNOWN-GENDER) - val raddr* = delay(port[`raddr],read-latency(s)) - val ren* = delay(port[`ren],read-latency(s)) - val re = port[`rdata] - netlist[re] = WSubAccess(mem,raddr*,type(port[`rdata]),FEMALE) - update(re,port[`clk],ren*) - - val waddr* = delay(port[`waddr],write-latency(s) - 1) - val wen* = delay(port[`wen],write-latency(s) - 1) - val wmask* = delay(port[`wmask],write-latency(s) - 1) - val we = WSubAccess(port[`wdata],waddr*,type(port[`wdata]),FEMALE) - update(we,port[`clk],AND(wen*,wmask*)) + val rdata = mem-exp(rw,`rdata) + val raddr = mem-exp(rw,`raddr) + val ren = mem-exp(rw,`ren) + val wdata = mem-exp(rw,`wdata) + val waddr = mem-exp(rw,`waddr) + val wmask = mem-exp(rw,`wmask) + val wen = mem-exp(rw,`wen) + val clk = mem-exp(rw,`clk) + + declare(`wire,lowered-name(rdata),type(rdata)) + declare(`wire,lowered-name(raddr),type(raddr)) + declare(`wire,lowered-name(ren),type(ren)) + declare(`wire,lowered-name(wdata),type(wdata)) + declare(`wire,lowered-name(waddr),type(waddr)) + declare(`wire,lowered-name(wmask),type(wmask)) + declare(`wire,lowered-name(wen),type(wen)) + declare(`wire,lowered-name(clk),type(clk)) + + ; Both + assign(clk,netlist[clk]) + + ; Read + assign(raddr,netlist[raddr]) + assign(ren,netlist[ren]) + val raddr* = delay(raddr,read-latency(s),clk) + val ren* = delay(ren,read-latency(s),clk) + val rmem-port = WSubAccess(mem,raddr*,UnknownType(),UNKNOWN-GENDER) + update(rdata,rmem-port,clk,ren*) + + ; Write + assign(wdata,netlist[wdata]) + assign(waddr,netlist[waddr]) + assign(wmask,netlist[wmask]) + assign(wen,netlist[wen]) + + val wdata* = delay(wdata,write-latency(s) - 1,clk) + val waddr* = delay(waddr,write-latency(s) - 1,clk) + val wmask* = delay(wmask,write-latency(s) - 1,clk) + val wen* = delay(wen,write-latency(s) - 1,clk) + val wmem-port = WSubAccess(mem,waddr*,UnknownType(),UNKNOWN-GENDER) + update(wmem-port,wdata*,clk,AND(wen*,wmask*)) (s:Begin) : map(build-streams,s) s defn emit-streams () : emit(["module " name(m) "("]) + if !empty?(portdefs) : + for (x in portdefs, i in 0 to false) do : + if i != length(portdefs) : emit([tab x ","]) + else : emit([tab x]) + emit([");"]) + if !empty?(declares) : - for x in declares do : - emit(x) + for x in declares do : emit([tab x]) if !empty?(assigns) : - for x in assigns do : - emit(x) + for x in assigns do : emit([tab x]) if !empty?(initials) : emit(["`ifndef SYNTHESIS"]) @@ -2806,13 +2491,15 @@ defn emit-verilog (m:InModule) -> Module : for clk-stream in at-clock do : if !empty?(value(clk-stream)) : - emit(["always @(posedge " key(clk-stream) " ) begin"]) + emit([tab "always @(posedge " key(clk-stream) " ) begin"]) for x in value(clk-stream) do : - emit([tab x]) - emit(["end"]) + emit([tab tab x]) + emit([tab "end"]) + emit(["endmodule"]) build-netlist(body(m)) + build-ports() build-streams(body(m)) emit-streams() m |
