aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorazidar2015-07-02 11:33:58 -0700
committerazidar2015-07-14 11:29:54 -0700
commit52f2b8a0a5c4c099266291c1fd95ef9258306919 (patch)
treed61aff9dc94b3a8b0f8d6a21efc0b38763d2c0de /src
parentf20d88a47166a35c3baffb0f2d16357417d9bb05 (diff)
In progress commit
Diffstat (limited to 'src')
-rw-r--r--src/main/stanza/errors.stanza66
-rw-r--r--src/main/stanza/firrtl-ir.stanza29
-rw-r--r--src/main/stanza/ir-parser.stanza9
-rw-r--r--src/main/stanza/ir-utils.stanza9
-rw-r--r--src/main/stanza/passes.stanza276
-rw-r--r--src/main/stanza/verilog.stanza168
6 files changed, 283 insertions, 274 deletions
diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza
index 229a1406..8c47d112 100644
--- a/src/main/stanza/errors.stanza
+++ b/src/main/stanza/errors.stanza
@@ -605,11 +605,6 @@ public defn check-types (c:Circuit) -> Circuit :
if value(e) >= size(t) : add(errors,IndexTooLarge(info,value(e)))
(t) : add(errors,IndexOnNonVector(info))
(e:DoPrim) : check-types-primop(e,errors,info)
- (e:ReadPort|WritePort) :
- if type(index(e)) != u() : add(errors,IndexNotUInt(info))
- if type(enable(e)) != u() : add(errors,EnableNotUInt(info))
- (e:Register) :
- if type(enable(e)) != u() : add(errors,EnableNotUInt(info))
(e:UIntValue|SIntValue) : false
e
defn check-types-s (s:Stmt) -> Stmt :
@@ -649,9 +644,9 @@ defn WrongGender (info:FileInfo,expr:Symbol,wrong:Symbol,right:Symbol) :
PassException $ string-join $
[info ": Expression " expr "has gender " wrong " but requires gender " right "."]
-defn UnknownGenders (info:FileInfo,name:Symbol) :
+defn InferDirection (info:FileInfo,name:Symbol) :
PassException $ string-join $
- [info ": Accessor " name " has an unknown gender."]
+ [info ": Accessor " name " has a direction that requires inference."]
;---------------- Helper Functions --------------
defn dir-to-gender (d:Direction) -> Gender :
@@ -678,9 +673,6 @@ public defn check-genders (c:Circuit) -> Circuit :
(e:DoPrim) : MALE
(e:UIntValue) : MALE
(e:SIntValue) : MALE
- (e:ReadPort) : MALE
- (e:WritePort) : FEMALE
- (e:Register) : MALE
defn check-genders-e (info:FileInfo,e:Expression,genders:HashTable<Symbol,Gender>) -> False :
do(check-genders-e{info,_,genders},e)
@@ -693,9 +685,6 @@ public defn check-genders (c:Circuit) -> Circuit :
check-gender(info,genders,e,MALE)
(e:UIntValue) : false
(e:SIntValue) : false
- (e:ReadPort) : do(check-gender{info,genders,_,MALE},e)
- (e:WritePort) : do(check-gender{info,genders,_,MALE},e)
- (e:Register) : do(check-gender{info,genders,_,MALE},e)
defn check-genders-s (s:Stmt,genders:HashTable<Symbol,Gender>) -> False :
do(check-genders-e{info(s),_:Expression,genders},s)
@@ -707,8 +696,8 @@ public defn check-genders (c:Circuit) -> Circuit :
genders[name(s)] = MALE
(s:DefMemory) : genders[name(s)] = BI-GENDER
(s:DefInstance) : genders[name(s)] = MALE
- (s:WDefAccessor) :
- if gender(s) == UNKNOWN-GENDER : add(errors,UnknownGenders(info(s),name(s)))
+ (s:DefAccessor) :
+ if dir(s) == INFER : add(errors,InferDirection(info(s),name(s)))
check-gender(info(s),genders,index(s),MALE)
check-gender(info(s),genders,source(s),gender(s))
genders[name(s)] = gender(s)
@@ -751,26 +740,6 @@ public defmethod name (b:CheckLowForm) -> String : "Low Form Check"
public defmethod short-name (b:CheckLowForm) -> String : "low-form-check"
;----------------- Errors ------------------------
-defn IncorrectRegisterUsage (info:FileInfo) :
- PassException $ string-join $
- [info ": Register can only be used on the right side of a connect statement."]
-
-defn IncorrectReadPortUsage (info:FileInfo) :
- PassException $ string-join $
- [info ": ReadPort can only be used on the right side of a connect statement."]
-
-defn IncorrectWritePortUsage (info:FileInfo) :
- PassException $ string-join $
- [info ": WritePort can only be used on the left side of a connect statement."]
-
-defn NoReg (info:FileInfo,name:Symbol) :
- PassException $ string-join $
- [info ": Invalid reg declaration " name ". No reg declarations are allowed in low firrtl."]
-
-defn NoAccessor (info:FileInfo,name:Symbol) :
- PassException $ string-join $
- [info ": Invalid accessor declaration " name ". No accessor declarations are allowed in low firrtl."]
-
defn InvalidVec (info:FileInfo,name:Symbol) :
PassException $ string-join $
[info ": Expression " name " has an illegal vector type."]
@@ -781,7 +750,7 @@ defn InvalidBundle (info:FileInfo,name:Symbol) :
defn NoWhen (info:FileInfo) :
PassException $ string-join $
- [info ": Illegal when statement. No when statements are allowed in low firrtl."]
+ [info ": Illegal when statement. No when statements with multiple statements are allowed in low firrtl."]
defn SingleAssignment (info:FileInfo,name:Symbol) :
PassException $ string-join $
@@ -823,9 +792,6 @@ public defn check-low-form (c:Circuit) -> Circuit :
check-low-form-t(info,type(f),name(e))
if contains?(mems,name(e)) :
check-low-form-t(info,type(type(e) as VectorType),name(e))
- (e:Register) : add(errors,IncorrectRegisterUsage(info))
- (e:ReadPort) : add(errors,IncorrectReadPortUsage(info))
- (e:WritePort) : add(errors,IncorrectWritePortUsage(info))
(e) : check-low-form-t(info,type(e),to-symbol $ to-string(e))
defn check-low-form-s (s:Stmt) -> False :
match(s) :
@@ -840,27 +806,15 @@ public defn check-low-form (c:Circuit) -> Circuit :
add(insts,name(s))
(s:DefNode) :
check-correct-exp(info(s),value(s))
- (s:DefRegister) : add(errors,NoReg(info(s),name(s)))
- (s:DefAccessor) : add(errors,NoAccessor(info(s),name(s)))
- (s:Conditionally) : add(errors,NoWhen(info(s)))
+ (s:DefRegister) : false
+ (s:DefAccessor) : false
+ (s:Conditionally) :
+ if (not alt(s) typeof EmptyStmt) or (conseq(s) typeof Begin) : add(errors,NoWhen(info(s)))
(s:OnReset) : add(errors,NoOnReset(info(s)))
(s:BulkConnect) : add(errors,NoBulkConnect(info(s)))
(s:Connect) :
- match(exp(s)) :
- (e:Register) :
- check-low-form-t(info(s),type(e),to-symbol $ to-string(e))
- check-correct-exp(info(s),value(e))
- check-correct-exp(info(s),enable(e))
- (e:ReadPort) :
- check-low-form-t(info(s),type(e),to-symbol $ to-string(e))
- check-correct-exp(info(s),index(e))
- check-correct-exp(info(s),enable(e))
- (e) : check-correct-exp(info(s),e)
+ check-correct-exp(info(s),e)
match(loc(s)) :
- (e:WritePort) :
- check-low-form-t(info(s),type(e),to-symbol $ to-string(e))
- check-correct-exp(info(s),index(e))
- check-correct-exp(info(s),enable(e))
(e:Ref|Subfield) :
val n* = to-symbol $ to-string $ e
if contains?(assigned?,n*) : add(errors,SingleAssignment(info(s),n*))
diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza
index aeaecf47..92f955b9 100644
--- a/src/main/stanza/firrtl-ir.stanza
+++ b/src/main/stanza/firrtl-ir.stanza
@@ -8,14 +8,20 @@ public defmethod info! (x:?) : FileInfo()
public val expand-delin = `$
public val gen-delin = `#
-public definterface Direction
-public val INPUT = new Direction
-public val OUTPUT = new Direction
+public definterface PortDirection
+public val INPUT = new PortDirection
+public val OUTPUT = new PortDirection
public definterface Flip
public val DEFAULT = new Flip
public val REVERSE = new Flip
+public definterface AccDirection
+public val READ = new AccDirection
+public val WRITE = new AccDirection
+public val INFER = new AccDirection
+public val RDWR = new AccDirection
+
public definterface Width
public defstruct UnknownWidth <: Width
public defstruct IntWidth <: Width :
@@ -83,20 +89,6 @@ public defstruct DoPrim <: Expression :
args: List<Expression>
consts: List<Int>
type: Type with: (as-method => true)
-public defstruct ReadPort <: Expression :
- mem: Expression
- index: Expression
- type: Type with: (as-method => true)
- enable: Expression
-public defstruct WritePort <: Expression :
- mem: Expression
- index: Expression
- type: Type with: (as-method => true)
- enable: Expression
-public defstruct Register <: Expression :
- type: Type with: (as-method => true)
- value: Expression
- enable: Expression
public definterface Stmt
public defmulti info (s:Stmt) -> FileInfo
@@ -124,6 +116,7 @@ public defstruct DefNode <: Stmt : ;LOW
value: Expression
public defstruct DefAccessor <: Stmt :
info: FileInfo with: (as-method => true)
+ dir: AccDirection
name: Symbol
source: Expression
index: Expression
@@ -168,7 +161,7 @@ public defstruct Field :
public defstruct Port :
info: FileInfo
name: Symbol
- direction: Direction
+ pkind: PKind
type: Type
public definterface Module
diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza
index dd7679cc..374cf58c 100644
--- a/src/main/stanza/ir-parser.stanza
+++ b/src/main/stanza/ir-parser.stanza
@@ -243,15 +243,6 @@ defsyntax firrtl :
(t:UIntType) : UIntValue(v, width(t))
(t:SIntType) : SIntValue(v, width(t))
- expterm = (WritePort(?m:#exp, ?i:#exp, ?e:#exp)) : WritePort(m, i, UnknownType(), e)
- expterm != (WritePort) : FPE(form, "Invalid syntax for WritePort expression.")
-
- expterm = (ReadPort(?m:#exp, ?i:#exp, ?e:#exp)) : ReadPort(m, i, UnknownType(), e)
- expterm != (ReadPort) : FPE(form, "Invalid syntax for ReadPort expression.")
-
- expterm = (Register(?v:#exp, ?e:#exp)) : Register(UnknownType(), v, e)
- expterm != (Register) : FPE(form, "Invalid syntax for Register expression.")
-
expterm = (?op:#sym(?es:#exp ... ?ints:#int ... ?rest ...)) :
if not empty?(rest) :
FPE(rest, "Illegal operands to primitive operator.")
diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza
index 89de6793..e29bf4ac 100644
--- a/src/main/stanza/ir-utils.stanza
+++ b/src/main/stanza/ir-utils.stanza
@@ -160,9 +160,6 @@ defmethod print (o:OutputStream, e:Expression) :
print-all(o, [op(e) "("])
print-all(o, join(concat(args(e), consts(e)), ", "))
print(o, ")")
- (e:ReadPort) : print-all(o, ["ReadPort(" mem(e) ", " index(e) ", " enable(e) ")"])
- (e:WritePort) : print-all(o, ["WritePort(" mem(e) ", " index(e) ", " enable(e) ")"])
- (e:Register) : print-all(o, ["Register(" value(e) ", " enable(e) ")"])
print-debug(o,e)
defmethod print (o:OutputStream, c:Stmt) :
@@ -275,9 +272,6 @@ defmethod map (f: Expression -> Expression, e:Expression) -> Expression :
(e:Subfield) : Subfield(f(exp(e)), name(e), type(e))
(e:Index) : Index(f(exp(e)), value(e), type(e))
(e:DoPrim) : DoPrim(op(e), map(f, args(e)), consts(e), type(e))
- (e:ReadPort) : ReadPort(f(mem(e)), f(index(e)), type(e), f(enable(e)))
- (e:WritePort) : WritePort(f(mem(e)), f(index(e)), type(e), f(enable(e)))
- (e:Register) : Register(type(e),f(value(e)),f(enable(e)))
(e) : e
public defmulti map<?T> (f: Expression -> Expression, c:?T&Stmt) -> T
@@ -320,9 +314,6 @@ defmethod map (f: Type -> Type, c:Expression) -> Expression :
(c:Subfield) : Subfield(exp(c),name(c),f(type(c)))
(c:Index) : Index(exp(c),value(c),f(type(c)))
(c:DoPrim) : DoPrim(op(c),args(c),consts(c),f(type(c)))
- (c:ReadPort) : ReadPort(mem(c),index(c),f(type(c)),enable(c))
- (c:WritePort) : WritePort(mem(c),index(c),f(type(c)),enable(c))
- (c:Register) : Register(f(type(c)),value(c),enable(c))
(c) : c
public defmulti map<?T> (f: Type -> Type, c:?T&Stmt) -> T
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)
diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza
index 708430f2..4afd2a28 100644
--- a/src/main/stanza/verilog.stanza
+++ b/src/main/stanza/verilog.stanza
@@ -4,12 +4,55 @@ defpackage firrtl/verilog :
import firrtl/ir-utils
import firrtl/ir2
+public defstruct RemoveSeqMem <: Pass
+public defmethod pass (b:RemoveSeqMem) -> (Circuit -> Circuit) : remove-smem{_}
+public defmethod name (b:RemoveSeqMem) -> String : "Remove SeqMem"
+public defmethod short-name (b:RemoveSeqMem) -> String : "remove-smem"
+
+
+;============ Utilz =============
+
+;============ Remove Seq Mem =============
+
+defn remove-smem (m:InModule) -> InModule :
+ val hash = get-sym-hash(m)
+ val smems = Vector<Symbol>()
+ defn remove-smem-s (s:Stmt) -> Stmt :
+ map{remove-smem-s,_} $ match(s) :
+ (s:DefMemory) :
+ if seq?(s) : add(smems,name(s))
+ DefMemory(info(s),name(s),type(s),false)
+ (s:DefAccessor) :
+ if dir(s) == WRITE and contains?(smems, name(source(s) as Ref)) :
+ val regged-index = firrtl-gensym(name(index(s) as Ref),hash)
+ val ref = Ref(regged-index,type(index(s)))
+ Begin $ to-list $
+ [ DefRegister(info(s),regged-index,type(index(s)))
+ Connect(ref,index(s))
+ DefAccessor(info(s),dir(s),name(s),source(s),ref) ]
+ else : s
+ (s) : s
+
+ InModule(info(m),name(m),ports(m),remove-smem-s(body(m),hash))
+
+public defn remove-smem (c:Circuit) -> Circuit :
+ for m in modules(c) do :
+ match(m) :
+ (m:InModule) : remove-smem(m)
+ (m:ExModule) : m
+
+;============ VERILOG ==============
+
public defstruct Verilog <: Pass :
file : String
public defmethod pass (b:Verilog) -> (Circuit -> Circuit) : emit-verilog{file(b),_}
public defmethod name (b:Verilog) -> String : "To Verilog"
public defmethod short-name (b:Verilog) -> String : "To Verilog"
+defstruct DecAndConnect :
+ dec : Stmt
+ con : Connect
+
;============ Utilz =============
defn width! (w:Width) -> Int :
match(w) :
@@ -41,12 +84,6 @@ defn remove-subfield (e:Expression) -> Expression :
(e:Subfield) : Ref(to-symbol $ string-join $ [emit(exp(e)) "_" name(e)],type(e))
(e) : e
-definterface VKind
-defstruct WireKind <: VKind
-defstruct RegKind <: VKind
-defstruct SeqMemKind <: VKind
-defstruct ComMemKind <: VKind
-
;============ Verilog Backend =============
defn emit-as-type (e:Expression,t:Type) -> String :
@@ -139,19 +176,26 @@ defn emit (e:Expression) -> String :
v = concat(v, [" ^ " emit(x)])
v
+
+defn get-name (e:Expression) -> Symbol :
+ match(e) :
+ (e:Ref) : name(e)
+ (e:Subfield) : symbol-join([get-name(exp(e)) `. name(e))
+ (e) : error("Shouldn't be here")
+
defn emit-module (m:InModule) :
- val h = HashTable<Symbol,VKind>(symbol-hash)
+ val decs = HashTable<Symbol,Stmt>(sym-hash) ; all declarations
+ val cons = HashTable<Symbol,Stmt>(sym-hash) ; all connections
defn build-table (m:InModule) :
defn build-table (s:Stmt) -> Stmt :
- match(map(build-table,s)) :
- (s:DefWire) : h[name(s)] = WireKind()
- (s:DefMemory) :
- if seq?(s) : h[name(s)] = SeqMemKind()
- else : h[name(s)] = ComMemKind()
+ match(map(build-table,map(remove-subfield,s))) :
+ (s:DefWire|DefReg|DefAccessor|DefMemory|DefNode|DefInstance) : decs[name(s)] = s
+ (s:Conditionally) :
+ val n = name(loc(conseq(s) as Connect))
+ cons[n] = s
(s:Connect) :
- match(exp(s)) :
- (e:Register) : h[name(loc(s) as Ref)] = RegKind()
- (e) : false
+ val n = get-name(loc(s))
+ cons[n] = s
(s) : false
s
build-table(body(m))
@@ -166,14 +210,66 @@ defn emit-module (m:InModule) :
val inst-ports = HashTable<Symbol,Vector<Streamable>>(symbol-hash)
val sh = get-sym-hash(m)
+
+ for dec in decs do :
+ match(value(dec)) :
+
+ defn emit-pred-connect (s:Connect,en:Expression) :
+ if blocking?[name(loc(s) as Ref)] :
+ add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"])
+ else :
+ add(updates,["if(" emit(enable(reg)) ") begin"])
+ add(updates,[" " n " <= " emit(value(reg)) ";"])
+ add(updates,["end"])
+
+
+; add(updates,["if(" en ") begin"])
+; add(updates,[" " emit(mem(wp)) "[" emit(index(wp)) "] <= " emit(exp(s)) ";"])
+; add(updates,["end"])
+; else :
+; if exp(s) typeof Register :
+; val n = name(loc(s) as Ref)
+; val reg = exp(s) as Register
+; add(inits,[n " = {" width!(type(reg)) "{$random}};"])
+; add(updates,["if(" emit(enable(reg)) ") begin"])
+; add(updates,[" " n " <= " emit(value(reg)) ";"])
+; add(updates,["end"])
+; else if exp(s) typeof ReadPort :
+; val n = name(loc(s) as Ref)
+; val rp = exp(s) as ReadPort
+; match(h[name(mem(rp) as Ref)]) :
+; (k:SeqMemKind) :
+; val index* = Ref(firrtl-gensym(name(index(rp) as Ref),sh),type(index(rp)))
+; add(regs,[ "reg " get-width(type(index*)) " " name(index*) ";"])
+; add(inits,[name(index*) " = {" width!(type(index*)) "{$random}};"])
+; add(updates,["if(" emit(enable(rp)) ") begin"])
+; add(updates,[" " name(index*) " <= " emit(index(rp)) ";"])
+; add(updates,["end"])
+; add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index*) "];"])
+; (k:ComMemKind) :
+; add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index(rp)) "];"])
+; else :
+; add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"])
+
defn emit-s (s:Stmt) :
match(map(remove-subfield,s)) :
- (s:DefWire) :
- if h[name(s)] == RegKind() :
- add(regs,["reg " get-width(type(s)) " " name(s) ";"])
- else :
- add(wires,["wire " get-width(type(s)) " " name(s) ";"])
+ (s:DefWire) : add(wires,["wire " get-width(type(s)) " " name(s) ";"])
+ (s:DefRegister) : add(regs,["reg " get-width(type(s)) " " name(s) ";"])
+ (s:DefAccessor) :
+ switch {_ == dir(s)} :
+ READ :
+ match(h[name(source(s) as Ref)]) :
+ (k:SeqMemKind) :
+ val index* = Ref(firrtl-gensym(name(index(rp) as Ref),sh),type(index(rp)))
+ add(regs,[ "reg " get-width(type(index*)) " " name(index*) ";"])
+ add(inits,[name(index*) " = {" width!(type(index*)) "{$random}};"])
+ add(updates,["if(" emit(enable(rp)) ") begin"])
+ add(updates,[" " name(index*) " <= " emit(index(rp)) ";"])
+ add(updates,["end"])
+ add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index*) "];"])
+ (k:ComMemKind) :
+ add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index(rp)) "];"])
(s:DefInstance) :
inst-ports[name(s)] = Vector<Streamable>()
insts[name(s)] = name(module(s) as Ref)
@@ -190,36 +286,8 @@ defn emit-module (m:InModule) :
add(wires,["wire " get-width(type(value(s))) " " name(s) ";"])
add(assigns,["assign " name(s) " = " emit(value(s)) ";"])
(s:Begin) : do(emit-s, body(s))
- (s:Connect) :
- if loc(s) typeof WritePort :
- val wp = loc(s) as WritePort
- add(updates,["if(" emit(enable(wp)) ") begin"])
- add(updates,[" " emit(mem(wp)) "[" emit(index(wp)) "] <= " emit(exp(s)) ";"])
- add(updates,["end"])
- else :
- if exp(s) typeof Register :
- val n = name(loc(s) as Ref)
- val reg = exp(s) as Register
- add(inits,[n " = {" width!(type(reg)) "{$random}};"])
- add(updates,["if(" emit(enable(reg)) ") begin"])
- add(updates,[" " n " <= " emit(value(reg)) ";"])
- add(updates,["end"])
- else if exp(s) typeof ReadPort :
- val n = name(loc(s) as Ref)
- val rp = exp(s) as ReadPort
- match(h[name(mem(rp) as Ref)]) :
- (k:SeqMemKind) :
- val index* = Ref(firrtl-gensym(name(index(rp) as Ref),sh),type(index(rp)))
- add(regs,[ "reg " get-width(type(index*)) " " name(index*) ";"])
- add(inits,[name(index*) " = {" width!(type(index*)) "{$random}};"])
- add(updates,["if(" emit(enable(rp)) ") begin"])
- add(updates,[" " name(index*) " <= " emit(index(rp)) ";"])
- add(updates,["end"])
- add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index*) "];"])
- (k:ComMemKind) :
- add(assigns,["assign " n " = " emit(mem(rp)) "[" emit(index(rp)) "];"])
- else :
- add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"])
+ (s:Conditionally) : emit-pred-connect(pred(s),conseq(s) as Connect)
+ (s:Connect) : emit-pred-connect(UIntValue(1,1),s)
(s) : s
emit-s(body(m))