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.stanza110
1 files changed, 101 insertions, 9 deletions
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza
index 381ea753..dbb489c4 100644
--- a/src/main/stanza/passes.stanza
+++ b/src/main/stanza/passes.stanza
@@ -76,6 +76,7 @@ defstruct WIndexer <: Expression :
type: Type with: (as-method => true)
gender : Gender with: (as-method => true)
public defstruct WVoid <: Expression
+public defstruct WInvalid <: Expression
public defstruct WDefInstance <: Stmt :
info: FileInfo with: (as-method => true)
name: Symbol
@@ -90,8 +91,8 @@ defn get-gender (s:Stmt|Port) -> Gender :
match(s) :
(s:DefWire|DefRegister) : BI-GENDER
(s:WDefInstance|DefNode|DefInstance|DefPoison) : MALE
- (s:Begin|Connect|BulkConnect|Stop|Print|Empty) : UNKNOWN-GENDER
- (s:DefMemory) : FEMALE
+ (s:Begin|Connect|BulkConnect|Stop|Print|Empty|IsInvalid) : UNKNOWN-GENDER
+ (s:DefMemory) : MALE
(p:Port) :
switch { _ == direction(p) } :
INPUT : MALE
@@ -116,6 +117,7 @@ defmethod info (stmt:Empty) -> FileInfo : FileInfo()
defmethod type (exp:UIntValue) -> Type : UIntType(width(exp))
defmethod type (exp:SIntValue) -> Type : SIntType(width(exp))
defmethod type (exp:WVoid) -> Type : UnknownType()
+defmethod type (exp:WInvalid) -> Type : UnknownType()
defmethod get-type (s:WDefInstance) -> Type : type(s)
@@ -135,6 +137,7 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False :
(e1:WSubAccess,e2:WSubAccess) :
(index(e1) == index(e2)) and (exp(e1) == exp(e2))
(e1:WVoid,e2:WVoid) : true
+ (e1:WInvalid,e2:WInvalid) : true
(e1:WIndexer,e2:WIndexer) :
var bool = (length(exps(e1)) == length(exps(e2)))
for (e1* in exps(e1),e2* in exps(e2)) do :
@@ -153,6 +156,9 @@ defmethod equal? (e1:Expression,e2:Expression) -> True|False :
(cond(e1) == cond(e2)) and
(tval(e1) == tval(e2)) and
(fval(e1) == fval(e2))
+ (e1:ValidIf,e2:ValidIf) :
+ (cond(e1) == cond(e2)) and
+ (value(e1) == value(e2))
(e1,e2) : false
; ================= PRINTERS ===================
@@ -287,6 +293,9 @@ defmethod print (o:OutputStream, e:WSubAccess) :
defmethod print (o:OutputStream, e:WVoid) :
print(o,"VOID")
print-debug(o,e as ?)
+defmethod print (o:OutputStream, e:WInvalid) :
+ print(o,"INVALID")
+ print-debug(o,e as ?)
defmethod print (o:OutputStream, c:WIndexer) :
print-all(o, [exps(c) "[" index(c) "]"])
print-debug(o,c as ?)
@@ -692,6 +701,7 @@ defn infer-types (c:Circuit) -> Circuit :
val types = HashTable<Symbol,Type>(symbol-hash)
defn infer-types-e (e:Expression) -> Expression :
match(map(infer-types-e,e)) :
+ (e:ValidIf) : ValidIf(cond(e),value(e),type(value(e)))
(e:WRef) : WRef(name(e), types[name(e)],kind(e),gender(e))
(e:WSubField) : WSubField(exp(e),name(e),field-type(type(exp(e)),name(e)),gender(e))
(e:WSubIndex) : WSubIndex(exp(e),value(e),sub-type(type(exp(e))),gender(e))
@@ -781,6 +791,9 @@ defn resolve-genders (c:Circuit) :
defn resolve-s (s:Stmt) -> Stmt :
match(s) :
+ (s:IsInvalid) :
+ val exp* = resolve-e(exp(s),FEMALE)
+ IsInvalid(info(s),exp*)
(s:Connect) :
val loc* = resolve-e(loc(s),FEMALE)
val exp* = resolve-e(exp(s),MALE)
@@ -814,16 +827,20 @@ defn pull-muxes (c:Circuit) -> Circuit :
(e:WSubField) :
match(exp(e)) :
(e*:Mux) : Mux(cond(e*),WSubField(tval(e*),name(e),type(e),gender(e)),WSubField(fval(e*),name(e),type(e),gender(e)),type(e))
+ (e*:ValidIf) : ValidIf(cond(e*),WSubField(value(e*),name(e),type(e),gender(e)),type(e))
(e*) : e
(e:WSubIndex) :
match(exp(e)) :
(e*:Mux) : Mux(cond(e*),WSubIndex(tval(e*),value(e),type(e),gender(e)),WSubIndex(fval(e*),value(e),type(e),gender(e)),type(e))
+ (e*:ValidIf) : ValidIf(cond(e*),WSubIndex(value(e*),value(e),type(e),gender(e)),type(e))
(e*) : e
(e:WSubAccess) :
match(exp(e)) :
(e*:Mux) : Mux(cond(e*),WSubAccess(tval(e*),index(e),type(e),gender(e)),WSubAccess(fval(e*),index(e),type(e),gender(e)),type(e))
+ (e*:ValidIf) : ValidIf(cond(e*),WSubAccess(value(e*),index(e),type(e),gender(e)),type(e))
(e*) : e
(e:Mux) : e
+ (e:ValidIf) : e
(e) : e
defn pull-muxes (s:Stmt) -> Stmt :
@@ -888,6 +905,9 @@ defn create-exps (e:Expression) -> List<Expression> :
(e:Mux) :
for (e1 in create-exps(tval(e)), e2 in create-exps(fval(e))) map :
Mux(cond(e),e1,e2,mux-type-and-widths(e1,e2))
+ (e:ValidIf) :
+ for e1 in create-exps(value(e)) map :
+ ValidIf(cond(e),e1,type(e1))
(e) :
match(type(e)) :
(t:UIntType|SIntType|ClockType) : list(e)
@@ -919,6 +939,11 @@ defn fast-create-exps (e:Expression) -> List<Expression> :
Mux(cond(e),e1,e2,mux-type-and-widths(e1,e2))
hashed-create-exps[e] = x
x
+ (e:ValidIf) :
+ val x = for e1 in create-exps(value(e)) map :
+ ValidIf(cond(e),e1,type(e1))
+ hashed-create-exps[e] = x
+ x
(e) :
val es = Vector<List<Expression>>()
match(type(e)) :
@@ -938,8 +963,41 @@ defn fast-create-exps (e:Expression) -> List<Expression> :
defn expand-connects (c:Circuit) -> Circuit :
defn expand-connects (m:InModule) -> InModule :
mname = name(m)
+ val genders = HashTable<Symbol,Gender>(symbol-hash)
defn expand-s (s:Stmt) -> Stmt :
+ defn set-gender (e:Expression) -> Expression :
+ match(map(set-gender,e)) :
+ (e:WRef) : WRef(name(e),type(e),kind(e),genders[name(e)])
+ (e:WSubField) :
+ val f = {_ as Field} $
+ for f in fields(type(exp(e)) as BundleType) find :
+ name(f) == name(e)
+ val gender* = gender(exp(e)) * flip(f)
+ WSubField(exp(e),name(e),type(e),gender*)
+ (e:WSubIndex) : WSubIndex(exp(e),value(e),type(e),gender(exp(e)))
+ (e:WSubAccess) : WSubAccess(exp(e),index(e),type(e),gender(exp(e)))
+ (e) : e
match(s) :
+ (s:DefWire|DefRegister) :
+ genders[name(s)] = BI-GENDER
+ s
+ (s:WDefInstance|DefMemory|DefPoison|DefNode) :
+ genders[name(s)] = MALE
+ s
+ (s:IsInvalid) :
+ val n = get-size(exp(s))
+ val invalids = Vector<Stmt>()
+ val exps = create-exps(exp(s))
+ for i in 0 to n do :
+ val exp* = exps[i]
+ val gexp* = set-gender(exp*)
+ switch { _ == gender(gexp*) } :
+ BI-GENDER : add(invalids,IsInvalid(info(s),exp*))
+ FEMALE : add(invalids,IsInvalid(info(s),exp*))
+ else : false
+ if length(invalids) == 0 : Empty()
+ else if length(invalids) == 1 : invalids[0]
+ else : Begin(to-list(invalids))
(s:Connect) :
val n = get-size(loc(s))
val connects = Vector<Stmt>()
@@ -968,6 +1026,8 @@ defn expand-connects (c:Circuit) -> Circuit :
Begin(to-list(connects))
(s) : map(expand-s,s)
+ for p in ports(m) do :
+ genders[name(p)] = to-gender(direction(p))
InModule(info(m),name(m),ports(m),expand-s(body(m)))
Circuit(info(c),modules*, main(c)) where :
@@ -1046,6 +1106,7 @@ defn remove-access (c:Circuit) :
match(e) :
(e:DoPrim) : map(remove-e,e)
(e:Mux) : map(remove-e,e)
+ (e:ValidIf) : map(remove-e,e)
(e:UIntValue|SIntValue) : e
(e) :
if has-access?(e) :
@@ -1153,6 +1214,7 @@ defn expand-whens (c:Circuit) -> Circuit :
defn expand-whens (s:Stmt,netlist:HashTable<Expression,Expression>,p:Expression) -> Stmt :
match(s) :
(s:Connect) : netlist[loc(s)] = exp(s)
+ (s:IsInvalid) : netlist[exp(s)] = WInvalid()
(s:Conditionally) :
val exps = Vector<Expression>()
defn prefetch (s:Stmt) -> Stmt:
@@ -1171,7 +1233,12 @@ defn expand-whens (c:Circuit) -> Circuit :
(value:Expression) :
val tv = c-netlist[lvalue]
val fv = value
- netlist[lvalue] = Mux(pred(s),tv,fv,mux-type-and-widths(tv,fv))
+ val res = match(tv,fv) :
+ (tv:WInvalid,fv:WInvalid) : WInvalid()
+ (tv:WInvalid,fv) : ValidIf(NOT(pred(s)),fv,type(fv))
+ (tv,fv:WInvalid) : ValidIf(pred(s),tv,type(tv))
+ (tv,fv) : Mux(pred(s),tv,fv,mux-type-and-widths(tv,fv))
+ netlist[lvalue] = res
(value:False) :
netlist[lvalue] = c-netlist[lvalue]
(s:Print) :
@@ -1207,7 +1274,10 @@ defn expand-whens (c:Circuit) -> Circuit :
val rvalue =
if s typeof DefRegister : replace-void(e,netlist[e])
else : netlist[e]
- add(connections,Connect(info(s),e,rvalue))
+ val con = match(rvalue) :
+ (rvalue:WInvalid) : IsInvalid(info(s),e)
+ (rvalue) : Connect(info(s),e,rvalue)
+ add(connections,con)
(s:DefPoison|DefNode) :
add(stmts,s)
(s) : map(create,s)
@@ -1215,7 +1285,11 @@ defn expand-whens (c:Circuit) -> Circuit :
create(body(m))
for p in ports(m) do :
for e in get-female-refs(name(p),type(p),get-gender(p)) do :
- add(connections,Connect(info(p),e,netlist[e]))
+ val rvalue = netlist[e]
+ val con = match(rvalue) :
+ (rvalue:WInvalid) : IsInvalid(info(p),e)
+ (rvalue) : Connect(info(p),e,rvalue)
+ add(connections,con)
for x in simlist do :
add(stmts,x)
InModule(info(m),name(m),ports(m),Begin(list(Begin(to-list(stmts)),Begin(to-list(connections)))))
@@ -2170,6 +2244,7 @@ defn lower-types (m:Module) -> Module :
(k) : WRef(lowered-name(e),type(e),kind(e),gender(e))
(e:DoPrim) : map(lower-types-e,e)
(e:Mux) : map(lower-types-e,e)
+ (e:ValidIf) : map(lower-types-e,e)
match(s) :
(s:DefWire|DefPoison) :
if is-ground?(type(s)) : s
@@ -2201,6 +2276,13 @@ defn lower-types (m:Module) -> Module :
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:IsInvalid) :
+ val s* = map(lower-types-e,s)
+ if kind(exp(s*)) typeof MemKind :
+ val es = lower-mem(exp(s*))
+ Begin $ for e in es map :
+ IsInvalid(info(s*),e)
+ else : s*
(s:Connect) :
val s* = map(lower-types-e,s)
if kind(loc(s*)) typeof MemKind :
@@ -2277,6 +2359,7 @@ defn long! (t:Type) -> Long :
w = w + long!(type(f))
w
(t:VectorType) : to-long(size(t)) * long!(type(t))
+ (t:ClockType) : to-long(1)
defn rand-string (t:Type) -> Streamable :
val w* = ((long!(t) + to-long(31)) / to-long(32))
@@ -2292,8 +2375,8 @@ defn emit (x:?, top:Int) :
turn-off-debug(false)
match(e) :
(e:DoPrim) : emit(op-stream(e), top + 1)
- (e:Mux) :
- emit([cond(e) " ? " cast(tval(e)) " : " cast(fval(e))],top + 1)
+ (e:Mux) : emit([cond(e) " ? " cast(tval(e)) " : " cast(fval(e))],top + 1)
+ (e:ValidIf) : emit([cast(value(e))],top + 1)
(e:WRef) : print(e)
(e:WSubField) : print(lowered-name(e))
(e:WSubAccess) : print-all([lowered-name(exp(e)) "[" lowered-name(index(e)) "]"])
@@ -2422,6 +2505,10 @@ defn emit-verilog (m:InModule) -> Module :
defn build-netlist (s:Stmt) -> Stmt :
match(s) :
(s:Connect) : netlist[loc(s)] = exp(s)
+ (s:IsInvalid) :
+ val n = firrtl-gensym(`GEN,namehash)
+ val e = wref(n,type(exp(s)))
+ netlist[exp(s)] = e
(s:Conditionally) : add(simlist,s)
(s:DefNode) :
val e = WRef(name(s),get-type(s),NodeKind(),MALE)
@@ -2531,9 +2618,14 @@ defn emit-verilog (m:InModule) -> Module :
val e = wref(name(s),type(s))
update-and-reset(e,clock(s),reset(s),init(s))
initialize(e)
+ (s:IsInvalid) :
+ val wref = netlist[exp(s)] as WRef
+ declare(`reg,name(wref),type(exp(s)))
+ initialize(wref)
(s:DefPoison) :
- declare(`reg,name(s),type(s))
- val e = wref(name(s),type(s))
+ val n = firrtl-gensym(`GEN,namehash)
+ val e = wref(n,type(s))
+ declare(`reg,n,type(e))
initialize(e)
(s:DefNode) :
declare(`wire,name(s),type(value(s)))