diff options
| -rw-r--r-- | src/main/stanza/firrtl-ir.stanza | 11 | ||||
| -rw-r--r-- | src/main/stanza/ir-parser.stanza | 8 | ||||
| -rw-r--r-- | src/main/stanza/ir-utils.stanza | 16 | ||||
| -rw-r--r-- | src/main/stanza/passes.stanza | 132 | ||||
| -rw-r--r-- | test/passes/infer-types/bundle.fir | 6 | ||||
| -rw-r--r-- | test/passes/infer-types/gcd.fir | 10 | ||||
| -rw-r--r-- | test/passes/resolve-genders/ports.fir | 2 |
7 files changed, 117 insertions, 68 deletions
diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza index 16e7096b..d6733263 100644 --- a/src/main/stanza/firrtl-ir.stanza +++ b/src/main/stanza/firrtl-ir.stanza @@ -6,12 +6,9 @@ public definterface Direction public val INPUT = new Direction public val OUTPUT = new Direction -public definterface Gender -public val MALE = new Gender -public val FEMALE = new Gender -public val UNKNOWN-GENDER = new Gender -public val BI-GENDER = new Gender - +public definterface Flip +public val DEFAULT = new Flip +public val REVERSE = new Flip public definterface Width public defstruct UnknownWidth <: Width @@ -218,7 +215,7 @@ public defstruct UnknownType <: Type public defstruct Field : name: Symbol - gender: Gender + flip: Flip type: Type public defstruct Port : diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza index a9ea7c30..46b62162 100644 --- a/src/main/stanza/ir-parser.stanza +++ b/src/main/stanza/ir-parser.stanza @@ -88,10 +88,10 @@ rd.defsyntax firrtl : Module(ut(name), ports, Begin(body)) defrule field : - (male ?name:#symbol : ?type:#type) : - Field(ut(name), MALE, type) - (female ?name:#symbol : ?type:#type) : - Field(ut(name), FEMALE, type) + (?name:#symbol : ?type:#type) : + Field(ut(name), DEFAULT, type) + (flip ?name:#symbol : ?type:#type) : + Field(ut(name), REVERSE, type) defrule port : (input ?name:#symbol : ?type:#type) : diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza index 47f6154b..546fd6e7 100644 --- a/src/main/stanza/ir-utils.stanza +++ b/src/main/stanza/ir-utils.stanza @@ -8,20 +8,18 @@ defpackage firrtl.ir-utils : public defmulti print-debug (o:OutputStream, e:Expression|Stmt|Type|Element|Port|Field) -> False ;============== PRINTERS =================================== -defmethod print (o:OutputStream, g:Gender) : + +defmethod print (o:OutputStream, d:Flip) : print{o, _} $ - switch {g == _} : - MALE : "male" - FEMALE: "female" - BI-GENDER : "bi" - UNKNOWN-GENDER: "unknown" + switch {d == _} : + DEFAULT : "" + REVERSE: "flip" defmethod print (o:OutputStream, d:Direction) : print{o, _} $ switch {d == _} : INPUT : "input" OUTPUT: "output" - ;UNKNOWN-DIR : "unknown" defmethod print (o:OutputStream, w:Width) : print{o, _} $ @@ -216,7 +214,7 @@ defmethod print (o:OutputStream, t:Type) : print-debug(o,t) defmethod print (o:OutputStream, f:Field) : - print-all(o, [gender(f) " " name(f) " : " type(f)]) + print-all(o, [flip(f) " " name(f) " : " type(f)]) print-debug(o,f) defmethod print (o:OutputStream, p:Port) : @@ -263,7 +261,7 @@ public defn map<?T> (f: Type -> Type, t:?T&Type) -> T : (t:T&BundleType) : BundleType $ for p in fields(t) map : - Field(name(p), gender(p), f(type(p))) + Field(name(p), flip(p), f(type(p))) (t:T&VectorType) : VectorType(f(type(t)), size(t)) (t) : diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza index 51176ff6..ece7287e 100644 --- a/src/main/stanza/passes.stanza +++ b/src/main/stanza/passes.stanza @@ -24,7 +24,11 @@ defstruct ModuleKind <: Kind defstruct InstanceKind <: Kind defstruct StructuralMemKind <: Kind ; Separate kind because need special treatment -;val UNKNOWN-DIR = new Direction +public definterface Gender +public val MALE = new Gender +public val FEMALE = new Gender +public val UNKNOWN-GENDER = new Gender +public val BI-GENDER = new Gender defstruct WRef <: Expression : name: Symbol @@ -52,25 +56,41 @@ defstruct WDefAccessor <: Stmt : ;================ WORKING IR UTILS ========================= -defn times (f1:Gender,f2:Gender) -> Gender : - if (f1 == UNKNOWN-GENDER) : UNKNOWN-GENDER - else if (f2 == UNKNOWN-GENDER) : UNKNOWN-GENDER - else if (f1 == MALE) : f2 - else if (f2 == MALE) : f1 - else if (f1 == FEMALE and f2 == FEMALE) : MALE - else if (f1 == BI-GENDER) : f2 - else if (f2 == BI-GENDER) : f1 - else : UNKNOWN-GENDER +defn swap (g:Gender) -> Gender : + switch {_ == g} : + UNKNOWN-GENDER : UNKNOWN-GENDER + MALE : FEMALE + FEMALE : MALE + BI-GENDER : BI-GENDER + +defn times (g:Gender,flip:Flip) -> Gender : + switch {_ == flip} : + DEFAULT : g + REVERSE : swap(g) + +defn times (flip:Flip,g:Gender) -> Gender : + switch {_ == flip} : + DEFAULT : g + REVERSE : swap(g) defn to-field (p:Port) -> Field : - if direction(p) == OUTPUT : Field(name(p),FEMALE,type(p)) - else if direction(p) == INPUT : Field(name(p),MALE,type(p)) - else : Field(name(p),UNKNOWN-GENDER,type(p)) + Field(name(p),REVERSE,type(p)) + if direction(p) == OUTPUT : Field(name(p),REVERSE,type(p)) + else if direction(p) == INPUT : Field(name(p),DEFAULT,type(p)) + else : error("Shouldn't be here") defmulti gender (e:Expression) -> Gender defmethod gender (e:Expression) : MALE ; TODO, why was this OUTPUT before? It makes sense as male, not female +defmethod print (o:OutputStream, g:Gender) : + print{o, _} $ + switch {g == _} : + MALE : "male" + FEMALE: "female" + BI-GENDER : "bi" + UNKNOWN-GENDER: "unknown" + ;============== DEBUG STUFF ============================= public var PRINT-TYPES : True|False = false public var PRINT-KINDS : True|False = false @@ -91,7 +111,7 @@ defmethod print (o:OutputStream, k:Kind) : (k:StructuralMemKind) : "smem" defn hasGender (e:Expression|Stmt|Type|Element|Port|Field) : - e typeof Field|WRef|WSubfield|WIndex|WDefAccessor + e typeof WRef|WSubfield|WIndex|WDefAccessor defn hasWidth (e:Expression|Stmt|Type|Element|Port|Field) : e typeof UIntType|SIntType|UIntValue|SIntValue @@ -148,11 +168,6 @@ defmethod map (f: Expression -> Expression, e: WIndex) : defmethod map (f: Expression -> Expression, c:WDefAccessor) : WDefAccessor(name(c), f(source(c)), f(index(c)), gender(c)) -;================= DIRECTION =============================== -;defmulti gender (e:Expression) -> Gender -;defmethod gender (e:Expression) : - ;MALE - ;================= Bring to Working IR ======================== ; Returns a new Circuit with Refs, Subfields, Indexes and DefAccessors ; replaced with IR-internal nodes that contain additional @@ -201,6 +216,7 @@ defn resolve-kinds (c:Circuit) : for e in entries(s) do : kinds[key(e)] = get-elem-kind(value(e)) (s:DefWire) : kinds[name(s)] = NodeKind() + ;TODO add DefNode (s:DefRegister) : kinds[name(s)] = RegKind() (s:DefInstance) : kinds[name(s)] = InstanceKind() (s:DefMemory) : kinds[name(s)] = MemKind() @@ -634,13 +650,13 @@ defn resolve-genders (c:Circuit) : (s) : map(resolve-stmt,s) defn resolve-expr (e:Expression,desired:Gender) -> Expression : - defn bundle-field-gender (n:Symbol,t:Type) -> Gender : + defn bundle-field-flip (n:Symbol,t:Type) -> Flip : match(t) : (b:BundleType) : val field = for f in fields(b) find : name(f) == n match(field): - (f:Field) : gender(f) + (f:Field) : flip(f) (f) : error(string-join(["Could not find " n " in bundle "])) (b) : error(string-join(["Accessing subfield " n " on a non-Bundle type."])) @@ -651,9 +667,9 @@ defn resolve-genders (c:Circuit) : if gender == BI-GENDER : desired else : gender (e:WSubfield) : - val field-gender = bundle-field-gender(name(e),type(exp(e))) - val exp* = resolve-expr(exp(e),field-gender * desired) - val gender* = field-gender * gender(exp*) + val field-flip = bundle-field-flip(name(e),type(exp(e))) + val exp* = resolve-expr(exp(e),field-flip * desired) + val gender* = field-flip * gender(exp*) WSubfield(exp*,name(e),type(e),gender*) (e:WIndex) : val exp* = resolve-expr(exp(e),desired) @@ -669,8 +685,8 @@ defn resolve-genders (c:Circuit) : defn resolve-genders (m:Module, c:Circuit) -> Module : val genders = HashTable<Symbol,Gender>(symbol-hash) - for m in modules(c) do : - genders[name(m)] = FEMALE + ;for m in modules(c) do : + ;genders[name(m)] = FEMALE resolve-module(m,genders) @@ -688,28 +704,28 @@ defn resolve-genders (c:Circuit) : ; at the sight of the accessor declaration ; If not accessing a memory, all elements of the vector are ; explicitly written out, then indexed. Depending on the gender -; of the accessor, it is transformed into ManyConnect (male) or -; ConnectMany (female) +; of the accessor, it is transformed into ConnectToIndexed (male) or +; ConnectFromIndexed (female) -defstruct ManyConnect <: Stmt : +defstruct ConnectToIndexed <: Stmt : index: Expression locs: List<Expression> exp: Expression -defstruct ConnectMany <: Stmt : +defstruct ConnectFromIndexed <: Stmt : index: Expression loc: Expression exps: List<Expression> -defmethod print (o:OutputStream, c:ManyConnect) : +defmethod print (o:OutputStream, c:ConnectToIndexed) : print-all(o, [locs(c) "[" index(c) "] := " exp(c)]) -defmethod print (o:OutputStream, c:ConnectMany) : +defmethod print (o:OutputStream, c:ConnectFromIndexed) : print-all(o, [loc(c) " := " exps(c) "[" index(c) "]"]) -defmethod map (f: Expression -> Expression, c:ManyConnect) : - ManyConnect(f(index(c)), map(f, locs(c)), f(exp(c))) -defmethod map (f: Expression -> Expression, c:ConnectMany) : - ConnectMany(f(index(c)), f(loc(c)), map(f, exps(c))) +defmethod map (f: Expression -> Expression, c:ConnectToIndexed) : + ConnectToIndexed(f(index(c)), map(f, locs(c)), f(exp(c))) +defmethod map (f: Expression -> Expression, c:ConnectFromIndexed) : + ConnectFromIndexed(f(index(c)), f(loc(c)), map(f, exps(c))) defn expand-vector (e:Expression) -> List<Expression> : match(e) : @@ -761,10 +777,10 @@ defn expand-stmt (s:Stmt,preds:List<Expression>) -> Stmt : switch {gender(s) == _} : MALE : Begin(list(wire,connectmany)) where : val exps = expand-vector(source(s)) - val connectmany = ConnectMany(index(s),WRef(name(s),value-type,NodeKind(),FEMALE),exps) + val connectmany = ConnectFromIndexed(index(s),WRef(name(s),value-type,NodeKind(),FEMALE),exps) FEMALE: Begin(list(wire,manyconnect)) where : val locs = expand-vector(source(s)) - val manyconnect = ManyConnect(index(s),locs,WRef(name(s),value-type,NodeKind(),MALE)) + val manyconnect = ConnectToIndexed(index(s),locs,WRef(name(s),value-type,NodeKind(),MALE)) (s:Conditionally) : val conseq* = expand-stmt(conseq(s),List(pred(s),preds)) val alt-pred = DoPrim(EQUAL-UU-OP,list(UIntValue(0,IntWidth(1)),pred(s)),list(),UIntType(IntWidth(1))) @@ -779,7 +795,45 @@ defn expand-accessors (c:Circuit) : Module(name(m),ports(m),expand-stmt(body(m),list())) -;;=============== BUNDLE FLATTENING ========================= +;;=============== LOWERING TO GROUND TYPES ============================= +; All non-ground (elevated) types (Vectors, Bundles) are expanded out to +; individual ground types. +; This pass involves filling a table mapping the name of elevated types +; to the lowered ground expression names and genders. This allows +; references to be resolved. + +;defn build-table (t:Type,f:Flip,l:List<KeyValue<Symbol,Flip>>) -> List<KeyValue<Symbol,Flip>> : +; match (t) : +; (t:BundleType) : +; for field in fields(t) map : +; match(type(field)) : +; (t:BundleType) : append(l,lower-type(t,f * flip(field),l)) +; (t:VectorType) : append(l,lower-type(t,f * flip(field),l)) +; (t) : List(KeyValue(gensym(),f * flip(field))) +; (t:VectorType) : +; match(type(f)) : +; (t:BundleType) : append(l,lower-type(t,f,l)) +; (t:VectorType) : append(l,lower-type(t,f,l)) +; (t) : +; for i in size(t) map : +; List(KeyValue(gensym(),f)) +; (t) : l +; +;defn build-table (ports:List<Port>) -> HashMap<Symbol,List<[Symbol,Gender]>> : +; for p in ports do : +; match(type(p)) : +; (t:BundleType) : +; +;defn lower-module (m:Module,c:Circuit) -> Module : +; +; +;defn lower-to-ground (c:Circuit) : +; Circuit(modules*, main(c)) where : +; val modules* = +; for m in modules(c) map : +; lower-module(m,c) + + ;defn prefix (prefix, suffix) : ; symbol-join([prefix "/" suffix]) ; diff --git a/test/passes/infer-types/bundle.fir b/test/passes/infer-types/bundle.fir index 0c4fa760..d9b86115 100644 --- a/test/passes/infer-types/bundle.fir +++ b/test/passes/infer-types/bundle.fir @@ -3,9 +3,9 @@ ;CHECK: Infer Types circuit top : module subtracter : - wire z : {male x : UInt, female y: SInt} - node x = z.x ;CHECK: node x = z@<t:{male x : UInt@<t:UInt>, female y : SInt@<t:SInt>}>.x@<t:UInt> - node y = z.y ;CHECK: node y = z@<t:{male x : UInt@<t:UInt>, female y : SInt@<t:SInt>}>.y@<t:SInt> + wire z : { x : UInt, flip y: SInt} + node x = z.x ;CHECK: node x = z@<t:{ x : UInt@<t:UInt>, flip y : SInt@<t:SInt>}>.x@<t:UInt> + node y = z.y ;CHECK: node y = z@<t:{ x : UInt@<t:UInt>, flip y : SInt@<t:SInt>}>.y@<t:SInt> wire a : UInt(3)[10] ;CHECK: wire a : UInt(3)[10]@<t:UInt>@<t:UInt(3)[10]@<t:UInt>> node b = a.2 ;CHECK: node b = a@<t:UInt(3)[10]@<t:UInt>>.2@<t:UInt> diff --git a/test/passes/infer-types/gcd.fir b/test/passes/infer-types/gcd.fir index b4d92269..ea134c2f 100644 --- a/test/passes/infer-types/gcd.fir +++ b/test/passes/infer-types/gcd.fir @@ -22,14 +22,14 @@ circuit top : when gt(x, y) : ;CHECK: when gt(x@<t:UInt>, y@<t:UInt>)@<t:UInt> : inst s of subtracter - ;CHECK: inst s of subtracter@<t:{male x : UInt@<t:UInt>, male y : UInt@<t:UInt>, female z : UInt@<t:UInt>, male reset : UInt(1)@<t:UInt>}> + ;CHECK: inst s of subtracter@<t:{ x : UInt@<t:UInt>, y : UInt@<t:UInt>, flip z : UInt@<t:UInt>, reset : UInt(1)@<t:UInt>}> s.x := x s.y := y x := s.z - ;CHECK: s@<t:{male x : UInt@<t:UInt>, male y : UInt@<t:UInt>, female z : UInt@<t:UInt>, male reset : UInt(1)@<t:UInt>}>.reset@<t:UInt> := reset@<t:UInt> - ;CHECK: s@<t:{male x : UInt@<t:UInt>, male y : UInt@<t:UInt>, female z : UInt@<t:UInt>, male reset : UInt(1)@<t:UInt>}>.x@<t:UInt> := x@<t:UInt> - ;CHECK: s@<t:{male x : UInt@<t:UInt>, male y : UInt@<t:UInt>, female z : UInt@<t:UInt>, male reset : UInt(1)@<t:UInt>}>.y@<t:UInt> := y@<t:UInt> - ;CHECK: x@<t:UInt> := s@<t:{male x : UInt@<t:UInt>, male y : UInt@<t:UInt>, female z : UInt@<t:UInt>, male reset : UInt(1)@<t:UInt>}>.z@<t:UInt> + ;CHECK: s@<t:{ x : UInt@<t:UInt>, y : UInt@<t:UInt>, flip z : UInt@<t:UInt>, reset : UInt(1)@<t:UInt>}>.reset@<t:UInt> := reset@<t:UInt> + ;CHECK: s@<t:{ x : UInt@<t:UInt>, y : UInt@<t:UInt>, flip z : UInt@<t:UInt>, reset : UInt(1)@<t:UInt>}>.x@<t:UInt> := x@<t:UInt> + ;CHECK: s@<t:{ x : UInt@<t:UInt>, y : UInt@<t:UInt>, flip z : UInt@<t:UInt>, reset : UInt(1)@<t:UInt>}>.y@<t:UInt> := y@<t:UInt> + ;CHECK: x@<t:UInt> := s@<t:{ x : UInt@<t:UInt>, y : UInt@<t:UInt>, flip z : UInt@<t:UInt>, reset : UInt(1)@<t:UInt>}>.z@<t:UInt> else : inst s2 of subtracter s2.x := x diff --git a/test/passes/resolve-genders/ports.fir b/test/passes/resolve-genders/ports.fir index ea92cd24..d790272c 100644 --- a/test/passes/resolve-genders/ports.fir +++ b/test/passes/resolve-genders/ports.fir @@ -10,7 +10,7 @@ circuit top : input data : UInt(16) output ready : UInt(1) module top: - wire connect : { male data : UInt(16), female ready: UInt(1) } + wire connect : { data : UInt(16), flip ready: UInt(1) } inst src of source ;CHECK: inst src of source@<g:female> inst snk of sink ;CHECK: inst snk of sink@<g:female> connect.data := src.data ;CHECK: connect@<g:female>.data@<g:female> := src@<g:female>.data@<g:male> |
