diff options
| author | azidar | 2015-07-02 11:33:58 -0700 |
|---|---|---|
| committer | azidar | 2015-07-14 11:29:54 -0700 |
| commit | 52f2b8a0a5c4c099266291c1fd95ef9258306919 (patch) | |
| tree | d61aff9dc94b3a8b0f8d6a21efc0b38763d2c0de /src | |
| parent | f20d88a47166a35c3baffb0f2d16357417d9bb05 (diff) | |
In progress commit
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/stanza/errors.stanza | 66 | ||||
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 29 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 9 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 9 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 276 | ||||
| -rw-r--r-- | src/main/stanza/verilog.stanza | 168 |
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)) |
