From 903e5ba4502f5c62b1373df7b44ae1ee0dd66388 Mon Sep 17 00:00:00 2001 From: azidar Date: Thu, 2 Jul 2015 11:33:58 -0700 Subject: In progress commit --- src/main/stanza/errors.stanza | 66 ++-------- src/main/stanza/firrtl-ir.stanza | 29 ++-- src/main/stanza/ir-parser.stanza | 9 -- src/main/stanza/ir-utils.stanza | 9 -- src/main/stanza/passes.stanza | 276 ++++++++++++++++++++------------------- src/main/stanza/verilog.stanza | 168 +++++++++++++++++------- 6 files changed, 283 insertions(+), 274 deletions(-) (limited to 'src') 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) -> 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) -> 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 consts: List 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 (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 (f: Type -> Type, c:?T&Stmt) -> T diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index b2a53a70..6e030d24 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>) -> 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>) -> [Stmt List>] : @@ -517,7 +511,7 @@ defn infer-types (s:Stmt, l:List>) -> [Stmt List 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 : 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) -> List : 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,13 +862,13 @@ 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)) 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(s),gender(s)) + DefAccessor(info(s),name(l),memref,index(s),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) @@ -1226,66 +1220,17 @@ defn reduce-or (l:List) -> 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, table:HashTable,cons:Vector) -> 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,decs:Vector,cons:Vector) -> 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) -> Expression : defn get-single-read-enable (sym:Symbol,sv:SymbolicValue) -> Expression : defn active (e:Expression) -> True|False : @@ -1332,7 +1277,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 @@ -1386,41 +1331,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-hash) - val resets = HashTable(symbol-hash) - val flattn = HashTable(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() - val cons = Vector() - 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() + + defn expand-whens (ports:List, table:HashTable,cons:Vector) -> 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,decs:Vector,cons:Vector) -> 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-hash) + val resets = HashTable(symbol-hash) + ;val flattn = HashTable(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() + val cons = Vector() + 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 : @@ -1658,6 +1668,11 @@ defn gen-constraints (m:Module, h:HashTable, v:Vector) -> 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 : @@ -1666,9 +1681,6 @@ defn gen-constraints (m:Module, h:HashTable, v:Vector) -> 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) : @@ -1922,7 +1934,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() + 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-hash) + val decs = HashTable(sym-hash) ; all declarations + val cons = HashTable(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-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() 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)) -- cgit v1.2.3 From 3145eaab41e76cc8cd18ceea01d7548fa539f1b6 Mon Sep 17 00:00:00 2001 From: azidar Date: Thu, 2 Jul 2015 14:15:05 -0700 Subject: Partial commit --- src/main/stanza/verilog.stanza | 76 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index 4afd2a28..0e04df8a 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -180,7 +180,7 @@ defn emit (e:Expression) -> String : defn get-name (e:Expression) -> Symbol : match(e) : (e:Ref) : name(e) - (e:Subfield) : symbol-join([get-name(exp(e)) `. name(e)) + (e:Subfield) : error("Shouldn't be here") (e) : error("Shouldn't be here") defn emit-module (m:InModule) : @@ -191,7 +191,7 @@ defn emit-module (m:InModule) : 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)) + val n = get-name(loc(conseq(s) as Connect)) cons[n] = s (s:Connect) : val n = get-name(loc(s)) @@ -211,17 +211,62 @@ defn emit-module (m:InModule) : val sh = get-sym-hash(m) - for dec in decs do : + for (sym -> dec) in decs do : match(value(dec)) : + (dec:DefWire) : + add(wires,["wire " get-width(type(s)) " " name(s) ";"]) + emit-blocking-connect(cons[sym]) + (dec:DefRegister) : + add(regs,["reg " get-width(type(s)) " " name(s) ";"]) + emit-nonblocking-connect(cons[sym]) + (dec:DefMemory) : + val vtype = type(s) as VectorType + add(regs,["reg " get-width(type(vtype)) " " name(s) " [0:" size(vtype) "];"]) + add(inits,["for (initvar = 0; initvar < " size(vtype) "; initvar = initvar+1)"]) + add(inits,[" " name(s) "[initvar] = {" width!(type(vtype)) "{$random}};"]) + (s:DefNode) : + add(wires,["wire " get-width(type(value(s))) " " name(s) ";"]) + add(assigns,["assign " name(s) " = " emit(value(s)) ";"]) + (s:DefInstance) : + inst-ports[name(s)] = Vector() + insts[name(s)] = name(module(s) as Ref) + for f in fields(type(module(s)) as BundleType) do : + val n* = to-symbol $ string-join $ [name(s) "_" name(f)] + add(wires,["wire " get-width(type(f)) " " n* ";"]) + add(inst-ports[name(s)], ["." name(f) "( " n* " )"]) + (s:DefAccessor) : + switch {_ == dir(s)} : + READ : + val mem-declaration = decs[name(source(s) as Ref)] + val con = cons[sym] + if seq?(mem-declaration) : + val index* = Ref(firrtl-gensym(name(index(s) as Ref),sh),type(index(s))) + add(regs,[ "reg " get-width(type(index*)) " " name(index*) ";"]) ; to make it sequential, register the index for an additional cycle + add(inits,[name(index*) " = {" width!(type(index*)) "{$random}};"]) + add(updates,[name(index*) " <= " emit(index(s)) ";"]) + add(assigns,["assign " n " = " emit(mem(s)) "[" emit(index*) "];"]) + else : + add(assigns,["assign " n " = " emit(mem(s)) "[" emit(index(s)) "];"]) + + + - - 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"]) + defn emit-blocking-connect (s:Stmt) : + match(s) : + (s:Connect) : add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"]) + (s:Conditionally) : error("Shouldn't be here") + defn emit-nonblocking-connect (s:Stmt) : + match(s) : + (s:Connect) : + add(updates,[n " <= " emit(value(reg)) ";"]) + (s:Conditionally) : + match(conseq(s)) : + (c:Connect) : + add(updates,["if(" emit(pred(s)) ") begin"]) + add(updates,[" " emit(loc(c) " <= " emit(exp(c)) ";"]) + add(updates,["end"]) + (c) : error("Shouldn't be here") + (s) : error("Shouldn't be here") ; add(updates,["if(" en ") begin"]) @@ -253,8 +298,11 @@ defn emit-module (m:InModule) : ; add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"]) defn emit-s (s:Stmt) : - match(map(remove-subfield,s)) : - (s:DefWire) : add(wires,["wire " get-width(type(s)) " " name(s) ";"]) + match(s) : + (s:DefWire) : + add(wires,["wire " get-width(type(s)) " " name(s) ";"]) + add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"]) + (s:DefRegister) : add(regs,["reg " get-width(type(s)) " " name(s) ";"]) (s:DefAccessor) : switch {_ == dir(s)} : @@ -290,7 +338,7 @@ defn emit-module (m:InModule) : (s:Connect) : emit-pred-connect(UIntValue(1,1),s) (s) : s - emit-s(body(m)) + ;==== Actually printing module ===== val port-indent = " " -- cgit v1.2.3 From d9ece539b630ef9988f6f6e2159b5126e1728ccd Mon Sep 17 00:00:00 2001 From: azidar Date: Mon, 6 Jul 2015 17:45:06 -0700 Subject: Still partial commit, many tests pass. Many tests fail. --- src/main/stanza/compilers.stanza | 60 ++++----- src/main/stanza/errors.stanza | 29 ++--- src/main/stanza/firrtl-ir.stanza | 4 +- src/main/stanza/firrtl-test-main.stanza | 5 +- src/main/stanza/flo.stanza | 87 ------------- src/main/stanza/ir-parser.stanza | 17 ++- src/main/stanza/ir-utils.stanza | 26 ++-- src/main/stanza/passes.stanza | 138 +++++++++++++++++---- src/main/stanza/verilog.stanza | 210 +++++++------------------------- 9 files changed, 241 insertions(+), 335 deletions(-) (limited to 'src') diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index 2f6329dc..a3b04a94 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -3,40 +3,40 @@ defpackage firrtl/compiler : import verse import firrtl/passes import firrtl/errors - import firrtl/flo +; import firrtl/flo import firrtl/verilog import firrtl/ir2 import firrtl/ir-utils -public defstruct StandardFlo <: Compiler : - file: String with: (as-method => true) -public defmethod passes (c:StandardFlo) -> List : - to-list $ [ - CheckHighForm(expand-delin) - ;; TempElimination() - ToWorkingIR() - MakeExplicitReset() - ResolveKinds() - CheckKinds() - InferTypes() - CheckTypes() - ResolveGenders() - CheckGenders() - ExpandAccessors() - LowerToGround() - ExpandIndexedConnects() - ExpandWhens() - InferWidths() - Pad() - Inline() - SplitExp() - ToRealIR() - SpecialRename(`#,`_) - SpecialRename(`$,`::) - CheckHighForm(`::) - CheckLowForm() - Flo(file(c)) - ] +;public defstruct StandardFlo <: Compiler : +; file: String with: (as-method => true) +;public defmethod passes (c:StandardFlo) -> List : +; to-list $ [ +; CheckHighForm(expand-delin) +; ;; TempElimination() +; ToWorkingIR() +; MakeExplicitReset() +; ResolveKinds() +; CheckKinds() +; InferTypes() +; CheckTypes() +; ResolveGenders() +; CheckGenders() +; ExpandAccessors() +; LowerToGround() +; ExpandIndexedConnects() +; ExpandWhens() +; InferWidths() +; Pad() +; Inline() +; SplitExp() +; ToRealIR() +; SpecialRename(`#,`_) +; SpecialRename(`$,`::) +; CheckHighForm(`::) +; CheckLowForm() +; Flo(file(c)) +; ] public defstruct StandardVerilog <: Compiler : file: String with: (as-method => true) diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index 8c47d112..e726fd00 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -247,7 +247,7 @@ public defn check-high-form (c:Circuit,sym:Symbol) -> Circuit : defn check-valid-loc (info:FileInfo,e:Expression) -> False : match(e) : - (e:UIntValue|SIntValue|DoPrim|ReadPort|Register) : + (e:UIntValue|SIntValue|DoPrim) : add(errors,InvalidLOC(info)) (e) : false @@ -403,20 +403,7 @@ public defn check-kinds (c:Circuit) -> Circuit : (e:WIndex) : check-is-mem(info,exp(e)) (e) : false - defn check-kinds-e (info:FileInfo,e:Expression) -> False : - do(check-kinds-e{info,_},e) - match(e) : - (e:ReadPort) : - check-is-mem(info,mem(e)) - check-not-mem(info,index(e)) - check-not-mem(info,enable(e)) - (e:WritePort) : - check-is-mem(info,mem(e)) - check-not-mem(info,index(e)) - check-not-mem(info,enable(e)) - (e) : do(check-not-mem{info,_},e) defn check-kinds-s (s:Stmt) -> False : - do(check-kinds-e{info(s),_:Expression},s) match(s) : (s:DefNode) : check-not-mem(info(s),value(s)) (s:DefAccessor) : check-not-mem(info(s),index(s)) @@ -649,11 +636,19 @@ defn InferDirection (info:FileInfo,name:Symbol) : [info ": Accessor " name " has a direction that requires inference."] ;---------------- Helper Functions -------------- -defn dir-to-gender (d:Direction) -> Gender : +defn dir-to-gender (d:PortDirection) -> Gender : switch {_ == d} : INPUT : MALE OUTPUT : FEMALE +defn gender (s:DefAccessor) -> Gender : + switch {_ == acc-dir(s)} : + READ : MALE + WRITE : FEMALE + INFER : UNKNOWN-GENDER + RDWR : BI-GENDER + + ;----------------- Check Genders Pass --------------------- public defn check-genders (c:Circuit) -> Circuit : @@ -697,7 +692,7 @@ public defn check-genders (c:Circuit) -> Circuit : (s:DefMemory) : genders[name(s)] = BI-GENDER (s:DefInstance) : genders[name(s)] = MALE (s:DefAccessor) : - if dir(s) == INFER : add(errors,InferDirection(info(s),name(s))) + if acc-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) @@ -813,7 +808,7 @@ public defn check-low-form (c:Circuit) -> Circuit : (s:OnReset) : add(errors,NoOnReset(info(s))) (s:BulkConnect) : add(errors,NoBulkConnect(info(s))) (s:Connect) : - check-correct-exp(info(s),e) + check-correct-exp(info(s),exp(s)) match(loc(s)) : (e:Ref|Subfield) : val n* = to-symbol $ to-string $ e diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index 92f955b9..b698bae2 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -116,10 +116,10 @@ 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 + acc-dir: AccDirection public defstruct Conditionally <: Stmt : info: FileInfo with: (as-method => true) pred: Expression @@ -161,7 +161,7 @@ public defstruct Field : public defstruct Port : info: FileInfo name: Symbol - pkind: PKind + direction: PortDirection type: Type public definterface Module diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza index beb288b1..374fe438 100644 --- a/src/main/stanza/firrtl-test-main.stanza +++ b/src/main/stanza/firrtl-test-main.stanza @@ -11,7 +11,7 @@ #include("primop.stanza") #include("errors.stanza") #include("compilers.stanza") -#include("flo.stanza") +;#include("flo.stanza") #include("verilog.stanza") ;Custom Packages @@ -80,7 +80,8 @@ defn main () : run-passes(c,get-passes(to-list(pass-names))) else : switch {_ == compiler} : - "flo" : run-passes(c,StandardFlo(output as String)) + ;"flo" : run-passes(c,StandardFlo(output as String)) + "flo" : run-passes(c,StandardVerilog(output as String)) "verilog" : run-passes(c,StandardVerilog(output as String)) "verilute" : run-passes(c,InstrumentedVerilog(output as String,to-list $ pass-args)) else : error("Invalid compiler flag") diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza index fd000e20..cf15638d 100644 --- a/src/main/stanza/flo.stanza +++ b/src/main/stanza/flo.stanza @@ -5,93 +5,6 @@ defpackage firrtl/flo : import firrtl/ir2 import firrtl/passes -;========== Pad Widths ================== - -public defstruct Pad <: Pass -public defmethod pass (b:Pad) -> (Circuit -> Circuit) : pad-widths -public defmethod name (b:Pad) -> String : "Pad Widths" - -defn int-width! (t:Type) -> Int : - match(width!(t)) : - (w:IntWidth) : width(w) - (w) : error("Non-int width") - -defn set-width (desired:Int,t:Type) -> Type : - match(t) : - (t:UIntType) : UIntType(IntWidth(desired)) - (t:SIntType) : SIntType(IntWidth(desired)) - (t) : error("Non-ground type") - -defn pad-widths-e (desired:Int,e:Expression) -> Expression : - defn trim (desired:Int, e:Expression) : - ;; println-all(["TRIM " desired " e " e]) - DoPrim(BITS-SELECT-OP,list(e),list(desired - 1, 0),set-width(desired,type(e))) - defn pad (desired:Int, e:Expression) : - ;; println-all(["PAD " desired " e " e]) - DoPrim(PAD-OP,list(e),list(desired),set-width(desired,type(e))) - defn trim-pad (desired:Int, e:Expression) : - val i = int-width!(type(e)) - if i > desired : trim(desired, e) - else if i == desired : e - else : pad(desired, e) - defn self-pad-widths-e (e:Expression) -> Expression : - pad-widths-e(int-width!(type(e)), e) - ;; println-all(["PAD-E " desired " " e]) - match(e) : - (e:DoPrim) : - val new-desired = reduce(max, 0, map(int-width!{type(_)}, args(e))) - ;; println-all([" NEW DESIRED " new-desired]) - val e* = - if contains?([CONCAT-OP, DYN-SHIFT-RIGHT-OP, DYN-SHIFT-LEFT-OP], op(e)) : - DoPrim(op(e), map(self-pad-widths-e, args(e)), consts(e), type(e)) - else if contains?([MUX-OP], op(e)) : - DoPrim(op(e), list(pad-widths-e(1, args(e)[0]), pad-widths-e(new-desired, args(e)[1]), pad-widths-e(new-desired, args(e)[2])), consts(e), type(e)) - else : - map(pad-widths-e{new-desired,_},e) - trim-pad(desired, e*) - (e:WRef|WSubfield|WIndex) : - trim-pad(desired, e) - (e:UIntValue) : - val i = int-width!(type(e)) - if i > desired : trim(desired, e) - else : UIntValue(value(e),IntWidth(desired)) - (e:SIntValue) : - val i = int-width!(type(e)) - if i > desired : trim(desired, e) - else : SIntValue(value(e),IntWidth(desired)) - (e:Register) : - val value* = pad-widths-e(desired, value(e)) - Register(type(value*), value*, pad-widths-e(1, enable(e))) - (e:ReadPort) : - if int-width!(type(e)) != desired : error("ReadPort has different width than desired") - else : ReadPort(mem(e), self-pad-widths-e(index(e)), type(e), pad-widths-e(1, enable(e))) - (e:WritePort) : - if int-width!(type(e)) != desired : error("WritePort has different width than desired") - else : WritePort(mem(e), self-pad-widths-e(index(e)), type(e), pad-widths-e(1, enable(e))) - (e) : error(to-string $ e) - -defn pad-widths-s (s:Stmt) -> Stmt : - ;; println-all(["PAD-S " s]) - match(map(pad-widths-s,s)) : - (s:Connect) : - val i = int-width!(type(loc(s))) - val loc* = pad-widths-e(i,loc(s)) - val exp* = pad-widths-e(i,exp(s)) - Connect(info(s),loc*,exp*) - (s:DefNode) : - val i = int-width!(type(value(s))) - val exp* = pad-widths-e(i,value(s)) - DefNode(info(s),name(s),exp*) - (s) : - s - -public defn pad-widths (c:Circuit) -> Circuit : - Circuit{info(c),_,main(c)} $ - for m in modules(c) map : - match(m) : - (m:ExModule) : m - (m:InModule) : InModule(info(m),name(m),ports(m),pad-widths-s(body(m))) - ;============= Flo Backend ================ public defstruct Flo <: Pass : diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index 374cf58c..f85ff7c9 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -131,6 +131,10 @@ defsyntax firrtl : FPE(form, "Expected a vector type here.") when t not-typeof VectorType t + ;Error if not an accessor direction + accdir! = (?a:#accdir) : a + accdir! != () : FPE(form, "Expected an accessor direction here.") + ;Error if not an expression exp! = (?e:#exp) : e exp! != () : FPE(form, "Expected an expression here.") @@ -196,6 +200,12 @@ defsyntax firrtl : field = (flip ?name:#id! #:! ?type:#type!) : Field(name, REVERSE, type) field = (?name:#id #:! ?type:#type!) : Field(name, DEFAULT, type) + defrule accdir : + accdir = (read) : READ + accdir = (write) : WRITE + accdir = (infer) : INFER + accdir = (rdwr) : RDWR + defrule width : width = (?x:#int) : IntWidth(x) width = (?) : UnknownWidth() @@ -208,12 +218,15 @@ defsyntax firrtl : stmt = (smem ?name:#id! #:! ?t:#vectype!) : DefMemory(first-info(form),name, t, true) stmt = (inst ?name:#id! #of! ?m:#ref!) : DefInstance(first-info(form),name, m) stmt = (node ?name:#id! #=! ?e:#exp!) : DefNode(first-info(form),name, e) - stmt = (accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i) + stmt = (on-reset ?x:#exp := ?y:#exp!) : OnReset(first-info(form),x, y) + stmt = (read accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i,READ) + stmt = (write accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i,WRITE) + stmt = (infer accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i,INFER) + stmt = (rdwr accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i,RDWR) stmt = (?s:#stmt/when) : s stmt = (?x:#exp := ?y:#exp!) : Connect(first-info(form),x, y) stmt = (?x:#exp <> ?y:#exp!) : BulkConnect(first-info(form),x, y) - stmt = (on-reset ?x:#exp := ?y:#exp!) : OnReset(first-info(form),x, y) stmt = ((?s:#stmt ?ss:#stmt ... ?rest ...)) : if not empty?(rest) : diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index e29bf4ac..8e65005f 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -98,7 +98,15 @@ defmethod print (o:OutputStream, d:Flip) : DEFAULT : "" REVERSE: "flip" -defmethod print (o:OutputStream, d:Direction) : +defmethod print (o:OutputStream, d:AccDirection) : + print{o, _} $ + switch {d == _} : + READ : "read" + WRITE: "write" + INFER: "infer" + RDWR: "rdwr" + +defmethod print (o:OutputStream, d:PortDirection) : print{o, _} $ switch {d == _} : INPUT : "input" @@ -177,12 +185,16 @@ defmethod print (o:OutputStream, c:Stmt) : (c:DefNode) : print-all(o,["node " name(c) " = " value(c)]) (c:DefAccessor) : - print-all(o,["accessor " name(c) " = " source(c) "[" index(c) "]"]) + print-all(o,[acc-dir(c) " accessor " name(c) " = " source(c) "[" index(c) "]"]) (c:Conditionally) : - print-all(o, ["when " pred(c) " :"]) - print-debug(o,c) - print(o,"\n") - print(io,conseq(c)) + if conseq(c) typeof Begin : + print-all(o, ["when " pred(c) " :"]) + print-debug(o,c) + print(o,"\n") + print(io,conseq(c)) + else : + print-all(o, ["when " pred(c) " : " conseq(c)]) + print-debug(o,c) if alt(c) not-typeof EmptyStmt : print(o, "\nelse :") print(io, "\n") @@ -277,7 +289,7 @@ defmethod map (f: Expression -> Expression, e:Expression) -> Expression : public defmulti map (f: Expression -> Expression, c:?T&Stmt) -> T defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : match(c) : - (c:DefAccessor) : DefAccessor(info(c),name(c), f(source(c)), f(index(c))) + (c:DefAccessor) : DefAccessor(info(c),name(c), f(source(c)), f(index(c)),acc-dir(c)) (c:DefNode) : DefNode(info(c),name(c), f(value(c))) (c:DefInstance) : DefInstance(info(c),name(c), f(module(c))) (c:Conditionally) : Conditionally(info(c),f(pred(c)), conseq(c), alt(c)) diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 6e030d24..6ad4e63f 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -27,7 +27,8 @@ public val standard-passes = to-list $ [ Inline() SplitExp() CheckLowForm() - ToRealIR() ] + ToRealIR() + Pad() ] ;=============== WORKING IR ================================ public definterface Kind public defstruct WireKind <: Kind @@ -108,13 +109,13 @@ defn swap (f:Flip) -> Flip : DEFAULT : REVERSE REVERSE : DEFAULT -defn swap (d:Direction) -> Direction : +defn swap (d:PortDirection) -> PortDirection : switch {_ == d} : OUTPUT : INPUT INPUT : OUTPUT -public defn times (flip:Flip,d:Direction) -> Direction : flip * d -public defn times (d:Direction,flip:Flip) -> Direction : +public defn times (flip:Flip,d:PortDirection) -> PortDirection : flip * d +public defn times (d:PortDirection,flip:Flip) -> PortDirection : switch {_ == flip} : DEFAULT : d REVERSE : swap(d) @@ -135,13 +136,13 @@ defn to-field (p:Port) -> Field : else if direction(p) == INPUT : Field(name(p),REVERSE,type(p)) else : error("Shouldn't be here") -defn to-dir (g:Gender) -> Direction : +defn to-dir (g:Gender) -> PortDirection : switch {_ == g} : MALE : INPUT FEMALE : OUTPUT defn gender (s:DefAccessor) -> Gender : - switch {_ == dir(s)} : + switch {_ == acc-dir(s)} : READ : MALE WRITE : FEMALE INFER : UNKNOWN-GENDER @@ -331,6 +332,8 @@ 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) -> Stmt : + map{to-stmt,_} $ map(to-exp,s) Circuit(info(c),modules*, main(c)) where : val modules* = @@ -1342,7 +1345,7 @@ public defn expand-whens (c:Circuit) -> Circuit : 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)) + 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,decs:Vector,cons:Vector) -> Stmt : @@ -1352,7 +1355,7 @@ public defn expand-whens (c:Circuit) -> Circuit : 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)) + 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) @@ -1361,12 +1364,12 @@ public defn expand-whens (c:Circuit) -> Circuit : (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()) : + if en == UIntValue(to-long(1),UnknownWidth()) : add{cons,_} $ Connect(info(s),ref,e) else : - add{cons,_} $ Conditionally(en,Connect(info(s),ref,e),EmptyStmt()) + add{cons,_} $ Conditionally(info(s),en,Connect(info(s),ref,e),EmptyStmt()) (e:False) : - add(errors,RefNotConnected(info(s), name(s)) + add(errors,RefNotConnected(info(s), name(s))) (s:DefAccessor) : add(decs,s) val t = type(type(source(s)) as VectorType) @@ -1377,12 +1380,12 @@ public defn expand-whens (c:Circuit) -> Circuit : match(e) : (e:Expression) : val en = (to-exp $ optimize $ get-write-enable(table[n])) as Expression - if en == UIntValue(1,UnknownWidth()) : + if en == UIntValue(to-long(1),UnknownWidth()) : add{cons,_} $ Connect(info(s),ref,e) else : - add{cons,_} $ Conditionally(en,Connect(info(s),ref,e),EmptyStmt()) + add{cons,_} $ Conditionally(info(s),en,Connect(info(s),ref,e),EmptyStmt()) (e:False) : - add(errors,RefNotConnected(info(s), n) + add(errors,RefNotConnected(info(s), n)) (s:DefInstance) : add(decs,s) for f in fields(type(module(s)) as BundleType) map : @@ -1393,7 +1396,7 @@ public defn expand-whens (c:Circuit) -> Circuit : 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) + 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 @@ -1404,7 +1407,7 @@ public defn expand-whens (c:Circuit) -> Circuit : (m:InModule) : val assign = HashTable(symbol-hash) val resets = HashTable(symbol-hash) - ;val flattn = HashTable(symbol-hash) + val flattn = HashTable(symbol-hash) for p in ports(m) do : if direction(p) == OUTPUT : @@ -1431,10 +1434,12 @@ public defn expand-whens (c:Circuit) -> Circuit : 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 c* = Circuit(info(c),modules*, main(c)) where : val modules* = for m in modules(c) map : expand-whens(m) + throw(PassExceptions(errors)) when not empty?(errors) + c* ;;================ INFER WIDTHS ============================= @@ -1654,6 +1659,8 @@ defn gen-constraints (m:Module, h:HashTable, v:Vector) -> Mod defn gen-constraints-s (s:Stmt) -> Stmt : match(map(gen-constraints-s,s)) : (s:DefWire) : DefWire(info(s),name(s),h[name(s)]) + (s:DefRegister) : DefRegister(info(s),name(s),h[name(s)]) + (s:DefAccessor) : DefAccessor(info(s),name(s),gen-constraints(source(s)),gen-constraints(index(s)), acc-dir(s)) (s:DefInstance) : DefInstance(info(s),name(s),gen-constraints(module(s))) (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)] as VectorType,seq?(s)) (s:DefNode) : @@ -1672,7 +1679,7 @@ defn gen-constraints (m:Module, h:HashTable, v:Vector) -> Mod 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)) + map(gen-constraints-s,Conditionally(info(s),p,conseq(s),alt(s))) (s) : s defn gen-constraints (e:Expression) -> Expression : @@ -1708,8 +1715,11 @@ defn build-environment (c:Circuit,m:Module,h:HashTable) -> HashTabl defn build-environment (s:Stmt) -> False : match(s) : (s:DefWire) : h[name(s)] = remove-unknowns(type(s)) + (s:DefRegister) : h[name(s)] = remove-unknowns(type(s)) (s:DefInstance) : h[name(s)] = h[name(module(s) as WRef)] (s:DefMemory) : h[name(s)] = remove-unknowns(type(s)) + (s:DefAccessor) : + h[name(s)] = remove-unknowns(type(type(source(s)) as VectorType)) (s:DefNode) : h[name(s)] = remove-unknowns(type(value(s))) (s) : false do(build-environment,s) @@ -1746,7 +1756,9 @@ defn reduce-var-widths (c:Circuit,h:HashTable) -> Circuit : (w:MinusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ - _}) (w:ExpWidth) : apply(2,solve(arg1(w)),{pow(_,_) - 1}) (w:IntWidth) : width(w) - (w) : error("Shouldn't be here") + (w) : + println(w) + error("Shouldn't be here") val s = solve(w) if s typeof Int : IntWidth(s as Int) @@ -1889,14 +1901,16 @@ defn split-exp (c:Circuit) : add(v,DefNode(info,n*,e)) WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER) (e) : e + defn f (s:Stmt) -> False: split-exp-s(s,v,sh) match(s) : (s:Begin) : - defn f (s:Stmt) -> False: split-exp-s(s,v,sh) do(f,s) - (s:Conditionally) : error("Shouldn't be here") + (s:Conditionally) : + add(v,map(split-exp-e{_,false,info(s)},s)) + do(f,s) (s:Connect) : match(loc(s)) : - (e:WritePort) : add(v,map(split-exp-e{_,full-name(exp(s)),info(s)},s)) + ;(e:WritePort) : add(v,map(split-exp-e{_,full-name(exp(s)),info(s)},s)) (e) : add(v,map(split-exp-e{_,full-name(loc(s)),info(s)},s)) (s:DefNode) : add(v,map(split-exp-e{_,name(s),info(s)},s)) (s) : add(v,map(split-exp-e{_,false,info(s)},s)) @@ -1934,7 +1948,6 @@ defn to-real-ir (c:Circuit) : (e) : e defn to-stmt (s:Stmt) : match(map(to-exp,s)) : - (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) @@ -1993,7 +2006,7 @@ public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) : (s:DefInstance) : DefInstance(info(s),rename(name(s)),module(s)) (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s)) (s:DefNode) : DefNode(info(s),rename(name(s)),value(s)) - (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),source(s),index(s)) + (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),source(s),index(s),acc-dir(s)) (s) : map(to-stmt,s) defn to-port (p:Port) -> Port : Port(info(p),rename(name(p)),direction(p),type(p)) @@ -2006,3 +2019,80 @@ public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) : (m:ExModule) : m +;========== Pad Widths ================== + +public defstruct Pad <: Pass +public defmethod pass (b:Pad) -> (Circuit -> Circuit) : pad-widths +public defmethod name (b:Pad) -> String : "Pad Widths" + +defn int-width! (t:Type) -> Int : + match(width!(t)) : + (w:IntWidth) : width(w) + (w) : error("Non-int width") + +defn set-width (desired:Int,t:Type) -> Type : + match(t) : + (t:UIntType) : UIntType(IntWidth(desired)) + (t:SIntType) : SIntType(IntWidth(desired)) + (t) : error("Non-ground type") + +defn pad-widths-e (desired:Int,e:Expression) -> Expression : + defn trim (desired:Int, e:Expression) : + ;; println-all(["TRIM " desired " e " e]) + DoPrim(BITS-SELECT-OP,list(e),list(desired - 1, 0),set-width(desired,type(e))) + defn pad (desired:Int, e:Expression) : + ;; println-all(["PAD " desired " e " e]) + DoPrim(PAD-OP,list(e),list(desired),set-width(desired,type(e))) + defn trim-pad (desired:Int, e:Expression) : + val i = int-width!(type(e)) + if i > desired : trim(desired, e) + else if i == desired : e + else : pad(desired, e) + defn self-pad-widths-e (e:Expression) -> Expression : + pad-widths-e(int-width!(type(e)), e) + ;; println-all(["PAD-E " desired " " e]) + match(e) : + (e:DoPrim) : + val new-desired = reduce(max, 0, map(int-width!{type(_)}, args(e))) + ;; println-all([" NEW DESIRED " new-desired]) + val e* = + if contains?([CONCAT-OP, DYN-SHIFT-RIGHT-OP, DYN-SHIFT-LEFT-OP], op(e)) : + DoPrim(op(e), map(self-pad-widths-e, args(e)), consts(e), type(e)) + else if contains?([MUX-OP], op(e)) : + DoPrim(op(e), list(pad-widths-e(1, args(e)[0]), pad-widths-e(new-desired, args(e)[1]), pad-widths-e(new-desired, args(e)[2])), consts(e), type(e)) + else : + map(pad-widths-e{new-desired,_},e) + trim-pad(desired, e*) + (e:WRef|WSubfield|WIndex) : + trim-pad(desired, e) + (e:UIntValue) : + val i = int-width!(type(e)) + if i > desired : trim(desired, e) + else : UIntValue(value(e),IntWidth(desired)) + (e:SIntValue) : + val i = int-width!(type(e)) + if i > desired : trim(desired, e) + else : SIntValue(value(e),IntWidth(desired)) + (e) : error(to-string $ e) + +defn pad-widths-s (s:Stmt) -> Stmt : + ;; println-all(["PAD-S " s]) + match(map(pad-widths-s,s)) : + (s:Connect) : + val i = int-width!(type(loc(s))) + val loc* = pad-widths-e(i,loc(s)) + val exp* = pad-widths-e(i,exp(s)) + Connect(info(s),loc*,exp*) + (s:DefNode) : + val i = int-width!(type(value(s))) + val exp* = pad-widths-e(i,value(s)) + DefNode(info(s),name(s),exp*) + (s) : s + +public defn pad-widths (c:Circuit) -> Circuit : + Circuit{info(c),_,main(c)} $ + for m in modules(c) map : + match(m) : + (m:ExModule) : m + (m:InModule) : InModule(info(m),name(m),ports(m),pad-widths-s(body(m))) + diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index 0e04df8a..0367c333 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -4,43 +4,6 @@ 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() - 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 : @@ -49,10 +12,6 @@ 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) : @@ -105,9 +64,6 @@ defn emit (e:Expression) -> String : (e:SIntValue) : string-join $ [width!(type(e)) "'sd" value(e)] (e:Subfield) : error("Non-supported expression") (e:Index) : error("Non-supported expression") - (e:Register) : error("Non-supported expression") - (e:ReadPort) : error("Non-supported expression") - (e:WritePort) : error("Non-supported expression") (e:DoPrim) : val sargs = map(emit-as-type{_,type(e)},args(e)) val xargs = map(emit-signed-if-any{_,args(e)},args(e)) @@ -184,18 +140,20 @@ defn get-name (e:Expression) -> Symbol : (e) : error("Shouldn't be here") defn emit-module (m:InModule) : - val decs = HashTable(sym-hash) ; all declarations - val cons = HashTable(sym-hash) ; all connections + val decs = HashTable(symbol-hash) ; all declarations + val cons = HashTable(symbol-hash) ; all connections + val ens = HashTable(symbol-hash) ; all enables defn build-table (m:InModule) : defn build-table (s:Stmt) -> Stmt : match(map(build-table,map(remove-subfield,s))) : - (s:DefWire|DefReg|DefAccessor|DefMemory|DefNode|DefInstance) : decs[name(s)] = s + (s:DefWire|DefRegister|DefAccessor|DefMemory|DefNode|DefInstance) : decs[name(s)] = s (s:Conditionally) : val n = get-name(loc(conseq(s) as Connect)) - cons[n] = s + ens[n] = pred(s) + cons[n] = exp(conseq(s) as Connect) (s:Connect) : val n = get-name(loc(s)) - cons[n] = s + cons[n] = exp(s) (s) : false s build-table(body(m)) @@ -211,135 +169,59 @@ defn emit-module (m:InModule) : val sh = get-sym-hash(m) - for (sym -> dec) in decs do : - match(value(dec)) : - (dec:DefWire) : - add(wires,["wire " get-width(type(s)) " " name(s) ";"]) - emit-blocking-connect(cons[sym]) - (dec:DefRegister) : - add(regs,["reg " get-width(type(s)) " " name(s) ";"]) - emit-nonblocking-connect(cons[sym]) - (dec:DefMemory) : + for x in decs do : + val sym = key(x) + match(value(x)) : + (s:DefWire) : + add(wires,["wire " get-width(type(s)) " " sym ";"]) + add(assigns,["assign " sym " = " emit(cons[sym]) ";"]) + (s:DefRegister) : + add(regs,["reg " get-width(type(s)) " " sym ";"]) + if key?(ens,sym) : + add(updates,["if(" emit(ens[sym]) ") begin"]) + add(updates,[" " sym " <= " emit(cons[sym]) ";"]) + add(updates,["end"]) + else : + add(updates,[sym " <= " emit(cons[sym]) ";"]) + (s:DefMemory) : val vtype = type(s) as VectorType - add(regs,["reg " get-width(type(vtype)) " " name(s) " [0:" size(vtype) "];"]) + add(regs,["reg " get-width(type(vtype)) " " sym " [0:" size(vtype) "];"]) add(inits,["for (initvar = 0; initvar < " size(vtype) "; initvar = initvar+1)"]) - add(inits,[" " name(s) "[initvar] = {" width!(type(vtype)) "{$random}};"]) + add(inits,[" " sym "[initvar] = {" width!(type(vtype)) "{$random}};"]) (s:DefNode) : - add(wires,["wire " get-width(type(value(s))) " " name(s) ";"]) - add(assigns,["assign " name(s) " = " emit(value(s)) ";"]) + add(wires,["wire " get-width(type(value(s))) " " sym ";"]) + add(assigns,["assign " sym " = " emit(value(s)) ";"]) (s:DefInstance) : - inst-ports[name(s)] = Vector() - insts[name(s)] = name(module(s) as Ref) + inst-ports[sym] = Vector() + insts[sym] = name(module(s) as Ref) for f in fields(type(module(s)) as BundleType) do : - val n* = to-symbol $ string-join $ [name(s) "_" name(f)] + val n* = to-symbol $ string-join $ [sym "_" name(f)] add(wires,["wire " get-width(type(f)) " " n* ";"]) - add(inst-ports[name(s)], ["." name(f) "( " n* " )"]) + add(inst-ports[sym], ["." name(f) "( " n* " )"]) (s:DefAccessor) : - switch {_ == dir(s)} : + switch {_ == acc-dir(s)} : READ : val mem-declaration = decs[name(source(s) as Ref)] - val con = cons[sym] - if seq?(mem-declaration) : + if seq?(mem-declaration as DefMemory) : + ; to make it sequential, register the index for an additional cycle val index* = Ref(firrtl-gensym(name(index(s) as Ref),sh),type(index(s))) - add(regs,[ "reg " get-width(type(index*)) " " name(index*) ";"]) ; to make it sequential, register the index for an additional cycle + add(regs,[ "reg " get-width(type(index*)) " " name(index*) ";"]) add(inits,[name(index*) " = {" width!(type(index*)) "{$random}};"]) add(updates,[name(index*) " <= " emit(index(s)) ";"]) - add(assigns,["assign " n " = " emit(mem(s)) "[" emit(index*) "];"]) - else : - add(assigns,["assign " n " = " emit(mem(s)) "[" emit(index(s)) "];"]) - - - - - defn emit-blocking-connect (s:Stmt) : - match(s) : - (s:Connect) : add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"]) - (s:Conditionally) : error("Shouldn't be here") - defn emit-nonblocking-connect (s:Stmt) : - match(s) : - (s:Connect) : - add(updates,[n " <= " emit(value(reg)) ";"]) - (s:Conditionally) : - match(conseq(s)) : - (c:Connect) : - add(updates,["if(" emit(pred(s)) ") begin"]) - add(updates,[" " emit(loc(c) " <= " emit(exp(c)) ";"]) - add(updates,["end"]) - (c) : error("Shouldn't be here") - (s) : error("Shouldn't be here") - -; 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(s) : - (s:DefWire) : - add(wires,["wire " get-width(type(s)) " " name(s) ";"]) - add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"]) + ; emit read accessor + add(assigns,["assign " sym " = " emit(source(s)) "[" emit(index*) "];"]) + else : + ; emit read accessor + add(assigns,["assign " sym " = " emit(source(s)) "[" emit(index(s)) "];"]) + WRITE : + if key?(ens,sym) : + add(updates,["if(" emit(ens[sym]) ") begin"]) + add(updates,[" " emit(source(s)) "[" emit(index(s)) "] <= " emit(cons[sym]) ";"]) + add(updates,["end"]) + else : + add(updates,[emit(source(s)) "[" emit(index(s)) "] <= " emit(cons[sym]) ";"]) - (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() - insts[name(s)] = name(module(s) as Ref) - for f in fields(type(module(s)) as BundleType) do : - val n* = to-symbol $ string-join $ [name(s) "_" name(f)] - add(wires,["wire " get-width(type(f)) " " n* ";"]) - add(inst-ports[name(s)], ["." name(f) "( " n* " )"]) - (s:DefMemory) : - val vtype = type(s) as VectorType - add(regs,["reg " get-width(type(vtype)) " " name(s) " [0:" size(vtype) "];"]) - add(inits,["for (initvar = 0; initvar < " size(vtype) "; initvar = initvar+1)"]) - add(inits,[" " name(s) "[initvar] = {" width!(type(vtype)) "{$random}};"]) - (s:DefNode) : - 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:Conditionally) : emit-pred-connect(pred(s),conseq(s) as Connect) - (s:Connect) : emit-pred-connect(UIntValue(1,1),s) - (s) : s - - - ;==== Actually printing module ===== val port-indent = " " print-all(["module " name(m) "(input clk, input reset,\n"]) -- cgit v1.2.3 From df4bae5c7a95d3a56f95d86212f083b7ba121da7 Mon Sep 17 00:00:00 2001 From: azidar Date: Tue, 7 Jul 2015 10:13:29 -0700 Subject: Pass most tests. The ones that do not pass are not expected to, yet --- src/main/stanza/passes.stanza | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 6ad4e63f..b500f991 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -207,7 +207,7 @@ defmethod print (o:OutputStream, k:Kind) : (k:WriteAccessorKind) : "wacc" defn hasGender (e:?) : - e typeof WRef|WSubfield|WIndex + e typeof WRef|WSubfield|WIndex|DefAccessor defn hasWidth (e:?) : e typeof UIntType|SIntType|UIntValue|SIntValue @@ -622,7 +622,7 @@ defn resolve-genders (c:Circuit) : get-gender(name(s),MALE) DefInstance(info(s),name(s),resolve-expr(module(s),MALE)) (s:DefAccessor) : - val gender* = get-gender(name(s),UNKNOWN-GENDER) + val gender* = get-gender(name(s),gender(s)) val index* = resolve-expr(index(s),MALE) val source* = resolve-expr(source(s),gender*) DefAccessor(info(s),name(s),source*,index*,to-acc-dir(gender*)) @@ -702,17 +702,19 @@ defn expand-stmt (s:Stmt) -> Stmt : else : val vtype = type(type(source(s)) as VectorType) val wire = DefWire(info(s),name(s),vtype) - switch {gender(s) == _} : - MALE : Begin{list(wire,_)} $ ConnectFromIndexed( + switch {acc-dir(s) == _} : + READ : Begin{list(wire,_)} $ ConnectFromIndexed( info(s), index(s), WRef(name(wire),vtype,NodeKind(),FEMALE), expand-vector(source(s))) - FEMALE: Begin{list(wire,_)} $ ConnectToIndexed( + WRITE : Begin{list(wire,_)} $ ConnectToIndexed( info(s), index(s), expand-vector(source(s)), WRef(name(wire),vtype,NodeKind(),MALE)) + INFER : error("Shouldn't be here") + RDWR : error("Haven't implemented RDWR yet") (s) : map(expand-stmt,s) defn expand-accessors (c:Circuit) : -- cgit v1.2.3 From 521bac8227030f12090e45f4c1a0e02bf59884ec Mon Sep 17 00:00:00 2001 From: azidar Date: Tue, 7 Jul 2015 13:25:33 -0700 Subject: Passes riscv-mini tests --- src/main/stanza/passes.stanza | 6 +++++- src/main/stanza/verilog.stanza | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index b500f991..ed3f0079 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -1908,7 +1908,7 @@ defn split-exp (c:Circuit) : (s:Begin) : do(f,s) (s:Conditionally) : - add(v,map(split-exp-e{_,false,info(s)},s)) + add(v,map(split-exp-e{_,full-name(loc(conseq(s) as Connect)),info(s)},s)) do(f,s) (s:Connect) : match(loc(s)) : @@ -2089,6 +2089,10 @@ defn pad-widths-s (s:Stmt) -> Stmt : val i = int-width!(type(value(s))) val exp* = pad-widths-e(i,value(s)) DefNode(info(s),name(s),exp*) + (s:Conditionally) : + val i = int-width!(type(pred(s))) + val pred* = pad-widths-e(i,pred(s)) + Conditionally(info(s),pred*,conseq(s),alt(s)) (s) : s public defn pad-widths (c:Circuit) -> Circuit : diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index 0367c333..1904f92f 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -140,13 +140,16 @@ defn get-name (e:Expression) -> Symbol : (e) : error("Shouldn't be here") defn emit-module (m:InModule) : + val vdecs = Vector>() ; all declarations val decs = HashTable(symbol-hash) ; all declarations val cons = HashTable(symbol-hash) ; all connections val ens = HashTable(symbol-hash) ; all enables defn build-table (m:InModule) : defn build-table (s:Stmt) -> Stmt : match(map(build-table,map(remove-subfield,s))) : - (s:DefWire|DefRegister|DefAccessor|DefMemory|DefNode|DefInstance) : decs[name(s)] = s + (s:DefWire|DefRegister|DefAccessor|DefMemory|DefNode|DefInstance) : + add(vdecs,name(s) => s) + decs[name(s)] = s (s:Conditionally) : val n = get-name(loc(conseq(s) as Connect)) ens[n] = pred(s) @@ -169,7 +172,7 @@ defn emit-module (m:InModule) : val sh = get-sym-hash(m) - for x in decs do : + for x in vdecs do : val sym = key(x) match(value(x)) : (s:DefWire) : @@ -198,6 +201,8 @@ defn emit-module (m:InModule) : val n* = to-symbol $ string-join $ [sym "_" name(f)] add(wires,["wire " get-width(type(f)) " " n* ";"]) add(inst-ports[sym], ["." name(f) "( " n* " )"]) + if flip(f) == REVERSE : + add(assigns,["assign " n* " = " emit(cons[n*]) ";"]) (s:DefAccessor) : switch {_ == acc-dir(s)} : READ : @@ -210,9 +215,11 @@ defn emit-module (m:InModule) : add(updates,[name(index*) " <= " emit(index(s)) ";"]) ; emit read accessor + add(wires,["wire " get-width(type(type(source(s)) as VectorType)) " " sym ";"]) add(assigns,["assign " sym " = " emit(source(s)) "[" emit(index*) "];"]) else : ; emit read accessor + add(wires,["wire " get-width(type(type(source(s)) as VectorType)) " " sym ";"]) add(assigns,["assign " sym " = " emit(source(s)) "[" emit(index(s)) "];"]) WRITE : if key?(ens,sym) : @@ -231,8 +238,11 @@ defn emit-module (m:InModule) : if length(ports(m)) - 1 == i : end = "\n);\n" switch {_ == direction(p)} : - INPUT : print-all([port-indent "input " get-width(type(p)) " " name(p) end]) - OUTPUT : print-all([port-indent "output " get-width(type(p)) " " name(p) end]) + INPUT : + print-all([port-indent "input " get-width(type(p)) " " name(p) end]) + OUTPUT : + print-all([port-indent "output " get-width(type(p)) " " name(p) end]) + add(assigns,["assign " name(p) " = " emit(cons[name(p)]) ";"]) for w in wires do : print(" ") -- cgit v1.2.3 From a62fea153cf01e9f7517c6889198d02e5fbbb266 Mon Sep 17 00:00:00 2001 From: azidar Date: Tue, 7 Jul 2015 14:56:47 -0700 Subject: Updated flo backend --- src/main/stanza/compilers.stanza | 60 ++++++++++++++-------------- src/main/stanza/firrtl-test-main.stanza | 5 +-- src/main/stanza/flo.stanza | 71 +++++++++++++++++++++------------ src/main/stanza/passes.stanza | 1 + 4 files changed, 79 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index a3b04a94..2f6329dc 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -3,40 +3,40 @@ defpackage firrtl/compiler : import verse import firrtl/passes import firrtl/errors -; import firrtl/flo + import firrtl/flo import firrtl/verilog import firrtl/ir2 import firrtl/ir-utils -;public defstruct StandardFlo <: Compiler : -; file: String with: (as-method => true) -;public defmethod passes (c:StandardFlo) -> List : -; to-list $ [ -; CheckHighForm(expand-delin) -; ;; TempElimination() -; ToWorkingIR() -; MakeExplicitReset() -; ResolveKinds() -; CheckKinds() -; InferTypes() -; CheckTypes() -; ResolveGenders() -; CheckGenders() -; ExpandAccessors() -; LowerToGround() -; ExpandIndexedConnects() -; ExpandWhens() -; InferWidths() -; Pad() -; Inline() -; SplitExp() -; ToRealIR() -; SpecialRename(`#,`_) -; SpecialRename(`$,`::) -; CheckHighForm(`::) -; CheckLowForm() -; Flo(file(c)) -; ] +public defstruct StandardFlo <: Compiler : + file: String with: (as-method => true) +public defmethod passes (c:StandardFlo) -> List : + to-list $ [ + CheckHighForm(expand-delin) + ;; TempElimination() + ToWorkingIR() + MakeExplicitReset() + ResolveKinds() + CheckKinds() + InferTypes() + CheckTypes() + ResolveGenders() + CheckGenders() + ExpandAccessors() + LowerToGround() + ExpandIndexedConnects() + ExpandWhens() + InferWidths() + Pad() + Inline() + SplitExp() + ToRealIR() + SpecialRename(`#,`_) + SpecialRename(`$,`::) + CheckHighForm(`::) + CheckLowForm() + Flo(file(c)) + ] public defstruct StandardVerilog <: Compiler : file: String with: (as-method => true) diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza index 374fe438..beb288b1 100644 --- a/src/main/stanza/firrtl-test-main.stanza +++ b/src/main/stanza/firrtl-test-main.stanza @@ -11,7 +11,7 @@ #include("primop.stanza") #include("errors.stanza") #include("compilers.stanza") -;#include("flo.stanza") +#include("flo.stanza") #include("verilog.stanza") ;Custom Packages @@ -80,8 +80,7 @@ defn main () : run-passes(c,get-passes(to-list(pass-names))) else : switch {_ == compiler} : - ;"flo" : run-passes(c,StandardFlo(output as String)) - "flo" : run-passes(c,StandardVerilog(output as String)) + "flo" : run-passes(c,StandardFlo(output as String)) "verilog" : run-passes(c,StandardVerilog(output as String)) "verilute" : run-passes(c,InstrumentedVerilog(output as String,to-list $ pass-args)) else : error("Invalid compiler flag") diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza index cf15638d..9f4cdc8c 100644 --- a/src/main/stanza/flo.stanza +++ b/src/main/stanza/flo.stanza @@ -11,8 +11,16 @@ public defstruct Flo <: Pass : file : String public defmethod pass (b:Flo) -> (Circuit -> Circuit) : emit-flo{file(b),_} public defmethod name (b:Flo) -> String : "To Flo" + +definterface FloKind +defstruct FRegKind <: FloKind +defstruct FWritePortKind <: FloKind : + mem: Expression + index: Expression +defstruct FOutputPortKind <: FloKind defn is-sint? (arg:Expression) -> True|False : type(arg) typeof SIntType +defn type (s:DefAccessor) -> Type : type(type(source(s)) as VectorType) defn flo-op-name (op:PrimOp, args:List) -> String : switch {op == _ } : @@ -94,12 +102,6 @@ defn emit! (e:Expression,top:Symbol) : (e:SIntValue) : emit-all([value(e) "'" sane-width(width(e))], top) (e:Subfield) : emit-all([exp(e) "/" name(e)], top) (e:Index) : emit-all([exp(e) "/" value(e)], top) - ;(e:Pad) : - ;emit-all(["rsh'" prim-width(type(e)) " " value(e) " 0"], top) - (e:Register) : - emit-all(["reg'" prim-width(type(e)) " " enable(e) " " value(e)], top) - (e:ReadPort) : - emit-all(["rd'" prim-width(type(e)) " " "1" " " mem(e) " " index(e)], top) ;; enable(e) (e:DoPrim) : if cmp-op?(op(e)) : emit-all([flo-op-name(op(e), args(e)) "'" prim-width(type(args(e)[0]))], top) @@ -137,41 +139,60 @@ defn maybe-mov (e:Expression) -> String : (e) : false if need-mov?: "mov " else: "" -defn emit-s (s:Stmt, v:List, top:Symbol,sh:HashTable) : +defn emit-s (s:Stmt, flokinds:HashTable, top:Symbol,sh:HashTable) : + defn emit-connect (s:Connect, en:Expression) : + match(loc(s)) : + (r:Ref) : + val n = name(r) + if key?(flokinds,n) : + match(flokinds[n]) : + (k:FRegKind) : + emit-all(["reg'" prim-width(type(r)) " " en " " exp(s)], top) + (k:FWritePortKind) : + emit-all([top "::" n " = wr'" prim-width(type(r)) " " en " " mem(k) " " index(k) " " exp(s) "\n"], top) + (k:FOutputPortKind) : + emit-all([top "::" n " = out'" prim-width(type(r)) " " exp(s) "\n"], top) + (k) : error("Shouldn't be here") + else : + emit-all([top "::" n " = " maybe-mov(exp(s)) exp(s) "\n"], top) + (o) : + println-all(["CONNEcT LOC " loc(s)]) + error("Unknown Connect") match(s) : (s:DefWire) : "" (s:DefInstance) : error("Shouldn't be here") + (e:DefAccessor) : + if acc-dir == READ : + emit-all(["rd'" prim-width(type(e)) " " "1" " " source(e) " " index(e)], top) (s:DefMemory) : val vtype = type(s) as VectorType emit-all([top "::" name(s) " = mem'" prim-width(type(vtype)) " " size(vtype) "\n"], top) (s:DefNode) : emit-all([top "::" name(s) " = " maybe-mov(value(s)) value(s) "\n"], top) - (s:Begin) : do(emit-s{_, v, top,sh}, body(s)) - (s:Connect) : - match(loc(s)) : - (r:Ref) : - val n = name(r) - if contains?(v,n) : - emit-all([top "::" n " = out'" prim-width(type(r)) " " exp(s) "\n"], top) - else : - emit-all([top "::" n " = " maybe-mov(exp(s)) exp(s) "\n"], top) - (w:WritePort) : - val n = firrtl-gensym(`F,sh) - emit-all([top "::" n " = wr'" prim-width(type(w)) " " enable(w) " " mem(w) " " index(w) " " exp(s) "\n"], top) - (o) : - println-all(["CONNEcT LOC " loc(s)]) - error("Unknown Connect") + (s:Begin) : do(emit-s{_, flokinds, top,sh}, body(s)) + (s:Connect) : emit-connect(s,UIntValue(to-long(1),IntWidth(1))) + (s:Conditionally) : emit-connect(conseq(s) as Connect,pred(s)) (s) : s defn emit-module (m:InModule,sh:HashTable) : - val v = Vector() + val flokinds = HashTable(symbol-hash) + defn build-table (s:Stmt) -> False : + do(build-table,s) + match(s) : + (s:DefRegister) : flokinds[name(s)] = FRegKind() + (s:DefAccessor) : + switch {_ == acc-dir(s)} : + WRITE : flokinds[name(s)] = FWritePortKind(source(s),index(s)) + else : false + (s) : false + for port in ports(m) do : if name(port) ==`reset : emit-all([name(m) "::" name(port) " = rst'1\n"], name(m)) else : switch {_ == direction(port)} : INPUT : print-all([name(m) "::" name(port) " = " "in'" prim-width(type(port)) "\n"]) - OUTPUT : add(v,name(port)) - emit-s(body(m), to-list(v), name(m),sh) + OUTPUT : flokinds[name(port)] = FOutputPortKind() + emit-s(body(m), flokinds, name(m),sh) public defn emit-flo (file:String, c:Circuit) : with-output-file{file, _} $ fn () : diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index ed3f0079..43cc06a4 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -1867,6 +1867,7 @@ defn inline-instances (c:Circuit) : defn rename-s (s:Stmt,n:Symbol) -> Stmt : map{rename-e{_,n},_} $ match(map(rename-s{_,n},s)) : (s:DefWire) : DefWire(info(s),rename(name(s),n),type(s)) + (s:DefRegister) : DefRegister(info(s),rename(name(s),n),type(s)) (s:DefInstance) : error("Shouldn't be here") (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s)) (s:DefNode) : DefNode(info(s),rename(name(s),n),value(s)) -- cgit v1.2.3 From 1ed6d4a47c92072b12db4b784f239071e4928049 Mon Sep 17 00:00:00 2001 From: azidar Date: Fri, 10 Jul 2015 13:25:21 -0700 Subject: Added clock support --- src/main/stanza/compilers.stanza | 4 +- src/main/stanza/custom-compiler.stanza | 2 +- src/main/stanza/custom-passes.stanza | 2 +- src/main/stanza/errors.stanza | 31 +++---- src/main/stanza/firrtl-ir.stanza | 4 + src/main/stanza/flo.stanza | 1 + src/main/stanza/ir-parser.stanza | 47 +++++----- src/main/stanza/ir-utils.stanza | 40 +++++---- src/main/stanza/passes.stanza | 157 ++++++++++++++++++--------------- src/main/stanza/verilog.stanza | 79 +++++++++-------- 10 files changed, 198 insertions(+), 169 deletions(-) (limited to 'src') diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index 2f6329dc..c458f1e1 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -15,7 +15,7 @@ public defmethod passes (c:StandardFlo) -> List : CheckHighForm(expand-delin) ;; TempElimination() ToWorkingIR() - MakeExplicitReset() + ;; MakeExplicitReset() ResolveKinds() CheckKinds() InferTypes() @@ -45,7 +45,7 @@ public defmethod passes (c:StandardVerilog) -> List : CheckHighForm(expand-delin) TempElimination() ToWorkingIR() - MakeExplicitReset() + ;; MakeExplicitReset() ResolveKinds() CheckKinds() InferTypes() diff --git a/src/main/stanza/custom-compiler.stanza b/src/main/stanza/custom-compiler.stanza index 773b63ca..91732f22 100644 --- a/src/main/stanza/custom-compiler.stanza +++ b/src/main/stanza/custom-compiler.stanza @@ -17,7 +17,7 @@ public defmethod passes (c:InstrumentedVerilog) -> List : CheckHighForm(expand-delin) TempElimination() ToWorkingIR() - MakeExplicitReset() + ;; MakeExplicitReset() ResolveKinds() CheckKinds() InferTypes() diff --git a/src/main/stanza/custom-passes.stanza b/src/main/stanza/custom-passes.stanza index 6c1e58f6..4904d6d1 100644 --- a/src/main/stanza/custom-passes.stanza +++ b/src/main/stanza/custom-passes.stanza @@ -70,7 +70,7 @@ defn when-coverage (port-name:Symbol, reg-name:Symbol, instrument?:HashTable ; * Unique names per module ; * No name can be a prefix of any other name. ; * all references are declared @@ -88,9 +86,9 @@ defn ModuleNotDefined (info:FileInfo, name:Symbol) : PassException $ string-join $ [info ": Module " name " is not defined."] -defn WrongReset (info:FileInfo, name:Symbol) : - PassException $ string-join $ - [info ": Module " name " has a reset that is not of type UInt<1>."] +;defn WrongReset (info:FileInfo, name:Symbol) : +; PassException $ string-join $ +; [info ": Module " name " has a reset that is not of type UInt<1>."] defn IncorrectNumArgs (info:FileInfo, op:Symbol, n:Int) : PassException $ string-join $ @@ -324,15 +322,15 @@ public defn check-high-form (c:Circuit,sym:Symbol) -> Circuit : names[name(m)] = true for p in ports(m) do : names[name(p)] = true - if name(p) == `reset : - if direction(p) == OUTPUT : - add(errors,WrongReset(info!(m),name(m))) - else : - if type(p) typeof UIntType : - if width(type(p) as UIntType) != IntWidth(1) : - add(errors,WrongReset(info!(m),name(m))) - else : - add(errors,WrongReset(info!(m),name(m))) + ;if name(p) == `reset : + ; if direction(p) == OUTPUT : + ; add(errors,WrongReset(info!(m),name(m))) + ; else : + ; if type(p) typeof UIntType : + ; if width(type(p) as UIntType) != IntWidth(1) : + ; add(errors,WrongReset(info!(m),name(m))) + ; else : + ; add(errors,WrongReset(info!(m),name(m))) map(check-high-form-t{info(p),_},type(p)) map(check-high-form-w{info(p),_},type(p)) @@ -436,6 +434,8 @@ public defn check-kinds (c:Circuit) -> Circuit : ; o node's value cannot be a bundle with a flip in it ; o := has same types ; o 2nd arg in dshr/l must be UInt, in general do primops +; o clock must be ClockType +; o reset must be UInt<1> public defstruct CheckTypes <: Pass public defmethod pass (b:CheckTypes) -> (Circuit -> Circuit) : check-types @@ -499,6 +499,7 @@ defn NodeWithFlips (info:FileInfo) : ;---------------- Helper Functions -------------- defmethod equal? (t1:Type,t2:Type) -> True|False : match(t1,t2) : + (t1:ClockType,t2:ClockType) : true (t1:UIntType,t2:UIntType) : true (t1:SIntType,t2:SIntType) : true (t1:BundleType,t2:BundleType) : @@ -648,7 +649,6 @@ defn gender (s:DefAccessor) -> Gender : INFER : UNKNOWN-GENDER RDWR : BI-GENDER - ;----------------- Check Genders Pass --------------------- public defn check-genders (c:Circuit) -> Circuit : @@ -728,6 +728,7 @@ public defn check-genders (c:Circuit) -> Circuit : ; o no accessors ; o only vecs are for memories ; o no bundles (future, will have them for mems) +; o only predicated conditional connects public defstruct CheckLowForm <: Pass public defmethod pass (b:CheckLowForm) -> (Circuit -> Circuit) : check-low-form diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index b698bae2..b9d2cee4 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -101,6 +101,8 @@ public defstruct DefRegister <: Stmt : info: FileInfo with: (as-method => true) name: Symbol type: Type + clock: Expression + reset: Expression public defstruct DefInstance <: Stmt : ;LOW info: FileInfo with: (as-method => true) name: Symbol @@ -110,6 +112,7 @@ public defstruct DefMemory <: Stmt : ;LOW name: Symbol type: VectorType seq?: True|False + clock: Expression public defstruct DefNode <: Stmt : ;LOW info: FileInfo with: (as-method => true) name: Symbol @@ -151,6 +154,7 @@ public defstruct BundleType <: Type : public defstruct VectorType <: Type : type: Type size: Int +public defstruct ClockType <: Type public defstruct UnknownType <: Type public defstruct Field : diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza index 9f4cdc8c..d8fe705f 100644 --- a/src/main/stanza/flo.stanza +++ b/src/main/stanza/flo.stanza @@ -69,6 +69,7 @@ defn prim-width (type:Type) -> Int : match(type) : (t:UIntType) : sane-width(width(t)) (t:SIntType) : sane-width(width(t)) + (t:ClockType) : 1 (t) : error("Bad prim width type") defn sizeof (in: Int) -> Int : diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index f85ff7c9..96c50c3c 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -38,8 +38,8 @@ OPERATORS[`div] = DIV-OP OPERATORS[`mod] = MOD-OP OPERATORS[`quo] = QUO-OP OPERATORS[`rem] = REM-OP -OPERATORS[`add-wrap] = ADD-WRAP-OP -OPERATORS[`sub-wrap] = SUB-WRAP-OP +OPERATORS[`addw] = ADD-WRAP-OP +OPERATORS[`subw] = SUB-WRAP-OP OPERATORS[`lt] = LESS-OP OPERATORS[`leq] = LESS-EQ-OP OPERATORS[`gt] = GREATER-OP @@ -49,20 +49,20 @@ OPERATORS[`neq] = NEQUAL-OP OPERATORS[`mux] = MUX-OP OPERATORS[`pad] = PAD-OP OPERATORS[`neg] = NEG-OP -OPERATORS[`as-UInt] = AS-UINT-OP -OPERATORS[`as-SInt] = AS-SINT-OP +OPERATORS[`asUInt] = AS-UINT-OP +OPERATORS[`asSInt] = AS-SINT-OP OPERATORS[`dshl] = DYN-SHIFT-LEFT-OP OPERATORS[`dshr] = DYN-SHIFT-RIGHT-OP OPERATORS[`shl] = SHIFT-LEFT-OP OPERATORS[`shr] = SHIFT-RIGHT-OP -OPERATORS[`convert] = CONVERT-OP -OPERATORS[`bit-and-reduce] = BIT-AND-REDUCE-OP -OPERATORS[`bit-or-reduce] = BIT-OR-REDUCE-OP -OPERATORS[`bit-xor-reduce] = BIT-XOR-REDUCE-OP -OPERATORS[`bit-not] = BIT-NOT-OP -OPERATORS[`bit-and] = BIT-AND-OP -OPERATORS[`bit-or] = BIT-OR-OP -OPERATORS[`bit-xor] = BIT-XOR-OP +OPERATORS[`cvt] = CONVERT-OP +OPERATORS[`andr] = BIT-AND-REDUCE-OP +OPERATORS[`orr] = BIT-OR-REDUCE-OP +OPERATORS[`xorr] = BIT-XOR-REDUCE-OP +OPERATORS[`not] = BIT-NOT-OP +OPERATORS[`and] = BIT-AND-OP +OPERATORS[`or] = BIT-OR-OP +OPERATORS[`xor] = BIT-XOR-OP OPERATORS[`cat] = CONCAT-OP OPERATORS[`bit] = BIT-SELECT-OP OPERATORS[`bits] = BITS-SELECT-OP @@ -187,7 +187,10 @@ defsyntax firrtl : inttype = (SInt) : SIntType(w) inttype = (SInt) : SIntType(UnknownWidth()) + clktype = (Clock) : ClockType() + type = (?t:#typeterm ?ops:#typeop ...) : apply-suffix-ops(t, ops) + type = (?t:#clktype) : t typeop = ((@get ?size:#int$)) : (fn (t) : VectorType(t, size)) typeterm = (?t:#inttype) : t @@ -213,16 +216,16 @@ defsyntax firrtl : ;Main Statement Productions defrule statements : stmt = (wire ?name:#id! #:! ?t:#type!) : DefWire(first-info(form),name, t) - stmt = (reg ?name:#id! #:! ?t:#type!) : DefRegister(first-info(form),name, t) - stmt = (cmem ?name:#id! #:! ?t:#vectype!) : DefMemory(first-info(form),name, t, false) - stmt = (smem ?name:#id! #:! ?t:#vectype!) : DefMemory(first-info(form),name, t, true) - stmt = (inst ?name:#id! #of! ?m:#ref!) : DefInstance(first-info(form),name, m) - stmt = (node ?name:#id! #=! ?e:#exp!) : DefNode(first-info(form),name, e) - stmt = (on-reset ?x:#exp := ?y:#exp!) : OnReset(first-info(form),x, y) - stmt = (read accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i,READ) - stmt = (write accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i,WRITE) - stmt = (infer accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i,INFER) - stmt = (rdwr accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i,RDWR) + stmt = (reg ?name:#id! #:! ?t:#type! ?clk:#exp! ?reset:#exp!) : DefRegister(first-info(form),name, t,clk,reset) + stmt = (cmem ?name:#id! #:! ?t:#vectype! ?clk:#exp!) : DefMemory(first-info(form),name, t, false, clk) + stmt = (smem ?name:#id! #:! ?t:#vectype! ?clk:#exp!) : DefMemory(first-info(form),name, t, true, clk) + stmt = (inst ?name:#id! #of! ?m:#ref!) : DefInstance(first-info(form),name,m) + stmt = (node ?name:#id! #=! ?e:#exp!) : DefNode(first-info(form),name,e) + stmt = (onreset ?x:#exp := ?y:#exp!) : OnReset(first-info(form),x,y) + stmt = (read accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s,i,READ) + stmt = (write accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s,i,WRITE) + stmt = (infer accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s,i,INFER) + stmt = (rdwr accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name,s, i,RDWR) stmt = (?s:#stmt/when) : s stmt = (?x:#exp := ?y:#exp!) : Connect(first-info(form),x, y) diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 8e65005f..bd8a0fd6 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -128,8 +128,8 @@ defmethod print (o:OutputStream, op:PrimOp) : MOD-OP : "mod" QUO-OP : "quo" REM-OP : "rem" - ADD-WRAP-OP : "add-wrap" - SUB-WRAP-OP : "sub-wrap" + ADD-WRAP-OP : "addw" + SUB-WRAP-OP : "subw" LESS-OP : "lt" LESS-EQ-OP : "leq" GREATER-OP : "gt" @@ -138,21 +138,21 @@ defmethod print (o:OutputStream, op:PrimOp) : NEQUAL-OP : "neq" MUX-OP : "mux" PAD-OP : "pad" - AS-UINT-OP : "as-UInt" - AS-SINT-OP : "as-SInt" + AS-UINT-OP : "asUInt" + AS-SINT-OP : "asSInt" DYN-SHIFT-LEFT-OP : "dshl" DYN-SHIFT-RIGHT-OP : "dshr" SHIFT-LEFT-OP : "shl" SHIFT-RIGHT-OP : "shr" - CONVERT-OP : "convert" + CONVERT-OP : "cvt" NEG-OP : "neg" - BIT-NOT-OP : "bit-not" - BIT-AND-OP : "bit-and" - BIT-OR-OP : "bit-or" - BIT-XOR-OP : "bit-xor" - BIT-AND-REDUCE-OP : "bit-and-reduce" - BIT-OR-REDUCE-OP : "bit-or-reduce" - BIT-XOR-REDUCE-OP : "bit-xor-reduce" + BIT-NOT-OP : "not" + BIT-AND-OP : "and" + BIT-OR-OP : "or" + BIT-XOR-OP : "xor" + BIT-AND-REDUCE-OP : "andr" + BIT-OR-REDUCE-OP : "orr" + BIT-XOR-REDUCE-OP : "xorr" CONCAT-OP : "cat" BIT-SELECT-OP : "bit" BITS-SELECT-OP : "bits" @@ -176,10 +176,10 @@ defmethod print (o:OutputStream, c:Stmt) : (c:DefWire) : print-all(o,["wire " name(c) " : " type(c)]) (c:DefRegister) : - print-all(o,["reg " name(c) " : " type(c)]) + print-all(o,["reg " name(c) " : " type(c) ", " clock(c) ", " reset(c)]) (c:DefMemory) : - if seq?(c) : print-all(o,["smem " name(c) " : " type(c)]) - else : print-all(o,["cmem " name(c) " : " type(c)]) + if seq?(c) : print-all(o,["smem " name(c) " : " type(c) ", " clock(c)]) + else : print-all(o,["cmem " name(c) " : " type(c) ", " clock(c)]) (c:DefInstance) : print-all(o,["inst " name(c) " of " module(c)]) (c:DefNode) : @@ -206,7 +206,7 @@ defmethod print (o:OutputStream, c:Stmt) : (c:BulkConnect) : print-all(o, [loc(c) " <> " exp(c)]) (c:OnReset) : - print-all(o, ["on-reset " loc(c) " := " exp(c)]) + print-all(o, ["onreset " loc(c) " := " exp(c)]) (c:EmptyStmt) : print(o, "skip") if not c typeof Conditionally|Begin|EmptyStmt : print-debug(o,c) @@ -215,6 +215,8 @@ defmethod print (o:OutputStream, t:Type) : match(t) : (t:UnknownType) : print(o, "?") + (t:ClockType) : + print(o, "Clock") (t:UIntType) : match(width(t)) : (w:UnknownWidth) : print-all(o, ["UInt"]) @@ -290,6 +292,8 @@ public defmulti map (f: Expression -> Expression, c:?T&Stmt) -> T defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt : match(c) : (c:DefAccessor) : DefAccessor(info(c),name(c), f(source(c)), f(index(c)),acc-dir(c)) + (c:DefRegister) : DefRegister(info(c),name(c), type(c), f(clock(c)), f(reset(c))) + (c:DefMemory) : DefMemory(info(c),name(c), type(c), seq?(c), f(clock(c))) (c:DefNode) : DefNode(info(c),name(c), f(value(c))) (c:DefInstance) : DefInstance(info(c),name(c), f(module(c))) (c:Conditionally) : Conditionally(info(c),f(pred(c)), conseq(c), alt(c)) @@ -332,8 +336,8 @@ public defmulti map (f: Type -> Type, c:?T&Stmt) -> T defmethod map (f: Type -> Type, c:Stmt) -> Stmt : match(c) : (c:DefWire) : DefWire(info(c),name(c),f(type(c))) - (c:DefRegister) : DefRegister(info(c),name(c),f(type(c))) - (c:DefMemory) : DefMemory(info(c),name(c),f(type(c)) as VectorType,seq?(c)) + (c:DefRegister) : DefRegister(info(c),name(c),f(type(c)),clock(c),reset(c)) + (c:DefMemory) : DefMemory(info(c),name(c),f(type(c)) as VectorType,seq?(c),clock(c)) (c) : c public defmulti mapr (f: Width -> Width, t:?T&Type) -> T diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 43cc06a4..f844d7cc 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -12,7 +12,7 @@ public val standard-passes = to-list $ [ CheckHighForm(expand-delin) TempElimination() ToWorkingIR() - MakeExplicitReset() + ;MakeExplicitReset() ResolveKinds() CheckKinds() InferTypes() @@ -350,47 +350,48 @@ defn to-working-ir (c:Circuit) : ; If reset is not explicitly passed to instantiations, then this ; pass autmatically connects the parent module's reset to the ; instantiation's reset -public defstruct MakeExplicitReset <: Pass -public defmethod pass (b:MakeExplicitReset) -> (Circuit -> Circuit) : make-explicit-reset -public defmethod name (b:MakeExplicitReset) -> String : "Make Explicit Reset" -public defmethod short-name (b:MakeExplicitReset) -> String : "make-explicit-reset" - -defn make-explicit-reset (c:Circuit) : - defn find-explicit (c:Circuit) -> List : - defn explicit? (m:Module) -> True|False : - for p in ports(m) any? : - name(p) == `reset - val explicit-reset = Vector() - for m in modules(c) do: - if explicit?(m) : add(explicit-reset,name(m)) - to-list(explicit-reset) - - defn make-explicit (m:Module, explicit-reset:List) -> Module : - defn route-reset (s:Stmt) -> Stmt : - match(s) : - (s:DefInstance) : - val iref = WSubfield(WRef(name(s), UnknownType(), InstanceKind(), UNKNOWN-GENDER),`reset,UnknownType(),UNKNOWN-GENDER) - val pref = WRef(`reset, UnknownType(), PortKind(), MALE) - Begin(to-list([s,Connect(info(s),iref,pref)])) - (s) : map(route-reset,s) - - var ports! = ports(m) - if not contains?(explicit-reset,name(m)) : - ports! = append(ports(m),list(Port(FileInfo(),`reset,INPUT,UIntType(IntWidth(1))))) - match(m) : - (m:InModule) : - val body! = route-reset(body(m)) - InModule(info(m),name(m),ports!,body!) - (m:ExModule) : ExModule(info(m),name(m),ports!) - - defn make-explicit-reset (m:Module, c:Circuit) -> Module : - val explicit-reset = find-explicit(c) - make-explicit(m,explicit-reset) - Circuit(info(c),modules*, main(c)) where : - val modules* = - for m in modules(c) map : - make-explicit-reset(m,c) +;public defstruct MakeExplicitReset <: Pass +;public defmethod pass (b:MakeExplicitReset) -> (Circuit -> Circuit) : make-explicit-reset +;public defmethod name (b:MakeExplicitReset) -> String : "Make Explicit Reset" +;public defmethod short-name (b:MakeExplicitReset) -> String : "make-explicit-reset" +; +;defn make-explicit-reset (c:Circuit) : +; defn find-explicit (c:Circuit) -> List : +; defn explicit? (m:Module) -> True|False : +; for p in ports(m) any? : +; name(p) == `reset +; val explicit-reset = Vector() +; for m in modules(c) do: +; if explicit?(m) : add(explicit-reset,name(m)) +; to-list(explicit-reset) +; +; defn make-explicit (m:Module, explicit-reset:List) -> Module : +; defn route-reset (s:Stmt) -> Stmt : +; match(s) : +; (s:DefInstance) : +; val iref = WSubfield(WRef(name(s), UnknownType(), InstanceKind(), UNKNOWN-GENDER),`reset,UnknownType(),UNKNOWN-GENDER) +; val pref = WRef(`reset, UnknownType(), PortKind(), MALE) +; Begin(to-list([s,Connect(info(s),iref,pref)])) +; (s) : map(route-reset,s) +; +; var ports! = ports(m) +; if not contains?(explicit-reset,name(m)) : +; ports! = append(ports(m),list(Port(FileInfo(),`reset,INPUT,UIntType(IntWidth(1))))) +; match(m) : +; (m:InModule) : +; val body! = route-reset(body(m)) +; InModule(info(m),name(m),ports!,body!) +; (m:ExModule) : ExModule(info(m),name(m),ports!) +; +; defn make-explicit-reset (m:Module, c:Circuit) -> Module : +; val explicit-reset = find-explicit(c) +; make-explicit(m,explicit-reset) +; +; Circuit(info(c),modules*, main(c)) where : +; val modules* = +; for m in modules(c) map : +; make-explicit-reset(m,c) ;=============== Resolve Kinds ============================= ; It is useful for the compiler to know information about @@ -852,7 +853,7 @@ defn lower (body:Stmt) -> Stmt : DefWire(info(s),name(x),type(x)) (s:DefRegister) : Begin{_} $ for x in generate-entry(name(s),type(s)) map : - DefRegister(info(s),name(x),type(x)) + DefRegister(info(s),name(x),type(x),clock(s),reset(s)) (s:DefInstance) : val fields = for f in fields(type(module(s)) as BundleType) map-append : @@ -866,7 +867,7 @@ defn lower (body:Stmt) -> Stmt : DefNode(info(s),name(s),exp(x)) (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)) + DefMemory(info(s),name(x),VectorType(type(x),size(s)),seq?(s),clock(s)) (s:DefAccessor) : val ls = generate-entry(name(s),type(s)) val rs = generate-entry(name(source(s) as WRef),type(s)) @@ -1262,14 +1263,13 @@ defn get-write-enable (sv:SymbolicValue) -> SymbolicValue : (sv: SVNul) : SVExp(zero) (sv) : sv -defn merge-resets (assign:HashTable, resets:HashTable) -> HashTable : +defn merge-resets (assign:HashTable, resets:HashTable, rsignals:HashTable) -> HashTable : val table = HashTable(symbol-hash) - val reset = WRef(`reset, UnknownType(), PortKind(), MALE) for i in get-unique-keys(list(assign,resets)) do : table[i] = match(get?(assign,i,false),get?(resets,i,false)) : - (a:SymbolicValue,r:SymbolicValue) : SVMux(reset,r,a) + (a:SymbolicValue,r:SymbolicValue) : SVMux(rsignals[i],r,a) (a:SymbolicValue,r:False) : a - (a:False,r:SymbolicValue) : SVMux(reset,r,SVNul()) + (a:False,r:SymbolicValue) : SVMux(rsignals[i],r,SVNul()) (a:False,r:False) : error("Shouldn't be here") table @@ -1277,12 +1277,17 @@ defn build-tables (s:Stmt, assign:HashTable, resets:HashTable, flattn:HashTable, + rsignals:HashTable, ) -> False : match(s) : (s:DefWire) : assign[name(s)] = SVNul() flattn[name(s)] = true - (s:DefRegister|DefAccessor) : + (s:DefRegister) : + assign[name(s)] = SVNul() + flattn[name(s)] = false + rsignals[name(s)] = reset(s) + (s:DefAccessor) : assign[name(s)] = SVNul() flattn[name(s)] = false (s:DefInstance) : ;TODO only add instance input ports. This probably involves correcting instance genders @@ -1313,8 +1318,8 @@ defn build-tables (s:Stmt, val assign-a = deepcopy(assign) val resets-c = deepcopy(resets) val resets-a = deepcopy(resets) - build-tables(conseq(s),assign-c,resets-c,flattn) - build-tables(alt(s),assign-a,resets-a,flattn) + build-tables(conseq(s),assign-c,resets-c,flattn,rsignals) + build-tables(alt(s),assign-a,resets-a,flattn,rsignals) for i in get-unique-keys(list(assign-c,assign-a)) do : assign[i] = combine(flattn,assign-c,assign-a,i) as SymbolicValue val r = combine(flattn,resets-c,resets-a,i) @@ -1334,7 +1339,7 @@ defn build-tables (s:Stmt, (e) : error("Shouldn't be here with ~" % [e]) if s typeof Connect : assign[key*] = SVExp(exp(s)) if s typeof OnReset : resets[key*] = SVExp(exp(s)) - (s:Begin) : for s* in body(s) do: build-tables(s*,assign,resets,flattn) + (s:Begin) : for s* in body(s) do: build-tables(s*,assign,resets,flattn,rsignals) (s:DefMemory|DefNode|EmptyStmt) : false ;--------------- Expand Whens Pass ------------------- @@ -1410,13 +1415,14 @@ public defn expand-whens (c:Circuit) -> Circuit : val assign = HashTable(symbol-hash) val resets = HashTable(symbol-hash) val flattn = HashTable(symbol-hash) + val rsignals = HashTable(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) + build-tables(body(m),assign,resets,flattn,rsignals) 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) @@ -1427,7 +1433,7 @@ public defn expand-whens (c:Circuit) -> Circuit : println-debug("====== Resets ======") for x in resets do : println-debug(x) - val table = merge-resets(assign,resets) + val table = merge-resets(assign,resets,rsignals) println-debug("====== Table ======") for x in table do : println-debug(x) val decs = Vector() @@ -1654,6 +1660,7 @@ public defn width! (t:Type) -> Width : match(t) : (t:UIntType) : width(t) (t:SIntType) : width(t) + (t:ClockType) : IntWidth(1) (t) : error("No width!") public defn width! (e:Expression) -> Width : width!(type(e)) @@ -1661,10 +1668,10 @@ defn gen-constraints (m:Module, h:HashTable, v:Vector) -> Mod defn gen-constraints-s (s:Stmt) -> Stmt : match(map(gen-constraints-s,s)) : (s:DefWire) : DefWire(info(s),name(s),h[name(s)]) - (s:DefRegister) : DefRegister(info(s),name(s),h[name(s)]) + (s:DefRegister) : DefRegister(info(s),name(s),h[name(s)],gen-constraints(clock(s)),gen-constraints(reset(s))) (s:DefAccessor) : DefAccessor(info(s),name(s),gen-constraints(source(s)),gen-constraints(index(s)), acc-dir(s)) (s:DefInstance) : DefInstance(info(s),name(s),gen-constraints(module(s))) - (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)] as VectorType,seq?(s)) + (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)] as VectorType,seq?(s),gen-constraints(clock(s))) (s:DefNode) : val l = h[name(s)] val r = gen-constraints(value(s)) @@ -1720,8 +1727,7 @@ defn build-environment (c:Circuit,m:Module,h:HashTable) -> HashTabl (s:DefRegister) : h[name(s)] = remove-unknowns(type(s)) (s:DefInstance) : h[name(s)] = h[name(module(s) as WRef)] (s:DefMemory) : h[name(s)] = remove-unknowns(type(s)) - (s:DefAccessor) : - h[name(s)] = remove-unknowns(type(type(source(s)) as VectorType)) + (s:DefAccessor) : h[name(s)] = remove-unknowns(type(type(source(s)) as VectorType)) (s:DefNode) : h[name(s)] = remove-unknowns(type(value(s))) (s) : false do(build-environment,s) @@ -1867,9 +1873,9 @@ defn inline-instances (c:Circuit) : defn rename-s (s:Stmt,n:Symbol) -> Stmt : map{rename-e{_,n},_} $ match(map(rename-s{_,n},s)) : (s:DefWire) : DefWire(info(s),rename(name(s),n),type(s)) - (s:DefRegister) : DefRegister(info(s),rename(name(s),n),type(s)) + (s:DefRegister) : DefRegister(info(s),rename(name(s),n),type(s),clock(s),reset(s)) (s:DefInstance) : error("Shouldn't be here") - (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s)) + (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s),clock(s)) (s:DefNode) : DefNode(info(s),rename(name(s),n),value(s)) (s) : s for m in modules(c) do : @@ -1898,11 +1904,17 @@ defn split-exp (c:Circuit) : defn split-exp-e (e:Expression,n:Symbol|False,info:FileInfo) -> Expression : match(map(split-exp-e{_,n,info},e)) : (e:DoPrim) : - val n* = - if n typeof False : firrtl-gensym(`T,sh) - else : firrtl-gensym(symbol-join([n as Symbol gen-delin]),sh) - add(v,DefNode(info,n*,e)) - WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER) + var all-same-type? = true + for x in args(e) do : + if type(x) != type(e) : all-same-type? = false + all-same-type? = false + if not all-same-type? : + val n* = + if n typeof False : firrtl-gensym(`T,sh) + else : firrtl-gensym(symbol-join([n as Symbol gen-delin]),sh) + add(v,DefNode(info,n*,e)) + WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER) + else : e (e) : e defn f (s:Stmt) -> False: split-exp-s(s,v,sh) match(s) : @@ -1913,25 +1925,24 @@ defn split-exp (c:Circuit) : do(f,s) (s:Connect) : match(loc(s)) : - ;(e:WritePort) : add(v,map(split-exp-e{_,full-name(exp(s)),info(s)},s)) (e) : add(v,map(split-exp-e{_,full-name(loc(s)),info(s)},s)) (s:DefNode) : add(v,map(split-exp-e{_,name(s),info(s)},s)) (s) : add(v,map(split-exp-e{_,false,info(s)},s)) false - val start-time = current-time-us() + ;val start-time = current-time-us() Circuit{info(c),_,main(c)} $ for m in modules(c) map : match(m) : (m:InModule) : val v = Vector() val sh = get-sym-hash(m) - val before = current-time-us() - start-time - println-all(["Before split: " before]) + ;val before = current-time-us() - start-time + ;println-all(["Before split: " before]) split-exp-s(body(m),v,sh) - val now = current-time-us() - start-time - println-all(["After split: " now]) - println-all(["Diff: " now - before]) + ;val now = current-time-us() - start-time + ;println-all(["After split: " now]) + ;println-all(["Diff: " now - before]) InModule(info(m),name(m),ports(m),Begin(to-list(v))) (m:ExModule) : m @@ -2005,9 +2016,9 @@ public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) : defn to-stmt (s:Stmt) -> Stmt : map{to-type,_} $ match(map(to-exp,s)) : (s:DefWire) : DefWire(info(s),rename(name(s)),type(s)) - (s:DefRegister) : DefRegister(info(s),rename(name(s)),type(s)) + (s:DefRegister) : DefRegister(info(s),rename(name(s)),type(s),clock(s),reset(s)) (s:DefInstance) : DefInstance(info(s),rename(name(s)),module(s)) - (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s)) + (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s),clock(s)) (s:DefNode) : DefNode(info(s),rename(name(s)),value(s)) (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),source(s),index(s),acc-dir(s)) (s) : map(to-stmt,s) diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index 1904f92f..23591f45 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -36,6 +36,7 @@ defn get-width (t:Type) -> String : match(t) : (t:UIntType) : emit(width(t)) (t:SIntType) : emit(width(t)) + (t:ClockType) : emit(IntWidth(1)) (t) : error("Non-supported type.") defn remove-subfield (e:Expression) -> Expression : @@ -140,8 +141,8 @@ defn get-name (e:Expression) -> Symbol : (e) : error("Shouldn't be here") defn emit-module (m:InModule) : - val vdecs = Vector>() ; all declarations - val decs = HashTable(symbol-hash) ; all declarations + val vdecs = Vector>() ; all declarations in order, to preserve ordering + val decs = HashTable(symbol-hash) ; all declarations, for fast lookups val cons = HashTable(symbol-hash) ; all connections val ens = HashTable(symbol-hash) ; all enables defn build-table (m:InModule) : @@ -166,7 +167,7 @@ defn emit-module (m:InModule) : val regs = Vector() val inits = Vector() val assigns = Vector() - val updates = Vector() + val updates = HashTable>(symbol-hash) val insts = HashTable(symbol-hash) ; inst -> module val inst-ports = HashTable>(symbol-hash) @@ -180,12 +181,14 @@ defn emit-module (m:InModule) : add(assigns,["assign " sym " = " emit(cons[sym]) ";"]) (s:DefRegister) : add(regs,["reg " get-width(type(s)) " " sym ";"]) + val my-clk-update = get?(updates,get-name(clock(s)),Vector()) if key?(ens,sym) : - add(updates,["if(" emit(ens[sym]) ") begin"]) - add(updates,[" " sym " <= " emit(cons[sym]) ";"]) - add(updates,["end"]) + add(my-clk-update,["if(" emit(ens[sym]) ") begin"]) + add(my-clk-update,[" " sym " <= " emit(cons[sym]) ";"]) + add(my-clk-update,["end"]) else : - add(updates,[sym " <= " emit(cons[sym]) ";"]) + add(my-clk-update,[sym " <= " emit(cons[sym]) ";"]) + updates[get-name(clock(s))] = my-clk-update (s:DefMemory) : val vtype = type(s) as VectorType add(regs,["reg " get-width(type(vtype)) " " sym " [0:" size(vtype) "];"]) @@ -204,15 +207,17 @@ defn emit-module (m:InModule) : if flip(f) == REVERSE : add(assigns,["assign " n* " = " emit(cons[n*]) ";"]) (s:DefAccessor) : + val mem-declaration = decs[name(source(s) as Ref)] as DefMemory switch {_ == acc-dir(s)} : READ : - val mem-declaration = decs[name(source(s) as Ref)] - if seq?(mem-declaration as DefMemory) : + if seq?(mem-declaration) : ; to make it sequential, register the index for an additional cycle val index* = Ref(firrtl-gensym(name(index(s) as Ref),sh),type(index(s))) add(regs,[ "reg " get-width(type(index*)) " " name(index*) ";"]) add(inits,[name(index*) " = {" width!(type(index*)) "{$random}};"]) - add(updates,[name(index*) " <= " emit(index(s)) ";"]) + val my-clk-update = get?(updates,get-name(clock(mem-declaration)),Vector()) + add(my-clk-update,[name(index*) " <= " emit(index(s)) ";"]) + updates[get-name(clock(mem-declaration))] = my-clk-update ; emit read accessor add(wires,["wire " get-width(type(type(source(s)) as VectorType)) " " sym ";"]) @@ -222,27 +227,28 @@ defn emit-module (m:InModule) : add(wires,["wire " get-width(type(type(source(s)) as VectorType)) " " sym ";"]) add(assigns,["assign " sym " = " emit(source(s)) "[" emit(index(s)) "];"]) WRITE : + val my-clk-update = get?(updates,get-name(clock(mem-declaration)),Vector()) if key?(ens,sym) : - add(updates,["if(" emit(ens[sym]) ") begin"]) - add(updates,[" " emit(source(s)) "[" emit(index(s)) "] <= " emit(cons[sym]) ";"]) - add(updates,["end"]) + add(my-clk-update,["if(" emit(ens[sym]) ") begin"]) + add(my-clk-update,[" " emit(source(s)) "[" emit(index(s)) "] <= " emit(cons[sym]) ";"]) + add(my-clk-update,["end"]) else : - add(updates,[emit(source(s)) "[" emit(index(s)) "] <= " emit(cons[sym]) ";"]) + add(my-clk-update,[emit(source(s)) "[" emit(index(s)) "] <= " emit(cons[sym]) ";"]) + updates[get-name(clock(mem-declaration))] = my-clk-update ;==== Actually printing module ===== val port-indent = " " - print-all(["module " name(m) "(input clk, input reset,\n"]) + print-all(["module " name(m) "(\n"]) for (p in ports(m),i in 1 to false) do : - if name(p) !=`reset : - var end = ",\n" - if length(ports(m)) - 1 == i : - end = "\n);\n" - switch {_ == direction(p)} : - INPUT : - print-all([port-indent "input " get-width(type(p)) " " name(p) end]) - OUTPUT : - print-all([port-indent "output " get-width(type(p)) " " name(p) end]) - add(assigns,["assign " name(p) " = " emit(cons[name(p)]) ";"]) + var end = ",\n" + if length(ports(m)) == i : + end = "\n);\n" + switch {_ == direction(p)} : + INPUT : + print-all([port-indent "input " get-width(type(p)) " " name(p) end]) + OUTPUT : + print-all([port-indent "output " get-width(type(p)) " " name(p) end]) + add(assigns,["assign " name(p) " = " emit(cons[name(p)]) ";"]) for w in wires do : print(" ") @@ -268,23 +274,22 @@ defn emit-module (m:InModule) : for x in insts do : println-all([" " value(x) " " key(x) " ("]) - print(" ") - print-all([".clk( clk )"]) + ;print-all([".clk( clk )"]) for (y in inst-ports[key(x)],i in 1 to false) do : - print(",\n") print(" ") print-all(y) - ;if length(inst-ports[key(x)]) != i : - ;print(",\n") + if length(inst-ports[key(x)]) != i : + print(",\n") println("\n );") - if length(updates) != 0 : - println(" always @(posedge clk) begin") - for u in updates do : - print(" ") - println-all(u) - println(" end") - + for x in updates do : + if length(value(x)) != 0 : + println-all([" always @(posedge " key(x) ") begin"]) + for u in value(x) do : + print(" ") + println-all(u) + println(" end") + println("endmodule") -- cgit v1.2.3 From 9b6d8514a3be860562d8d524fa425c87d1537e8a Mon Sep 17 00:00:00 2001 From: azidar Date: Mon, 13 Jul 2015 16:22:43 -0700 Subject: Added tests for clocks. Added remove scope and special chars passes. Added tests. Made more tests pass --- src/main/stanza/compilers.stanza | 19 ++-- src/main/stanza/custom-compiler.stanza | 8 +- src/main/stanza/errors.stanza | 8 +- src/main/stanza/firrtl-ir.stanza | 7 +- src/main/stanza/passes.stanza | 183 ++++++++++++++++++++++++++++++--- src/main/stanza/verilog.stanza | 1 + 6 files changed, 191 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza index c458f1e1..b87c654e 100644 --- a/src/main/stanza/compilers.stanza +++ b/src/main/stanza/compilers.stanza @@ -12,10 +12,11 @@ public defstruct StandardFlo <: Compiler : file: String with: (as-method => true) public defmethod passes (c:StandardFlo) -> List : to-list $ [ - CheckHighForm(expand-delin) + RemoveSpecialChars() + RemoveScopes() + CheckHighForm() ;; TempElimination() ToWorkingIR() - ;; MakeExplicitReset() ResolveKinds() CheckKinds() InferTypes() @@ -31,9 +32,8 @@ public defmethod passes (c:StandardFlo) -> List : Inline() SplitExp() ToRealIR() - SpecialRename(`#,`_) - SpecialRename(`$,`::) - CheckHighForm(`::) + RemoveSpecialChars() + CheckHighForm() CheckLowForm() Flo(file(c)) ] @@ -42,7 +42,9 @@ public defstruct StandardVerilog <: Compiler : file: String with: (as-method => true) public defmethod passes (c:StandardVerilog) -> List : to-list $ [ - CheckHighForm(expand-delin) + RemoveSpecialChars() + RemoveScopes() + CheckHighForm() TempElimination() ToWorkingIR() ;; MakeExplicitReset() @@ -60,9 +62,8 @@ public defmethod passes (c:StandardVerilog) -> List : Pad() SplitExp() ToRealIR() - SpecialRename(`#,`_) - SpecialRename(`$,`__) - CheckHighForm(`__) + RemoveSpecialChars() + CheckHighForm() CheckLowForm() Verilog(file(c)) ] diff --git a/src/main/stanza/custom-compiler.stanza b/src/main/stanza/custom-compiler.stanza index 91732f22..4d63a173 100644 --- a/src/main/stanza/custom-compiler.stanza +++ b/src/main/stanza/custom-compiler.stanza @@ -14,7 +14,9 @@ public defstruct InstrumentedVerilog <: Compiler : public defmethod passes (c:InstrumentedVerilog) -> List : to-list $ [ WhenCoverage(args(c)[0],args(c)[1]) - CheckHighForm(expand-delin) + RemoveSpecialChars() + RemoveScopes() + CheckHighForm() TempElimination() ToWorkingIR() ;; MakeExplicitReset() @@ -31,8 +33,8 @@ public defmethod passes (c:InstrumentedVerilog) -> List : InferWidths() SplitExp() ToRealIR() - SpecialRename(`#,`_) - CheckHighForm(expand-delin) + RemoveSpecialChars() + CheckHighForm() CheckLowForm() Verilog(file(c)) ] diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza index b92939d7..608b47d2 100644 --- a/src/main/stanza/errors.stanza +++ b/src/main/stanza/errors.stanza @@ -39,9 +39,8 @@ defpackage firrtl/errors : ; * Width sizes are positive ; * Primops have the correct number of arguments -public defstruct CheckHighForm <: Pass : - sym : Symbol -public defmethod pass (b:CheckHighForm) -> (Circuit -> Circuit) : check-high-form{_,sym(b)} +public defstruct CheckHighForm <: Pass +public defmethod pass (b:CheckHighForm) -> (Circuit -> Circuit) : check-high-form public defmethod name (b:CheckHighForm) -> String : "High Form Check" public defmethod short-name (b:CheckHighForm) -> String : "high-form-check" @@ -240,7 +239,7 @@ defn check-high-form-primop (e:DoPrim, errors:Vector,info:FileInf BITS-SELECT-OP : correct-num(1,2) ;--------------- Check High Form Pass ------------------- -public defn check-high-form (c:Circuit,sym:Symbol) -> Circuit : +public defn check-high-form (c:Circuit) -> Circuit : val errors = Vector() defn check-valid-loc (info:FileInfo,e:Expression) -> False : @@ -334,7 +333,6 @@ public defn check-high-form (c:Circuit,sym:Symbol) -> Circuit : map(check-high-form-t{info(p),_},type(p)) map(check-high-form-w{info(p),_},type(p)) - names[`reset] = true match(m) : (m:ExModule) : false (m:InModule) : check-high-form-s(body(m),names) diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index b9d2cee4..b37e974f 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -5,8 +5,11 @@ defpackage firrtl/ir2 : public defmulti info! (x:?) -> FileInfo public defmethod info! (x:?) : FileInfo() -public val expand-delin = `$ -public val gen-delin = `# +public val vector-expand-delin = `_ +public val bundle-expand-delin = `_ +public val scope-delin = `% +public val temp-delin = `! +public val inline-delin = `^ public definterface PortDirection public val INPUT = new PortDirection diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index f844d7cc..99679cf6 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -9,10 +9,9 @@ defpackage firrtl/passes : ;============== Pass List ================ public val standard-passes = to-list $ [ - CheckHighForm(expand-delin) + CheckHighForm() TempElimination() ToWorkingIR() - ;MakeExplicitReset() ResolveKinds() CheckKinds() InferTypes() @@ -282,6 +281,155 @@ defmethod map (f: Type -> Type, e: WSubfield) : defmethod map (f: Type -> Type, e: WIndex) : WIndex(exp(e), value(e), f(type(e)), gender(e)) +;================= Remove Special Characters ======================== +; Returns a new Circuit where all names have all special characters +; removed, except _. + +public defstruct RemoveSpecialChars <: Pass +public defmethod pass (b:RemoveSpecialChars) -> (Circuit -> Circuit) : remove-special-chars +public defmethod name (b:RemoveSpecialChars) -> String : "Remove Special Characters" +public defmethod short-name (b:RemoveSpecialChars) -> String : "rem-spec-chars" + +;------------ Helper Functions ------------- + +defn get-new-string (n:Char) -> String : + switch {n == _} : + '_' : "__" + '~' : "_A" + '!' : "_B" + '@' : "_C" + '#' : "_D" + '$' : "_E" + '%' : "_F" + '^' : "_G" + '*' : "_H" + '-' : "_I" + '+' : "_J" + '=' : "_K" + '?' : "_L" + '/' : "_M" + else : to-string(n) + +;------------ Pass ------------------ + +defn remove-special-chars (c:Circuit) : + defn rename (n:Symbol) -> Symbol : + val n* = Vector() + for c in to-string(n) do : + add(n*,get-new-string(c)) + symbol-join(n*) + defn rename-t (t:Type) -> Type : + match(map(rename-t,t)) : + (t:BundleType) : BundleType $ + for f in fields(t) map : + Field(rename(name(f)),flip(f),type(f)) + (e) : e + defn rename-e (e:Expression) -> Expression : + map{rename-t,_} $ match(map(rename-e,e)) : + (e:Ref) : Ref(rename(name(e)),type(e)) + (e:Subfield) : Subfield(exp(e),rename(name(e)),type(e)) + (e) : e + defn rename-s (s:Stmt) -> Stmt : + map{rename-t,_} $ match(map(rename-e,s)) : + (s:DefWire) : DefWire(info(s),rename(name(s)),type(s)) + (s:DefRegister) : DefRegister(info(s),rename(name(s)),type(s),clock(s),reset(s)) + (s:DefInstance) : DefInstance(info(s),rename(name(s)),module(s)) + (s:DefMemory) : DefMemory(info(s),rename(name(s)),type(s),seq?(s),clock(s)) + (s:DefNode) : DefNode(info(s),rename(name(s)),value(s)) + (s:DefAccessor) : DefAccessor(info(s),rename(name(s)),source(s),index(s),acc-dir(s)) + (s) : map(rename-s,s) + + Circuit(info(c),modules*, main(c)) where : + val modules* = + for m in modules(c) map : + match(m) : + (m:InModule) : + val ports* = for p in ports(m) map : + Port(info(p),rename(name(p)),direction(p),rename-t(type(p))) + InModule(info(m),rename(name(m)), ports*, rename-s(body(m))) + (m:ExModule) : m + +;================= Remove Scopes ======================== +; Returns a new Circuit where duplicate names have been +; renamed. + +public defstruct RemoveScopes <: Pass +public defmethod pass (b:RemoveScopes) -> (Circuit -> Circuit) : remove-scopes +public defmethod name (b:RemoveScopes) -> String : "Remove Scopes" +public defmethod short-name (b:RemoveScopes) -> String : "rem-scopes" + +;------------ Helper Functions ------------- + +defn lookup (n:Symbol, env:Vector>) -> Symbol : lookup(n,env,length(env) - 1) +defn lookup (n:Symbol, env:Vector>, index:Int) -> Symbol : + if index < 0 : n + else : + if not key?(env[index],n) : lookup(n,env,index - 1) + else : symbol-join([n scope-delin (env[index])[n]]) + +;------------ Pass ------------------ + +defn remove-scopes (c:Circuit) : + defn remove-scopes (m:InModule) : + val occurrences = HashTable(symbol-hash) + val uses = HashTable(symbol-hash) + defn rename (n:Symbol,env:Vector>) -> Symbol : + if occurrences[n] > 1 : + val i = get?(uses,n,0) + uses[n] = i + 1 + env[length(env) - 1][n] = i + symbol-join([n `% i]) + else : n + defn build-s (s:Stmt) : + match(s) : + (s:DefWire|DefRegister|DefInstance|DefMemory|DefNode|DefAccessor) : + occurrences[name(s)] = get?(occurrences,name(s),0) + 1 + (s) : do(build-s,s) + defn remove-scopes-e (e:Expression,env:Vector>) : + match(map(remove-scopes-e{_,env},e)) : + (e:Ref) : Ref(lookup(name(e),env),type(e)) + (e) : e + defn remove-scopes-s (s:Stmt,env:Vector>) -> Stmt : + match(map(remove-scopes-e{_,env},s)) : + (s:DefWire) : DefWire(info(s),rename(name(s),env),type(s)) + (s:DefRegister) : DefRegister(info(s),rename(name(s),env),type(s),clock(s),reset(s)) + (s:DefInstance) : DefInstance(info(s),rename(name(s),env),module(s)) + (s:DefMemory) : DefMemory(info(s),rename(name(s),env),type(s),seq?(s),clock(s)) + (s:DefNode) : DefNode(info(s),rename(name(s),env),value(s)) + (s:DefAccessor) : DefAccessor(info(s),rename(name(s),env),source(s),index(s),acc-dir(s)) + (s:Conditionally) : + add(env,HashTable(symbol-hash)) + val conseq* = remove-scopes-s(conseq(s),env) + pop(env) + + add(env,HashTable(symbol-hash)) + val alt* = remove-scopes-s(alt(s),env) + pop(env) + Conditionally(info(s),pred(s),conseq*,alt*) + (s) : map(remove-scopes-s{_,env},s) + + ;build occurrences table + for p in ports(m) do : + occurrences[name(p)] = get?(occurrences,name(p),0) + 1 + build-s(body(m)) + + ;rename + val env = Vector>() + add(env,HashTable(symbol-hash)) + val ports* = + for p in ports(m) map : + Port(info(p),rename(name(p),env),direction(p),type(p)) + val body* = remove-scopes-s(body(m),env) + + InModule(info(m),name(m), ports*, body*) + + Circuit(info(c),modules*, main(c)) where : + val modules* = + for m in modules(c) map : + match(m) : + (m:InModule) : remove-scopes(m) + (m:ExModule) : m + ;================= Temporary Variable Elimination ======================== ; Returns a new Circuit where temporary variables are removed and returns ; the resulting nested expression @@ -771,18 +919,19 @@ defn index-of-elem (t:BundleType, s:Symbol) -> Int : error("Shouldn't be here") defn generate-entry (n:Symbol,t:Type) -> List : - defn uniquify (n*:Symbol) -> Symbol : symbol-join([n expand-delin n*]) + defn v-uniquify (n*:Symbol) -> Symbol : symbol-join([n vector-expand-delin n*]) + defn b-uniquify (n*:Symbol) -> Symbol : symbol-join([n bundle-expand-delin n*]) match(t) : (t:BundleType) : for f in fields(t) map-append : val es = generate-entry(name(f),type(f)) for e in es map : - NTF(uniquify(name(e)),type(e),flip(e) * flip(f)) + NTF(b-uniquify(name(e)),type(e),flip(e) * flip(f)) (t:VectorType) : for i in 0 to size(t) map-append : val es = generate-entry(to-symbol(i),type(t)) for e in es map : - NTF(uniquify(name(e)),type(e),flip(e)) + NTF(v-uniquify(name(e)),type(e),flip(e)) (t) : list $ NTF(n,t,DEFAULT) defn expand-expr (e:Expression) -> List : @@ -986,9 +1135,9 @@ defn expand-connect-indexed-stmt (s: Stmt,sh:HashTable) -> Stmt : DoPrim(EQUAL-OP,list(e1,e2),List(),UIntType(UnknownWidth())) defn get-name (e:Expression) -> Symbol : match(e) : - (e:WRef) : symbol-join([name(e) gen-delin]) - (e:WSubfield) : symbol-join([get-name(exp(e)) `. name(e) gen-delin]) - (e:WIndex) : symbol-join([get-name(exp(e)) `. to-symbol(value(e)) gen-delin]) + (e:WRef) : symbol-join([name(e) temp-delin]) + (e:WSubfield) : symbol-join([get-name(exp(e)) `. name(e) temp-delin]) + (e:WIndex) : symbol-join([get-name(exp(e)) `. to-symbol(value(e)) temp-delin]) (e) : `T match(s) : (s:ConnectToIndexed) : Begin $ @@ -1857,17 +2006,17 @@ defn inline-instances (c:Circuit) : (e:WSubfield) : match(kind(exp(e) as WRef)) : (k:InstanceKind) : - WRef(symbol-join([name(exp(e) as WRef) expand-delin name(e)]),type(e),k,gender(e)) + WRef(symbol-join([name(exp(e) as WRef) inline-delin name(e)]),type(e),k,gender(e)) (k:MemKind) : e (e) : e - defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n expand-delin ref]) + defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n inline-delin ref]) defn rename-e (e:Expression,n:Symbol) -> Expression : match(map(rename-e{_,n},e)) : (e:WRef) : WRef(rename(name(e),n),type(e),kind(e),gender(e)) (e:WSubfield) : match(kind(exp(e) as WRef)) : (k:InstanceKind) : - WRef(symbol-join([name(exp(e) as WRef) expand-delin name(e)]),type(e),k,gender(e)) + WRef(symbol-join([name(exp(e) as WRef) inline-delin name(e)]),type(e),k,gender(e)) (k:MemKind) : e (e) : e defn rename-s (s:Stmt,n:Symbol) -> Stmt : @@ -1911,7 +2060,7 @@ defn split-exp (c:Circuit) : if not all-same-type? : val n* = if n typeof False : firrtl-gensym(`T,sh) - else : firrtl-gensym(symbol-join([n as Symbol gen-delin]),sh) + else : firrtl-gensym(symbol-join([n as Symbol temp-delin]),sh) add(v,DefNode(info,n*,e)) WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER) else : e @@ -1923,10 +2072,12 @@ defn split-exp (c:Circuit) : (s:Conditionally) : add(v,map(split-exp-e{_,full-name(loc(conseq(s) as Connect)),info(s)},s)) do(f,s) - (s:Connect) : - match(loc(s)) : - (e) : add(v,map(split-exp-e{_,full-name(loc(s)),info(s)},s)) - (s:DefNode) : add(v,map(split-exp-e{_,name(s),info(s)},s)) + (s:Connect) : + val exp* = map(split-exp-e{_,full-name(loc(s)),info(s)},exp(s)) + add(v,Connect(info(s),loc(s),exp(s))) + (s:DefNode) : + val exp* = map(split-exp-e{_,name(s),info(s)},value(s)) + add(v,DefNode(info(s),name(s),exp*)) (s) : add(v,map(split-exp-e{_,false,info(s)},s)) false diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza index 23591f45..29112271 100644 --- a/src/main/stanza/verilog.stanza +++ b/src/main/stanza/verilog.stanza @@ -249,6 +249,7 @@ defn emit-module (m:InModule) : OUTPUT : print-all([port-indent "output " get-width(type(p)) " " name(p) end]) add(assigns,["assign " name(p) " = " emit(cons[name(p)]) ";"]) + if length(ports(m)) == 0 : print(");\n") for w in wires do : print(" ") -- cgit v1.2.3