aboutsummaryrefslogtreecommitdiff
path: root/src/main/stanza/passes.stanza
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/stanza/passes.stanza')
-rw-r--r--src/main/stanza/passes.stanza276
1 files changed, 144 insertions, 132 deletions
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza
index 5dbba545..86ef5b26 100644
--- a/src/main/stanza/passes.stanza
+++ b/src/main/stanza/passes.stanza
@@ -65,13 +65,6 @@ public defstruct WIndex <: Expression :
type: Type with: (as-method => true)
gender: Gender with: (as-method => true)
-public defstruct WDefAccessor <: Stmt :
- info: FileInfo with: (as-method => true)
- name: Symbol
- source: Expression
- index: Expression
- gender: Gender
-
defstruct ConnectToIndexed <: Stmt :
info: FileInfo with: (as-method => true)
index: Expression
@@ -147,6 +140,20 @@ defn to-dir (g:Gender) -> Direction :
MALE : INPUT
FEMALE : OUTPUT
+defn gender (s:DefAccessor) -> Gender :
+ switch {_ == dir(s)} :
+ READ : MALE
+ WRITE : FEMALE
+ INFER : UNKNOWN-GENDER
+ RDWR : BI-GENDER
+
+defn to-acc-dir (g:Gender) -> AccDirection :
+ switch {_ == g} :
+ MALE : READ
+ FEMALE : WRITE
+ UNKNOWN-GENDER : INFER
+ BI-GENDER : RDWR
+
defmulti gender (e:Expression) -> Gender
defmethod gender (e:Expression) :
MALE
@@ -199,14 +206,14 @@ defmethod print (o:OutputStream, k:Kind) :
(k:WriteAccessorKind) : "wacc"
defn hasGender (e:?) :
- e typeof WRef|WSubfield|WIndex|WDefAccessor
+ e typeof WRef|WSubfield|WIndex
defn hasWidth (e:?) :
e typeof UIntType|SIntType|UIntValue|SIntValue
defn hasType (e:?) :
- e typeof Ref|Subfield|Index|DoPrim|WritePort|ReadPort|WRef|WSubfield
- |WIndex|DefWire|DefRegister|DefMemory|Register
+ e typeof Ref|Subfield|Index|DoPrim|WRef|WSubfield
+ |WIndex|DefWire|DefRegister|DefMemory
|VectorType|Port|Field
defn hasKind (e:?) :
@@ -249,10 +256,6 @@ defmethod print (o:OutputStream, e:WIndex) :
print-all(o,[exp(e) "[" value(e) "]"])
print-debug(o,e as ?)
-defmethod print (o:OutputStream, s:WDefAccessor) :
- print-all(o,["accessor " name(s) " = " source(s) "[" index(s) "]"])
- print-debug(o,s)
-
defmethod print (o:OutputStream, c:ConnectToIndexed) :
print-all(o, [locs(c) "[" index(c) "] := " exp(c)])
print-debug(o,c as ?)
@@ -266,8 +269,6 @@ defmethod map (f: Expression -> Expression, e: WSubfield) :
defmethod map (f: Expression -> Expression, e: WIndex) :
WIndex(f(exp(e)), value(e), type(e), gender(e))
-defmethod map (f: Expression -> Expression, c:WDefAccessor) :
- WDefAccessor(info(c),name(c), f(source(c)), f(index(c)), gender(c))
defmethod map (f: Expression -> Expression, c:ConnectToIndexed) :
ConnectToIndexed(info(c),f(index(c)), map(f, locs(c)), f(exp(c)))
defmethod map (f: Expression -> Expression, c:ConnectFromIndexed) :
@@ -330,10 +331,6 @@ defn to-working-ir (c:Circuit) :
(e:Subfield) : WSubfield(exp(e), name(e), type(e), UNKNOWN-GENDER)
(e:Index) : WIndex(exp(e), value(e), type(e), UNKNOWN-GENDER)
(e) : e
- defn to-stmt (s:Stmt) :
- match(map(to-exp,s)) :
- (s:DefAccessor) : WDefAccessor(info(s),name(s),source(s),index(s), UNKNOWN-GENDER)
- (s) : map(to-stmt,s)
Circuit(info(c),modules*, main(c)) where :
val modules* =
@@ -423,7 +420,7 @@ defn resolve-kinds (c:Circuit) :
(s:DefRegister) : kinds[name(s)] = RegKind()
(s:DefInstance) : kinds[name(s)] = InstanceKind()
(s:DefMemory) : kinds[name(s)] = MemKind()
- (s:WDefAccessor) : kinds[name(s)] = AccessorKind()
+ (s:DefAccessor) : kinds[name(s)] = AccessorKind()
(s) : false
map(find-stmt,s)
@@ -497,9 +494,6 @@ defn infer-exp-types (e:Expression, l:List<KeyValue<Symbol,Type>>) -> Expression
(e:WIndex) : WIndex(exp(e),value(e), get-vector-subtype(type(exp(e))),gender(e))
(e:DoPrim) : lower-and-type-primop(e)
;DoPrim(op(e),args(e),consts(e),get-primop-rettype(e))
- (e:ReadPort) : ReadPort(mem(e),index(e),get-vector-subtype(type(mem(e))),enable(e))
- (e:WritePort) : WritePort(mem(e),index(e),get-vector-subtype(type(mem(e))),enable(e))
- (e:Register) : Register(type(value(e)),value(e),enable(e))
(e:UIntValue|SIntValue) : e
defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue<Symbol,Type>>] :
@@ -517,7 +511,7 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue<
(s:DefMemory) : [s,List(name(s) => type(s),l)]
(s:DefInstance) : [s, List(name(s) => type(module(s)),l)]
(s:DefNode) : [s, List(name(s) => type(value(s)),l)]
- (s:WDefAccessor) : [s, List(name(s) => get-vector-subtype(type(source(s))),l)]
+ (s:DefAccessor) : [s, List(name(s) => get-vector-subtype(type(source(s))),l)]
(s:Conditionally) :
val [s*,l*] = infer-types(conseq(s),l)
val [s**,l**] = infer-types(alt(s),l)
@@ -624,11 +618,11 @@ defn resolve-genders (c:Circuit) :
(s:DefInstance) :
get-gender(name(s),MALE)
DefInstance(info(s),name(s),resolve-expr(module(s),MALE))
- (s:WDefAccessor) :
+ (s:DefAccessor) :
val gender* = get-gender(name(s),UNKNOWN-GENDER)
val index* = resolve-expr(index(s),MALE)
val source* = resolve-expr(source(s),gender*)
- WDefAccessor(info(s),name(s),source*,index*,gender*)
+ DefAccessor(info(s),name(s),source*,index*,to-acc-dir(gender*))
(s:Connect) :
Connect(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE))
(s:BulkConnect) :
@@ -696,8 +690,8 @@ defn expand-vector (e:Expression) -> List<Expression> :
defn expand-stmt (s:Stmt) -> Stmt :
match(s) :
- (s:WDefAccessor) :
- println-all-debug(["Matched WDefAcc with " name(s)])
+ (s:DefAccessor) :
+ println-all-debug(["Matched DefAcc with " name(s)])
val mem? = match(source(s)) :
(e:WRef) : kind(e) typeof MemKind
(e) : false
@@ -829,9 +823,9 @@ defn lower-ports (ports:List<Port>) -> List<Port> :
for x in generate-entry(name(p),type(p)) map :
Port(info(p),name(x),direction(p) * flip(x),type(x))
-defn type (s:WDefAccessor) -> Type : type(type(source(s)) as VectorType)
+defn type (s:DefAccessor) -> Type : type(type(source(s)) as VectorType)
defn size (s:DefMemory) -> Int : size(type(s))
-defn size (s:WDefAccessor) -> Int : size(type(source(s)) as VectorType)
+defn size (s:DefAccessor) -> Int : size(type(source(s)) as VectorType)
defn base-name (e:Expression) -> Symbol :
match(e) :
(e:WRef) : name(e)
@@ -868,14 +862,14 @@ defn lower (body:Stmt) -> Stmt :
(s:DefMemory) : Begin $
for x in generate-entry(name(s),type(type(s))) map :
DefMemory(info(s),name(x),VectorType(type(x),size(s)), seq?(s))
- (s:WDefAccessor) :
+ (s:DefAccessor) :
val ls = generate-entry(name(s),type(s))
val rs = generate-entry(name(source(s) as WRef),type(s))
val index* = exp(head $ expand-expr(index(s)))
Begin $ for (l in ls, r in rs) map:
if flip(r) == REVERSE : error("Shouldn't be here")
val memref = WRef(name(r),VectorType(type(r),size(s)),MemKind(),gender(s))
- WDefAccessor(info(s),name(l),memref,index*,gender(s))
+ DefAccessor(info(s),name(l),memref,index*,to-acc-dir(gender(s)))
(s:OnReset|Connect) : Begin $
for (l in expand-expr(loc(s)), r in expand-expr(exp(s))) map :
val lgender = FEMALE * flip(l)
@@ -1229,66 +1223,17 @@ defn reduce-or (l:List<Expression>) -> Expression :
; 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.
-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 has-nul?(table[name(p)]) :
- println("Uninitialized: ~" % [to-string(name(p))]);TODO actually collect error
- else : 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|DefMemory) : add(decs,s)
- (s:DefWire) :
- add(decs,s)
- val ref = WRef(name(s),type(s),NodeKind(),FEMALE)
- if has-nul?(table[name(s)]) :
- println("Uninitialized: ~" % [to-string(name(s))]);TODO actually collect error
- else : add{cons,_} $ Connect(info(s),ref,to-exp(table[name(s)]) as Expression)
- (s:DefRegister) :
- val e = to-exp(table[name(s)])
- match(e) :
- (e:Expression) :
- add{decs,_} $ DefWire(info(s),name(s),type(s))
- val ref = WRef(name(s),type(s),NodeKind(),FEMALE)
- add{cons,_} $ Connect(info(s),ref,Register(type(s),e,to-exp(optimize $ get-write-enable(table[name(s)])) as Expression))
- (e:False) : false
- (s:WDefAccessor) :
- val t = type(type(source(s)) as VectorType)
- val n = name(s)
- switch {_ == gender(s)} :
- MALE :
- add{decs,_} $ DefWire(info(s),n,t)
- val ref = WRef(n,t,WriteAccessorKind(),FEMALE)
- add{cons,_} $ Connect(info(s),ref,ReadPort(source(s),index(s),t,get-read-enable(n,table)))
- FEMALE :
- add(decs,DefWire(info(s),n,t))
- val ref = WRef(n,t,WriteAccessorKind(),MALE)
- val enable = (to-exp $ optimize $ get-write-enable(table[n])) as Expression
- val wp = WritePort(source(s),index(s),t,enable as Expression)
- val e = to-exp(table[n])
- add{cons,_} $ Connect(info(s),wp,ref)
- match(e) :
- (e:False) :
- println("Uninitialized: ~" % [to-string(n)]) ;TODO actually collect error
- (e:Expression) :
- add{cons,_} $ Connect(info(s),ref,e)
- (s:DefInstance) :
- 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 has-nul?(table[n]) :
- println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error
- else : add{cons,_} $ Connect(info(s),sref,to-exp(table[n]) as Expression)
- (s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : false
- s
+;----------------- Errors ------------------------
+
+defn RefNotInitialized (info:FileInfo, name:Symbol) :
+ PassException $ string-join $
+ [info ": Reference " name " is not fully initialized."]
+
+defn RefNotConnected (info:FileInfo, name:Symbol) :
+ PassException $ string-join $
+ [info ": Reference " name " is never connected to."]
+;---------------- 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 :
@@ -1335,7 +1280,7 @@ defn build-tables (s:Stmt,
(s:DefWire) :
assign[name(s)] = SVNul()
flattn[name(s)] = true
- (s:DefRegister|WDefAccessor) :
+ (s:DefRegister|DefAccessor) :
assign[name(s)] = SVNul()
flattn[name(s)] = false
(s:DefInstance) : ;TODO only add instance input ports. This probably involves correcting instance genders
@@ -1389,41 +1334,106 @@ defn build-tables (s:Stmt,
if s typeof OnReset : resets[key*] = SVExp(exp(s))
(s:Begin) : for s* in body(s) do: build-tables(s*,assign,resets,flattn)
(s:DefMemory|DefNode|EmptyStmt) : false
-
-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)
-
- 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)
- 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)
- 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)
- InModule(info(m),name(m),ports(m),Begin(append(to-list(decs),to-list(cons))))
-
-defn expand-whens (c:Circuit) -> Circuit :
+
+;--------------- Expand Whens Pass -------------------
+
+public defn expand-whens (c:Circuit) -> Circuit :
+ val errors = Vector<PassException>()
+
+ 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 has-nul?(table[name(p)]) :
+ add(errors,RefNotInitialized(info(p), name(p))
+ else : 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|DefMemory) : add(decs,s)
+ (s:DefWire) :
+ add(decs,s)
+ val ref = WRef(name(s),type(s),NodeKind(),FEMALE)
+ if has-nul?(table[name(s)]) :
+ add(errors,RefNotInitialized(info(s), name(s))
+ else : 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 == UIntValue(1,UnknownWidth()) :
+ add{cons,_} $ Connect(info(s),ref,e)
+ else :
+ add{cons,_} $ Conditionally(en,Connect(info(s),ref,e),EmptyStmt())
+ (e:False) :
+ add(errors,RefNotConnected(info(s), name(s))
+ (s:DefAccessor) :
+ add(decs,s)
+ val t = type(type(source(s)) as VectorType)
+ 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 == UIntValue(1,UnknownWidth()) :
+ add{cons,_} $ Connect(info(s),ref,e)
+ else :
+ add{cons,_} $ Conditionally(en,Connect(info(s),ref,e),EmptyStmt())
+ (e:False) :
+ add(errors,RefNotConnected(info(s), n)
+ (s:DefInstance) :
+ 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 has-nul?(table[n]) :
+ add(errors,RefNotInitialized(info(s), n)
+ else : add{cons,_} $ Connect(info(s),sref,to-exp(table[n]) as Expression)
+ (s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : 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)
+
+ 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)
+ 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)
+ 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)
+ InModule(info(m),name(m),ports(m),Begin(append(to-list(decs),to-list(cons))))
+
Circuit(info(c),modules*, main(c)) where :
val modules* =
for m in modules(c) map :
@@ -1661,6 +1671,11 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod
add(v,WGeq(width!(type(l)),width!(type(e))))
add(v,WGeq(width!(type(e)),width!(type(l))))
Connect(info(s),l,e)
+ (s:Conditionally) :
+ val p = gen-constraints(pred(s))
+ add(v,WGeq(width!(type(p)),IntWidth(1)))
+ add(v,WGeq(IntWidth(1),width!(type(p))))
+ Conditionally(info(s),p,conseq(s),alt(s))
(s) : s
defn gen-constraints (e:Expression) -> Expression :
@@ -1669,9 +1684,6 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod
(e:WSubfield) : WSubfield(exp(e),name(e),bundle-field-type(type(exp(e)),name(e)),gender(e))
(e:WIndex) : error("Shouldn't be here")
(e:DoPrim) : DoPrim(op(e),args(e),consts(e),primop-gen-constraints(e,v))
- (e:ReadPort) : ReadPort(mem(e),index(e),type(type(mem(e)) as VectorType),enable(e))
- (e:WritePort) : WritePort(mem(e),index(e),type(type(mem(e)) as VectorType),enable(e))
- (e:Register) : Register(type(value(e)),value(e),enable(e))
(e:UIntValue) :
match(width(e)) :
(w:UnknownWidth) :
@@ -1925,7 +1937,7 @@ defn to-real-ir (c:Circuit) :
(e) : e
defn to-stmt (s:Stmt) :
match(map(to-exp,s)) :
- (e:WDefAccessor) : error("Shouldn't be here")
+ (e:DefAccessor) : error("Shouldn't be here")
(e:ConnectToIndexed) : error("Shouldn't be here")
(e:ConnectFromIndexed) : error("Shouldn't be here")
(e) : map(to-stmt,e)