aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile14
-rw-r--r--TODO28
-rw-r--r--notes/notes.03.16.15.txt24
-rw-r--r--notes/notes.03.18.15.txt52
-rw-r--r--notes/stanza-cheatsheet.txt8
-rw-r--r--src/main/stanza/passes.stanza326
-rw-r--r--test/passes/expand-accessors/accessor-mem.fir12
-rw-r--r--test/passes/expand-accessors/accessor-vec.fir20
-rw-r--r--test/passes/expand-accessors/one-when.fir20
-rw-r--r--test/passes/expand-accessors/two-when.fir57
-rw-r--r--test/passes/expand-whens/one-when.fir15
-rw-r--r--test/passes/expand-whens/two-when.fir28
-rw-r--r--test/passes/lower-to-ground/accessor.fir33
-rw-r--r--test/passes/lower-to-ground/bundle-vecs.fir31
-rw-r--r--test/passes/lower-to-ground/bundle.fir53
-rw-r--r--test/passes/lower-to-ground/nested-vec.fir34
16 files changed, 564 insertions, 191 deletions
diff --git a/Makefile b/Makefile
index 4259b7ec..543ee75c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,14 @@
# Installs stanza into /usr/local/bin
# TODO Talk to Patrick to fill this in
+
root_dir ?= $(PWD)
test_dir ?= $(root_dir)/test
firrtl_dir ?= $(root_dir)/src/main/stanza
-all: build check
+all-noise:
+ ${MAKE} all || ${MAKE} fail
+
+all: build check done
install:
cd src/lib && unzip stanzam.zip
@@ -22,3 +26,11 @@ check:
clean:
rm -f $(test_dir)/*/*/*.out
rm -f $(test_dir)/*/*.out
+
+done:
+ say "done"
+
+fail:
+ say "fail"
+
+.PHONY: all install build-deploy build check clean fail succeed
diff --git a/TODO b/TODO
index ee4332da..7ae833a5 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,16 @@
TODO
- Figure out how widths propogate for all updated primops
- Remove letrec. Add to expressions: Register(input,en), ReadPort(mem,index,enable), WritePort(mem,index,enable)
- Add bit-reduce-and etc to primops
- Write pass to rename identifiers (alpha-transform)
- Add partial bulk connect
+ Figure out how widths propogate for all updated primops (Adam)
+ Remove letrec. Add to expressions: Register(input,en), ReadPort(mem,index,enable), WritePort(mem,index,enable) (Patrick)
+ Add bit-reduce-and etc to primops (Jonathan)
+ Write pass to rename identifiers (alpha-transform) (Adam)
+ Add partial bulk connect (Scott, Stephen)
+ Add FIFOs to the IR (Palmer)
+ Registers/Memories only have data and enable fields, which can be written/read from. These are set by the front-end. This will probably have to wait (Palmer)
+ Multi-streams for print statements (Jack)
+ Consider def female node. (Patrick)
+ Think about supporting memories (Scott)
+
Update spec
add new field for sequential or combinational
add assertions
@@ -25,3 +31,15 @@ Tests:
Error if declare anything other than module in circuit
Error if incorrectly assign stuff, like use = instead of :=
Error: Node not parsed for stmts
+
+Male node:
+defnode n = e
+==>
+wire n
+n := e
+
+Female node:
+defnode n = e
+==>
+wire n
+e := n
diff --git a/notes/notes.03.16.15.txt b/notes/notes.03.16.15.txt
new file mode 100644
index 00000000..d017a015
--- /dev/null
+++ b/notes/notes.03.16.15.txt
@@ -0,0 +1,24 @@
+Why did we remove the letrec?
+
+Why was it there? A way to express all the enables and input values without the need for the when statement, and also allows you to analyze the graph without worrying about last connect semantics, and allows you to analyze the graph without worrying about compound datatypes, known widths, known genders.
+
+Now we have a way to do it without this. We introduced the Register expression and read/writeport expressions, which enable you to declare them as a function of their inputs and enables. We expand all datatypes into their ground types. Lastly, we express the graph such that for every wire declaration, we ensure that there is only ever one connect to each wire.
+
+lowered form and higher form
+
+
+Add FIFOs to the IR - major semantics work.
+Write a pass expecting to be used on high firrtl, (in current firrtl it could break because we add new constructs) but is used on low firrtl.
+
+Front-end will write to special r.enable value that it will assign 1 to whenever r is written (or if a mem, read).
+
+Registers now have 2 fields, .data and .enable. Declare:
+reg r : { pckg : {enable} , valid}
+r.data := blah ; which has type {pckg : {enable, valid}}
+r.enable := UInt(1)
+bleh := r.data
+; no enable required
+
+Memories require enables on both reads and writes.
+
+
diff --git a/notes/notes.03.18.15.txt b/notes/notes.03.18.15.txt
new file mode 100644
index 00000000..7fdb1c3b
--- /dev/null
+++ b/notes/notes.03.18.15.txt
@@ -0,0 +1,52 @@
+WHEN EXPANSION
+
+Goal:
+reg r
+wire w
+when p1 :
+ w := b
+ r.init := x
+ when p2 :
+ w := c
+ r := d
+r := e
+
+==>
+
+1. Remove last connect semantics
+2. Remove conditional blocks
+3. Eliminate concept of scoping
+
+Exp | Value
+--------------
+r | e
+w | mux(p1,mux(p2,c,b),null)
+r.init | mux(p1,x,null)
+
+==>
+
+Symbolic Value - what can appear in value column
+sv = e
+ | null
+ | svmux(e,sv1,sv2)
+
+State:
+{
+ r => void
+ r.init => p1
+ w => svmux(e,_,_)
+}
+
+==>
+
+Build two tables, one mapping symbols to symbolic values, and another mapping symbols to declared types
+
+if w is a wire:
+merge {r=>x, w=>y} with {r=>x} under p : {r=>svmux(p,x,x), w=>y}
+
+if s is a reg:
+merge {r=>x,s=>y} with {r=>x} under p : {r=>svmux(p,x,x), s=>svmux(p,y,void)}
+
+
+
+
diff --git a/notes/stanza-cheatsheet.txt b/notes/stanza-cheatsheet.txt
index 09342997..215fafbd 100644
--- a/notes/stanza-cheatsheet.txt
+++ b/notes/stanza-cheatsheet.txt
@@ -55,3 +55,11 @@ list(a) -> a
list(a,b) -> a,b
println-all([a b c])
+
+to extract values (with correct type-age) from a tuple:
+val x = [1 "hi"]
+val [a,b] = x
+a typeof Int
+b typeof String
+
+to combine symbols: symbol-join
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza
index ece7287e..fe048cfb 100644
--- a/src/main/stanza/passes.stanza
+++ b/src/main/stanza/passes.stanza
@@ -56,6 +56,17 @@ defstruct WDefAccessor <: Stmt :
;================ WORKING IR UTILS =========================
+defn plus (g1:Gender,g2:Gender) -> Gender :
+ switch fn ([x,y]) : g1 == x and g2 == y :
+ [FEMALE,MALE] : UNKNOWN-GENDER
+ [MALE,FEMALE] : UNKNOWN-GENDER
+ [MALE,MALE] : MALE
+ [FEMALE,FEMALE] : FEMALE
+ [BI-GENDER,MALE] : MALE
+ [BI-GENDER,FEMALE] : FEMALE
+ [MALE,BI-GENDER] : MALE
+ [FEMALE,BI-GENDER] : FEMALE
+
defn swap (g:Gender) -> Gender :
switch {_ == g} :
UNKNOWN-GENDER : UNKNOWN-GENDER
@@ -63,15 +74,32 @@ defn swap (g:Gender) -> Gender :
FEMALE : MALE
BI-GENDER : BI-GENDER
-defn times (g:Gender,flip:Flip) -> Gender :
+defn swap (f:Flip) -> Flip :
+ switch {_ == f} :
+ DEFAULT : REVERSE
+ REVERSE : DEFAULT
+
+defn swap (d:Direction) -> Direction :
+ switch {_ == d} :
+ OUTPUT : INPUT
+ INPUT : OUTPUT
+
+defn times (flip:Flip,d:Direction) -> Direction : flip * d
+defn times (d:Direction,flip:Flip) -> Direction :
switch {_ == flip} :
- DEFAULT : g
- REVERSE : swap(g)
+ DEFAULT : d
+ REVERSE : swap(d)
+defn times (g:Gender,flip:Flip) -> Gender : flip * g
defn times (flip:Flip,g:Gender) -> Gender :
switch {_ == flip} :
DEFAULT : g
REVERSE : swap(g)
+
+defn times (f1:Flip,f2:Flip) -> Flip :
+ switch {_ == f2} :
+ DEFAULT : f1
+ REVERSE : swap(f1)
defn to-field (p:Port) -> Field :
Field(name(p),REVERSE,type(p))
@@ -79,6 +107,11 @@ defn to-field (p:Port) -> Field :
else if direction(p) == INPUT : Field(name(p),DEFAULT,type(p))
else : error("Shouldn't be here")
+defn to-dir (g:Gender) -> Direction :
+ switch {_ == g} :
+ MALE : INPUT
+ FEMALE : OUTPUT
+
defmulti gender (e:Expression) -> Gender
defmethod gender (e:Expression) :
MALE ; TODO, why was this OUTPUT before? It makes sense as male, not female
@@ -91,6 +124,10 @@ defmethod print (o:OutputStream, g:Gender) :
BI-GENDER : "bi"
UNKNOWN-GENDER: "unknown"
+defmethod type (exp:UIntValue) -> Type : UIntType(width(exp))
+defmethod type (exp:SIntValue) -> Type : SIntType(width(exp))
+defmethod type (exp:Null) -> Type : UnknownType()
+
;============== DEBUG STUFF =============================
public var PRINT-TYPES : True|False = false
public var PRINT-KINDS : True|False = false
@@ -580,8 +617,7 @@ defn infer-types (c:Circuit) -> Circuit :
Circuit{ _, main(c) } $
for m in modules(c) map :
infer-types(m,l)
-
-
+
;============= RESOLVE ACCESSOR GENDER ============================
; To ensure a proper circuit, we must ensure that assignments
; only work on expressions that can be assigned to. Similarly,
@@ -696,16 +732,12 @@ defn resolve-genders (c:Circuit) :
resolve-genders(m,c)
;;============== EXPAND ACCESSORS ================================
-; This pass expands accessors into either ReadPort/WritePort if it
-; accesses a memory, or a ManyConnect/ConnectMany otherwise.
-; If accessing a memory, female accessors turn into WritePorts and
-; male accessors turn into ReadPorts. The enable signals are
-; calculated by ANDing all predicates of all parent nested whens
-; at the sight of the accessor declaration
-; If not accessing a memory, all elements of the vector are
+; This pass expands non-memory accessors into ConnectToIndexed or
+; ConnectFromIndexed. All elements of the vector are
; explicitly written out, then indexed. Depending on the gender
; of the accessor, it is transformed into ConnectToIndexed (male) or
; ConnectFromIndexed (female)
+; Eg:
defstruct ConnectToIndexed <: Stmt :
index: Expression
@@ -728,72 +760,37 @@ defmethod map (f: Expression -> Expression, c:ConnectFromIndexed) :
ConnectFromIndexed(f(index(c)), f(loc(c)), map(f, exps(c)))
defn expand-vector (e:Expression) -> List<Expression> :
- match(e) :
- (e:WRef) :
- match(type(e)) :
- (t:VectorType) :
- var l = list()
- for i in 0 to size(t) do :
- l = List(WIndex(e,i,type(t),gender(e)),l)
- l
- (t) : error("Shouldn't be here, TODO")
- (e) : error("Shouldn't be here, TODO")
-
-defn contained-type (e:Expression) -> Type :
- match(e) :
- (e:WRef) :
- match(type(e)) :
- (t:VectorType) : type(t)
- (t) : error("Shouldn't be here, TODO")
- (t) : error("Shouldn't be here, TODO")
-
-defn and-all (l:List<Expression>) -> Expression :
- if length(l) == 0 : UIntValue(1,IntWidth(1))
- else : DoPrim(BIT-AND-OP,list(l[0],and-all(tail(l))),list(),UIntType(IntWidth(1)))
-
-defn expand-stmt (s:Stmt,preds:List<Expression>) -> Stmt :
+ val t = type(e) as VectorType
+ for i in 0 to size(t) map-append :
+ list(WIndex(e,i,type(t),gender(e as ?))) ;always be WRef|WSubfield|WIndex
+
+defn expand-stmt (s:Stmt) -> Stmt :
match(s) :
(s:WDefAccessor) :
println-all(["Matched WDefAcc with " name(s)])
val mem? = match(source(s)) :
(e:WRef) : kind(e) typeof MemKind
(e) : false
- if mem? :
- val enable = and-all(preds)
- val value-type = contained-type(source(s))
- val wire = DefWire(name(s),value-type)
- switch {gender(s) == _} :
- MALE :
- val read = ReadPort(source(s),index(s),value-type,enable)
- val connect = Connect(WRef(name(s),value-type,NodeKind(),FEMALE),read)
- Begin(list(wire,connect))
- FEMALE:
- val write = WritePort(source(s),index(s),value-type,enable)
- val connect = Connect(write,WRef(name(s),value-type,NodeKind(),MALE))
- Begin(list(wire,connect))
+ if mem? : s
else :
- val value-type = contained-type(source(s))
- val wire = DefWire(name(s),value-type)
+ val vtype = type(type(source(s)) as VectorType)
+ val wire = DefWire(name(s),vtype)
switch {gender(s) == _} :
- MALE : Begin(list(wire,connectmany)) where :
- val exps = expand-vector(source(s))
- val connectmany = ConnectFromIndexed(index(s),WRef(name(s),value-type,NodeKind(),FEMALE),exps)
- FEMALE: Begin(list(wire,manyconnect)) where :
- val locs = expand-vector(source(s))
- val manyconnect = ConnectToIndexed(index(s),locs,WRef(name(s),value-type,NodeKind(),MALE))
- (s:Conditionally) :
- val conseq* = expand-stmt(conseq(s),List(pred(s),preds))
- val alt-pred = DoPrim(EQUAL-UU-OP,list(UIntValue(0,IntWidth(1)),pred(s)),list(),UIntType(IntWidth(1)))
- val alt* = expand-stmt(alt(s),List(alt-pred,preds))
- Conditionally(pred(s),conseq*,alt*)
- (s) : map(expand-stmt{_,preds},s)
+ MALE : Begin{list(wire,_)} $ ConnectFromIndexed(
+ index(s),
+ WRef(name(wire),vtype,NodeKind(),FEMALE),
+ expand-vector(source(s)))
+ FEMALE: Begin{list(wire,_)} $ ConnectToIndexed(
+ index(s),
+ expand-vector(source(s)),
+ WRef(name(wire),vtype,NodeKind(),MALE))
+ (s) : map(expand-stmt,s)
defn expand-accessors (c:Circuit) :
Circuit(modules*, main(c)) where :
val modules* =
for m in modules(c) map :
- Module(name(m),ports(m),expand-stmt(body(m),list()))
-
+ Module(name(m),ports(m),expand-stmt(body(m)))
;;=============== LOWERING TO GROUND TYPES =============================
; All non-ground (elevated) types (Vectors, Bundles) are expanded out to
@@ -802,37 +799,174 @@ defn expand-accessors (c:Circuit) :
; to the lowered ground expression names and genders. This allows
; references to be resolved.
-;defn build-table (t:Type,f:Flip,l:List<KeyValue<Symbol,Flip>>) -> List<KeyValue<Symbol,Flip>> :
-; match (t) :
-; (t:BundleType) :
-; for field in fields(t) map :
-; match(type(field)) :
-; (t:BundleType) : append(l,lower-type(t,f * flip(field),l))
-; (t:VectorType) : append(l,lower-type(t,f * flip(field),l))
-; (t) : List(KeyValue(gensym(),f * flip(field)))
-; (t:VectorType) :
-; match(type(f)) :
-; (t:BundleType) : append(l,lower-type(t,f,l))
-; (t:VectorType) : append(l,lower-type(t,f,l))
-; (t) :
-; for i in size(t) map :
-; List(KeyValue(gensym(),f))
-; (t) : l
-;
-;defn build-table (ports:List<Port>) -> HashMap<Symbol,List<[Symbol,Gender]>> :
-; for p in ports do :
-; match(type(p)) :
-; (t:BundleType) :
-;
-;defn lower-module (m:Module,c:Circuit) -> Module :
-;
-;
-;defn lower-to-ground (c:Circuit) :
-; Circuit(modules*, main(c)) where :
-; val modules* =
-; for m in modules(c) map :
-; lower-module(m,c)
+defn num-elems (t:Type) -> Int :
+ match(t) :
+ (t:BundleType) :
+ var sum = 0
+ for f in fields(t) do :
+ sum = sum + num-elems(type(f))
+ sum
+ (t:VectorType) : size(t) * num-elems(type(t))
+ (t) : 1
+
+defn index-of-elem (t:BundleType, s:Symbol) -> Int :
+ var sum = 0
+ label<Int> ret :
+ for f in fields(t) do :
+ if s == name(f) : ret(sum)
+ else : sum = sum + num-elems(type(f))
+ error("Shouldn't be here")
+
+defn lower-ports (m:Module, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) -> List<Port> :
+ val entries = table[name(m)]
+ val directions =
+ for p in ports(m) map-append :
+ to-list(for i in 0 to num-elems(type(p)) stream : direction(p))
+ for (kv in entries, d in directions) map :
+ val exp = key(kv) as WRef
+ val dir* = d * value(kv)
+ Port(name(exp),dir*,type(exp))
+
+defn lower (body:Stmt, table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) -> Stmt :
+ defn lower-stmt (s:Stmt) -> Stmt :
+ defn add-to-table (y:Symbol,k:KeyValue<Expression,Flip>,ctable:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) :
+ val contains? = for x in ctable any? :
+ key(x) == y
+ if contains? : ctable[y] = append(ctable[y],list(k))
+ else : ctable[y] = list(k)
+ match(s) :
+ (s:DefWire) : Begin{_} $
+ for t in table[name(s)] map :
+ DefWire(name(key(t) as WRef),type(key(t)))
+ (s:DefRegister) : Begin{_} $
+ for t in table[name(s)] map :
+ DefRegister(name(key(t) as WRef),type(key(t)))
+ (s:DefInstance) : s
+ (s:DefNode) :
+ val s* = Begin $ list(
+ DefWire(name(s),type(value(s))),
+ Connect(WRef(name(s),type(value(s)),NodeKind(),UNKNOWN-GENDER),value(s)))
+ lower-stmt(s*)
+ (s:Connect) : Begin{_} $
+ for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map :
+ val lgender = FEMALE * value(l)
+ val rgender = MALE * value(r)
+ switch fn ([x,y]) : lgender == x and rgender == y :
+ [FEMALE,MALE] : Connect(key(l),key(r))
+ [MALE,FEMALE] : Connect(key(r),key(l))
+ (s:WDefAccessor) : Begin{_} $
+ for (l in table[name(s)], r in expand-expr(source(s))) map:
+ WDefAccessor(name(key(l) as WRef),key(r),index(s),value(r) * gender(s))
+ (s:ConnectFromIndexed) : Begin(ls) where :
+ val ctable = HashTable<Symbol,List<KeyValue<Expression,Flip>>>(symbol-hash)
+ for e in exps(s) do :
+ for (r in expand-expr(e),l in expand-expr(loc(s))) do :
+ add-to-table(name(key(l) as WRef),r,ctable)
+ val ls =
+ for l in expand-expr(loc(s)) map :
+ val lgender = FEMALE * value(l)
+ var rgender = BI-GENDER
+ val exps = for e in ctable[name(key(l) as WRef)] map :
+ rgender = rgender + (MALE * value(e))
+ key(e)
+ switch fn ([x,y]) : lgender == x and rgender == y :
+ [FEMALE,MALE] : ConnectFromIndexed(index(s),key(l),exps)
+ [MALE,FEMALE] : ConnectToIndexed(index(s),exps,key(l))
+ (s:ConnectToIndexed) : Begin(ls) where :
+ val ctable = HashTable<Symbol,List<KeyValue<Expression,Flip>>>(symbol-hash)
+ for ls in locs(s) do :
+ for (l in expand-expr(ls),r in expand-expr(exp(s))) do :
+ add-to-table(name(key(r) as WRef),l,ctable)
+ val ls =
+ for r in expand-expr(exp(s)) map :
+ val n = name(key(r) as WRef)
+ val rgender = MALE * value(r)
+ var lgender = BI-GENDER
+ val locs = for l in ctable[n] map :
+ lgender = lgender + (FEMALE * value(l))
+ key(l)
+ switch fn ([x,y]) : lgender == x and rgender == y :
+ [FEMALE,MALE] : ConnectToIndexed(index(s),locs,key(r))
+ [MALE,FEMALE] : ConnectFromIndexed(index(s),key(r),locs)
+ (s:DefMemory) : Begin{_} $
+ for t in table[name(s)] map :
+ DefMemory(name(key(t) as WRef),VectorType(type(key(t)),size(type(s))))
+ (s) : map(lower-stmt,s)
+
+ defn expand-expr (e:Expression) -> List<KeyValue<Expression,Flip>> :
+ match(e) :
+ (e:WRef) : table[name(e)]
+ (e:WSubfield) :
+ val exps = expand-expr(exp(e))
+ val begin = index-of-elem(type(exp(e)) as BundleType,name(e))
+ val len = num-elems(type(e))
+ headn(tailn(exps,begin),len)
+ (e:WIndex) :
+ val exps = expand-expr(exp(e))
+ val len = num-elems(type(e))
+ headn(tailn(exps,len * value(e)),len)
+ (e) : list(KeyValue(e, DEFAULT))
+
+ println(table)
+ lower-stmt(body)
+
+defn get-entries (n:Symbol,t:Type) -> List<KeyValue<WRef,Flip>> :
+ defn uniquify (w:WRef) -> WRef :
+ val name* = symbol-join([n "#" name(w)])
+ WRef(name*,type(w),kind(w),gender(w))
+ match(t) :
+ (t:BundleType) :
+ for f in fields(t) map-append :
+ val es = get-entries(name(f),type(f))
+ for e in es map :
+ uniquify(key(e)) => value(e) * flip(f)
+ (t:VectorType) :
+ for i in 0 to size(t) map-append :
+ val es = get-entries(to-symbol(i),type(t))
+ for e in es map :
+ uniquify(key(e)) => value(e)
+ (t) : list(KeyValue(WRef(n,t,NodeKind(),UNKNOWN-GENDER),DEFAULT))
+
+defn lower-module (m:Module,table:HashTable<Symbol,List<KeyValue<Expression,Flip>>>) -> Module :
+ defn build-table-ports (ports:List<Port>) :
+ for p in ports do :
+ table[name(p)] = get-entries(name(p),type(p))
+
+ defn build-table-stmt (stmt:Stmt) -> Stmt:
+ match(stmt) :
+ (s:DefWire) : table[name(s)] = get-entries(name(s),type(s))
+ (s:DefRegister) : table[name(s)] = get-entries(name(s),type(s))
+ (s:DefInstance) :
+ val r = WRef(name(s),type(module(s)),InstanceKind(),FEMALE)
+ val ports = table[name(module(s) as WRef)]
+ table[name(s)] =
+ for w in ports map-append :
+ list(KeyValue(WSubfield(r,name(key(w) as WRef),type(key(w) as WRef),UNKNOWN-GENDER), value(w)))
+ (s:DefMemory) : table[name(s)] = get-entries(name(s),type(type(s) as VectorType))
+ (s:DefNode) : table[name(s)] = get-entries(name(s),type(value(s)))
+ (s:WDefAccessor) : table[name(s)] = get-entries(name(s),type(type(source(s)) as VectorType))
+ (s) : map(build-table-stmt,s)
+ stmt
+
+ build-table-ports(ports(m))
+ build-table-stmt(body(m))
+ Module(name(m),ports*,body*) where :
+ val body* = lower(body(m),table)
+ val ports* = lower-ports(m,table)
+
+defn lower-to-ground (c:Circuit) -> Circuit :
+ val table = HashTable<Symbol,List<KeyValue<Expression,Flip>>>(symbol-hash)
+ defn build-table-module (m:Module) -> ? :
+ table[name(m)] = for p in ports(m) map-append : get-entries(name(p),type(p))
+
+ for m in modules(c) map :
+ build-table-module(m)
+
+ Circuit(modules*, main(c)) where :
+ val modules* =
+ for m in modules(c) map :
+ lower-module(m,table)
;defn prefix (prefix, suffix) :
; symbol-join([prefix "/" suffix])
@@ -2101,7 +2235,7 @@ public defn run-passes (c: Circuit, p: List<Char>) :
if contains(p,'e') : do-stage("Infer Types", infer-types)
if contains(p,'f') : do-stage("Resolve Genders", resolve-genders)
if contains(p,'g') : do-stage("Expand Accessors", expand-accessors)
- ;if contains(p,'h') : do-stage("Flatten Bundles", flatten-bundles)
+ if contains(p,'h') : do-stage("Lower To Ground", lower-to-ground)
;if contains(p,'i') : do-stage("Expand Bundles", expand-bundles)
;if contains(p,'j') : do-stage("Expand Multi Connects", expand-multi-connects)
;if contains(p,'k') : do-stage("Expand Whens", expand-whens)
diff --git a/test/passes/expand-accessors/accessor-mem.fir b/test/passes/expand-accessors/accessor-mem.fir
index 32002d47..01257279 100644
--- a/test/passes/expand-accessors/accessor-mem.fir
+++ b/test/passes/expand-accessors/accessor-mem.fir
@@ -5,15 +5,15 @@ circuit top :
module top :
mem m : UInt(32)[10][10][10]
wire i : UInt
- accessor a = m[i] ;CHECK: a := ReadPort(m, i, UInt(1))
- accessor b = a[i] ;CHECK: b := (a.9 a.8 a.7 a.6 a.5 a.4 a.3 a.2 a.1 a.0)[i]
- accessor c = b[i] ;CHECK: c := (b.9 b.8 b.7 b.6 b.5 b.4 b.3 b.2 b.1 b.0)[i]
+ accessor a = m[i] ;CHECK: accessor a = m[i]
+ accessor b = a[i] ;CHECK: b := (a.0 a.1 a.2 a.3 a.4 a.5 a.6 a.7 a.8 a.9)[i]
+ accessor c = b[i] ;CHECK: c := (b.0 b.1 b.2 b.3 b.4 b.5 b.6 b.7 b.8 b.9)[i]
wire j : UInt
j := c
- accessor x = m[i] ;CHECK: WritePort(m, i, UInt(1)) := x
- accessor y = x[i] ;CHECK: (x.9 x.8 x.7 x.6 x.5 x.4 x.3 x.2 x.1 x.0)[i] := y
- accessor z = y[i] ;CHECK: (y.9 y.8 y.7 y.6 y.5 y.4 y.3 y.2 y.1 y.0)[i] := z
+ accessor x = m[i] ;CHECK: accessor x = m[i]
+ accessor y = x[i] ;CHECK: (x.0 x.1 x.2 x.3 x.4 x.5 x.6 x.7 x.8 x.9)[i] := y
+ accessor z = y[i] ;CHECK: (y.0 y.1 y.2 y.3 y.4 y.5 y.6 y.7 y.8 y.9)[i] := z
z := j
; CHECK: Finished Expand Accessors
diff --git a/test/passes/expand-accessors/accessor-vec.fir b/test/passes/expand-accessors/accessor-vec.fir
index 4314e062..599abb8f 100644
--- a/test/passes/expand-accessors/accessor-vec.fir
+++ b/test/passes/expand-accessors/accessor-vec.fir
@@ -5,15 +5,23 @@ circuit top :
module top :
wire m : UInt(32)[10][10][10]
wire i : UInt
- accessor a = m[i] ;CHECK: a := (m.9 m.8 m.7 m.6 m.5 m.4 m.3 m.2 m.1 m.0)[i]
- accessor b = a[i] ;CHECK: b := (a.9 a.8 a.7 a.6 a.5 a.4 a.3 a.2 a.1 a.0)[i]
- accessor c = b[i] ;CHECK: c := (b.9 b.8 b.7 b.6 b.5 b.4 b.3 b.2 b.1 b.0)[i]
+ accessor a = m[i] ;CHECK: a := (m.0 m.1 m.2 m.3 m.4 m.5 m.6 m.7 m.8 m.9)[i]
+ accessor b = a[i] ;CHECK: b := (a.0 a.1 a.2 a.3 a.4 a.5 a.6 a.7 a.8 a.9)[i]
+ accessor c = b[i] ;CHECK: c := (b.0 b.1 b.2 b.3 b.4 b.5 b.6 b.7 b.8 b.9)[i]
wire j : UInt
j := c
- accessor x = m[i] ;CHECK: (m.9 m.8 m.7 m.6 m.5 m.4 m.3 m.2 m.1 m.0)[i] := x
- accessor y = x[i] ;CHECK: (x.9 x.8 x.7 x.6 x.5 x.4 x.3 x.2 x.1 x.0)[i] := y
- accessor z = y[i] ;CHECK: (y.9 y.8 y.7 y.6 y.5 y.4 y.3 y.2 y.1 y.0)[i] := z
+ accessor x = m[i] ;CHECK: (m.0 m.1 m.2 m.3 m.4 m.5 m.6 m.7 m.8 m.9)[i] := x
+ accessor y = x[i] ;CHECK: (x.0 x.1 x.2 x.3 x.4 x.5 x.6 x.7 x.8 x.9)[i] := y
+ accessor z = y[i] ;CHECK: (y.0 y.1 y.2 y.3 y.4 y.5 y.6 y.7 y.8 y.9)[i] := z
z := j
+ wire p : {n : UInt(32)[10]}
+ accessor q = p.n[i] ;CHECK: (p.n.0 p.n.1 p.n.2 p.n.3 p.n.4 p.n.5 p.n.6 p.n.7 p.n.8 p.n.9)[i] := q
+ q := j
+
+ wire r : {m : UInt(32)}[10]
+ accessor s = r[i] ;CHECK: s := (r.0 r.1 r.2 r.3 r.4 r.5 r.6 r.7 r.8 r.9)[i]
+ j := s.m
+
; CHECK: Finished Expand Accessors
diff --git a/test/passes/expand-accessors/one-when.fir b/test/passes/expand-accessors/one-when.fir
deleted file mode 100644
index 2597c1d7..00000000
--- a/test/passes/expand-accessors/one-when.fir
+++ /dev/null
@@ -1,20 +0,0 @@
-; RUN: firrtl %s abcdefg c | tee %s.out | FileCheck %s
-
-;CHECK: Expand Accessors
-circuit top :
- module top :
- mem m : UInt(1)[2]
- wire i : UInt(1)
- wire p : UInt(1)
- when p :
- accessor a = m[i] ;CHECK: a := ReadPort(m, i, bit-and(p, UInt(1)))
- i := a
- accessor b = m[i] ;CHECK: WritePort(m, i, bit-and(p, UInt(1))) := b
- b := i
- else :
- accessor c = m[i] ;CHECK: c := ReadPort(m, i, bit-and(equal-uu(UInt(0), p), UInt(1)))
- i := c
- accessor d = m[i] ;CHECK: WritePort(m, i, bit-and(equal-uu(UInt(0), p), UInt(1))) := d
- d := i
-
-; CHECK: Finished Expand Accessors
diff --git a/test/passes/expand-accessors/two-when.fir b/test/passes/expand-accessors/two-when.fir
deleted file mode 100644
index 87c8fc54..00000000
--- a/test/passes/expand-accessors/two-when.fir
+++ /dev/null
@@ -1,57 +0,0 @@
-; RUN: firrtl %s abcdefg c | tee %s.out | FileCheck %s
-
-;CHECK: Expand Accessors
-circuit top :
- module top :
- mem m : UInt(1)[2]
- wire i : UInt(1)
- wire p : UInt(1)
- when p :
- wire p2 : UInt(1)
- when p2 :
- accessor a = m[i]
- i := a
- accessor b = m[i]
- b := i
- ;CHECK : wire a : UInt(1)
- ;CHECK : a := ReadPort(m, i, bit-and(p2, bit-and(p, UInt(1))))
- ;CHECK : i := a
- ;CHECK : wire b : UInt(1)
- ;CHECK : WritePort(m, i, bit-and(p2, bit-and(p, UInt(1)))) := b
- ;CHECK : b := i
- else :
- accessor c = m[i]
- i := c
- accessor d = m[i]
- d := i
- ;CHECK : wire c : UInt(1)
- ;CHECK : c := ReadPort(m, i, bit-and(equal-uu(UInt(0), p2), bit-and(p, UInt(1))))
- ;CHECK : i := c
- ;CHECK : wire d : UInt(1)
- ;CHECK : WritePort(m, i, bit-and(equal-uu(UInt(0), p2), bit-and(p, UInt(1)))) := d
- ;CHECK : d := i
- else :
- when p2 :
- accessor w = m[i]
- i := w
- accessor x = m[i]
- x := i
- ;CHECK : wire w : UInt(1)
- ;CHECK : w := ReadPort(m, i, bit-and(p2, bit-and(equal-uu(UInt(0), p), UInt(1))))
- ;CHECK : i := w
- ;CHECK : wire x : UInt(1)
- ;CHECK : WritePort(m, i, bit-and(p2, bit-and(equal-uu(UInt(0), p), UInt(1)))) := x
- ;CHECK : x := i
- else :
- accessor y = m[i]
- i := y
- accessor z = m[i]
- z := i
- ;CHECK : wire y : UInt(1)
- ;CHECK : y := ReadPort(m, i, bit-and(equal-uu(UInt(0), p2), bit-and(equal-uu(UInt(0), p), UInt(1))))
- ;CHECK : i := y
- ;CHECK : wire z : UInt(1)
- ;CHECK : WritePort(m, i, bit-and(equal-uu(UInt(0), p2), bit-and(equal-uu(UInt(0), p), UInt(1)))) := z
- ;CHECK : z := i
-
-; CHECK: Finished Expand Accessors
diff --git a/test/passes/expand-whens/one-when.fir b/test/passes/expand-whens/one-when.fir
new file mode 100644
index 00000000..78c59493
--- /dev/null
+++ b/test/passes/expand-whens/one-when.fir
@@ -0,0 +1,15 @@
+circuit top :
+ module top :
+ mem m : UInt(1)[2]
+ wire i : UInt(1)
+ wire p : UInt(1)
+ when p :
+ accessor a = m[i]
+ i := a
+ accessor b = m[i]
+ b := i
+ else :
+ accessor c = m[i]
+ i := c
+ accessor d = m[i]
+ d := i
diff --git a/test/passes/expand-whens/two-when.fir b/test/passes/expand-whens/two-when.fir
new file mode 100644
index 00000000..16fae1e2
--- /dev/null
+++ b/test/passes/expand-whens/two-when.fir
@@ -0,0 +1,28 @@
+circuit top :
+ module top :
+ mem m : UInt(1)[2]
+ wire i : UInt(1)
+ wire p : UInt(1)
+ when p :
+ wire p2 : UInt(1)
+ when p2 :
+ accessor a = m[i]
+ i := a
+ accessor b = m[i]
+ b := i
+ else :
+ accessor c = m[i]
+ i := c
+ accessor d = m[i]
+ d := i
+ else :
+ when p2 :
+ accessor w = m[i]
+ i := w
+ accessor x = m[i]
+ x := i
+ else :
+ accessor y = m[i]
+ i := y
+ accessor z = m[i]
+ z := i
diff --git a/test/passes/lower-to-ground/accessor.fir b/test/passes/lower-to-ground/accessor.fir
new file mode 100644
index 00000000..56171246
--- /dev/null
+++ b/test/passes/lower-to-ground/accessor.fir
@@ -0,0 +1,33 @@
+; RUN: firrtl %s abcdefgh c | tee %s.out | FileCheck %s
+
+; CHECK: Lower To Ground
+circuit top :
+ module m :
+ wire i : UInt
+ wire j : UInt
+
+ wire a : UInt(32)[4]
+ ; CHECK: wire a#0 : UInt(32)
+ ; CHECK: wire a#1 : UInt(32)
+ ; CHECK: wire a#2 : UInt(32)
+ ; CHECK: wire a#3 : UInt(32)
+
+ accessor b = a[i]
+ ; CHECK: wire b : UInt(32)
+ ; CHECK: b := (a#0 a#1 a#2 a#3)[i]
+ j := b
+
+ accessor c = a[i]
+ ; CHECK: wire c : UInt(32)
+ ; CHECK: (a#0 a#1 a#2 a#3)[i] := c
+ c := j
+
+ mem p : UInt(32)[10]
+ accessor t = p[i]
+ ; CHECK: accessor t = p[i]
+ j := t
+ accessor r = p[i]
+ ; CHECK: accessor r = p[i]
+ r := j
+
+; CHECK: Finished Lower To Ground
diff --git a/test/passes/lower-to-ground/bundle-vecs.fir b/test/passes/lower-to-ground/bundle-vecs.fir
new file mode 100644
index 00000000..a4ead6ed
--- /dev/null
+++ b/test/passes/lower-to-ground/bundle-vecs.fir
@@ -0,0 +1,31 @@
+; RUN: firrtl %s abcdefgh c | tee %s.out | FileCheck %s
+
+; CHECK: Lower To Ground
+circuit top :
+ module q :
+ wire i : UInt
+ wire j : UInt
+
+ wire a : { x : UInt(32), flip y : UInt(32) }[2]
+ ; CHECK: wire a#0#x : UInt(32)
+ ; CHECK: wire a#0#y : UInt(32)
+ ; CHECK: wire a#1#x : UInt(32)
+ ; CHECK: wire a#1#y : UInt(32)
+
+ accessor b = a[i]
+ ; CHECK: wire b#x : UInt(32)
+ ; CHECK: wire b#y : UInt(32)
+ ; CHECK: b#x := (a#0#x a#1#x)[i]
+ ; CHECK: (a#0#y a#1#y)[i] := b#y
+ j := b
+
+ accessor c = a[i]
+ ; CHECK: wire c#x : UInt(32)
+ ; CHECK: wire c#y : UInt(32)
+ ; CHECK: (a#0#x a#1#x)[i] := c#x
+ ; CHECK: c#y := (a#0#y a#1#y)[i]
+ c := j
+
+
+; CHECK: Finished Lower To Ground
+
diff --git a/test/passes/lower-to-ground/bundle.fir b/test/passes/lower-to-ground/bundle.fir
new file mode 100644
index 00000000..990b6b7f
--- /dev/null
+++ b/test/passes/lower-to-ground/bundle.fir
@@ -0,0 +1,53 @@
+; RUN: firrtl %s abcdefgh c | tee %s.out | FileCheck %s
+
+circuit top :
+ module m :
+ input a : { x : UInt, flip y: SInt}
+ output b : { x : UInt, flip y: SInt}
+ module subtracter :
+ input c : { x : UInt[5], flip y : { x : UInt[3], flip y : SInt } }
+ wire a : { x : UInt, flip y : SInt}
+ wire b : { x : UInt, flip y : SInt}
+ a := b
+ inst i of m
+ i.a := a
+ b := i.b
+ wire d : UInt[5]
+
+;CHECK: Lower To Ground
+;CHECK: circuit top :
+;CHECK: module m :
+;CHECK: input a#x : UInt
+;CHECK: output a#y : SInt
+;CHECK: output b#x : UInt
+;CHECK: input b#y : SInt
+;CHECK: input reset : UInt(1)
+;CHECK: module subtracter :
+;CHECK: input c#x#0 : UInt
+;CHECK: input c#x#1 : UInt
+;CHECK: input c#x#2 : UInt
+;CHECK: input c#x#3 : UInt
+;CHECK: input c#x#4 : UInt
+;CHECK: output c#y#x#0 : UInt
+;CHECK: output c#y#x#1 : UInt
+;CHECK: output c#y#x#2 : UInt
+;CHECK: input c#y#y : SInt
+;CHECK: input reset : UInt(1)
+;CHECK: wire a#x : UInt
+;CHECK: wire a#y : SInt
+;CHECK: wire b#x : UInt
+;CHECK: wire b#y : SInt
+;CHECK: a#x := b#x
+;CHECK: b#y := a#y
+;CHECK: inst i of m
+;CHECK: i.reset := reset
+;CHECK: i.a#x := a#x
+;CHECK: a#y := i.a#y
+;CHECK: b#x := i.b#x
+;CHECK: i.b#y := b#y
+;CHECK: wire d#0 : UInt
+;CHECK: wire d#1 : UInt
+;CHECK: wire d#2 : UInt
+;CHECK: wire d#3 : UInt
+;CHECK: wire d#4 : UInt
+;CHECK: Finished Lower To Ground
diff --git a/test/passes/lower-to-ground/nested-vec.fir b/test/passes/lower-to-ground/nested-vec.fir
new file mode 100644
index 00000000..8eafb8e8
--- /dev/null
+++ b/test/passes/lower-to-ground/nested-vec.fir
@@ -0,0 +1,34 @@
+; RUN: firrtl %s abcdefgh c | tee %s.out | FileCheck %s
+
+; CHECK: Lower To Ground
+circuit top :
+ module q :
+ wire i : UInt
+ wire j : { x : UInt(32), flip y : UInt(32) }
+
+ wire a : { x : UInt(32), flip y : UInt(32) }[2]
+ ; CHECK: wire a#0#x : UInt(32)
+ ; CHECK: wire a#0#y : UInt(32)
+ ; CHECK: wire a#1#x : UInt(32)
+ ; CHECK: wire a#1#y : UInt(32)
+
+ accessor b = a[i]
+ ; CHECK: wire b#x : UInt(32)
+ ; CHECK: wire b#y : UInt(32)
+ ; CHECK: b#x := (a#0#x a#1#x)[i]
+ ; CHECK: (a#0#y a#1#y)[i] := b#y
+ j := b
+
+ mem m : { x : UInt(32), flip y : UInt(32) }[2]
+ ; CHECK: mem m#x : UInt(32)[2]
+ ; CHECK: mem m#y : UInt(32)[2]
+
+ accessor c = m[i] ; MALE
+ ; CHECK: accessor c#x = m#x[i]
+ ; CHECK: accessor c#y = m#y[i]
+ ; CHECK: c#x := j#x
+ ; CHECK: j#y := c#y
+ c := j
+
+; CHECK: Finished Lower To Ground
+