aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjackbackrack2015-06-02 08:47:40 -0700
committerjackbackrack2015-06-02 08:47:40 -0700
commitb178ca42fd9d4f7b94d80c01cd810bf18da9ebc8 (patch)
tree033e197aa2e297187e21712faf1957eb405b435b /src
parente668a13b285c87678a708a8af5bee2cfa0f7645b (diff)
parent8fc826a2770f46d63d8d7b1bccf14d2bf6e6b7cd (diff)
merge + fix trim to use correct bits operands
Diffstat (limited to 'src')
-rw-r--r--src/lib/stanza.zipbin3716930 -> 3729434 bytes
-rw-r--r--src/main/stanza/compilers.stanza12
-rw-r--r--src/main/stanza/custom-compiler.stanza38
-rw-r--r--src/main/stanza/custom-passes.stanza106
-rw-r--r--src/main/stanza/errors.stanza263
-rw-r--r--src/main/stanza/firrtl-ir.stanza25
-rw-r--r--src/main/stanza/firrtl-test-main.stanza10
-rw-r--r--src/main/stanza/flo.stanza22
-rw-r--r--src/main/stanza/ir-parser.stanza12
-rw-r--r--src/main/stanza/ir-utils.stanza61
-rw-r--r--src/main/stanza/passes.stanza376
-rw-r--r--src/main/stanza/primop.stanza1
-rw-r--r--src/main/stanza/verilog.stanza90
13 files changed, 786 insertions, 230 deletions
diff --git a/src/lib/stanza.zip b/src/lib/stanza.zip
index aed19c22..8dc3ea0a 100644
--- a/src/lib/stanza.zip
+++ b/src/lib/stanza.zip
Binary files differ
diff --git a/src/main/stanza/compilers.stanza b/src/main/stanza/compilers.stanza
index 8b84cc54..0c3978ab 100644
--- a/src/main/stanza/compilers.stanza
+++ b/src/main/stanza/compilers.stanza
@@ -12,7 +12,7 @@ public defstruct StandardFlo <: Compiler :
file: String with: (as-method => true)
public defmethod passes (c:StandardFlo) -> List<Pass> :
to-list $ [
- CheckHighForm()
+ CheckHighForm(expand-delin)
;; TempElimination()
ToWorkingIR()
MakeExplicitReset()
@@ -31,6 +31,9 @@ public defmethod passes (c:StandardFlo) -> List<Pass> :
Inline()
SplitExp()
ToRealIR()
+ SpecialRename(`#,`_)
+ SpecialRename(`$,`::)
+ CheckHighForm(`::)
Flo(file(c))
]
@@ -38,8 +41,13 @@ public defstruct StandardVerilog <: Compiler :
file: String with: (as-method => true)
public defmethod passes (c:StandardVerilog) -> List<Pass> :
to-list $ [
+<<<<<<< HEAD
CheckHighForm()
;; TempElimination()
+=======
+ CheckHighForm(expand-delin)
+ TempElimination()
+>>>>>>> upstream/master
ToWorkingIR()
MakeExplicitReset()
ResolveKinds()
@@ -53,9 +61,9 @@ public defmethod passes (c:StandardVerilog) -> List<Pass> :
ExpandIndexedConnects()
ExpandWhens()
InferWidths()
- ;Inline()
SplitExp()
ToRealIR()
+ SpecialRename(`#,`_)
Verilog(file(c))
]
diff --git a/src/main/stanza/custom-compiler.stanza b/src/main/stanza/custom-compiler.stanza
new file mode 100644
index 00000000..1ca29bdd
--- /dev/null
+++ b/src/main/stanza/custom-compiler.stanza
@@ -0,0 +1,38 @@
+defpackage firrtl/custom-compiler :
+ import core
+ import verse
+ import firrtl/ir-utils
+ import firrtl/ir2
+ import firrtl/passes
+ import firrtl/errors
+ import firrtl/verilog
+ import firrtl/custom-passes
+
+public defstruct InstrumentedVerilog <: Compiler :
+ file: String with: (as-method => true)
+ args: List<String>
+public defmethod passes (c:InstrumentedVerilog) -> List<Pass> :
+ to-list $ [
+ WhenCoverage(args(c)[0],args(c)[1])
+ CheckHighForm(expand-delin)
+ TempElimination()
+ ToWorkingIR()
+ MakeExplicitReset()
+ ResolveKinds()
+ CheckKinds()
+ InferTypes()
+ CheckTypes()
+ ResolveGenders()
+ CheckGenders()
+ ExpandAccessors()
+ LowerToGround()
+ ExpandIndexedConnects()
+ ExpandWhens()
+ InferWidths()
+ SplitExp()
+ ToRealIR()
+ SpecialRename(`#,`_)
+ Verilog(file(c))
+ ]
+
+
diff --git a/src/main/stanza/custom-passes.stanza b/src/main/stanza/custom-passes.stanza
new file mode 100644
index 00000000..e4c3d9d3
--- /dev/null
+++ b/src/main/stanza/custom-passes.stanza
@@ -0,0 +1,106 @@
+defpackage firrtl/custom-passes :
+ import core
+ import verse
+ import firrtl/ir-utils
+ import firrtl/ir2
+
+public defstruct WhenCoverage <: Pass :
+ port-name : String
+ reg-name : String
+public defmethod pass (b:WhenCoverage) -> (Circuit -> Circuit) : when-coverage{port-name(b),reg-name(b),_}
+public defmethod name (b:WhenCoverage) -> String : "When Coverage"
+public defmethod short-name (b:WhenCoverage) -> String : "when-coverage"
+
+;============ Utilz =============
+defn concat-all (ls:List<Expression>) -> Expression :
+ if length(ls) == 0 : error("Shouldn't be here")
+ if length(ls) == 1 : head(ls)
+ else : DoPrim( CONCAT-OP,
+ list(head(ls),concat-all(tail(ls))),
+ list(),
+ UIntType(UnknownWidth()))
+
+;============ When Coverage Pass =============
+;port width = 1 bit per scope + portwidths of all instances
+
+defn needs-instrumentation (m:Module,ms:List<Module>,instrument?:HashTable<Symbol,True|False>) -> False :
+ defn needs-instrumentation-s (s:Stmt) -> False :
+ match(s) :
+ (s:Conditionally) :instrument?[name(m)] = true
+ (s:DefInstance) :
+ val module-of-inst = for x in ms find : name(x) == name(module(s) as Ref)
+ if module-of-inst != false :
+ needs-instrumentation(module-of-inst as Module,ms,instrument?)
+ instrument?[name(m)] = instrument?[name(module-of-inst as Module)]
+ (s) : false
+ do(needs-instrumentation-s,s)
+
+ match(m) :
+ (m:InModule) : do(needs-instrumentation-s,body(m))
+ (m:ExModule) : false
+
+defn when-coverage (port-name:Symbol, reg-name:Symbol, instrument?:HashTable<Symbol,True|False>, m:InModule) -> InModule :
+ val when-bits = Vector<Ref>()
+ val inst-bits = Vector<Ref>()
+ val sym = HashTable<Symbol,Int>(symbol-hash)
+ val w1 = IntWidth(1)
+ val t1 = UIntType(w1)
+ val u1 = UIntValue(1,w1)
+ defn when-coverage (s:Stmt) -> Stmt :
+ match(s) :
+ (s:Conditionally) :
+ val ref = Ref(firrtl-gensym(reg-name,sym),t1)
+ add(when-bits,ref)
+ val conseq* = Begin(list(Connect(FileInfo()ref,u1),conseq(s)))
+ map(when-coverage,Conditionally(info(s),pred(s),conseq*,alt(s)))
+ (s:DefInstance) :
+ if instrument?[name(module(s) as Ref)] :
+ val ref = Ref(firrtl-gensym(port-name,sym),UIntType(UnknownWidth()))
+ add(inst-bits,ref)
+ val sfld = Subfield(Ref(name(s),UnknownType()),port-name,UnknownType())
+ Begin(list(s,Connect(FileInfo(),ref,sfld)))
+ else : s
+ (s) : map(when-coverage,s)
+
+ val body* = when-coverage(body(m))
+ val logic = Vector<Stmt>()
+ val port-ref = Ref(port-name,UIntType(UnknownWidth()))
+
+ val w-ls = to-list $ when-bits
+ if length(w-ls) != 0 :
+ val reg-ref = Ref(reg-name,UIntType(IntWidth(length(w-ls))))
+ add{logic,_} $ DefRegister(FileInfo(),name(reg-ref),type(reg-ref))
+ add{logic,_} $ OnReset(FileInfo(),reg-ref,UIntValue(0,IntWidth(length(w-ls))))
+ for (x in w-ls, i in 0 to false) do :
+ add{logic,_} $ DefWire(FileInfo(),name(x),type(x))
+ add{logic,_} $ Connect(FileInfo(),x,DoPrim(BIT-SELECT-OP,list(reg-ref),list(i),UIntType(w1)))
+ add{logic,_} $ Connect(FileInfo(),reg-ref,concat-all(w-ls))
+
+ val i-ls = to-list $ inst-bits
+ if length(i-ls) != 0 :
+ for (x in i-ls, i in 0 to false) do :
+ add{logic,_} $ DefWire(FileInfo(),name(x),type(x))
+ add{logic,_} $ Connect(FileInfo(),x,UIntValue(0,UnknownWidth()))
+
+ if instrument?[name(m)] : add{logic,_} $ Connect(FileInfo(),port-ref,concat-all(append(w-ls,i-ls)))
+
+ if length(logic) != 0 :
+ val ports* = List(Port(FileInfo(),port-name,OUTPUT,UIntType(UnknownWidth())),ports(m))
+ val body** = Begin(list(Begin(to-list $ logic),body*))
+ InModule(info(m),name(m),ports*,body**)
+ else : m
+
+public defn when-coverage (port-name:String, reg-name:String, c:Circuit) :
+ val instrument? = HashTable<Symbol,True|False>(symbol-hash)
+ for m in modules(c) do :
+ instrument?[name(m)] = false
+ val top = for m in modules(c) find : name(m) == main(c)
+ if top != false : needs-instrumentation(top as Module,modules(c),instrument?)
+
+ val modules* = for m in modules(c) map :
+ match(m) :
+ (m:InModule) :
+ when-coverage(to-symbol $ port-name,to-symbol $ reg-name,instrument?,m)
+ (m:ExModule) : m
+ Circuit(info(c),modules*,main(c))
+
diff --git a/src/main/stanza/errors.stanza b/src/main/stanza/errors.stanza
index 8c5532b0..0795a2a9 100644
--- a/src/main/stanza/errors.stanza
+++ b/src/main/stanza/errors.stanza
@@ -19,7 +19,6 @@ defpackage firrtl/errors :
; o No names
; o No Unknowns
; o All widths are positive
-; o Pad's width is greater than value's width
; o pad's width is greater than value's width
; o widths are large enough to contain value
@@ -43,9 +42,13 @@ defpackage firrtl/errors :
; * No name can be a prefix of any other name.
; * all references are declared
; * UInt only has positive ints
+; * Vector types has positive size
+; * Width sizes are positive
+; * Primops have the correct number of arguments
-public defstruct CheckHighForm <: Pass
-public defmethod pass (b:CheckHighForm) -> (Circuit -> Circuit) : check-high-form
+public defstruct CheckHighForm <: Pass :
+ sym : Symbol
+public defmethod pass (b:CheckHighForm) -> (Circuit -> Circuit) : check-high-form{_,sym(b)}
public defmethod name (b:CheckHighForm) -> String : "High Form Check"
public defmethod short-name (b:CheckHighForm) -> String : "high-form-check"
@@ -94,6 +97,22 @@ 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 $
+ [info ": Primop " op " requires " n " expression arguments."]
+
+defn IncorrectNumConsts (info:FileInfo, op:Symbol, n:Int) :
+ PassException $ string-join $
+ [info ": Primop " op " requires " n " integer arguments."]
+
+defn NegWidth (info:FileInfo) :
+ PassException $ string-join $
+ [info ": Width cannot be negative."]
+
+defn NegVecSize (info:FileInfo) :
+ PassException $ string-join $
+ [info ": Vector type size cannot be negative."]
+
;---------------- Helper Functions --------------
defn has-flip? (t:Type) -> True|False :
var has? = false
@@ -114,28 +133,70 @@ defn contains?<?T> (c:?T,cs:Streamable<?T>) -> True|False :
if x == c : myret(true)
false
-defn is-prefix? (s:Symbol,v:Vector<Symbol>) -> Symbol|False :
+defn is-prefix? (s:Symbol,v:Vector<Symbol>,sym:Symbol) -> Symbol|False :
+ defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False :
+ var is? = true
+ val s1* = to-string(s1)
+ val s2* = to-string(s2)
+ for (x in s1*, y in s2*) do :
+ if x != y : is? = false
+ if length(s1*) > length(s2*) :
+ if s1*[length(s2*)] != to-string(sym)[0] : is? = false
+ if length(s1*) < length(s2*) :
+ if s2*[length(s1*)] != to-string(sym)[0] : is? = false
+ if length(s1*) == length(s2*) :
+ is? = false
+ is?
label<Symbol|False> myret :
for x in v do :
if is-prefix?(x,s) : myret(x)
false
-defn is-prefix? (s1:Symbol,s2:Symbol) -> True|False :
- var is? = true
- val s1* = to-string(s1)
- val s2* = to-string(s2)
- for (x in s1*, y in s2*) do :
- if x != y : is? = false
- if length(s1*) > length(s2*) :
- if s1*[length(s2*)] != '$' : is? = false
- if length(s1*) < length(s2*) :
- if s2*[length(s1*)] != '$' : is? = false
- if length(s1*) == length(s2*) :
- is? = false
- is?
+defn check-high-form-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) -> False :
+ defn correct-num (ne:Int|False,nc:Int) -> False :
+ if not (ne typeof False) :
+ if length(args(e)) != ne as Int : add(errors,IncorrectNumArgs(info,to-symbol(op(e)),ne as Int))
+ if length(consts(e)) != nc : add(errors,IncorrectNumConsts(info,to-symbol $ op(e),nc))
+
+ switch {op(e) == _} :
+ ADD-OP : correct-num(2,0)
+ SUB-OP : correct-num(2,0)
+ MUL-OP : correct-num(2,0)
+ DIV-OP : correct-num(2,0)
+ MOD-OP : correct-num(2,0)
+ QUO-OP : correct-num(2,0)
+ REM-OP : correct-num(2,0)
+ ADD-WRAP-OP : correct-num(2,0)
+ SUB-WRAP-OP : correct-num(2,0)
+ LESS-OP : correct-num(2,0)
+ LESS-EQ-OP : correct-num(2,0)
+ GREATER-OP : correct-num(2,0)
+ GREATER-EQ-OP : correct-num(2,0)
+ EQUAL-OP : correct-num(2,0)
+ NEQUAL-OP : correct-num(2,0)
+ MUX-OP : correct-num(3,0)
+ PAD-OP : correct-num(1,1)
+ AS-UINT-OP : correct-num(1,0)
+ AS-SINT-OP : correct-num(1,0)
+ DYN-SHIFT-LEFT-OP : correct-num(2,0)
+ DYN-SHIFT-RIGHT-OP : correct-num(2,0)
+ SHIFT-LEFT-OP : correct-num(1,1)
+ SHIFT-RIGHT-OP : correct-num(1,1)
+ CONVERT-OP : correct-num(1,0)
+ NEG-OP : correct-num(1,0)
+ BIT-NOT-OP : correct-num(1,0)
+ BIT-AND-OP : correct-num(2,0)
+ BIT-OR-OP : correct-num(2,0)
+ BIT-XOR-OP : correct-num(2,0)
+ BIT-AND-REDUCE-OP : correct-num(false,0)
+ BIT-OR-REDUCE-OP : correct-num(false,0)
+ BIT-XOR-REDUCE-OP : correct-num(false,0)
+ CONCAT-OP : correct-num(2,0)
+ BIT-SELECT-OP : correct-num(1,1)
+ BITS-SELECT-OP : correct-num(1,2)
;--------------- Check High Form Pass -------------------
-public defn check-high-form (c:Circuit) -> Circuit :
+public defn check-high-form (c:Circuit,sym:Symbol) -> Circuit :
val errors = Vector<PassException>()
defn check-valid-loc (info:FileInfo,e:Expression) -> False :
@@ -144,6 +205,20 @@ public defn check-high-form (c:Circuit) -> Circuit :
add(errors,InvalidLOC(info))
(e) : false
+ defn check-high-form-w (info:FileInfo,w:Width) -> Width :
+ match(w) :
+ (w:IntWidth) :
+ if width(w) < 0 : add(errors,NegWidth(info))
+ w
+ (w) : w
+
+ defn check-high-form-t (info:FileInfo,t:Type) -> Type :
+ match(map(check-high-form-t{info,_},t)) :
+ (t:VectorType) :
+ if size(t) < 0 : add(errors,NegVecSize(info))
+ (t) : false
+ map(check-high-form-w{info,_:Width},t)
+
defn check-high-form-e (info:FileInfo,e:Expression,names:Vector<Symbol>) -> Expression :
match(map(check-high-form-e{info,_,names},e)) :
(e:Ref) :
@@ -157,18 +232,23 @@ public defn check-high-form (c:Circuit) -> Circuit :
match(exp(e)) :
(e:Ref|Subfield|Index) : false
(e) : add(errors,InvalidIndex(info))
+ (e:DoPrim) : check-high-form-primop(e,errors,info)
;; (e:UIntValue) :
;; if value(e) < 0 :
;; add(errors,NegUInt(info))
(e) : false
+ map(check-high-form-w{info,_:Width},e)
+ map(check-high-form-t{info,_:Type},e)
e
defn check-high-form-s (s:Stmt,names:Vector<Symbol>) -> Stmt :
defn check-name (info:FileInfo,name:Symbol) -> False :
if contains?(name,names) : add(errors,NotUnique(info,name))
- val prefix = is-prefix?(name,names)
+ val prefix = is-prefix?(name,names,sym)
if prefix typeof Symbol : add(errors,IsPrefix(info,name,prefix as Symbol))
+ map(check-high-form-t{info(s),_:Type},s)
+
map{check-high-form-s{_,names},_} $ {
match(map(check-high-form-e{info(s),_,names},s)) :
(s:DefWire|DefRegister) :
@@ -191,6 +271,8 @@ public defn check-high-form (c:Circuit) -> Circuit :
add(names,name(s))
(s:Connect) :
check-valid-loc(info(s),loc(s))
+ (s:BulkConnect) :
+ check-valid-loc(info(s),loc(s))
(s) : false
s }()
@@ -209,10 +291,15 @@ public defn check-high-form (c:Circuit) -> Circuit :
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))
+
add(names,`reset)
- check-high-form-s(body(m),names)
+ match(m) :
+ (m:ExModule) : false
+ (m:InModule) : check-high-form-s(body(m),names)
false
var number-top-m = 0
@@ -284,8 +371,6 @@ public defn check-kinds (c:Circuit) -> Circuit :
check-is-mem(info,mem(e))
check-not-mem(info,index(e))
check-not-mem(info,enable(e))
- ;(e:Pad) :
- ;check-not-mem(info,value(e))
(e) : do(check-not-mem{info,_},e)
defn check-kinds-s (s:Stmt) -> False :
do(check-kinds-e{info(s),_:Expression},s)
@@ -296,6 +381,9 @@ public defn check-kinds (c:Circuit) -> Circuit :
(s:Connect) :
check-not-mem(info(s),loc(s))
check-not-mem(info(s),exp(s))
+ (s:BulkConnect) :
+ check-not-mem(info(s),loc(s))
+ check-not-mem(info(s),exp(s))
(s:OnReset) :
check-is-reg(info(s),loc(s))
check-not-mem(info(s),exp(s))
@@ -303,13 +391,14 @@ public defn check-kinds (c:Circuit) -> Circuit :
do(check-kinds-s,s)
for m in modules(c) do :
- check-kinds-s(body(m))
+ match(m) :
+ (m:ExModule) : false
+ (m:InModule) : check-kinds-s(body(m))
throw(PassExceptions(errors)) when not empty?(errors)
c
;==================== CHECK TYPES =====================
-; o expression in pad must be a ground type
; o Subfields are only on bundles, before type inference <- need to not error, just do unknown-type
; o Indexes are only on vectors
; o pred in conditionally must be of type UInt
@@ -348,10 +437,6 @@ defn EnableNotUInt (info:FileInfo) :
PassException $ string-join $
[info ": Enable is not of UIntType."]
-;defn PadNotGround (info:FileInfo) :
- ;PassException $ string-join $
- ;[info ": Illegal Pad on non-ground type."]
-
defn InvalidConnect (info:FileInfo) :
PassException $ string-join $
[info ": Type mismatch."]
@@ -360,6 +445,27 @@ defn PredNotUInt (info:FileInfo) :
PassException $ string-join $
[info ": Predicate not a UIntType."]
+defn OpNotGround (info:FileInfo, op:Symbol) :
+ PassException $ string-join $
+ [info ": Primop " op " cannot operate on non-ground types."]
+
+defn OpNotUInt (info:FileInfo, op:Symbol,e:Symbol) :
+ PassException $ string-join $
+ [info ": Primop " op " requires argument " e " to be a UInt type."]
+
+defn OpNotAllUInt (info:FileInfo, op:Symbol) :
+ PassException $ string-join $
+ [info ": Primop " op " requires all arguments to be UInt type."]
+
+defn OpNotAllSameType (info:FileInfo, op:Symbol) :
+ PassException $ string-join $
+ [info ": Primop " op " requires all operands to have the same type."]
+
+defn NodeWithFlips (info:FileInfo) :
+ PassException $ string-join $
+ [info ": Node cannot be a bundle type with flips."]
+
+
;---------------- Helper Functions --------------
defmethod equal? (t1:Type,t2:Type) -> True|False :
match(t1,t2) :
@@ -380,6 +486,64 @@ defmethod equal? (t1:Type,t2:Type) -> True|False :
defn u () -> UIntType : UIntType(UnknownWidth())
defn s () -> SIntType : SIntType(UnknownWidth())
+defn check-types-primop (e:DoPrim, errors:Vector<PassException>,info:FileInfo) -> False :
+ defn all-same-type (ls:List<Expression>) -> False :
+ for x in ls do :
+ if type(head(ls)) != type(x) :
+ add(errors,OpNotAllSameType(info,to-symbol $ op(e)))
+ defn all-ground (ls:List<Expression>) -> False :
+ for x in ls do :
+ if not (type(x) typeof UIntType or type(x) typeof SIntType) :
+ add(errors,OpNotGround(info,to-symbol $ op(e)))
+ defn all-uint (ls:List<Expression>) -> False :
+ for x in ls do :
+ if not (type(x) typeof UIntType) :
+ add(errors,OpNotAllUInt(info,to-symbol $ op(e)))
+ defn is-uint (x:Expression) -> False :
+ if not (type(x) typeof UIntType) :
+ add(errors,OpNotUInt(info,to-symbol $ op(e),to-symbol(x)))
+
+ all-ground(args(e))
+
+ switch {op(e) == _} :
+ ADD-OP : false
+ SUB-OP : false
+ MUL-OP : false
+ DIV-OP : false
+ MOD-OP : false
+ QUO-OP : false
+ REM-OP : false
+ ADD-WRAP-OP : false
+ SUB-WRAP-OP : false
+ LESS-OP : false
+ LESS-EQ-OP : false
+ GREATER-OP : false
+ GREATER-EQ-OP : false
+ EQUAL-OP : all-same-type(args(e))
+ NEQUAL-OP : all-same-type(args(e))
+ MUX-OP :
+ all-same-type(tail(args(e)))
+ is-uint(head(args(e)))
+ PAD-OP : false
+ AS-UINT-OP : false
+ AS-SINT-OP : false
+ DYN-SHIFT-LEFT-OP : is-uint(args(e)[1])
+ DYN-SHIFT-RIGHT-OP : is-uint(args(e)[1])
+ SHIFT-LEFT-OP : false
+ SHIFT-RIGHT-OP : false
+ CONVERT-OP : false
+ NEG-OP : false
+ BIT-NOT-OP : all-uint(args(e))
+ BIT-AND-OP : all-uint(args(e))
+ BIT-OR-OP : all-uint(args(e))
+ BIT-XOR-OP : all-uint(args(e))
+ BIT-AND-REDUCE-OP : all-uint(args(e))
+ BIT-OR-REDUCE-OP : all-uint(args(e))
+ BIT-XOR-REDUCE-OP : all-uint(args(e))
+ CONCAT-OP : all-uint(args(e))
+ BIT-SELECT-OP : all-uint(args(e))
+ BITS-SELECT-OP : all-uint(args(e))
+
;----------------- Check Types Pass ---------------------
public defn check-types (c:Circuit) -> Circuit :
val errors = Vector<PassException>()
@@ -397,33 +561,32 @@ public defn check-types (c:Circuit) -> Circuit :
(t:VectorType) :
if value(e) >= size(t) : add(errors,IndexTooLarge(info,value(e)))
(t) : add(errors,IndexOnNonVector(info))
- (e:DoPrim) : false ;check-types-primop(e)
+ (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:Pad) :
- ;val t = type(value(e))
- ;if not (t == u() or t == s()) : add(errors,PadNotGround(info))
(e:UIntValue|SIntValue) : false
e
defn check-types-s (s:Stmt) -> Stmt :
- map{check-types-s,_} $
- match(map(check-types-e{info(s),_},s)) :
- (s:Connect) :
- if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s)))
- s
- (s:OnReset) :
- if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s)))
- s
- (s:Conditionally) :
- if type(pred(s)) != u() : add(errors,PredNotUInt(info(s)))
- s
- (s) : s
+ map{check-types-s,_} $ {
+ match(map(check-types-e{info(s),_},s)) :
+ (s:Connect) :
+ if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s)))
+ (s:OnReset) :
+ if type(loc(s)) != type(exp(s)) : add(errors,InvalidConnect(info(s)))
+ (s:Conditionally) :
+ if type(pred(s)) != u() : add(errors,PredNotUInt(info(s)))
+ (s:DefNode) :
+ if has-flip?(type(value(s))) : add(errors,NodeWithFlips(info(s)))
+ (s) : false
+ s }()
for m in modules(c) do :
- check-types-s(body(m))
+ match(m) :
+ (m:ExModule) : false
+ (m:InModule) : check-types-s(body(m))
throw(PassExceptions(errors)) when not empty?(errors)
c
@@ -469,7 +632,6 @@ public defn check-genders (c:Circuit) -> Circuit :
val f = {_ as Field} $ for f in fields(type(exp(e)) as BundleType) find : name(f) == name(e)
get-gender(exp(e),genders) * flip(f)
(e:WIndex) : get-gender(exp(e),genders)
- ;(e:Pad) : MALE
(e:DoPrim) : MALE
(e:UIntValue) : MALE
(e:SIntValue) : MALE
@@ -483,7 +645,6 @@ public defn check-genders (c:Circuit) -> Circuit :
(e:WRef) : false
(e:WSubfield) : false
(e:WIndex) : false
- ;(e:Pad) : check-gender(info,genders,value(e),MALE)
(e:DoPrim) :
for e in args(e) do :
check-gender(info,genders,e,MALE)
@@ -511,6 +672,9 @@ public defn check-genders (c:Circuit) -> Circuit :
(s:Connect) :
check-gender(info(s),genders,loc(s),FEMALE)
check-gender(info(s),genders,exp(s),MALE)
+ (s:BulkConnect) :
+ check-gender(info(s),genders,loc(s),FEMALE)
+ check-gender(info(s),genders,exp(s),MALE)
(s:OnReset) :
check-gender(info(s),genders,loc(s),FEMALE)
check-gender(info(s),genders,exp(s),MALE)
@@ -524,6 +688,9 @@ public defn check-genders (c:Circuit) -> Circuit :
val genders = HashTable<Symbol,Gender>(symbol-hash)
for p in ports(m) do :
genders[name(p)] = dir-to-gender(direction(p))
- check-genders-s(body(m),genders)
+ match(m) :
+ (m:ExModule) : false
+ (m:InModule) : check-genders-s(body(m),genders)
throw(PassExceptions(errors)) when not empty?(errors)
c
+
diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza
index 39538498..18e069b4 100644
--- a/src/main/stanza/firrtl-ir.stanza
+++ b/src/main/stanza/firrtl-ir.stanza
@@ -5,6 +5,9 @@ defpackage firrtl/ir2 :
public defmulti info! (x:?) -> FileInfo
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
@@ -114,6 +117,7 @@ public defstruct DefMemory <: Stmt : ;LOW
info: FileInfo with: (as-method => true)
name: Symbol
type: VectorType
+ seq?: True|False
public defstruct DefNode <: Stmt : ;LOW
info: FileInfo with: (as-method => true)
name: Symbol
@@ -130,7 +134,11 @@ public defstruct Conditionally <: Stmt :
alt: Stmt
public defstruct Begin <: Stmt : ;LOW
body: List<Stmt>
-public defstruct OnReset <: Stmt : ;LOW
+public defstruct OnReset <: Stmt :
+ info: FileInfo with: (as-method => true)
+ loc: Expression
+ exp: Expression
+public defstruct BulkConnect <: Stmt :
info: FileInfo with: (as-method => true)
loc: Expression
exp: Expression
@@ -163,12 +171,21 @@ public defstruct Port :
direction: Direction
type: Type
-public defstruct Module :
+public definterface Module
+public defmulti name (m:Module) -> Symbol
+public defmulti ports (m:Module) -> List<Port>
+
+public defstruct InModule <: Module :
info: FileInfo
- name: Symbol
- ports: List<Port>
+ name: Symbol with: (as-method => true)
+ ports: List<Port> with: (as-method => true)
body: Stmt
+public defstruct ExModule <: Module :
+ info: FileInfo
+ name: Symbol with: (as-method => true)
+ ports: List<Port> with: (as-method => true)
+
public defstruct Circuit :
info: FileInfo
modules: List<Module>
diff --git a/src/main/stanza/firrtl-test-main.stanza b/src/main/stanza/firrtl-test-main.stanza
index 5a7e593d..071717bb 100644
--- a/src/main/stanza/firrtl-test-main.stanza
+++ b/src/main/stanza/firrtl-test-main.stanza
@@ -13,6 +13,10 @@
#include("flo.stanza")
#include("verilog.stanza")
+;Custom Packages
+#include("custom-passes.stanza")
+#include("custom-compiler.stanza")
+
defpackage firrtl-main :
import core
import verse
@@ -22,6 +26,9 @@ defpackage firrtl-main :
import stz/parser
import firrtl/ir-utils
import firrtl/compiler
+ ;Custom Packages
+ import firrtl/custom-passes
+ import firrtl/custom-compiler
defn set-printvars! (p:List<Char>) :
if contains(p,'t') : PRINT-TYPES = true
@@ -47,6 +54,7 @@ defn main () :
var output = false
var compiler = false
val pass-names = Vector<String>()
+ val pass-args = Vector<String>()
var printvars = ""
for (s in args, i in 0 to false) do :
if s == "-i" : input = args[i + 1]
@@ -54,6 +62,7 @@ defn main () :
if s == "-x" : add(pass-names,args[i + 1])
if s == "-X" : compiler = args[i + 1]
if s == "-p" : printvars = args[i + 1]
+ if s == "-s" : add(pass-args,args[i + 1])
if input == false :
error("No input file provided. Use -i flag.")
@@ -72,6 +81,7 @@ defn main () :
switch {_ == compiler} :
"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")
main()
diff --git a/src/main/stanza/flo.stanza b/src/main/stanza/flo.stanza
index c75071cd..bb9365ae 100644
--- a/src/main/stanza/flo.stanza
+++ b/src/main/stanza/flo.stanza
@@ -24,9 +24,11 @@ defn set-width (desired:Int,t:Type) -> Type :
defn pad-widths-e (desired:Int,e:Expression) -> Expression :
defn trim (desired:Int, e:Expression) :
- DoPrim(BITS-SELECT-OP,list(e),list(0,desired),set-width(desired,type(e)))
+ ;; 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) :
- DoPrim(PAD-OP,list(e),list(),set-width(desired,type(e)))
+ ;; 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)
@@ -83,7 +85,9 @@ defn pad-widths-s (s:Stmt) -> Stmt :
public defn pad-widths (c:Circuit) -> Circuit :
Circuit{info(c),_,main(c)} $
for m in modules(c) map :
- Module(info(m),name(m),ports(m),pad-widths-s(body(m)))
+ match(m) :
+ (m:ExModule) : error("Cannot use flo backend with external modules")
+ (m:InModule) : InModule(info(m),name(m),ports(m),pad-widths-s(body(m)))
;============= Flo Backend ================
@@ -217,7 +221,7 @@ defn maybe-mov (e:Expression) -> String :
(e) : false
if need-mov?: "mov " else: ""
-defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol) :
+defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol,sh:HashTable<Symbol,Int>) :
match(s) :
(s:DefWire) : ""
(s:DefInstance) : error("Shouldn't be here")
@@ -226,7 +230,7 @@ defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol) :
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}, body(s))
+ (s:Begin) : do(emit-s{_, v, top,sh}, body(s))
(s:Connect) :
match(loc(s)) :
(r:Ref) :
@@ -236,14 +240,14 @@ defn emit-s (s:Stmt, v:List<Symbol>, top:Symbol) :
else :
emit-all([top "::" n " = " maybe-mov(exp(s)) exp(s) "\n"], top)
(w:WritePort) :
- val n = firrtl-gensym(`F)
+ 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) : s
-defn emit-module (m:Module) :
+defn emit-module (m:InModule,sh:HashTable<Symbol,Int>) :
val v = Vector<Symbol>()
for port in ports(m) do :
if name(port) ==`reset :
@@ -251,10 +255,10 @@ defn emit-module (m:Module) :
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))
+ emit-s(body(m), to-list(v), name(m),sh)
public defn emit-flo (file:String, c:Circuit) :
with-output-file{file, _} $ fn () :
- emit-module(modules(c)[0])
+ emit-module(modules(c)[0] as InModule,get-sym-hash(modules(c)[0] as InModule))
false
c
diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza
index 0833543f..cbfe106e 100644
--- a/src/main/stanza/ir-parser.stanza
+++ b/src/main/stanza/ir-parser.stanza
@@ -151,9 +151,15 @@ defsyntax firrtl :
module = (module ?name:#id! #:! (?ps:#port ... ?cs:#stmt ... ?rest ...)) :
if not empty?(rest) :
FPE(rest, "Expected a statement here.")
- Module(first-info(form),name, ps, Begin(cs))
+ InModule(first-info(form),name, ps, Begin(cs))
+ module = (exmodule ?name:#id! #:! (?ps:#port ... ?rest ...)) :
+ if not empty?(rest) :
+ FPE(rest, "Expected a port here.")
+ ExModule(first-info(form),name, ps)
module != (module) :
FPE(form, "Invalid syntax for module definition.")
+ module != (exmodule) :
+ FPE(form, "Invalid syntax for exmodule definition.")
defrule port :
port = (input ?name:#id! #:! ?type:#type!) : Port(first-info(form),name, INPUT, type)
@@ -187,13 +193,15 @@ defsyntax firrtl :
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 = (mem ?name:#id! #:! ?t:#vectype!) : DefMemory(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 = (accessor ?name:#id! #=! ?s:#exp![?i:#exp$]) : DefAccessor(first-info(form),name, s, i)
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 ...)) :
diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza
index d2afca05..c39a1ad1 100644
--- a/src/main/stanza/ir-utils.stanza
+++ b/src/main/stanza/ir-utils.stanza
@@ -9,15 +9,42 @@ public defmulti print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field|M
;============== GENSYM STUFF ======================
-val sym-hash = HashTable<Symbol,Int>(symbol-hash)
-public defn firrtl-gensym (s:Symbol) -> Symbol :
- val cur = get?(sym-hash,s,0)
- val nxt = cur + 1
- sym-hash[s] = nxt
- symbol-join([s cur])
+
+public defn firrtl-gensym (s:Symbol) -> Symbol : firrtl-gensym(s,HashTable<Symbol,Int>(symbol-hash))
+
+public defn firrtl-gensym (s:Symbol,sym-hash:HashTable<Symbol,Int>) -> Symbol :
+ defn get-new (s:Symbol, i:Int) -> Symbol :
+ val s* = symbol-join([s i])
+ if contains?(keys(sym-hash),s*) :
+ get-new(s,i + 1)
+ else :
+ sym-hash[s] = i
+ sym-hash[s*] = 0
+ s*
+ get-new(s,0)
-public defn firrtl-gensym () -> Symbol :
- firrtl-gensym(`gen)
+public defn firrtl-gensym (sym-hash:HashTable<Symbol,Int>) -> Symbol :
+ firrtl-gensym(`gen,sym-hash)
+
+public defn get-sym-hash (m:InModule) -> HashTable<Symbol,Int> :
+ val sym-hash = HashTable<Symbol,Int>(symbol-hash)
+ defn add-name (s:Symbol) -> False :
+ sym-hash[s] = 0
+ defn to-port (p:Port) -> False : add-name(name(p))
+ defn to-stmt (s:Stmt) -> Stmt :
+ match(s) :
+ (s:DefWire) : add-name(name(s))
+ (s:DefRegister) : add-name(name(s))
+ (s:DefInstance) : add-name(name(s))
+ (s:DefMemory) : add-name(name(s))
+ (s:DefNode) : add-name(name(s))
+ (s:DefAccessor) : add-name(name(s))
+ (s) : false
+ map(to-stmt,s)
+
+ to-stmt(body(m))
+ map(to-port,ports(m))
+ sym-hash
;============== Exceptions =====================
@@ -127,7 +154,8 @@ defmethod print (o:OutputStream, c:Stmt) :
(c:DefRegister) :
print-all(o,["reg " name(c) " : " type(c)])
(c:DefMemory) :
- print-all(o,["mem " name(c) " : " type(c)])
+ if seq?(c) : print-all(o,["smem " name(c) " : " type(c)])
+ else : print-all(o,["cmem " name(c) " : " type(c)])
(c:DefInstance) :
print-all(o,["inst " name(c) " of " module(c)])
(c:DefNode) :
@@ -147,6 +175,8 @@ defmethod print (o:OutputStream, c:Stmt) :
do(print{o,_}, join(body(c), "\n"))
(c:Connect) :
print-all(o, [loc(c) " := " exp(c)])
+ (c:BulkConnect) :
+ print-all(o, [loc(c) " <> " exp(c)])
(c:OnReset) :
print-all(o, ["on-reset " loc(c) " := " exp(c)])
(c:EmptyStmt) :
@@ -181,7 +211,7 @@ defmethod print (o:OutputStream, p:Port) :
print-all(o, [direction(p) " " name(p) " : " type(p)])
print-debug(o,p)
-defmethod print (o:OutputStream, m:Module) :
+defmethod print (o:OutputStream, m:InModule) :
print-all(o, ["module " name(m) " :"])
print-debug(o,m)
print(o,"\n")
@@ -190,6 +220,14 @@ defmethod print (o:OutputStream, m:Module) :
println(io,p)
print(io,body(m))
+defmethod print (o:OutputStream, m:ExModule) :
+ print-all(o, ["exmodule " name(m) " :"])
+ print-debug(o,m)
+ print(o,"\n")
+ val io = IndentedStream(o, 3)
+ for p in ports(m) do :
+ println(io,p)
+
defmethod print (o:OutputStream, c:Circuit) :
print-all(o, ["circuit " main(c) " :"])
print-debug(o,c)
@@ -231,6 +269,7 @@ defmethod map (f: Expression -> Expression, c:Stmt) -> Stmt :
(c:DefInstance) : DefInstance(info(c),name(c), f(module(c)))
(c:Conditionally) : Conditionally(info(c),f(pred(c)), conseq(c), alt(c))
(c:Connect) : Connect(info(c),f(loc(c)), f(exp(c)))
+ (c:BulkConnect) : BulkConnect(info(c),f(loc(c)), f(exp(c)))
(c:OnReset) : OnReset(info(c),f(loc(c)),f(exp(c)))
(c) : c
@@ -272,7 +311,7 @@ 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)
+ (c:DefMemory) : DefMemory(info(c),name(c),f(type(c)) as VectorType,seq?(c))
(c) : c
public defmulti mapr<?T> (f: Width -> Width, t:?T&Type) -> T
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza
index b6926a7b..80035325 100644
--- a/src/main/stanza/passes.stanza
+++ b/src/main/stanza/passes.stanza
@@ -9,7 +9,7 @@ defpackage firrtl/passes :
;============== Pass List ================
public val standard-passes = to-list $ [
- CheckHighForm()
+ CheckHighForm(expand-delin)
TempElimination()
ToWorkingIR()
MakeExplicitReset()
@@ -85,6 +85,11 @@ defstruct ConnectFromIndexed <: Stmt :
;================ WORKING IR UTILS =========================
+;defmethod equal? (f1:Flip, f2:Flip) -> True|False :
+; switch fn ([x,y]) : f1 == x and f2 == y :
+; [DEFAULT,DEFAULT] : true
+; [REVERSE,REVERSE] : true
+; else : false
defn plus (g1:Gender,g2:Gender) -> Gender :
switch fn ([x,y]) : g1 == x and g2 == y :
@@ -304,7 +309,9 @@ defn temp-elimination (c:Circuit) :
Circuit(info(c),modules*, main(c)) where :
val modules* =
for m in modules(c) map :
- Module(info(m),name(m), ports(m), temp-elim-s(body(m)))
+ match(m) :
+ (m:InModule) : InModule(info(m),name(m), ports(m), temp-elim-s(body(m)))
+ (m:ExModule) : m
;================= Bring to Working IR ========================
; Returns a new Circuit with Refs, Subfields, Indexes and DefAccessors
@@ -330,7 +337,9 @@ defn to-working-ir (c:Circuit) :
Circuit(info(c),modules*, main(c)) where :
val modules* =
for m in modules(c) map :
- Module(info(m),name(m), ports(m), to-stmt(body(m)))
+ match(m) :
+ (m:InModule) : InModule(info(m),name(m), ports(m), to-stmt(body(m)))
+ (m:ExModule) : m
;=============== MAKE EXPLICIT RESET =======================
; All modules have an implicit reset signal - however, the
@@ -367,8 +376,11 @@ defn make-explicit-reset (c:Circuit) :
var ports! = ports(m)
if not contains?(explicit-reset,name(m)) :
ports! = append(ports(m),list(Port(FileInfo(),`reset,INPUT,UIntType(IntWidth(1)))))
- val body! = route-reset(body(m))
- Module(info(m),name(m),ports!,body!)
+ 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)
@@ -417,15 +429,20 @@ defn resolve-kinds (c:Circuit) :
kinds[name(m)] = ModuleKind()
for p in ports(m) do :
kinds[name(p)] = PortKind()
- find-stmt(body(m))
+ match(m) :
+ (m:InModule) : find-stmt(body(m))
+ (m:ExModule) : false
defn resolve-kinds (m:Module, c:Circuit) -> Module :
val kinds = HashTable<Symbol,Kind>(symbol-hash)
for m in modules(c) do :
kinds[name(m)] = ModuleKind()
find(m,kinds)
- val body! = resolve(body(m),kinds)
- Module(info(m),name(m),ports(m),body!)
+ match(m) :
+ (m:InModule) :
+ val body! = resolve(body(m),kinds)
+ InModule(info(m),name(m),ports(m),body!)
+ (m:ExModule) : ExModule(info(m),name(m),ports(m))
Circuit(info(c),modules*, main(c)) where :
val modules* =
@@ -504,15 +521,18 @@ defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt List<KeyValue<
val [s*,l*] = infer-types(conseq(s),l)
val [s**,l**] = infer-types(alt(s),l)
[Conditionally(info(s),pred(s),s*,s**),l]
- (s:Connect|OnReset|EmptyStmt) : [s,l]
+ (s:Connect|BulkConnect|OnReset|EmptyStmt) : [s,l]
defn infer-types (m:Module, l:List<KeyValue<Symbol,Type>>) -> Module :
val ptypes =
for p in ports(m) map :
name(p) => type(p)
println-all-debug(append(ptypes,l))
- val [s,l*] = infer-types(body(m),append(ptypes, l))
- Module(info(m),name(m),ports(m),s)
+ match(m) :
+ (m:InModule) :
+ val [s,l*] = infer-types(body(m),append(ptypes, l))
+ InModule(info(m),name(m),ports(m),s)
+ (m:ExModule) : m
defn infer-types (c:Circuit) -> Circuit :
val l =
@@ -565,8 +585,11 @@ defn resolve-genders (c:Circuit) :
var done? = true
defn resolve-iter (m:Module) -> Module :
- val body* = resolve-stmt(body(m))
- Module(info(m),name(m),ports(m),body*)
+ match(m) :
+ (m:InModule) :
+ val body* = resolve-stmt(body(m))
+ InModule(info(m),name(m),ports(m),body*)
+ (m:ExModule) : m
defn get-gender (n:Symbol,g:Gender) -> Gender :
defn force-gender (n:Symbol,g:Gender) -> Gender :
@@ -607,6 +630,8 @@ defn resolve-genders (c:Circuit) :
WDefAccessor(info(s),name(s),source*,index*,gender*)
(s:Connect) :
Connect(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE))
+ (s:BulkConnect) :
+ BulkConnect(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE))
(s:OnReset) :
OnReset(info(s),resolve-expr(loc(s),FEMALE),resolve-expr(exp(s),MALE))
(s:Conditionally) :
@@ -696,7 +721,9 @@ defn expand-accessors (c:Circuit) :
Circuit(info(c),modules*, main(c)) where :
val modules* =
for m in modules(c) map :
- Module(info(m),name(m),ports(m),expand-stmt(body(m)))
+ match(m) :
+ (m:InModule) : InModule(info(m),name(m),ports(m),expand-stmt(body(m)))
+ (m:ExModule) : m
;;=============== LOWERING TO GROUND TYPES =============================
; All non-ground (elevated) types (Vectors, Bundles) are expanded out to
@@ -742,9 +769,8 @@ defn index-of-elem (t:BundleType, s:Symbol) -> Int :
else : sum = sum + num-elems(type(f))
error("Shouldn't be here")
-
defn generate-entry (n:Symbol,t:Type) -> List<NTF> :
- defn uniquify (n*:Symbol) -> Symbol : symbol-join([n "_" n*])
+ defn uniquify (n*:Symbol) -> Symbol : symbol-join([n expand-delin n*])
match(t) :
(t:BundleType) :
for f in fields(t) map-append :
@@ -840,7 +866,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)))
+ DefMemory(info(s),name(x),VectorType(type(x),size(s)), seq?(s))
(s:WDefAccessor) :
val ls = generate-entry(name(s),type(s))
val rs = generate-entry(name(source(s) as WRef),type(s))
@@ -863,6 +889,28 @@ defn lower (body:Stmt) -> Stmt :
[MALE,FEMALE] :
if s typeof Connect : Connect(info(s),r*,l*)
else : OnReset(info(s),r*,l*)
+ (s:BulkConnect) :
+ val ls-fake = generate-entry(`null,type(loc(s)))
+ val rs-fake = generate-entry(`null,type(exp(s)))
+ val ls = expand-expr(loc(s))
+ val rs = expand-expr(exp(s))
+ val ls* = Vector<EF>()
+ val rs* = Vector<EF>()
+ for (l-fake in ls-fake,l in ls) do :
+ for (r-fake in rs-fake, r in rs) do :
+ if name(l-fake) == name(r-fake) and flip(l-fake) == flip(r-fake) and type(l-fake) == type(r-fake) :
+ add(ls*,l)
+ add(rs*,r)
+ Begin $ for (l in to-list(ls*), r in to-list(rs*)) map :
+ val lgender = FEMALE * flip(l)
+ val rgender = MALE * flip(r)
+ val l* = set-gender(exp(l),lgender,flip(l))
+ val r* = set-gender(exp(r),rgender,flip(r))
+ println-all-debug(["Left: " l " with Gender: " lgender])
+ println-all-debug(["Right: " r " with Gender: " rgender])
+ switch fn ([x,y]) : lgender == x and rgender == y :
+ [FEMALE,MALE] : Connect(info(s),l*,r*)
+ [MALE,FEMALE] : Connect(info(s),r*,l*)
(s:ConnectFromIndexed) : Begin(ls) where :
val ctable = HashTable<Symbol,Vector<EF>>(symbol-hash)
for e in exps(s) do :
@@ -908,9 +956,13 @@ defn lower (body:Stmt) -> Stmt :
lower-stmt(body)
defn lower-module (c:Circuit,m:Module) -> Module :
- Module(info(m),name(m),ports*,body*) where :
- val body* = lower(body(m))
- val ports* = lower-ports(ports(m))
+ val ports* = lower-ports(ports(m))
+ match(m) :
+ (m:InModule) :
+ val body* = lower(body(m))
+ InModule(info(m),name(m),ports*,body*)
+ (m:ExModule) :
+ ExModule(info(m),name(m),ports*)
defn lower-to-ground (c:Circuit) -> Circuit :
Circuit(info(c),modules*, main(c)) where :
@@ -928,20 +980,20 @@ public defmethod pass (b:ExpandIndexedConnects) -> (Circuit -> Circuit) : expand
public defmethod name (b:ExpandIndexedConnects) -> String : "Expand Indexed Connects"
public defmethod short-name (b:ExpandIndexedConnects) -> String : "expand-indexed-connects"
-defn expand-connect-indexed-stmt (s: Stmt) -> Stmt :
+defn expand-connect-indexed-stmt (s: Stmt,sh:HashTable<Symbol,Int>) -> Stmt :
defn equality (e1:Expression,e2:Expression) -> Expression :
DoPrim(EQUAL-OP,list(e1,e2),List(),UIntType(UnknownWidth()))
defn get-name (e:Expression) -> Symbol :
match(e) :
- (e:WRef) : symbol-join([name(e) `__])
- (e:WSubfield) : symbol-join([get-name(exp(e)) `. name(e) `__])
- (e:WIndex) : symbol-join([get-name(exp(e)) `. to-symbol(value(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) : `T
match(s) :
(s:ConnectToIndexed) : Begin $
if length(locs(s)) == 0 : list(EmptyStmt())
else :
- val ref = WRef(firrtl-gensym(get-name(exp(s))),type(index(s)),NodeKind(),UNKNOWN-GENDER)
+ val ref = WRef(firrtl-gensym(get-name(index(s)),sh),type(index(s)),NodeKind(),UNKNOWN-GENDER)
append(
list(DefNode(info(s),name(ref),index(s)))
to-list $
@@ -955,7 +1007,7 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt :
(s:ConnectFromIndexed) : Begin $
if length(exps(s)) == 0 : list(EmptyStmt())
else :
- val ref = WRef(firrtl-gensym(get-name(loc(s))),type(index(s)),NodeKind(),UNKNOWN-GENDER)
+ val ref = WRef(firrtl-gensym(get-name(index(s)),sh),type(index(s)),NodeKind(),UNKNOWN-GENDER)
append(
list(Connect(info(s),loc(s),head(exps(s))),DefNode(info(s),name(ref),index(s)))
to-list $
@@ -966,10 +1018,14 @@ defn expand-connect-indexed-stmt (s: Stmt) -> Stmt :
EmptyStmt()
)
)
- (s) : map(expand-connect-indexed-stmt,s)
+ (s) : map(expand-connect-indexed-stmt{_,sh},s)
defn expand-connect-indexed (m: Module) -> Module :
- Module(info(m),name(m),ports(m),expand-connect-indexed-stmt(body(m)))
+ match(m) :
+ (m:InModule) :
+ val sh = get-sym-hash(m)
+ InModule(info(m),name(m),ports(m),expand-connect-indexed-stmt(body(m),sh))
+ (m:ExModule) : m
defn expand-connect-indexed (c: Circuit) -> Circuit :
Circuit(info(c),modules*, main(c)) where :
@@ -1173,63 +1229,49 @@ defn expand-whens (ports:List<Port>, table:HashTable<Symbol,SymbolicValue>,cons:
for p in ports do :
if direction(p) == OUTPUT :
val ref = WRef(name(p),type(p),PortKind(),FEMALE)
- add{cons,_} $
- if has-nul?(table[name(p)]) :
- println("Uninitialized: ~" % [to-string(name(p))]);TODO actually collect error
- EmptyStmt()
- else : Connect(FileInfo(),ref,to-exp(table[name(p)]) as Expression)
+ if has-nul?(table[name(p)]) :
+ println("Uninitialized: ~" % [to-string(name(p))]);TODO actually collect error
+ else : add{cons,_} $ Connect(FileInfo(),ref,to-exp(table[name(p)]) as Expression)
defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stmt>,cons:Vector<Stmt>) -> Stmt :
match(map(expand-whens{_,table,decs,cons},s)) :
(s:DefNode|DefMemory) : add(decs,s)
(s:DefWire) :
add(decs,s)
- add{cons,_} $ {
- 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
- EmptyStmt()
- else : Connect(info(s),ref,to-exp(table[name(s)]) as Expression)
- }()
+ 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) :
- ;add(decs,DefWire(info(s),name(s),type(s)))
- ;add{cons,_} $ {
- ; val ref = WRef(name(s),type(s),RegKind(),FEMALE)
- ; val e = to-exp(table[name(s)])
- ; match(e) :
- ; (e:False) : EmptyStmt()
- ; (e:Expression) : Connect(info(s),ref,Register(type(s),e, to-exp(optimize $ get-write-enable(table[name(s)])) as Expression))
- ;}()
val e = to-exp(table[name(s)])
- add{cons,_} $ {
- match(e) :
- (e:False) : EmptyStmt()
- (e:Expression) : DefNode(info(s),name(s),Register(type(s),e,to-exp(optimize $ get-write-enable(table[name(s)])) as Expression))
- }()
+ 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)
- add{cons,_} $ {
switch {_ == gender(s)} :
MALE :
- Begin $ list $ DefNode(info(s),n,ReadPort(source(s),index(s),t,get-read-enable(n,table)))
+ 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(),FEMALE)
+ 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])
- val s* = match(e) :
+ add{cons,_} $ Connect(info(s),wp,ref)
+ match(e) :
(e:False) :
println("Uninitialized: ~" % [to-string(n)]) ;TODO actually collect error
- EmptyStmt()
(e:Expression) :
- Connect(info(s),ref,e)
- val enable = (to-exp $ optimize $ get-write-enable(table[n])) as Expression
- val wp = WritePort(source(s),index(s),t,enable as Expression)
- Begin $ list(Connect(info(s),wp,ref),s*)
- }()
+ add{cons,_} $ Connect(info(s),ref,e)
(s:DefInstance) :
add(decs,s)
- add{cons,_} $ Begin $
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
@@ -1239,9 +1281,7 @@ defn expand-whens (s:Stmt, table:HashTable<Symbol,SymbolicValue>,decs:Vector<Stm
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
- EmptyStmt()
- else : Connect(info(s),sref,to-exp(table[n]) as Expression)
- else : EmptyStmt()
+ else : add{cons,_} $ Connect(info(s),sref,to-exp(table[n]) as Expression)
(s:Connect|Conditionally|OnReset|Begin|EmptyStmt) : false
s
@@ -1347,34 +1387,37 @@ defn build-tables (s:Stmt,
(s:DefMemory|DefNode|EmptyStmt) : false
defn expand-whens (m:Module) -> Module :
- val assign = HashTable<Symbol,SymbolicValue>(symbol-hash)
- val resets = HashTable<Symbol,SymbolicValue>(symbol-hash)
- val flattn = HashTable<Symbol,True|False>(symbol-hash)
-
- for p in ports(m) do :
- if direction(p) == OUTPUT :
- assign[name(p)] = SVNul()
- flattn[name(p)] = false
-
- build-tables(body(m),assign,resets,flattn)
- for x in assign do : assign[key(x)] = optimize(value(x))
- for x in resets do : resets[key(x)] = optimize(value(x))
- ;val enables = get-enables(assign,kinds)
- ;for x in enables do : enables[key(x)] = optimize(value(x))
-
- println-debug("====== Assigns ======")
- for x in assign do : println-debug(x)
- println-debug("====== Resets ======")
- for x in resets do : println-debug(x)
-
- val table = merge-resets(assign,resets)
- println-debug("====== Table ======")
- for x in table do : println-debug(x)
- val decs = Vector<Stmt>()
- val cons = Vector<Stmt>()
- expand-whens(ports(m),table,cons)
- expand-whens(body(m),table,decs,cons)
- Module(info(m),name(m),ports(m),Begin(append(to-list(decs),to-list(cons))))
+ match(m) :
+ (m:ExModule) : m
+ (m:InModule) :
+ val assign = HashTable<Symbol,SymbolicValue>(symbol-hash)
+ val resets = HashTable<Symbol,SymbolicValue>(symbol-hash)
+ val flattn = HashTable<Symbol,True|False>(symbol-hash)
+
+ for p in ports(m) do :
+ if direction(p) == OUTPUT :
+ assign[name(p)] = SVNul()
+ flattn[name(p)] = false
+
+ build-tables(body(m),assign,resets,flattn)
+ for x in assign do : assign[key(x)] = optimize(value(x))
+ for x in resets do : resets[key(x)] = optimize(value(x))
+ ;val enables = get-enables(assign,kinds)
+ ;for x in enables do : enables[key(x)] = optimize(value(x))
+
+ println-debug("====== Assigns ======")
+ for x in assign do : println-debug(x)
+ println-debug("====== Resets ======")
+ for x in resets do : println-debug(x)
+
+ val table = merge-resets(assign,resets)
+ println-debug("====== Table ======")
+ for x in table do : println-debug(x)
+ val decs = Vector<Stmt>()
+ val cons = Vector<Stmt>()
+ expand-whens(ports(m),table,cons)
+ expand-whens(body(m),table,decs,cons)
+ InModule(info(m),name(m),ports(m),Begin(append(to-list(decs),to-list(cons))))
defn expand-whens (c:Circuit) -> Circuit :
Circuit(info(c),modules*, main(c)) where :
@@ -1409,6 +1452,8 @@ public defstruct MaxWidth <: Width :
public defstruct ExpWidth <: Width :
arg1 : Width
+val width-name-hash = HashTable<Symbol,Int>(symbol-hash)
+
public defmulti map<?T> (f: Width -> Width, w:?T&Width) -> T
defmethod map (f: Width -> Width, w:Width) -> Width :
match(w) :
@@ -1600,7 +1645,7 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod
match(map(gen-constraints-s,s)) :
(s:DefWire) : DefWire(info(s),name(s),h[name(s)])
(s:DefInstance) : DefInstance(info(s),name(s),gen-constraints(module(s)))
- (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)] as VectorType)
+ (s:DefMemory) : DefMemory(info(s),name(s),h[name(s)] as VectorType,seq?(s))
(s:DefNode) :
val l = h[name(s)]
val r = gen-constraints(value(s))
@@ -1636,14 +1681,14 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod
(e:UIntValue) :
match(width(e)) :
(w:UnknownWidth) :
- val w* = VarWidth(firrtl-gensym(`w))
+ val w* = VarWidth(firrtl-gensym(`w,width-name-hash))
add(v,WGeq(w*,IntWidth(ceil-log2(value(e)))))
UIntValue(value(e),w*)
(w) : e
(e:SIntValue) :
match(width(e)) :
(w:UnknownWidth) :
- val w* = VarWidth(firrtl-gensym(`w))
+ val w* = VarWidth(firrtl-gensym(`w,width-name-hash))
add(v,WGeq(w*,IntWidth(1 + ceil-log2(abs(value(e))))))
SIntValue(value(e),w*)
(w) : e
@@ -1652,7 +1697,9 @@ defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Mod
val ports* =
for p in ports(m) map : Port(info(p),name(p),direction(p),h[name(p)])
- Module(info(m),name(m),ports*,gen-constraints-s(body(m)))
+ match(m) :
+ (m:ExModule) : ExModule(info(m),name(m),ports*)
+ (m:InModule) : InModule(info(m),name(m),ports*,gen-constraints-s(body(m)))
defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTable<Symbol,Type> :
defn build-environment (s:Stmt) -> False :
@@ -1665,7 +1712,10 @@ defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTabl
do(build-environment,s)
for p in ports(m) do :
h[name(p)] = bundle-field-type(h[name(m)],name(p))
- build-environment(body(m))
+
+ match(m) :
+ (m:ExModule) : false
+ (m:InModule) : build-environment(body(m))
h
defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit :
@@ -1706,15 +1756,18 @@ defn reduce-var-widths (c:Circuit,h:HashTable<Symbol,Width>) -> Circuit :
w*
val modules* = for m in modules(c) map :
- Module{info(m),name(m),_,mapr(reduce-var-widths-w,body(m))} $
- for p in ports(m) map :
- Port(info(p),name(p),direction(p),mapr(reduce-var-widths-w,type(p)))
+ val ports* = for p in ports(m) map :
+ Port(info(p),name(p),direction(p),mapr(reduce-var-widths-w,type(p)))
+
+ match(m) :
+ (m:ExModule) : ExModule(info(m),name(m),ports*)
+ (m:InModule) : InModule(info(m),name(m),ports*,mapr(reduce-var-widths-w,body(m)))
Circuit(info(c),modules*,main(c))
defn remove-unknowns-w (w:Width) -> Width :
match(w) :
- (w:UnknownWidth) : VarWidth(firrtl-gensym(`w))
+ (w:UnknownWidth) : VarWidth(firrtl-gensym(`w,width-name-hash))
(w) : w
defn remove-unknowns (t:Type) -> Type : mapr(remove-unknowns-w,t)
@@ -1758,7 +1811,7 @@ public defmethod name (b:Inline) -> String : "Inline Instances"
public defmethod short-name (b:Inline) -> String : "inline-instances"
defn inline-instances (c:Circuit) :
- val h = HashTable<Symbol,Module>(symbol-hash)
+ val h = HashTable<Symbol,InModule>(symbol-hash)
val h-s = HashTable<Symbol,Stmt>(symbol-hash)
defn inline-inst (s:Stmt) -> Stmt :
match(map(inline-inst,s)) :
@@ -1781,30 +1834,32 @@ defn inline-instances (c:Circuit) :
(e:WSubfield) :
match(kind(exp(e) as WRef)) :
(k:InstanceKind) :
- WRef(symbol-join([name(exp(e) as WRef) "_" name(e)]),type(e),k,gender(e))
+ WRef(symbol-join([name(exp(e) as WRef) expand-delin name(e)]),type(e),k,gender(e))
(k:MemKind) : e
(e) : e
- defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n "_" ref])
+ defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n expand-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) "_" name(e)]),type(e),k,gender(e))
+ WRef(symbol-join([name(exp(e) as WRef) expand-delin name(e)]),type(e),k,gender(e))
(k:MemKind) : e
(e) : e
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:DefInstance) : error("Shouldn't be here")
- (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s))
+ (s:DefMemory) : DefMemory(info(s),rename(name(s),n),type(s),seq?(s))
(s:DefNode) : DefNode(info(s),rename(name(s),n),value(s))
(s) : s
for m in modules(c) do :
- h[name(m)] = m
- val top = (for m in modules(c) find : name(m) == main(c)) as Module
- Circuit(info(c),list(Module(info(top),name(top),ports(top),inline-inst(body(top)))),main(c))
+ match(m) :
+ (m:ExModule) : error("Cannot inline with external modules")
+ (m:InModule) : h[name(m)] = m
+ val top = (for m in modules(c) find : name(m) == main(c)) as InModule
+ Circuit(info(c),list(InModule(info(top),name(top),ports(top),inline-inst(body(top)))),main(c))
;================= Split Expressions ========================
@@ -1821,34 +1876,38 @@ defn full-name (e:Expression) -> Symbol :
(e) : error("Non-supported expression.")
defn split-exp (c:Circuit) :
- defn split-exp-s (s:Stmt,v:Vector<Stmt>) -> False :
+ defn split-exp-s (s:Stmt,v:Vector<Stmt>,sh:HashTable<Symbol,Int>) -> False :
+ 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)
+ (e) : e
match(s) :
(s:Begin) :
- defn f (s:Stmt) -> False: split-exp-s(s,v)
+ defn f (s:Stmt) -> False: split-exp-s(s,v,sh)
do(f,s)
(s:Conditionally) : error("Shouldn't be here")
(s:Connect) :
match(loc(s)) :
- (e:WritePort) : add(v,map(split-exp-e{_,v,full-name(exp(s)),info(s)},s))
- (e) : add(v,map(split-exp-e{_,v,full-name(loc(s)),info(s)},s))
- (s:DefNode) : add(v,map(split-exp-e{_,v,name(s),info(s)},s))
- (s) : add(v,map(split-exp-e{_,v,false,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))
false
- defn split-exp-e (e:Expression,v:Vector<Stmt>,n:Symbol|False,info:FileInfo) -> Expression :
- match(map(split-exp-e{_,v,n,info},e)):
- (e:DoPrim) :
- val n* =
- if n typeof False : firrtl-gensym(`T)
- else : firrtl-gensym(symbol-join([n as Symbol `__]))
- add(v,DefNode(info,n*,e))
- WRef(n*,type(e),NodeKind(),UNKNOWN-GENDER)
- (e) : e
Circuit{info(c),_,main(c)} $
for m in modules(c) map :
- val v = Vector<Stmt>()
- split-exp-s(body(m),v)
- Module(info(m),name(m),ports(m),Begin(to-list(v)))
+ match(m) :
+ (m:InModule) :
+ val v = Vector<Stmt>()
+ val sh = get-sym-hash(m)
+ split-exp-s(body(m),v,sh)
+ InModule(info(m),name(m),ports(m),Begin(to-list(v)))
+ (m:ExModule) : m
;================= Bring to Real IR ========================
; Returns a new Circuit with only real IR nodes.
@@ -1874,5 +1933,60 @@ defn to-real-ir (c:Circuit) :
Circuit(info(c),modules*, main(c)) where :
val modules* =
for m in modules(c) map :
- Module(info(m),name(m), ports(m), to-stmt(body(m)))
+ match(m) :
+ (m:InModule) : InModule(info(m),name(m), ports(m), to-stmt(body(m)))
+ (m:ExModule) : m
+
+;================= Special Rename ========================
+; Returns a new Circuit with only real IR nodes.
+public defstruct SpecialRename <: Pass :
+ original-sym : Symbol
+ new-sym : Symbol
+public defmethod pass (b:SpecialRename) -> (Circuit -> Circuit) : special-rename{original-sym(b),new-sym(b),_:Circuit}
+public defmethod name (b:SpecialRename) -> String : "Special Rename"
+public defmethod short-name (b:SpecialRename) -> String : "special-rename"
+
+public defn special-rename (original-sym:Symbol,new-sym:Symbol,c:Circuit) :
+ defn rename (s:Symbol) -> Symbol :
+ val y = Vector<String>()
+ val os = to-string $ original-sym
+ val ns = to-string $ new-sym
+ defn rename (st:String) -> False :
+ if st == os :
+ add(y,ns)
+ else if length(st) <= length(os) :
+ add(y,st)
+ else :
+ if substring(st,0,length(os)) == os :
+ add(y,ns)
+ rename(substring(st,length(os),length(st)))
+ else :
+ add(y,substring(st,0,1))
+ rename(substring(st,1,length(st)))
+ rename(to-string(s))
+ to-symbol $ string-join $ to-list(y)
+ defn to-exp (e:Expression) -> Expression :
+ match(map(to-exp,e)) :
+ (e:Ref) : Ref(rename(name(e)), type(e))
+ (e:Subfield) : Subfield(exp(e),rename(name(e)),type(e))
+ (e) : e
+ defn to-stmt (s:Stmt) -> Stmt :
+ 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: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) : map(to-stmt,s)
+
+ defn to-port (p:Port) -> Port : Port(info(p),rename(name(p)),direction(p),type(p))
+
+ Circuit(info(c),modules*, main(c)) where :
+ val modules* =
+ for m in modules(c) map :
+ match(m) :
+ (m:InModule) : InModule(info(m),name(m), map(to-port,ports(m)), to-stmt(body(m)))
+ (m:ExModule) : m
+
diff --git a/src/main/stanza/primop.stanza b/src/main/stanza/primop.stanza
index 34ede86c..0e343d74 100644
--- a/src/main/stanza/primop.stanza
+++ b/src/main/stanza/primop.stanza
@@ -5,6 +5,7 @@ defpackage firrtl/primops :
import firrtl/ir-utils
import firrtl/passes
+
public defn lower-and-type-primop (e:DoPrim) -> DoPrim :
defn u () : UIntType(UnknownWidth())
defn s () : SIntType(UnknownWidth())
diff --git a/src/main/stanza/verilog.stanza b/src/main/stanza/verilog.stanza
index 19472573..bee10177 100644
--- a/src/main/stanza/verilog.stanza
+++ b/src/main/stanza/verilog.stanza
@@ -38,6 +38,11 @@ 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 =============
@@ -109,7 +114,24 @@ defn emit (e:Expression) -> String :
v = concat(v, [" ^ " emit(x)])
v
-defn emit-module (m:Module) :
+defn emit-module (m:InModule) :
+ val h = HashTable<Symbol,VKind>(symbol-hash)
+ 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()
+ (s:Connect) :
+ match(exp(s)) :
+ (e:Register) : h[name(loc(s) as Ref)] = RegKind()
+ (e) : false
+ (s) : false
+ s
+ build-table(body(m))
+ build-table(m)
+
val wires = Vector<Streamable>()
val regs = Vector<Streamable>()
val inits = Vector<Streamable>()
@@ -117,39 +139,36 @@ defn emit-module (m:Module) :
val updates = Vector<Streamable>()
val insts = HashTable<Symbol,Symbol>(symbol-hash) ; inst -> module
val inst-ports = HashTable<Symbol,Vector<Streamable>>(symbol-hash)
+
+ val sh = get-sym-hash(m)
defn emit-s (s:Stmt) :
match(map(remove-subfield,s)) :
- (s:DefWire) : add(wires,["wire " get-width(type(s)) " " name(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:DefInstance) :
inst-ports[name(s)] = Vector<Streamable>()
insts[name(s)] = name(module(s) as Ref)
for f in fields(type(module(s)) as BundleType) do :
- ;val sf = value(s) as Subfield
- ;val e = exp(sf) as Ref
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
- val innerwidth =
- 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) " = {" width!(type(vtype)) "{$random}};"])
- (s:DefNode) :
- if value(s) typeof Register :
- val reg = value(s) as Register
- add(regs,["reg " get-width(type(reg)) " " name(s) ";"])
- add(inits,[name(s) " = {" width!(type(reg)) "{$random}};"])
- add(updates,["if(" emit(enable(reg)) ") begin"])
- add(updates,[" " name(s) " <= " emit(value(reg)) ";"])
- add(updates,["end"])
- else if value(s) typeof ReadPort :
- val rp = value(s) as ReadPort
- add(assigns,["assign " name(s) " = " emit(mem(rp)) "[" emit(index(rp)) "];"])
+ if seq?(s) :
+ 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) " = {" width!(type(vtype)) "{$random}};"])
else :
- add(wires,["wire " get-width(type(value(s))) " " name(s) ";"])
- add(assigns,["assign " name(s) " = " emit(value(s)) ";"])
+ 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) " = {" 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:Connect) :
if loc(s) typeof WritePort :
@@ -158,7 +177,29 @@ defn emit-module (m:Module) :
add(updates,[" " emit(mem(wp)) "[" emit(index(wp)) "] <= " emit(exp(s)) ";"])
add(updates,["end"])
else :
- add(assigns,["assign " emit(loc(s)) " = " emit(exp(s)) ";"])
+ 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) : s
emit-s(body(m))
@@ -219,5 +260,8 @@ defn emit-module (m:Module) :
public defn emit-verilog (file:String, c:Circuit) :
with-output-file{file, _} $ fn () :
for m in modules(c) do :
- emit-module(m)
+ match(m) :
+ (m:InModule) : emit-module(m)
+ (m:ExModule) : false
+
c