aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--TODO126
-rw-r--r--notes/chisel.04.13.15.txt29
-rw-r--r--notes/female-node.txt13
-rw-r--r--notes/flo.txt2
-rw-r--r--spec/spec.tex1
-rw-r--r--src/main/stanza/firrtl-ir.stanza4
-rw-r--r--src/main/stanza/ir-parser.stanza1
-rw-r--r--src/main/stanza/ir-utils.stanza65
-rw-r--r--src/main/stanza/passes.stanza1669
-rw-r--r--test/chisel3/BitsOps.fir17
-rw-r--r--test/chisel3/BundleWire.fir14
-rw-r--r--test/chisel3/ComplexAssign.fir15
-rw-r--r--test/chisel3/Counter.fir17
-rw-r--r--test/chisel3/DirChange.fir7
-rw-r--r--test/chisel3/EnableShiftRegister.fir24
-rw-r--r--test/chisel3/GCD.fir24
-rw-r--r--test/chisel3/LFSR16.fir20
-rw-r--r--test/chisel3/MemorySearch.fir43
-rw-r--r--test/chisel3/ModuleVec.fir25
-rw-r--r--test/chisel3/Mul.fir44
-rw-r--r--test/chisel3/Outer.fir17
-rw-r--r--test/chisel3/RegisterVecShift.fir34
-rw-r--r--test/chisel3/Risc.fir66
-rw-r--r--test/chisel3/Rom.fir24
-rw-r--r--test/chisel3/SIntOps.fir49
-rw-r--r--test/chisel3/Stack.fir41
-rw-r--r--test/chisel3/Tbl.fir16
-rw-r--r--test/chisel3/UIntOps.fir44
-rw-r--r--test/chisel3/VecApp.fir8
-rw-r--r--test/chisel3/VecShiftRegister.fir19
-rw-r--r--test/chisel3/VendingMachine.fir46
-rw-r--r--test/passes/infer-widths/simple.fir5
-rw-r--r--test/passes/inline/gcd.fir45
-rw-r--r--test/passes/split-exp/gcd.fir45
-rw-r--r--test/passes/to-flo/gcd.fir45
36 files changed, 1602 insertions, 1065 deletions
diff --git a/Makefile b/Makefile
index acdda20c..51d30ae1 100644
--- a/Makefile
+++ b/Makefile
@@ -23,6 +23,9 @@ build:
check:
cd $(test_dir)/passes && lit -v . --path=$(root_dir)/utils/bin/
+chisel3:
+ cd $(test_dir)/chisel3 && lit -v . --path=$(root_dir)/utils/bin/
+
clean:
rm -f $(test_dir)/*/*/*.out
rm -f $(test_dir)/*/*.out
diff --git a/TODO b/TODO
index 0d091776..7c243b8a 100644
--- a/TODO
+++ b/TODO
@@ -1,63 +1,79 @@
-Patrick Learned how to Fork.
-
-TODO
- Change parser to use <> syntax (and update all tests) (patrick)
- Think about on-reset, add it
- Think about expanding mems, more complicated than first glance!
- Think about max(op1,op2) for muxes.
- Make instances always male, flip the bundles on declaration
- Talk to palmer/patrick about how writing passes is going to be supported
- Add asserts, printf to spec
- Write lowering step for primops
- Figure out how widths propogate for all updated primops (Adam)
- Add bit-reduce-and etc to primops (Jonathan)
- //HANDLED IN FRONT END// Write pass to rename identifiers (alpha-transform) (Adam)
- Add partial bulk connect (Scott, Stephen)
- Add FIFOs to the IR (Palmer)
- Multi-streams for print statements/asserts (Jack)
- Consider def female node. (Patrick)
- Think about supporting generic primops on bundles and vecs (Adam) (wait until front-end more completed)
-
- Update spec
- add assertions
- cannot connect directly to a mem (loc can never contain a mem)
- Front-end needs to guarantee unique names per module.
- FIRRTL rule: No name can be a prefix of any other name.
- Future questions to address in spec:
- Introduction – motivation, and intended usage
- Philosophical justifications for all constructs
- More introduction for types, e.g. what is a ground type?
- What is a statement? What is an expression? What is a memory? Difference between vector type and memory? What are accessors for?
- Why would I ever write an empty statement? Mainly for use by compiler/passes
- What is a structural element? Duplication?
- Subtracting two unsigned numbers… Should talk to a math guy to figure it out
- What are shift left and shift right operations? HW doesn’t have these concepts. Need justification.
- What is lowered form? What is it for?
-
-
-Checks:
+================================================
+========== ADAM's BIG ASS TODO LIST ============
+================================================
+
+Important things:
+ Include new parser
+
+======== Update Core ==========
+Change all primops to be strict on data widths
+Merge pull request and update tests
+on-reset
+Write lowering step for primops
+Add bit-reduce-and etc to primops (Jonathan)
+Add source locaters
+Add Unit Tests for each pass
+
+======== Check Passes ==========
+Parser
+ Error if incorrectly assign stuff, like use = instead of :=
+Well-formed high firrtl
+ Unique names per module
+ No name can be a prefix of any other name.
+ No nested modules
+ Only modules in circuit (no statements or expressions)
+ Cannot connect directly to a mem ever
Subfields are only on bundles, before type inference
- After adding dynamic assertions, insert bounds check with accessor expansion
+ Can only connect to a Ref or Subfield or Index
+ UInt only has positive ints
+After adding dynamic assertions, insert bounds check with accessor expansion
+Well-formed low firrtl
All things only assigned to once
- Front-end needs to guarantee unique names per module.
- FIRRTL rule: No name can be a prefix of any other name.
-Tests:
- Error if declare anything other than module in circuit
- Error if incorrectly assign stuff, like use = instead of :=
- Error: Node not parsed for stmts
+======== Other Passes ========
+PrimOp lowering
-Male node:
-defnode n = e
-==>
-wire n
-n := e
+======== Think About ========
+annotation system
+zero-width wires
+on-reset
+expanding mems (consider changing defmem to be size, and element type)
+Make instances always male, flip the bundles on declaration
+Multi-streams for print statements/asserts (Jack)
+Consider def female node. (Patrick)
+Talk to palmer/patrick about how writing passes is going to be supported
+Figure out how widths propogate for all updated primops (Adam)
+Add partial bulk connect (Scott, Stephen)
+Add FIFOs to the IR (Palmer)
+Think about supporting generic primops on bundles and vecs (Adam) (wait until front-end more completed)
-Female node:
-defnode n = e
-==>
-wire n
-e := n
+======== Update Spec ========
+Add Not to spec
+add assertions and printfs
+cannot connect directly to a mem (loc can never contain a mem)
+Front-end needs to guarantee unique names per module.
+FIRRTL rule: No name can be a prefix of any other name.
+Future questions to address in spec:
+ Introduction – motivation, and intended usage
+ Philosophical justifications for all constructs
+ More introduction for types, e.g. what is a ground type?
+ What is a statement? What is an expression? What is a memory? Difference between vector type and memory? What are accessors for?
+ Why would I ever write an empty statement? Mainly for use by compiler/passes
+ What is a structural element? Duplication?
+ Subtracting two unsigned numbers… Should talk to a math guy to figure it out
+ What are shift left and shift right operations? HW doesn’t have these concepts. Need justification.
+ What is lowered form? What is it for?
+======== Pass Ideas ==========
+Bounds checks for accessors
+Overflow checks for add/add-wrap
+Check combinational
+Fast C++ where wires/register/instances are predicated
+======== Next layer components =======
+Accelerator with config registers
+Schedulable
+ Decouple
+ Nack
+Scheduler
diff --git a/notes/chisel.04.13.15.txt b/notes/chisel.04.13.15.txt
new file mode 100644
index 00000000..b9a1d099
--- /dev/null
+++ b/notes/chisel.04.13.15.txt
@@ -0,0 +1,29 @@
+Std Library Discussion
+
+FIRRTL Feedback:
+ Can we write an asynchronous FIFO using our implicit clock port semantics? (Patrick)
+ Unclear.
+
+ Can't mux between Bundle Types. (Stephen)
+ We think that is ok.
+
+ Bit-wise operation on SInts. Knocking down low bits. (Stephen)
+ Good point, we can define these.
+
+ UInt - UInt = SInt
+ ...
+
+ cmem vs reg of vec?
+ reg of vec has initialization, and can be accessed combinationally
+ maybe
+
+ subword updates?
+ modeled through the bundle types
+ not supported, but need to figure out how to support it
+
+ printfs and asserts
+
+ all primops require same widths. Need explicit incrementer node.
+
+ add padTo
+
diff --git a/notes/female-node.txt b/notes/female-node.txt
new file mode 100644
index 00000000..5125e8df
--- /dev/null
+++ b/notes/female-node.txt
@@ -0,0 +1,13 @@
+Male node:
+male defnode n = e
+==>
+wire n
+n := e
+
+Female node:
+female defnode n = e
+==>
+wire n
+e := n
+
+
diff --git a/notes/flo.txt b/notes/flo.txt
new file mode 100644
index 00000000..70fed3cf
--- /dev/null
+++ b/notes/flo.txt
@@ -0,0 +1,2 @@
+Questions:
+ WritePort(
diff --git a/spec/spec.tex b/spec/spec.tex
index a246b663..f7f1a2ee 100644
--- a/spec/spec.tex
+++ b/spec/spec.tex
@@ -100,6 +100,7 @@
\vert &\kws{shl} \vert \kws{shl-u} \vert \kws{shl-s} &\text{Unsigned/Signed Shift Left}\\
\vert &\kws{shr} \vert \kws{shr-u} \vert \kws{shr-s} &\text{Unsigned/Signed Shift Right}\\
\vert &\kws{convert} \vert \kws{convert-u} \vert \kws{convert-s} &\text{Unsigned to Signed Conversion}\\
+\vert &\kws{not} &\text{Unsigned Not}\\
\vert &\kws{and} &\text{Unsigned And}\\
\vert &\kws{or} &\text{Unsigned Or}\\
\vert &\kws{xor} &\text{Unsigned Xor}\\
diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza
index 402409c0..d9105430 100644
--- a/src/main/stanza/firrtl-ir.stanza
+++ b/src/main/stanza/firrtl-ir.stanza
@@ -81,6 +81,9 @@ public val GREATER-EQ-UU-OP = new PrimOp
public val GREATER-EQ-US-OP = new PrimOp
public val GREATER-EQ-SU-OP = new PrimOp
public val GREATER-EQ-SS-OP = new PrimOp
+public val NEQUAL-OP = new PrimOp
+public val NEQUAL-UU-OP = new PrimOp
+public val NEQUAL-SS-OP = new PrimOp
public val EQUAL-OP = new PrimOp
public val EQUAL-UU-OP = new PrimOp
public val EQUAL-SS-OP = new PrimOp
@@ -105,6 +108,7 @@ public val SHIFT-RIGHT-S-OP = new PrimOp
public val CONVERT-OP = new PrimOp
public val CONVERT-U-OP = new PrimOp
public val CONVERT-S-OP = new PrimOp
+public val BIT-NOT-OP = new PrimOp
public val BIT-AND-OP = new PrimOp
public val BIT-OR-OP = new PrimOp
public val BIT-XOR-OP = new PrimOp
diff --git a/src/main/stanza/ir-parser.stanza b/src/main/stanza/ir-parser.stanza
index 491fc22c..d6d33467 100644
--- a/src/main/stanza/ir-parser.stanza
+++ b/src/main/stanza/ir-parser.stanza
@@ -184,6 +184,7 @@ defsyntax firrtl :
operators[`convert] = CONVERT-OP
operators[`convert-u] = CONVERT-U-OP
operators[`convert-s] = CONVERT-S-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
diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza
index 80cd39a7..ae8fdbe9 100644
--- a/src/main/stanza/ir-utils.stanza
+++ b/src/main/stanza/ir-utils.stanza
@@ -289,31 +289,48 @@ defmethod map (f: Type -> Type, c:Stmt) -> Stmt :
(c:DefMemory) : DefRegister(name(c),f(type(c)))
(c) : c
+public defmulti mapr<?T> (f: Width -> Width, t:?T&Type) -> T
+defmethod mapr (f: Width -> Width, t:Type) -> Type :
+ defn apply-t (t:Type) -> Type :
+ map{f,_} $ map(apply-t,t)
+ apply-t(t)
+
+public defmulti mapr<?T> (f: Width -> Width, s:?T&Stmt) -> T
+defmethod mapr (f: Width -> Width, s:Stmt) -> Stmt :
+ defn apply-t (t:Type) -> Type : mapr(f,t)
+ defn apply-e (e:Expression) -> Expression :
+ map{f,_} $ map{apply-t,_} $ map(apply-e,e)
+ defn apply-s (s:Stmt) -> Stmt :
+ map{apply-t,_} $ map{apply-e,_} $ map(apply-s,s)
+ apply-s(s)
+
+
;================= HELPER FUNCTIONS USING MAP ===================
-; These don't work properly..
-;public defmulti do (f:Expression -> ?, e:Expression) -> False
-;defmethod do (f:Expression -> ?, e:Expression) -> False :
-; for x in e map :
-; f(x)
-; x
-; false
-;
-;public defmulti do (f:Expression -> ?, s:Stmt) -> False
-;defmethod do (f:Expression -> ?, s:Stmt) -> False :
-; defn f* (x:Expression) :
-; f(x)
-; x
-; map(f*,s)
-; false
-;
-;public defmulti do (f:Stmt -> ?, s:Stmt) -> False
-;defmethod do (f:Stmt -> ?, s:Stmt) -> False :
-; defn f* (x:Stmt) :
-; f(x)
-; x
-; map(f*,s)
-; false
-;
+public defmulti do (f:Expression -> ?, e:Expression) -> False
+defmethod do (f:Expression -> ?, e:Expression) -> False :
+ defn f* (x:Expression) :
+ f(x)
+ x
+ map(f*,e)
+ false
+
+public defmulti do (f:Expression -> ?, s:Stmt) -> False
+defmethod do (f:Expression -> ?, s:Stmt) -> False :
+ defn f* (x:Expression) :
+ f(x)
+ x
+ map(f*,s)
+ false
+
+public defmulti do (f:Stmt -> ?, s:Stmt) -> False
+defmethod do (f:Stmt -> ?, s:Stmt) -> False :
+ defn f* (x:Stmt) :
+ f(x)
+ x
+ map(f*,s)
+ false
+
+; Not well defined - usually use dor on fields of a recursive type
;public defmulti dor (f:Expression -> ?, e:Expression) -> False
;defmethod dor (f:Expression -> ?, e:Expression) -> False :
; f(e)
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza
index f5bd655a..aa940ceb 100644
--- a/src/main/stanza/passes.stanza
+++ b/src/main/stanza/passes.stanza
@@ -189,7 +189,6 @@ defn any-debug? (e:Expression|Stmt|Type|Port|Field) :
(hasGender(e) and PRINT-GENDERS) or
(hasType(e) and PRINT-TYPES) or
(hasWidth(e) and PRINT-WIDTHS) or
- (hasType(e) and PRINT-WIDTHS) or
(hasKind(e) and PRINT-KINDS)
defmethod print-debug (o:OutputStream, e:Expression|Stmt|Type|Port|Field) :
@@ -492,6 +491,7 @@ defn get-primop-rettype (e:DoPrim) -> Type :
CONVERT-OP : s()
CONVERT-U-OP : s()
CONVERT-S-OP : s()
+ BIT-NOT-OP : u()
BIT-AND-OP : u()
BIT-OR-OP : u()
BIT-XOR-OP : u()
@@ -985,7 +985,7 @@ defn expand-connect-indexed (c: Circuit) -> Circuit :
; times.
defn initialize-registers (c:Circuit) :
- defn to-wire-name (y:Symbol) : to-symbol("~$init" % [y])
+ defn to-wire-name (y:Symbol) : symbol-join([ y "$init"])
defn add-when (s:Stmt,h:HashTable<Symbol,Type>) -> Stmt :
var inits = List<Stmt>()
for kv in h do :
@@ -1266,11 +1266,12 @@ defn expand-whens (assign:HashTable<Symbol,SymbolicValue>,
add(decs,Connect(ref,reg))
(k:InstanceKind) :
val s = stmts[n] as DefInstance
- val x = split(to-string(n),'.')
+ val x = to-symbol(split(to-string(n),'.')[0])
val f = to-symbol(split(to-string(n),'.')[1])
- val ref = WSubfield(module(s),f,bundle-field-type(type(module(s)),f),FEMALE)
+ val ref = WRef(x,type(module(s)),k,FEMALE)
+ val sref = WSubfield(ref,f,bundle-field-type(type(module(s)),f),FEMALE)
if has-nul?(assign[n]) : println("Uninitialized: ~" % [to-string(n)]);TODO actually collect error
- else : add(decs,Connect(ref,to-exp(assign[n])))
+ else : add(decs,Connect(sref,to-exp(assign[n])))
(k) :
val s = stmts[n] as DefWire
val ref = WRef(n,type(s),k,FEMALE)
@@ -1433,13 +1434,20 @@ defstruct MinusWidth <: Width :
arg1 : Width
arg2 : Width
defstruct MaxWidth <: Width :
- arg1 : Width
- arg2 : Width
+ args : List<Width>
+
+public defmulti map<?T> (f: Width -> Width, w:?T&Width) -> T
+defmethod map (f: Width -> Width, w:Width) -> Width :
+ match(w) :
+ (w:MaxWidth) : MaxWidth(map(f,args(w)))
+ (w:PlusWidth) : PlusWidth(f(arg1(w)),f(arg2(w)))
+ (w:MinusWidth) : MinusWidth(f(arg1(w)),f(arg2(w)))
+ (w) : w
defmethod print (o:OutputStream, w:VarWidth) :
print(o,name(w))
defmethod print (o:OutputStream, w:MaxWidth) :
- print-all(o,["max(" arg1(w) "," arg2(w) ")"])
+ print-all(o,["max" args(w)])
defmethod print (o:OutputStream, w:PlusWidth) :
print-all(o,[ arg1(w) " + " arg2(w)])
defmethod print (o:OutputStream, w:MinusWidth) :
@@ -1449,1007 +1457,701 @@ definterface Constraint
defstruct WGeq <: Constraint :
loc : Width
exp : Width
-defstruct WEq <: Constraint :
- loc : Width
- exp : Width
defmethod print (o:OutputStream, c:WGeq) :
print-all(o,[ loc(c) " >= " exp(c)])
-defmethod print (o:OutputStream, c:WEq) :
- print-all(o,[ loc(c) " = " exp(c)])
+defmethod equal? (w1:Width,w2:Width) -> True|False :
+ match(w1,w2) :
+ (w1:VarWidth,w2:VarWidth) : name(w1) == name(w2)
+ (w1:MaxWidth,w2:MaxWidth) :
+ label<True|False> ret :
+ if not length(args(w1)) == length(args(w2)) : ret(false)
+ else :
+ for w in args(w1) do :
+ if not contains?(args(w2),w) : ret(false)
+ ret(true)
+ (w1:IntWidth,w2:IntWidth) : width(w1) == width(w2)
+ (w1,w2) : false
+defn apply (a:Int|False,b:Int|False, f: (Int,Int) -> Int) -> Int|False :
+ if a typeof Int and b typeof Int : f(a as Int, b as Int)
+ else : false
+
+; TODO: I should make MaxWidth take a variable list of arguments, which would make it easier to write the simplify function. It looks like there isn't a bug in the algorithm, but simplification reallllly speeds it up.
-;defn remove-var-widths (c:Circuit) -> Circuit :
-
-;defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Int> :
+defn solve-constraints (l:List<WGeq>) -> HashTable<Symbol,Int> :
+ defn contains? (n:Symbol,h:HashTable<Symbol,?>) -> True|False : key?(h,n)
+ defn make-unique (ls:List<WGeq>) -> HashTable<Symbol,Width> :
+ val h = HashTable<Symbol,Width>(symbol-hash)
+ for g in ls do :
+ match(loc(g)) :
+ (w:VarWidth) :
+ val n = name(w)
+ if contains?(n,h) : h[n] = MaxWidth(list(exp(g),h[n]))
+ else : h[n] = exp(g)
+ (w) : w
+ h
+ defn simplify (w:Width) -> Width :
+ match(map(simplify,w)) :
+ (w:MaxWidth) :
+ val v = Vector<Width>()
+ for w* in args(w) do :
+ match(w*) :
+ (w:MaxWidth) :
+ for x in args(w) do : add(v,x)
+ (w) : add(v,w)
+ MaxWidth(unique(v))
+ (w) : w
+ defn substitute (w:Width,h:HashTable<Symbol,Width>) -> Width :
+ ;println-all(["Substituting for [" w "]"])
+ val w* = simplify(w)
+ ;println-all(["After Simplify: [" w "]"])
+ match(map(substitute{_,h},simplify(w))) :
+ (w:VarWidth) :
+ ;println("matched varwidth!")
+ if contains?(name(w),h) :
+ ;println("Contained!")
+ ;println-all(["Width: " w])
+ ;println-all(["Accessed: " h[name(w)]])
+ val t = simplify(substitute(h[name(w)],h))
+ ;val t = h[name(w)]
+ ;println-all(["Width after sub: " t])
+ h[name(w)] = t
+ t
+ else : w
+ (w):
+ ;println-all(["not varwidth!" w])
+ w
+ defn b-sub (w:Width,h:HashTable<Symbol,Width>) -> Width:
+ match(map(b-sub{_,h},w)) :
+ (w:VarWidth) :
+ if key?(h,name(w)) : h[name(w)]
+ else : w
+ (w) : w
+ defn remove-cycle (n:Symbol,w:Width) -> Width :
+ ;println-all(["Removing cycle for " n " inside " w])
+ val w* = match(map(remove-cycle{n,_},w)) :
+ (w:MaxWidth) : MaxWidth(to-list(filter({_ != VarWidth(n)},args(w))))
+ (w) : w
+ ;println-all(["After removing cycle for " n ", returning " w*])
+ w*
+ defn self-rec? (n:Symbol,w:Width) -> True|False :
+ var has? = false
+ defn look (w:Width) -> Width :
+ match(map(look,w)) :
+ (w:VarWidth) : if name(w) == n : has? = true
+ (w) : w
+ w
+ look(w)
+ has?
+ defn evaluate (h:HashTable<Symbol,Width>) -> HashTable<Symbol,Int> :
+ defn apply (a:Int|False,b:Int|False, f: (Int,Int) -> Int) -> Int|False :
+ if a typeof Int and b typeof Int : f(a as Int, b as Int)
+ else : false
+ defn apply-l (l:List<Int|False>,f:(Int,Int) -> Int) -> Int|False :
+ if length(l) == 0 : 0
+ else : apply(head(l),apply-l(tail(l),f),f)
+ defn max (a:Int,b:Int) -> Int :
+ if a > b : a
+ else : b
+ defn solve (w:Width) -> Int|False :
+ match(w) :
+ (w:VarWidth) : false
+ (w:MaxWidth) : apply-l(map(solve,args(w)),max)
+ (w:PlusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ + _})
+ (w:MinusWidth) : apply(solve(arg1(w)),solve(arg2(w)),{_ - _})
+ (w:IntWidth) : width(w)
+ (w) : error("Shouldn't be here")
+
+ val i = HashTable<Symbol,Int>(symbol-hash)
+ for x in h do :
+ val s = solve(value(x))
+ if s typeof Int : i[key(x)] = s as Int
+ i
+
+ ; Forward solve
+ ; Returns a solved list where each constraint undergoes:
+ ; 1) Continuous Solving (using triangular solving)
+ ; 2) Remove Cycles
+ ; 3) Move to solved if not self-recursive
+ val u = make-unique(l)
+ println("======== UNIQUE CONSTRAINTS ========")
+ for x in u do : println(x)
+ println("====================================")
+
+ val f = HashTable<Symbol,Width>(symbol-hash)
+ val o = Vector<Symbol>()
+ for x in u do :
+ ;println("==== SOLUTIONS TABLE ====")
+ ;for x in f do : println(x)
+ ;println("=========================")
+
+ val [n e] = [key(x) value(x)]
+
+ val e-sub = substitute(e,f)
+ ;println(["Solving " n " => " e])
+ ;println(["After Substitute: " n " => " e-sub])
+ ;println("==== SOLUTIONS TABLE (Post Substitute) ====")
+ ;for x in f do : println(x)
+ ;println("=========================")
+ val e* = remove-cycle{n,_} $ e-sub
+ ;println(["After Remove Cycle: " n " => " e*])
+ if not self-rec?(n,e*) :
+ ;println-all(["Not rec!: " n " => " e*])
+ ;println-all(["Adding [" n "=>" e* "] to Solutions Table"])
+ add(o,n)
+ f[n] = e*
+
+ ;println("Forward Solved Constraints")
+ ;for x in f do : println(x)
+
+ ; Backwards Solve
+ val b = HashTable<Symbol,Width>(symbol-hash)
+ for i in (length(o) - 1) through 0 by -1 do :
+ val n = o[i]
+ ;println-all(["SOLVE BACK: [" n " => " f[n] "]"])
+ ;println("==== SOLUTIONS TABLE ====")
+ ;for x in b do : println(x)
+ ;println("=========================")
+ val e* = simplify(b-sub(f[n],b))
+ ;println-all(["BACK RETURN: [" n " => " e* "]"])
+ b[n] = e*
+ ;println("==== SOLUTIONS TABLE (Post backsolve) ====")
+ ;for x in b do : println(x)
+ ;println("=========================")
+
+ ; Evaluate
+ val e = evaluate(b)
+ ;println("Evaluated Constraints")
+ ;for x in e do : println(x)
+ e
defn width! (t:Type) -> Width :
match(t) :
(t:UIntType) : width(t)
(t:SIntType) : width(t)
(t) : error("No width!")
-defn prim-width (e:DoPrim,v:Vector<WGeq>) -> Width :
- defn e-width (e:Expression) -> Width : width!(type(e))
- defn wpc (l:List<Expression>,c:List<Int>) : PlusWidth(e-width(l[0]),IntWidth(c[0]))
- defn wmc (l:List<Expression>,c:List<Int>) : MinusWidth(e-width(l[0]),IntWidth(c[0]))
- defn maxw (l:List<Expression>) : MaxWidth(e-width(l[0]),e-width(l[1]))
- defn mp1 (l:List<Expression>) : PlusWidth(MaxWidth(e-width(l[0]),e-width(l[1])),IntWidth(1))
- defn sum (l:List<Expression>) : PlusWidth(e-width(l[0]),e-width(l[1]))
- switch {op(e) == _} :
- ADD-UU-OP : mp1(args(e))
- ADD-US-OP : mp1(args(e))
- ADD-SU-OP : mp1(args(e))
- ADD-SS-OP : mp1(args(e))
- SUB-UU-OP : mp1(args(e))
- SUB-US-OP : mp1(args(e))
- SUB-SU-OP : mp1(args(e))
- SUB-SS-OP : mp1(args(e))
- MUL-UU-OP : sum(args(e))
- MUL-US-OP : sum(args(e))
- MUL-SU-OP : sum(args(e))
- MUL-SS-OP : sum(args(e))
- ;(p:DIV-UU-OP) :
- ;(p:DIV-US-OP) :
- ;(p:DIV-SU-OP) :
- ;(p:DIV-SS-OP) :
- ;(p:MOD-UU-OP) :
- ;(p:MOD-US-OP) :
- ;(p:MOD-SU-OP) :
- ;(p:MOD-SS-OP) :
- ;(p:QUO-UU-OP) :
- ;(p:QUO-US-OP) :
- ;(p:QUO-SU-OP) :
- ;(p:QUO-SS-OP) :
- ;(p:REM-UU-OP) :
- ;(p:REM-US-OP) :
- ;(p:REM-SU-OP) :
- ;(p:REM-SS-OP) :
- ADD-WRAP-UU-OP : maxw(args(e))
- ADD-WRAP-US-OP : maxw(args(e))
- ADD-WRAP-SU-OP : maxw(args(e))
- ADD-WRAP-SS-OP : maxw(args(e))
- SUB-WRAP-UU-OP : maxw(args(e))
- SUB-WRAP-US-OP : maxw(args(e))
- SUB-WRAP-SU-OP : maxw(args(e))
- SUB-WRAP-SS-OP : maxw(args(e))
- LESS-UU-OP : IntWidth(1)
- LESS-US-OP : IntWidth(1)
- LESS-SU-OP : IntWidth(1)
- LESS-SS-OP : IntWidth(1)
- LESS-EQ-UU-OP : IntWidth(1)
- LESS-EQ-US-OP : IntWidth(1)
- LESS-EQ-SU-OP : IntWidth(1)
- LESS-EQ-SS-OP : IntWidth(1)
- GREATER-UU-OP : IntWidth(1)
- GREATER-US-OP : IntWidth(1)
- GREATER-SU-OP : IntWidth(1)
- GREATER-SS-OP : IntWidth(1)
- GREATER-EQ-UU-OP : IntWidth(1)
- GREATER-EQ-US-OP : IntWidth(1)
- GREATER-EQ-SU-OP : IntWidth(1)
- GREATER-EQ-SS-OP : IntWidth(1)
- EQUAL-UU-OP : IntWidth(1)
- EQUAL-SS-OP : IntWidth(1)
- MUX-UU-OP : maxw(args(e))
- MUX-SS-OP : maxw(args(e))
- PAD-U-OP : IntWidth(consts(e)[0])
- PAD-S-OP : IntWidth(consts(e)[0])
- AS-UINT-U-OP : e-width(args(e)[0])
- AS-UINT-S-OP : e-width(args(e)[0])
- AS-SINT-U-OP : e-width(args(e)[0])
- AS-SINT-S-OP : e-width(args(e)[0])
- SHIFT-LEFT-U-OP : wpc(args(e),consts(e))
- SHIFT-LEFT-S-OP : wpc(args(e),consts(e))
- SHIFT-RIGHT-U-OP : wmc(args(e),consts(e))
- SHIFT-RIGHT-S-OP : wmc(args(e),consts(e))
- CONVERT-U-OP : PlusWidth(e-width(args(e)[0]),IntWidth(1))
- CONVERT-S-OP : e-width(args(e)[0])
- BIT-AND-OP : maxw(args(e))
- BIT-OR-OP : maxw(args(e))
- BIT-XOR-OP : maxw(args(e))
- CONCAT-OP : sum(args(e))
- BIT-SELECT-OP : IntWidth(1)
- BITS-SELECT-OP : IntWidth(consts(e)[0] - consts(e)[1])
-
-defn gen-constraints (c:Circuit, m:Module) -> List<WGeq> :
- val v = Vector<WGeq>()
- val h = HashTable<Symbol,Type>(symbol-hash)
-
- defn get-width (e:Expression) -> Width :
- match(e) :
- (e:WRef) :
- val [wdec wref] = match(kind(e)) :
- (k:InstanceKind) : error("Shouldn't be here")
- (k:MemKind) :
- [width! $ type $ (h[name(e)] as VectorType),
- width! $ type $ (type(e) as VectorType)]
- (k) :
- [width! $ h[name(e)],
- width! $ type(e)]
- add(v,WGeq(wdec,wref))
- add(v,WGeq(wref,wdec))
- wdec
- (e:WSubfield) : ;assumes only subfields are instances
- val wdec = width! $ bundle-field-type(h[name(exp(e) as WRef)],name(e))
- val wref = width! $ bundle-field-type(type(exp(e)),name(e))
- add(v,WGeq(wdec,wref))
- add(v,WGeq(wref,wdec))
- wdec
- (e:WIndex) : error("Shouldn't be here")
- (e:UIntValue) : width(e)
- (e:SIntValue) : width(e)
- (e:DoPrim) : prim-width(e,v)
- (e:ReadPort|WritePort) :
- add(v,WGeq(get-width(enable(e)),IntWidth(1)))
- add(v,WGeq(IntWidth(1),get-width(enable(e))))
- get-width(mem(e))
- (e:Register) :
- add(v,WGeq(get-width(enable(e)),IntWidth(1)))
- add(v,WGeq(IntWidth(1),get-width(enable(e))))
- val w = width!(type(e))
- add(v,WGeq(get-width(value(e)),w))
- add(v,WGeq(w,get-width(value(e))))
- w
- defn gen-constraints (s:Stmt) -> Stmt :
- match(map(gen-constraints,s)) :
- (s:DefWire) : h[name(s)] = type(s)
- (s:DefInstance) : h[name(s)] = h[name(module(s) as WRef)]
- (s:DefMemory) : h[name(s)] = type(s)
- (s:DefNode) : h[name(s)] = type(value(s))
+defn width! (e:Expression) -> Width : width!(type(e))
+
+defn gen-constraints (m:Module, h:HashTable<Symbol,Type>, v:Vector<WGeq>) -> Module:
+ defn prim-type (e:DoPrim,v:Vector<WGeq>) -> Type :
+ defn add-c (w:Width) -> Type:
+ val w* = VarWidth(gensym(`w))
+ add(v,WGeq(w*,w))
+ add(v,WGeq(w,w*))
+ match(type(e)) :
+ (t:UIntType) : UIntType(w*)
+ (t:SIntType) : SIntType(w*)
+ (t) : error("Shouldn't be here")
+ defn wpc (l:List<Expression>,c:List<Int>) :
+ add-c(PlusWidth(width!(l[0]),IntWidth(c[0])))
+ defn wmc (l:List<Expression>,c:List<Int>) :
+ add-c(MinusWidth(width!(l[0]),IntWidth(c[0])))
+ defn maxw (l:List<Expression>) :
+ add-c(MaxWidth(list(width!(l[0]),width!(l[1]))))
+ defn cons (ls:List<Expression>) :
+ val l = width!(ls[0])
+ val r = width!(ls[1])
+ add(v,WGeq(l,r))
+ add(v,WGeq(r,l))
+ add-c(l)
+ add-c(r)
+ defn mp1 (l:List<Expression>) :
+ add-c(PlusWidth(MaxWidth(list(width!(l[0]),width!(l[1]))),IntWidth(1)))
+ defn sum (l:List<Expression>) :
+ add-c(PlusWidth(width!(l[0]),width!(l[1])))
+
+ println-all(["Looking at " op(e) " with inputs " args(e)])
+ switch {op(e) == _} :
+ ADD-UU-OP : mp1(args(e))
+ ADD-US-OP : mp1(args(e))
+ ADD-SU-OP : mp1(args(e))
+ ADD-SS-OP : mp1(args(e))
+ SUB-UU-OP : mp1(args(e))
+ SUB-US-OP : mp1(args(e))
+ SUB-SU-OP : mp1(args(e))
+ SUB-SS-OP : mp1(args(e))
+ MUL-UU-OP : sum(args(e))
+ MUL-US-OP : sum(args(e))
+ MUL-SU-OP : sum(args(e))
+ MUL-SS-OP : sum(args(e))
+ ;(p:DIV-UU-OP) :
+ ;(p:DIV-US-OP) :
+ ;(p:DIV-SU-OP) :
+ ;(p:DIV-SS-OP) :
+ ;(p:MOD-UU-OP) :
+ ;(p:MOD-US-OP) :
+ ;(p:MOD-SU-OP) :
+ ;(p:MOD-SS-OP) :
+ ;(p:QUO-UU-OP) :
+ ;(p:QUO-US-OP) :
+ ;(p:QUO-SU-OP) :
+ ;(p:QUO-SS-OP) :
+ ;(p:REM-UU-OP) :
+ ;(p:REM-US-OP) :
+ ;(p:REM-SU-OP) :
+ ;(p:REM-SS-OP) :
+ ADD-WRAP-UU-OP : maxw(args(e))
+ ADD-WRAP-US-OP : maxw(args(e))
+ ADD-WRAP-SU-OP : maxw(args(e))
+ ADD-WRAP-SS-OP : maxw(args(e))
+ SUB-WRAP-UU-OP : maxw(args(e))
+ SUB-WRAP-US-OP : maxw(args(e))
+ SUB-WRAP-SU-OP : maxw(args(e))
+ SUB-WRAP-SS-OP : maxw(args(e))
+ LESS-UU-OP : add-c(IntWidth(1))
+ LESS-US-OP : add-c(IntWidth(1))
+ LESS-SU-OP : add-c(IntWidth(1))
+ LESS-SS-OP : add-c(IntWidth(1))
+ LESS-EQ-UU-OP : add-c(IntWidth(1))
+ LESS-EQ-US-OP : add-c(IntWidth(1))
+ LESS-EQ-SU-OP : add-c(IntWidth(1))
+ LESS-EQ-SS-OP : add-c(IntWidth(1))
+ GREATER-UU-OP : add-c(IntWidth(1))
+ GREATER-US-OP : add-c(IntWidth(1))
+ GREATER-SU-OP : add-c(IntWidth(1))
+ GREATER-SS-OP : add-c(IntWidth(1))
+ GREATER-EQ-UU-OP : add-c(IntWidth(1))
+ GREATER-EQ-US-OP : add-c(IntWidth(1))
+ GREATER-EQ-SU-OP : add-c(IntWidth(1))
+ GREATER-EQ-SS-OP : add-c(IntWidth(1))
+ EQUAL-UU-OP : add-c(IntWidth(1))
+ EQUAL-SS-OP : add-c(IntWidth(1))
+ MUX-UU-OP : cons(args(e))
+ MUX-SS-OP : cons(args(e))
+ PAD-U-OP : add-c(IntWidth(consts(e)[0]))
+ PAD-S-OP : add-c(IntWidth(consts(e)[0]))
+ AS-UINT-U-OP : add-c(width!(args(e)[0]))
+ AS-UINT-S-OP : add-c(width!(args(e)[0]))
+ AS-SINT-U-OP : add-c(width!(args(e)[0]))
+ AS-SINT-S-OP : add-c(width!(args(e)[0]))
+ SHIFT-LEFT-U-OP : wpc(args(e),consts(e))
+ SHIFT-LEFT-S-OP : wpc(args(e),consts(e))
+ SHIFT-RIGHT-U-OP : wmc(args(e),consts(e))
+ SHIFT-RIGHT-S-OP : wmc(args(e),consts(e))
+ CONVERT-U-OP : add-c(PlusWidth(width!(args(e)[0]),IntWidth(1)))
+ CONVERT-S-OP : add-c(width!(args(e)[0]))
+ BIT-NOT-OP : maxw(args(e))
+ BIT-AND-OP : maxw(args(e))
+ BIT-OR-OP : maxw(args(e))
+ BIT-XOR-OP : maxw(args(e))
+ CONCAT-OP : sum(args(e))
+ BIT-SELECT-OP : add-c(IntWidth(1))
+ BITS-SELECT-OP : add-c(IntWidth(consts(e)[0] - consts(e)[1]))
+
+ defn gen-constraints-s (s:Stmt) -> Stmt :
+ match(map(gen-constraints-s,s)) :
+ (s:DefWire) : DefWire(name(s),h[name(s)])
+ (s:DefInstance) : DefInstance(name(s),gen-constraints(module(s)))
+ (s:DefMemory) : DefMemory(name(s),h[name(s)] as VectorType)
+ (s:DefNode) : DefNode(name(s),gen-constraints(value(s)))
(s:Connect) :
- add(v,WGeq(get-width(loc(s)),get-width(exp(s))))
- add(v,WGeq(get-width(exp(s)),get-width(loc(s))))
- (s) : ""
- s
+ val l = gen-constraints(loc(s))
+ val e = gen-constraints(exp(s))
+ add(v,WGeq(width!(type(l)),width!(type(e))))
+ add(v,WGeq(width!(type(e)),width!(type(l))))
+ Connect(l,e)
+ (s) : s
+
+ defn gen-constraints (e:Expression) -> Expression :
+ match(map(gen-constraints,e)) :
+ (e:WRef) : WRef(name(e),h[name(e)],kind(e),gender(e))
+ (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),prim-type(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) :
+ val w* = VarWidth(gensym(`w))
+ 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(gensym(`w))
+ add(v,WGeq(w*,IntWidth(1 + ceil-log2(abs(value(e))))))
+ SIntValue(value(e),w*)
+ (w) : e
+ (e) : e
- for m in modules(c) do :
- h[name(m)] = BundleType(map(to-field,ports(m)))
- for p in ports(m) do :
- h[name(p)] = type(p)
- gen-constraints(body(m))
- to-list(v)
+ val ports* =
+ for p in ports(m) map : Port(name(p),direction(p),h[name(p)])
+ Module(name(m),ports*,gen-constraints-s(body(m)))
-defn remove-unknown-widths (c:Circuit) -> Circuit :
- defn remove-unknown-widths-wid (w:Width) -> Width :
- match(w) :
- (w:UnknownWidth) : VarWidth(gensym(`w))
+defn build-environment (c:Circuit,m:Module,h:HashTable<Symbol,Type>) -> HashTable<Symbol,Type> :
+ defn build-environment (s:Stmt) -> False :
+ match(s) :
+ (s:DefWire) : 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:DefNode) : h[name(s)] = remove-unknowns(type(value(s)))
+ (s) : false
+ 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))
+ h
+
+defn replace-var-widths (c:Circuit,h:HashTable<Symbol,Int>) -> Circuit :
+ defn replace-var-widths-w (w:Width) -> Width :
+ println-all(["REPLACE: " w])
+ val w* = match(w) :
+ (w:VarWidth) :
+ if key?(h,name(w)) : IntWidth(h[name(w)])
+ else: w
(w) : w
- defn remove-unknown-widths-type (t:Type) -> Type :
- map{remove-unknown-widths-wid,_} $
- map(remove-unknown-widths-type,t)
- defn remove-unknown-widths-exp (e:Expression) -> Expression :
- map{remove-unknown-widths-wid,_} $
- map{remove-unknown-widths-type,_} $
- map(remove-unknown-widths-exp,e)
- defn remove-unknown-widths-stmt (s:Stmt) -> Stmt :
- map{remove-unknown-widths-type,_} $
- map{remove-unknown-widths-exp,_} $
- map(remove-unknown-widths-stmt,s)
+ println-all(["WITH: " w*])
+ w*
+
val modules* = for m in modules(c) map :
- Module{name(m),_,body(m)} $
+ Module{name(m),_,mapr(replace-var-widths-w,body(m))} $
for p in ports(m) map :
- Port(name(p),direction(p),remove-unknown-widths-type(type(p)))
-
- val modules** = for m in modules* map :
- Module(name(m),ports(m),remove-unknown-widths-stmt(body(m)))
- Circuit(modules**,main(c))
-
-defn infer-widths (c:Circuit) -> Circuit :
- val c* = remove-unknown-widths(c)
- for m in modules(c*) do :
- val l = gen-constraints(c*,m)
- for x in l do : println(x)
- c*
- ;val h = solve-constraints(l)
- ;replace-var-widths(c*,h)
-
-
-
-
-
-
-
-
-
+ Port(name(p),direction(p),mapr(replace-var-widths-w,type(p)))
+ Circuit(modules*,main(c))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-;;==================== WIDTH INFERENCE ======================
-;defstruct WidthVar <: Width :
-; name: Symbol
-;
-;defmethod print (o:OutputStream, w:WidthVar) :
-; print(o, name(w))
-;
-;defn width! (t:Type) :
-; match(t) :
-; (t:UIntType) : width(t)
-; (t:SIntType) : width(t)
-; (t) : error("No width field.")
-;
-;defn put-width (t:Type, w:Width) :
-; match(t) :
-; (t:UIntType) : UIntType(w)
-; (t:SIntType) : SIntType(w)
-; (t) : t
-;
-;defn put-width (e:Expression, w:Width) :
-; val type* = put-width(type(e), w)
-; put-type(e, type*)
-;
-;defn add-width-vars (t:Type) :
-; defn width? (w:Width) :
+;defn remove-unknown-widths (c:Circuit) -> Circuit :
+; defn remove-unknown-widths-w (w:Width) -> Width :
; match(w) :
-; (w:UnknownWidth) : WidthVar(gensym())
+; (w:UnknownWidth) : VarWidth(gensym(`w))
; (w) : w
-; match(t) :
-; (t:UIntType) : UIntType(width?(width(t)))
-; (t:SIntType) : SIntType(width?(width(t)))
-; (t) : map(add-width-vars, t)
-;
-;defn uint-width (i:Int) :
-; var v:Int = i
-; var n:Int = 0
-; while v != 0 :
-; v = v >> 1
-; n = n + 1
-; IntWidth(n)
-;
-;defn sint-width (i:Int) :
-; if i > 0 :
-; val w = uint-width(i)
-; IntWidth(width(w) + 1)
-; else :
-; val w = uint-width(neg(i) - 1)
-; IntWidth(width(w) + 1)
-;
-;defn to-exp (w:Width) :
-; match(w) :
-; (w:IntWidth) : ELit(width(w))
-; (w:WidthVar) : EVar(name(w))
-; (w) : error $ string-join $ [
-; "Cannot convert " w " to exp."]
-;
-;defn primop-width (op:PrimOp, ws:List<Width>, ints:List<Int>) -> Exp :
-; defn wmax (w1:Width, w2:Width) :
-; EMax(to-exp(w1), to-exp(w2))
-; defn wplus (w1:Width, w2:Width) :
-; EPlus(to-exp(w1), to-exp(w2))
-; defn wplus (w1:Width, w2:Int) :
-; EPlus(to-exp(w1), ELit(w2))
-; defn wminus (w1:Width, w2:Width) :
-; EMinus(to-exp(w1), to-exp(w2))
-; defn wminus (w1:Width, w2:Int) :
-; EMinus(to-exp(w1), ELit(w2))
-; defn wmax-inc (w1:Width, w2:Width) :
-; EPlus(wmax(w1, w2), ELit(1))
-;
-; switch {op == _} :
-; ADD-OP : wmax-inc(ws[0], ws[1])
-; ADD-WRAP-OP : wmax(ws[0], ws[1])
-; SUB-OP : wmax-inc(ws[0], ws[1])
-; SUB-WRAP-OP : wmax(ws[0], ws[1])
-; MUL-OP : wplus(ws[0], ws[1])
-; DIV-OP : wminus(ws[0], ws[1])
-; MOD-OP : to-exp(ws[1])
-; SHIFT-LEFT-OP : wplus(ws[0], ints[0])
-; SHIFT-RIGHT-OP : wminus(ws[0], ints[0])
-; PAD-OP : ELit(ints[0])
-; BIT-AND-OP : wmax(ws[0], ws[1])
-; BIT-OR-OP : wmax(ws[0], ws[1])
-; BIT-XOR-OP : wmax(ws[0], ws[1])
-; CONCAT-OP : wplus(ws[0], ints[0])
-; BIT-SELECT-OP : ELit(1)
-; BITS-SELECT-OP : ELit(ints[0])
-; MUX-OP : wmax(ws[1], ws[2])
-; LESS-OP : ELit(1)
-; LESS-EQ-OP : ELit(1)
-; GREATER-OP : ELit(1)
-; GREATER-EQ-OP : ELit(1)
-; EQUAL-OP : ELit(1)
-;
-;defn put-type (el:Element, t:Type) -> Element :
-; match(el) :
-; (el:Register) : Register(t, value(el), enable(el))
-; (el:Memory) : Memory(t, writers(el))
-; (el:Node) : Node(t, value(el))
-; (el:Instance) : Instance(t, module(el), ports(el))
-;
-;defn generate-constraints (c:Circuit) -> [Circuit, Vector<WConstraint>] :
-; ;Constraints
-; val cs = Vector<WConstraint>()
-; defn new-constraint (Constraint: (Symbol, Exp) -> WConstraint, wvar:Width, width:Width) :
-; match(wvar) :
-; (wvar:WidthVar) :
-; add(cs, Constraint(name(wvar), to-exp(width)))
-; (wvar) :
-; false
-;
-; defn to-width (e:Exp) :
-; match(e) :
-; (e:ELit) :
-; IntWidth(width(e))
-; (e:EVar) :
-; WidthVar(name(e))
-; (e) :
-; val x = gensym()
-; add(cs, WidthEqual(x, e))
-; WidthVar(x)
-;
-; ;Module types
-; val mod-types = HashTable<Symbol,Type>(symbol-hash)
-;
-; defn add-port-vars (m:Module) -> Module :
-; val ports* =
+; val modules* = for m in modules(c) map :
+; Module{name(m),_,body(m)} $
; for p in ports(m) map :
-; val type* = add-width-vars(type(p))
-; Port(name(p), gender(p), type*)
-; mod-types[name(m)] = BundleType(ports*)
-; Module(name(m), ports*, body(m))
-;
-; ;Add Width Variables
-; defn add-module-vars (m:Module) -> Module :
-; val types = HashTable<Symbol,Type>(symbol-hash)
-; for p in ports(m) do :
-; types[name(p)] = type(p)
-;
-; defn infer-exp-width (e:Expression) -> Expression :
-; match(map(infer-exp-width, e)) :
-; (e:WRef) :
-; match(kind(e)) :
-; (k:ModuleKind) : put-type(e, mod-types[name(e)])
-; (k) : put-type(e, types[name(e)])
-; (e:WSubfield) :
-; val t = bundle-field-type(type(exp(e)), name(e))
-; put-width(e, width!(t))
-; (e:UIntValue) :
-; match(width(e)) :
-; (w:UnknownWidth) : UIntValue(value(e), uint-width(value(e)))
-; (w) : e
-; (e:SIntValue) :
-; match(width(e)) :
-; (w:UnknownWidth) : SIntValue(value(e), sint-width(value(e)))
-; (w) : e
-; (e:DoPrim) :
-; val widths = map(width!{type(_)}, args(e))
-; val w = to-width(primop-width(op(e), widths, consts(e)))
-; put-width(e, w)
-; (e:ReadPort) :
-; val elem-type = type(type(mem(e)) as VectorType)
-; put-width(e, width!(elem-type))
-;
-; defn infer-comm-width (c:Stmt) :
-; match(c) :
-; (c:LetRec) :
-; ;Add width vars to elements
-; var entries*: List<KeyValue<Symbol,Element>> =
-; for entry in entries(c) map :
-; val el-name = key(entry)
-; key(entry) =>
-; match(value(entry)) :
-; (el:Register|Node) :
-; put-type(el, add-width-vars(type(el)))
-; (el:Memory) :
-; el
-; (el:Instance) :
-; val mod-type = type(infer-exp-width(module(el))) as BundleType
-; val type = BundleType $ to-list $
-; for p in ports(mod-type) filter :
-; gender(p) == OUTPUT
-; put-type(el, type)
-;
-; ;Add vars to environment
-; for entry in entries* do :
-; types[key(entry)] = type(value(entry))
-;
-; ;Infer types for elements
-; entries* =
-; for entry in entries* map :
-; key(entry) => map(infer-exp-width, value(entry))
-;
-; ;Generate constraints
-; for entry in entries* do :
-; val el-name = key(entry)
-; match(value(entry)) :
-; (el:Register) :
-; new-constraint(WidthEqual, reg-width, val-width) where :
-; val reg-width = width!(types[el-name])
-; val val-width = width!(type(value(el)))
-; (el:Node) :
-; new-constraint(WidthEqual, node-width, val-width) where :
-; val node-width = width!(types[el-name])
-; val val-width = width!(type(value(el)))
-; (el:Instance) :
-; val mod-type = type(module(el)) as BundleType
-; for entry in ports(el) do :
-; new-constraint(WidthGreater, port-width, val-width) where :
-; val port-name = key(entry)
-; val port-width = width!(bundle-field-type(mod-type, port-name))
-; val val-width = width!(type(value(entry)))
-; (el) : false
-;
-; ;Analyze body
-; LetRec(entries*, infer-comm-width(body(c)))
-;
-; (c:Connect) :
-; val loc* = infer-exp-width(loc(c))
-; val exp* = infer-exp-width(exp(c))
-; new-constraint(WidthGreater, loc-width, exp-width) where :
-; val loc-width = width!(type(loc*))
-; val exp-width = width!(type(exp*))
-; Connect(loc*, exp*)
-;
-; (c:Begin) :
-; map(infer-comm-width, c)
-;
-; Module(name(m), ports(m), body*) where :
-; val body* = infer-comm-width(body(m))
-;
-; val c* =
-; Circuit(modules*, main(c)) where :
-; val ms = map(add-port-vars, modules(c))
-; val modules* = map(add-module-vars, ms)
-; [c*, cs]
-;
+; Port(name(p),direction(p),mapr(remove-unknown-widths-w,type(p)))
;
-;;================== FILL WIDTHS ============================
-;defn fill-widths (c:Circuit, solved:Streamable<WidthEqual>) :
-; ;Populate table
-; val table = HashTable<Symbol, Width>(symbol-hash)
-; for eq in solved do :
-; table[name(eq)] = IntWidth(width(value(eq) as ELit))
-;
-; defn width? (w:Width) :
-; match(w) :
-; (w:WidthVar) : get?(table, name(w), UnknownWidth())
-; (w) : w
-;
-; defn fill-type (t:Type) :
-; match(t) :
-; (t:UIntType) : UIntType(width?(width(t)))
-; (t:SIntType) : SIntType(width?(width(t)))
-; (t) : map(fill-type, t)
-;
-; defn fill-exp (e:Expression) -> Expression :
-; val e* = map(fill-exp, e)
-; val type* = fill-type(type(e))
-; put-type(e*, type*)
-;
-; defn fill-element (e:Element) :
-; val e* = map(fill-exp, e)
-; val type* = fill-type(type(e))
-; put-type(e*, type*)
-;
-; defn fill-comm (c:Stmt) :
-; match(c) :
-; (c:LetRec) :
-; val entries* =
-; for e in entries(c) map :
-; key(e) => fill-element(value(e))
-; LetRec(entries*, fill-comm(body(c)))
-; (c) :
-; map{fill-comm, _} $
-; map(fill-exp, c)
-;
-; defn fill-port (p:Port) :
-; Port(name(p), gender(p), fill-type(type(p)))
-;
-; defn fill-mod (m:Module) :
-; Module(name(m), ports*, body*) where :
-; val ports* = map(fill-port, ports(m))
-; val body* = fill-comm(body(m))
-;
-; Circuit(modules*, main(c)) where :
-; val modules* = map(fill-mod, modules(c))
-;
-;
-;;=============== TYPE INFERENCE DRIVER =====================
-;defn infer-widths (c:Circuit) :
-; val [c*, cs] = generate-constraints(c)
-; val solved = solve-widths(cs)
-; fill-widths(c*, solved)
-;
-;
-;;================ PAD WIDTHS ===============================
-;defn pad-widths (c:Circuit) :
-; ;Pad an expression to the given width
-; defn pad-exp (e:Expression, w:Int) :
-; match(type(e)) :
-; (t:UIntType|SIntType) :
-; val prev-w = width!(t) as IntWidth
-; if width(prev-w) < w :
-; val type* = put-width(t, IntWidth(w))
-; DoPrim(PAD-OP, list(e), list(w), type*)
-; else :
-; e
-; (t) :
-; e
-;
-; defn pad-exp (e:Expression, w:Width) :
-; val w-value = width(w as IntWidth)
-; pad-exp(e, w-value)
-;
-; ;Convenience
-; defn max-width (es:Streamable<Expression>) :
-; defn int-width (e:Expression) :
-; width(width!(type(e)) as IntWidth)
-; maximum(stream(int-width, es))
-;
-; defn match-widths (es:List<Expression>) :
-; val w = max-width(es)
-; map(pad-exp{_, w}, es)
-;
-; ;Match widths for an expression
-; defn match-exp-width (e:Expression) :
-; match(map(match-exp-width, e)) :
-; (e:DoPrim) :
-; if contains?([BIT-AND-OP, BIT-OR-OP, BIT-XOR-OP, EQUAL-OP], op(e)) :
-; val args* = match-widths(args(e))
-; DoPrim(op(e), args*, consts(e), type(e))
-; else if op(e) == MUX-OP :
-; val args* = List(head(args(e)), match-widths(tail(args(e))))
-; DoPrim(op(e), args*, consts(e), type(e))
-; else :
-; e
-; (e) : e
-;
-; defn match-element-width (e:Element) :
-; match(map(match-exp-width, e)) :
-; (e:Register) :
-; val w = width!(type(e))
-; val value* = pad-exp(value(e), w)
-; Register(type(e), value*, enable(e))
-; (e:Memory) :
-; val width = width!(type(type(e) as VectorType))
-; val writers* =
-; for w in writers(e) map :
-; WritePort(index(w), pad-exp(value(w), width), enable(w))
-; Memory(type(e), writers*)
-; (e:Node) :
-; val w = width!(type(e))
-; val value* = pad-exp(value(e), w)
-; Node(type(e), value*)
-; (e:Instance) :
-; val mod-type = type(module(e)) as BundleType
-; val ports* =
-; for p in ports(e) map :
-; val port-type = bundle-field-type(mod-type, key(p))
-; val port-val = pad-exp(value(p), width!(port-type))
-; key(p) => port-val
-; Instance(type(e), module(e), ports*)
-;
-; ;Match widths for a command
-; defn match-comm-width (c:Stmt) :
-; match(map(match-exp-width, c)) :
-; (c:LetRec) :
-; val entries* =
-; for e in entries(c) map :
-; key(e) => match-element-width(value(e))
-; LetRec(entries*, match-comm-width(body(c)))
-; (c:Connect) :
-; val w = width!(type(loc(c)))
-; val exp* = pad-exp(exp(c), w)
-; Connect(loc(c), exp*)
-; (c) :
-; map(match-comm-width, c)
-;
-; defn match-mod-width (m:Module) :
-; Module(name(m), ports(m), body*) where :
-; val body* = match-comm-width(body(m))
-;
-; Circuit(modules*, main(c)) where :
-; val modules* = map(match-mod-width, modules(c))
-;
-;
-;;================== INLINING ===============================
-;defn inline-instances (c:Circuit) :
-; val module-table = HashTable<Symbol,Module>(symbol-hash)
-; val inlined? = HashTable<Symbol,True|False>(symbol-hash)
-; for m in modules(c) do :
-; module-table[name(m)] = m
-; inlined?[name(m)] = false
-;
-; ;Convert a module into a sequence of elements
-; defn to-elements (m:Module,
-; inst:Symbol,
-; port-exps:List<KeyValue<Symbol,Expression>>) ->
-; List<KeyValue<Symbol, Element>> :
-; defn rename-exp (e:Expression) :
-; match(e) :
-; (e:WRef) : WRef(prefix(inst, name(e)), type(e), kind(e), dir(e))
-; (e) : map(rename-exp, e)
-;
-; defn to-elements (c:Stmt) -> List<KeyValue<Symbol,Element>> :
-; match(c) :
-; (c:LetRec) :
-; val entries* =
-; for entry in entries(c) map :
-; val name* = prefix(inst, key(entry))
-; val element* = map(rename-exp, value(entry))
-; name* => element*
-; val body* = to-elements(body(c))
-; append(entries*, body*)
-; (c:Connect) :
-; val ref = loc(c) as WRef
-; val name* = prefix(inst, name(ref))
-; list(name* => Node(type(exp(c)), rename-exp(exp(c))))
-; (c:Begin) :
-; map-append(to-elements, body(c))
-;
-; val inputs =
-; for p in ports(m) map-append :
-; if gender(p) == INPUT :
-; val port-exp = lookup!(port-exps, name(p))
-; val name* = prefix(inst, name(p))
-; list(name* => Node(type(port-exp), port-exp))
-; else :
-; List()
-; append(inputs, to-elements(body(m)))
-;
-; ;Inline all instances in the module
-; defn inline-instances (m:Module) :
-; defn rename-exp (e:Expression) :
-; match(e) :
-; (e:WSubfield) :
-; val inst-exp = exp(e) as WRef
-; val name* = prefix(name(inst-exp), name(e))
-; WRef(name*, type(e), NodeKind(), dir(e))
-; (e) :
-; map(rename-exp, e)
-;
-; defn inline-elems (es:List<KeyValue<Symbol,Element>>) :
-; for entry in es map-append :
-; match(value(entry)) :
-; (el:Instance) :
-; val mod-name = name(module(el) as WRef)
-; val module = inlined-module(mod-name)
-; to-elements(module, key(entry), ports(el))
-; (el) :
-; list(entry)
-;
-; defn inline-comm (c:Stmt) :
-; match(map(rename-exp, c)) :
-; (c:LetRec) :
-; val entries* = inline-elems(entries(c))
-; LetRec(entries*, inline-comm(body(c)))
-; (c) :
-; map(inline-comm, c)
-;
-; Module(name(m), ports(m), inline-comm(body(m)))
-;
-; ;Retrieve the inlined instance of a module
-; defn inlined-module (name:Symbol) :
-; if inlined?[name] :
-; module-table[name]
-; else :
-; val module* = inline-instances(module-table[name])
-; module-table[name] = module*
-; inlined?[name] = true
-; module*
-;
-; ;Return the fully inlined circuit
-; val main-module = inlined-module(main(c))
-; Circuit(list(main-module), main(c))
-
-
-;;;================ UTILITIES ================================
-;
-;
-;
-;defn* root-ref (i:Immediate) :
-; match(i) :
-; (f:Subfield) : root-ref(imm(f))
-; (ind:Index) : root-ref(imm(ind))
-; (r) : r
-;
-;;defn lookup<?T> (e: Streamable<KeyValue<Immediate,?T>>, i:Immediate) :
-;; for entry in e search :
-;; if eqv?(key(entry), i) :
-;; value(entry)
-;;
-;;defn lookup!<?T> (e: Streamable<KeyValue<Immediate,?T>>, i:Immediate) :
-;; lookup(e, i) as T
-;;
-;;============ CHECK IF NAMES ARE UNIQUE ====================
-;defn check-duplicate-symbols (names: Streamable<Symbol>, msg: String) :
-; val dict = HashTable<Symbol, True>(symbol-hash)
-; for name in names do:
-; if key?(dict, name):
-; throw $ PassException $ string-join $
-; [msg ": " name]
-; else:
-; dict[name] = true
-;
-;defn check-duplicates (t: Type) :
-; match(t) :
-; (t:BundleType) :
-; val names = map(name, ports(t))
-; check-duplicate-symbols{names, string-join(_)} $
-; ["Duplicate port name in bundle "]
-; do(check-duplicates{type(_)}, ports(t))
-; (t:VectorType) :
-; check-duplicates(type(t))
-; (t) : false
-;
-;defn check-duplicates (c: Stmt) :
-; match(c) :
-; (c:DefWire) : check-duplicates(type(c))
-; (c:DefRegister) : check-duplicates(type(c))
-; (c:DefMemory) : check-duplicates(type(c))
-; (c) : do(check-duplicates, children(c))
-;
-;defn defined-names (c: Stmt) :
-; generate<Symbol> :
-; loop(c) where :
-; defn loop (c:Stmt) :
-; match(c) :
-; (c:Stmt&HasName) : yield(name(c))
-; (c) : do(loop, children(c))
-;
-;defn check-duplicates (m: Module):
-; ;Check all duplicate names in all types in all ports and body
-; do(check-duplicates{type(_)}, ports(m))
-; check-duplicates(body(m))
-;
-; ;Check all names defined in module
-; val names = concat(stream(name, ports(m)),
-; defined-names(body(m)))
-; check-duplicate-symbols{names, string-join(_)} $
-; ["Duplicate definition name in module " name(m)]
-;
-;defn check-duplicates (c: Circuit) :
-; ;Check all duplicate names in all modules
-; do(check-duplicates, modules(c))
-;
-; ;Check all defined modules
-; val names = stream(name, modules(c))
-; check-duplicate-symbols(names, "Duplicate module name")
-;
-;
-
-
-
-
-
+; val modules** = for m in modules* map :
+; Module(name(m),ports(m),mapr(remove-unknown-widths-w,body(m)))
+; Circuit(modules**,main(c))
+
+defn remove-unknowns-w (w:Width) -> Width :
+ match(w) :
+ (w:UnknownWidth) : VarWidth(gensym(`w))
+ (w) : w
+defn remove-unknowns (t:Type) -> Type : mapr(remove-unknowns-w,t)
+defn infer-widths (c:Circuit) -> Circuit :
+ defn deepcopy (t:HashTable<Symbol,Type>) -> HashTable<Symbol,Type> :
+ t0 where :
+ val t0 = HashTable<Symbol,Type>(symbol-hash)
+ for x in t do :
+ t0[key(x)] = value(x)
+
+ ;val c* = remove-unknown-widths(c)
+ ;println(c*)
+ val v = Vector<WGeq>()
+ val ports* = HashTable<Symbol,Type>(symbol-hash)
+ for m in modules(c) do :
+ ports*[name(m)] = remove-unknowns(BundleType(map(to-field,ports(m))))
+ val modules* = for m in modules(c) map :
+ println-all(["====== MODULE(" name(m) ") ENV ======"])
+ val h = build-environment(c,m,deepcopy(ports*))
+ for x in h do: println(x)
+ println-all(["====================================="])
+ val m* = gen-constraints(m,h,v)
+ println-all(["====== MODULE(" name(m) ") ======"])
+ println(m*)
+ println-all(["====================================="])
+ m*
+ println("======== ALL CONSTRAINTS ========")
+ for x in v do : println(x)
+ println("=================================")
+ val h = solve-constraints(to-list(v))
+ println("======== SOLVED CONSTRAINTS ========")
+ for x in h do : println(x)
+ println("====================================")
+ replace-var-widths(Circuit(modules*,main(c)),h)
+
+
+;================= Inline Instances ========================
+; Inlines instances. Assumes module with same name as the
+; Circuit is the top level module
+
+defn inline-instances (c:Circuit) :
+ val h = HashTable<Symbol,Module>(symbol-hash)
+ val h-s = HashTable<Symbol,Stmt>(symbol-hash)
+ defn inline-inst (s:Stmt) -> Stmt :
+ match(map(inline-inst,s)) :
+ (s:DefInstance) :
+ val n = name(module(s) as WRef)
+ val m = h[n]
+ val body* =
+ if key?(h-s,n) : h-s[n]
+ else :
+ val v = Vector<Stmt>()
+ for p in ports(m) do :
+ add(v,DefWire(name(p),type(p)))
+ add(v,inline-inst(body(m)))
+ Begin(to-list(v))
+ h-s[n] = body*
+ rename-s(body*,name(s))
+ (s) : map(inline-inst-e,s)
+ defn inline-inst-e (e:Expression) -> Expression :
+ match(map(inline-inst-e,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))
+ (k:MemKind) : e
+ (e) : e
+ defn rename (ref:Symbol,n:Symbol) -> Symbol : symbol-join([n "$" 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))
+ (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(rename(name(s),n),type(s))
+ (s:DefInstance) : error("Shouldn't be here")
+ (s:DefMemory) : DefMemory(rename(name(s),n),type(s))
+ (s:DefNode) : DefNode(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(list(Module(name(top),ports(top),inline-inst(body(top)))),main(c))
+
+
+;================= Split Expressions ========================
+; Intended to only work on low firrtl
+
+defn split-exp (c:Circuit) :
+ defn split-exp-s (s:Stmt,v:Vector<Stmt>) -> False :
+ match(s) :
+ (s:Begin) :
+ defn f (s:Stmt) -> False: split-exp-s(s,v)
+ do(f,s)
+ (s:Conditionally) : error("Shouldn't be here")
+ (s) : add(v,map(split-exp-e{_,v},s))
+ false
+ defn split-exp-e (e:Expression,v:Vector<Stmt>) -> Expression :
+ match(map(split-exp-e{_,v},e)):
+ (e:Subfield|DoPrim|ReadPort|Register|WritePort) :
+ val n = gensym(`T)
+ add(v,DefNode(n,e))
+ WRef(n,type(e),NodeKind(),UNKNOWN-GENDER)
+ (e) : e
-;;================ CLEANUP COMMANDS =========================
-;defn cleanup (c:Stmt) :
-; match(c) :
-; (c:Begin) :
-; to-command $ generate<Stmt> :
-; loop(c) where :
-; defn loop (c:Stmt) :
-; match(c) :
-; (c:Begin) : do(loop, body(c))
-; (c:EmptyStmt) : false
-; (c) : yield(cleanup(c))
-; (c) : map(cleanup{_ as Stmt}, c)
-;
-;defn cleanup (c:Circuit) :
-; val modules* =
-; for m in modules(c) map :
-; map(cleanup, m)
-; Circuit(modules*, main(c))
-;
+ Circuit{_,main(c)} $
+ for m in modules(c) map :
+ val v = Vector<Stmt>()
+ split-exp-s(body(m),v)
+ Module(name(m),ports(m),Begin(to-list(v)))
+;================= Bring to Real IR ========================
+; Returns a new Circuit with only real IR nodes.
+defn to-real-ir (c:Circuit) :
+ defn to-exp (e:Expression) :
+ match(map(to-exp,e)) :
+ (e:WRef) : Ref(name(e), type(e))
+ (e:WSubfield) : Subfield(exp(e),name(e),type(e))
+ (e:WRegInit) : error("Shouldn't be here")
+ (e:WIndex) : error("Shouldn't be here")
+ (e) : e
+ defn to-stmt (s:Stmt) :
+ match(map(to-exp,s)) :
+ (e:WDefAccessor) : error("Shouldn't be here")
+ (e:ConnectToIndexed) : error("Shouldn't be here")
+ (e:ConnectFromIndexed) : error("Shouldn't be here")
+ (e) : map(to-stmt,e)
-;;;============= SHIM ========================================
-;;defn shim (i:Immediate) -> Immediate :
-;; match(i) :
-;; (i:RegData) :
-;; Ref(name(i), gender(i), type(i))
-;; (i:InstPort) :
-;; val inst = Ref(name(i), UNKNOWN-GENDER, UnknownType())
-;; Subfield(inst, port(i), gender(i), type(i))
-;; (i:Subfield) :
-;; val imm* = shim(imm(i))
-;; put-imm(i, imm*)
-;; (i) : i
-;;
-;;defn shim (c:Stmt) -> Stmt :
-;; val c* = map(shim{_ as Immediate}, c)
-;; map(shim{_ as Stmt}, c*)
-;;
-;;defn shim (c:Circuit) -> Circuit :
-;; val modules* =
-;; for m in modules(c) map :
-;; Module(name(m), ports(m), shim(body(m)))
-;; Circuit(modules*, main(c))
-;;
-;;;================== INLINE MODULES =========================
-;;defn cat-name (p: String|Symbol, s: String|Symbol) -> Symbol :
-;; if p == "" or p == `this : ;; TODO: REMOVE THIS WHEN `THIS GETS REMOVED
-;; to-symbol(s)
-;; else if s == `this : ;; TODO: DITTO
-;; to-symbol(p)
-;; else :
-;; symbol-join([p, "/", s])
-;;
-;;defn inline-command (c: Stmt, mods: HashTable<Symbol, Module>, prefix: String, cmds: Vector<Stmt>) :
-;; defn rename (n: Symbol) -> Symbol :
-;; cat-name(prefix, n)
-;; defn inline-name (i:Immediate) -> Symbol :
-;; match(i) :
-;; (r:Ref) : rename(name(r))
-;; (f:Subfield) : cat-name(inline-name(imm(f)), name(f))
-;; (f:Index) : cat-name(inline-name(imm(f)), to-string(value(f)))
-;; defn inline-imm (i:Immediate) -> Ref :
-;; Ref(inline-name(i), gender(i), type(i))
-;; match(c) :
-;; (c:DefUInt) : add(cmds, DefUInt(rename(name(c)), value(c), width(c)))
-;; (c:DefSInt) : add(cmds, DefSInt(rename(name(c)), value(c), width(c)))
-;; (c:DefWire) : add(cmds, DefWire(rename(name(c)), type(c)))
-;; (c:DefRegister) : add(cmds, DefRegister(rename(name(c)), type(c)))
-;; (c:DefMemory) : add(cmds, DefMemory(rename(name(c)), type(c), size(c)))
-;; (c:DefInstance) : inline-module(mods, mods[name(module(c))], to-string(rename(name(c))), cmds)
-;; (c:DoPrim) : add(cmds, DoPrim(rename(name(c)), op(c), map(inline-imm, args(c)), consts(c)))
-;; (c:DefAccessor) : add(cmds, DefAccessor(rename(name(c)), inline-imm(source(c)), gender(c), inline-imm(index(c))))
-;; (c:Connect) : add(cmds, Connect(inline-imm(loc(c)), inline-imm(exp(c))))
-;; (c:Begin) : do(inline-command{_, mods, prefix, cmds}, body(c))
-;; (c:EmptyStmt) : c
-;; (c) : error("Unsupported command")
-;;
-;;defn inline-port (p: Port, prefix: String) -> Stmt :
-;; DefWire(cat-name(prefix, name(p)), type(p))
-;;
-;;defn inline-module (mods: HashTable<Symbol, Module>, mod: Module, prefix: String, cmds: Vector<Stmt>) :
-;; do(add{cmds, _}, map(inline-port{_, prefix}, ports(mod)))
-;; inline-command(body(mod), mods, prefix, cmds)
-;;
-;;defn inline-modules (c: Circuit) -> Circuit :
-;; val cmds = Vector<Stmt>()
-;; val mods = HashTable<Symbol, Module>(symbol-hash)
-;; for mod in modules(c) do :
-;; mods[name(mod)] = mod
-;; val top = mods[main(c)]
-;; inline-command(body(top), mods, "", cmds)
-;; val main* = Module(name(top), ports(top), Begin(to-list(cmds)))
-;; Circuit(list(main*), name(top))
-;;
-;;
-;;;============= FLO PRINTER ======================================
-;;;;; TODO:
-;;;;; not supported gt, lte
-;;
-;;defn flo-op-name (op:PrimOp) -> String :
-;; switch {op == _} :
-;; ADD-OP : "add"
-;; ADD-MOD-OP : "add"
-;; MINUS-OP : "sub"
-;; SUB-MOD-OP : "sub"
-;; MUL-OP : "mul" ;; todo: signed version
-;; DIV-OP : "div" ;; todo: signed version
-;; MOD-OP : "mod" ;; todo: signed version
-;; SHIFT-LEFT-OP : "lsh" ;; todo: signed version
-;; SHIFT-RIGHT-OP : "rsh"
-;; PAD-OP : "pad" ;; todo: signed version
-;; BIT-AND-OP : "and"
-;; BIT-OR-OP : "or"
-;; BIT-XOR-OP : "xor"
-;; CONCAT-OP : "cat"
-;; BIT-SELECT-OP : "rsh"
-;; BITS-SELECT-OP : "rsh"
-;; LESS-OP : "lt" ;; todo: signed version
-;; LESS-EQ-OP : "lte" ;; todo: swap args
-;; GREATER-OP : "gt" ;; todo: swap args
-;; GREATER-EQ-OP : "gte" ;; todo: signed version
-;; EQUAL-OP : "eq"
-;; MUX-OP : "mux"
-;; else : error $ string-join $
-;; ["Unable to print Primop: " op]
-;;
-;;defn emit (o:OutputStream, top:Symbol, ports:HashTable<Symbol, Port>, lits:HashTable<Symbol, DefUInt>, elt) :
-;; match(elt) :
-;; (e:String|Symbol|Int) :
-;; print(o, e)
-;; (e:Ref) :
-;; if key?(lits, name(e)) :
-;; val lit = lits[name(e)]
-;; print-all(o, [value(lit) "'" width(lit)])
-;; else :
-;; if key?(ports, name(e)) :
-;; print-all(o, [top "::"])
-;; print(o, name(e))
-;; (e:IntWidth) :
-;; print(o, value(e))
-;; (e:PrimOp) :
-;; print(o, flo-op-name(e))
-;; (e) :
-;; println-all(["EMIT " e])
-;; error("Unable to emit")
-;;
-;;defn emit-all (o:OutputStream, top:Symbol, ports:HashTable<Symbol, Port>, lits:HashTable<Symbol, DefUInt>, elts: Streamable) :
-;; for e in elts do : emit(o, top, ports, lits, e)
-;;
-;;defn prim-width (type:Type) -> Width :
-;; match(type) :
-;; (t:UIntType) : width(t)
-;; (t:SIntType) : width(t)
-;; (t) : error("Bad prim width type")
-;;
-;;defn emit-command (o:OutputStream, cmd:Stmt, top:Symbol, lits:HashTable<Symbol, DefUInt>, regs:HashTable<Symbol, DefRegister>, accs:HashTable<Symbol, DefAccessor>, ports:HashTable<Symbol, Port>, outs:HashTable<Symbol, Port>) :
-;; match(cmd) :
-;; (c:DefUInt) :
-;; lits[name(c)] = c
-;; (c:DefSInt) :
-;; emit-all(o, top, ports, lits, [name(c) " = " value(c) "'" width(c) "\n"])
-;; (c:DoPrim) : ;; NEED TO FIGURE OUT WHEN WIDTHS ARE NECESSARY AND EXTRACT
-;; emit-all(o, top, ports, lits, [name(c) " = " op(c)])
-;; for arg in args(c) do :
-;; print(o, " ")
-;; emit(o, top, ports, lits, arg)
-;; for const in consts(c) do :
-;; print(o, " ")
-;; emit(o, top, ports, lits, const)
-;; print("\n")
-;; (c:DefRegister) :
-;; regs[name(c)] = c
-;; (c:DefMemory) :
-;; emit-all(o, top, ports, lits, [name(c) " : mem'" prim-width(type(c)) " " size(c) "\n"])
-;; (c:DefAccessor) :
-;; accs[name(c)] = c
-;; (c:Connect) :
-;; val dst = name(loc(c) as Ref)
-;; val src = name(exp(c) as Ref)
-;; if key?(regs, dst) :
-;; val reg = regs[dst]
-;; emit-all(o, top, ports, lits, [dst " = reg'" prim-width(type(reg)) " 0'" prim-width(type(reg)) " " exp(c) "\n"])
-;; else if key?(accs, dst) :
-;; val acc = accs[dst]
-;; ;; assert(gender(acc) == OUTPUT)
-;; emit-all(o, top, ports, lits, [dst " = wr " source(acc) " " index(acc) " " exp(c) "\n"])
-;; else if key?(outs, dst) :
-;; val out = outs[dst]
-;; emit-all(o, top, ports, lits, [top "::" dst " = out'" prim-width(type(out)) " " exp(c) "\n"])
-;; else if key?(accs, src) :
-;; val acc = accs[src]
-;; ;; assert(gender(acc) == INPUT)
-;; emit-all(o, top, ports, lits, [dst " = rd " source(acc) " " index(acc) "\n"])
-;; else :
-;; emit-all(o, top, ports, lits, [dst " = mov " exp(c) "\n"])
-;; (c:Begin) :
-;; do(emit-command{o, _, top, lits, regs, accs, ports, outs}, body(c))
-;; (c:DefWire|EmptyStmt) :
-;; print("")
-;; (c) :
-;; error("Unable to print command")
-;;
-;;defn emit-module (o:OutputStream, m:Module) :
-;; val regs = HashTable<Symbol, DefRegister>(symbol-hash)
-;; val accs = HashTable<Symbol, DefAccessor>(symbol-hash)
-;; val lits = HashTable<Symbol, DefUInt>(symbol-hash)
-;; val outs = HashTable<Symbol, Port>(symbol-hash)
-;; val portz = HashTable<Symbol, Port>(symbol-hash)
-;; for port in ports(m) do :
-;; portz[name(port)] = port
-;; if gender(port) == OUTPUT :
-;; outs[name(port)] = port
-;; else if name(port) == `reset :
-;; print-all(o, [name(m) "::reset = rst\n"])
-;; else :
-;; print-all(o, [name(m) "::" name(port) " = " "in'" prim-width(type(port)) "\n"])
-;; emit-command(o, body(m), name(m), lits, regs, accs, portz, outs)
-;;
-;;public defn emit-circuit (o:OutputStream, c:Circuit) :
-;; emit-module(o, modules(c)[0])
+ Circuit(modules*, main(c)) where :
+ val modules* =
+ for m in modules(c) map :
+ Module(name(m), ports(m), to-stmt(body(m)))
+;============= FLO PRINTER ======================================
+; Emit
+
+defn flo-op-name (op:PrimOp) -> String :
+ switch {op == _ } :
+ ;NEG-OP : "neg"
+ ;NEG-OP : "neg"
+ ;NEG-OP : "neg"
+ ;NEG-OP : "neg"
+ ADD-UU-OP : "add"
+ ADD-US-OP : "add"
+ ADD-SU-OP : "add"
+ ADD-SS-OP : "add"
+ ADD-WRAP-UU-OP : "add"
+ ADD-WRAP-US-OP : "add"
+ ADD-WRAP-SU-OP : "add"
+ ADD-WRAP-SS-OP : "add"
+ SUB-UU-OP : "sub"
+ SUB-US-OP : "sub"
+ SUB-SU-OP : "sub"
+ SUB-SS-OP : "sub"
+ SUB-WRAP-UU-OP : "sub"
+ SUB-WRAP-US-OP : "sub"
+ SUB-WRAP-SU-OP : "sub"
+ SUB-WRAP-SS-OP : "sub"
+ MUL-UU-OP : "mul" ;; todo: signed version
+ MUL-US-OP : "mul" ;; todo: signed version
+ MUL-SU-OP : "mul" ;; todo: signed version
+ MUL-SS-OP : "mul" ;; todo: signed version
+ DIV-UU-OP : "div" ;; todo: signed version
+ DIV-US-OP : "div" ;; todo: signed version
+ DIV-SU-OP : "div" ;; todo: signed version
+ DIV-SS-OP : "div" ;; todo: signed version
+ MOD-UU-OP : "mod" ;; todo: signed version
+ MOD-US-OP : "mod" ;; todo: signed version
+ MOD-SU-OP : "mod" ;; todo: signed version
+ MOD-SS-OP : "mod" ;; todo: signed version
+ LESS-UU-OP : "lt" ;; todo: signed version
+ LESS-US-OP : "lt" ;; todo: signed version
+ LESS-SU-OP : "lt" ;; todo: signed version
+ LESS-SS-OP : "lt" ;; todo: signed version
+ LESS-EQ-UU-OP : "lte" ;; todo: swap args
+ LESS-EQ-US-OP : "lte" ;; todo: swap args
+ LESS-EQ-SU-OP : "lte" ;; todo: swap args
+ LESS-EQ-SS-OP : "lte" ;; todo: swap args
+ GREATER-UU-OP : "lte" ;; todo: swap args BROKEN
+ GREATER-US-OP : "lte" ;; todo: swap args BROKEN
+ GREATER-SU-OP : "lte" ;; todo: swap args BROKEN
+ GREATER-SS-OP : "lte" ;; todo: swap args BROKEN
+ GREATER-EQ-UU-OP : "lt" ;; todo: signed version
+ GREATER-EQ-US-OP : "lt" ;; todo: signed version
+ GREATER-EQ-SU-OP : "lt" ;; todo: signed version
+ GREATER-EQ-SS-OP : "lt" ;; todo: signed version
+ NEQUAL-UU-OP : "neq"
+ NEQUAL-SS-OP : "neq"
+ EQUAL-UU-OP : "eq"
+ EQUAL-SS-OP : "eq"
+ MUX-UU-OP : "mux"
+ MUX-SS-OP : "mux"
+ PAD-U-OP : "rsh" ;; todo: signed version
+ PAD-S-OP : "rsh" ;; todo: signed version
+ ;AS-UINT-U-OP :
+ ;AS-UINT-S-OP :
+ ;AS-SINT-U-OP :
+ ;AS-SINT-S-OP :
+ SHIFT-LEFT-U-OP : "lsh" ;; todo: signed version
+ SHIFT-LEFT-S-OP : "lsh" ;; todo: signed version
+ SHIFT-RIGHT-U-OP : "rsh"
+ SHIFT-RIGHT-S-OP : "rsh"
+ ;CONVERT-U-OP :
+ ;CONVERT-S-OP :
+ BIT-AND-OP : "and"
+ BIT-NOT-OP : "not"
+ BIT-OR-OP : "or"
+ BIT-XOR-OP : "xor"
+ CONCAT-OP : "cat"
+ BIT-SELECT-OP : "rsh"
+ BITS-SELECT-OP : "rsh"
+ else : error $ string-join $ ["Unable to print Primop: " op]
+
+defn sane-width (wd:Width) -> Int :
+ match(wd) :
+ (w:IntWidth) : max(1, width(w))
+ (w) : error("Unknown width")
+
+defn prim-width (type:Type) -> Int :
+ match(type) :
+ (t:UIntType) : sane-width(width(t))
+ (t:SIntType) : sane-width(width(t))
+ (t) : error("Bad prim width type")
+
+defn sizeof (in: Int) -> Int :
+ ;; if in == 1: 1 else: to-int(ceil(log(in)/log(2)))
+ max(1, ceil-log2(in))
+
+defn emit-all (o:OutputStream, es:Streamable, top:Symbol) :
+ for e in es do :
+ match(e) :
+ (ex:Expression) : emit!(o,e,top)
+ (ex:String) : print(o, ex)
+ (ex:Symbol) : print(o, ex)
+ ;; (ex:Int) : print-all(o, [ex "'" sizeof(ex)])
+ (ex:Int) : print(o, ex)
+ (ex) : print(o, ex)
+
+defn emit! (o:OutputStream, e:Expression,top:Symbol) :
+ defn cmp-op? (op: PrimOp) -> True|False :
+ contains?([EQUAL-OP, NEQUAL-OP, GREATER-OP, LESS-EQ-OP, LESS-OP, GREATER-EQ-OP], op)
+ match(e) :
+ (e:Ref) : emit-all(o,[top "::" name(e)], top)
+ (e:UIntValue) : emit-all(o,[value(e) "'" sane-width(width(e))], top)
+ (e:SIntValue) : emit-all(o,[value(e) "'" sane-width(width(e))], top)
+ (e:Subfield) : emit-all(o,[exp(e) "/" name(e)], top)
+ (e:Index) : emit-all(o,[exp(e) "/" value(e)], top)
+ (e:Register) :
+ emit-all(o,["reg'" prim-width(type(e)) " " enable(e) " " value(e)], top)
+ (e:ReadPort) :
+ emit-all(o,["rd'" prim-width(type(e)) " " enable(e) " " mem(e) " " index(e)], top)
+ (e:DoPrim) :
+ if cmp-op?(op(e)) :
+ emit-all(o, [flo-op-name(op(e)) "'" prim-width(type(args(e)[0]))], top)
+ if op(e) == GREATER-OP or op(e) == LESS-EQ-OP :
+ emit-all(o, [" " args(e)[1] " " args(e)[0]], top)
+ else :
+ emit-all(o, [" " args(e)[0] " " args(e)[1]], top)
+ else if op(e) == BIT-SELECT-OP :
+ emit-all(o, [flo-op-name(op(e)) "'1 " args(e)[0] " " consts(e)[0]], top)
+ else if op(e) == BITS-SELECT-OP :
+ val w = consts(e)[0] - consts(e)[1] + 1
+ emit-all(o, [flo-op-name(op(e)) "'" w " " args(e)[0] " " consts(e)[1]], top)
+ ;; else if op(e) == CONCAT-OP :
+ ;; val w = consts(e)[0] - consts(e)[1] + 1
+ ;; emit-all(o, [flo-op-name(op(e)) "'" w " " args(e)[0] " " consts(e)[1]], top)
+ else :
+ emit-all(o, [flo-op-name(op(e)) "'" prim-width(type(e))], top)
+ if op(e) == PAD-OP :
+ emit-all(o, [" " args(e)[0] " 0"], top)
+ else :
+ for arg in args(e) do :
+ print(o, " ")
+ emit!(o, arg, top)
+ for const in consts(e) do :
+ print(o, " ")
+ print(o, const)
+ (e) : print-all(o, ["EMIT(" e ")"])
+ ;(e) : emit-all(o, ["mov'" prim-width(type(e)) " " e], top) ;TODO, not sure which one is right
+
+defn emit-s (o:OutputStream, s:Stmt, v:List<Symbol>, top:Symbol) :
+ match(s) :
+ (s:DefWire) : ""
+ (s:DefInstance) : error("Shouldn't be here")
+ (s:DefMemory) :
+ val vtype = type(s) as VectorType
+ emit-all(o, [top "::" name(s) " = mem'" prim-width(type(vtype)) " " size(vtype) "\n"], top)
+ (s:DefNode) : emit-all(o, [top "::" name(s) " = " value(s) "\n"], top)
+ (s:Begin) : do(emit-s{o, _, v, top}, body(s))
+ (s:Connect) :
+ if loc(s) typeof WritePort :
+ val e = loc(s) as WritePort
+ val name = gensym(`F)
+ emit-all(o, [top "::" name " = wr'" prim-width(type(e)) " " enable(e) " " top "::" mem(e) " " index(e) " " exp(s) "\n"], top)
+ else :
+ val n = name(loc(s) as Ref)
+ if contains?(v,n) :
+ emit-all(o, [n " = out'" prim-width(type(loc(s))) " " exp(s) "\n"], top)
+ else :
+ emit-all(o, [top "::" n " = " exp(s) "\n"], top)
+ (s) : s
+
+defn emit-module (o:OutputStream, m:Module) :
+ val v = Vector<Symbol>()
+ for port in ports(m) do :
+ if name(port) ==`reset :
+ emit-all(o, [name(m) "::" name(port) " = rst'1\n"], name(m))
+ else : switch {_ == direction(port)} :
+ INPUT : print-all(o, [name(m) "::" name(port) " = " "in'" prim-width(type(port)) "\n"])
+ OUTPUT : add(v,name(port))
+ emit-s(o, body(m), to-list(v), name(m))
+
+public defn emit-flo (o:OutputStream, c:Circuit) :
+ emit-module(o, modules(c)[0])
+ c
;============= DRIVER ======================================
public defn run-passes (c: Circuit, p: List<Char>) :
@@ -2476,9 +2178,10 @@ public defn run-passes (c: Circuit, p: List<Char>) :
if contains(p,'p') : do-stage("Initialize Registers", initialize-registers)
if contains(p,'j') : do-stage("Expand Whens", expand-whens)
if contains(p,'k') : do-stage("Infer Widths", infer-widths)
- ;if contains(p,'n') : do-stage("Pad Widths", pad-widths)
- ;if contains(p,'o') : do-stage("Inline Instances", inline-instances)
-
+ if contains(p,'l') : do-stage("Inline Instances", inline-instances)
+ if contains(p,'m') : do-stage("Split Expressions", split-exp)
+ if contains(p,'n') : do-stage("Real IR", to-real-ir)
+ if contains(p,'o') : do-stage("To Flo", emit-flo{STANDARD-OUTPUT,_})
println("Done!")
diff --git a/test/chisel3/BitsOps.fir b/test/chisel3/BitsOps.fir
new file mode 100644
index 00000000..5fa56b60
--- /dev/null
+++ b/test/chisel3/BitsOps.fir
@@ -0,0 +1,17 @@
+circuit BitsOps :
+ module BitsOps :
+ input b : UInt(16)
+ input a : UInt(16)
+ output notout : UInt(16)
+ output andout : UInt(16)
+ output orout : UInt(16)
+ output xorout : UInt(16)
+
+ node T_13 : UInt = bit-not(a)
+ notout := T_13
+ node T_14 : UInt = bit-and(a, b)
+ andout := T_14
+ node T_15 : UInt = bit-or(a, b)
+ orout := T_15
+ node T_16 : UInt = bit-xor(a, b)
+ xorout := T_16 \ No newline at end of file
diff --git a/test/chisel3/BundleWire.fir b/test/chisel3/BundleWire.fir
new file mode 100644
index 00000000..72d3061e
--- /dev/null
+++ b/test/chisel3/BundleWire.fir
@@ -0,0 +1,14 @@
+circuit BundleWire :
+ module BundleWire :
+ output in : {input y : UInt(32), input x : UInt(32)}
+ output outs : {output y : UInt(32), output x : UInt(32)}[4]
+
+ wire coords : {output y : UInt(32), output x : UInt(32)}[4]
+ coords.0 := in
+ outs.0 := coords.0
+ coords.1 := in
+ outs.1 := coords.1
+ coords.2 := in
+ outs.2 := coords.2
+ coords.3 := in
+ outs.3 := coords.3 \ No newline at end of file
diff --git a/test/chisel3/ComplexAssign.fir b/test/chisel3/ComplexAssign.fir
new file mode 100644
index 00000000..2cf52370
--- /dev/null
+++ b/test/chisel3/ComplexAssign.fir
@@ -0,0 +1,15 @@
+circuit ComplexAssign :
+ module ComplexAssign :
+ input in : {output re : UInt(10), output im : UInt(10)}
+ output out : {output re : UInt(10), output im : UInt(10)}
+ input e : UInt(1)
+ when e :
+ wire T_19 : {output re : UInt(10), output im : UInt(10)}
+ T_19 := in
+ out.re := T_19.re
+ out.im := T_19.im
+ else :
+ node T_20 : UInt(1) = UInt(0, 1)
+ out.re := T_20
+ node T_21 : UInt(1) = UInt(0, 1)
+ out.im := T_21 \ No newline at end of file
diff --git a/test/chisel3/Counter.fir b/test/chisel3/Counter.fir
new file mode 100644
index 00000000..8bab249c
--- /dev/null
+++ b/test/chisel3/Counter.fir
@@ -0,0 +1,17 @@
+circuit Counter :
+ module Counter :
+ input inc : UInt(1)
+ output tot : UInt(8)
+ input amt : UInt(4)
+
+ node T_13 : UInt(8) = UInt(255, 8)
+ node T_14 : UInt(8) = UInt(0, 8)
+ reg T_15 : UInt(8)
+ T_15.init := T_14
+ when inc :
+ node T_16 : UInt = add-mod(T_15, amt)
+ node T_17 : UInt(1) = greater(T_16, T_13)
+ node T_18 : UInt(1) = UInt(0, 1)
+ node T_19 : UInt(1) = multiplex(T_17, T_18, T_16)
+ T_15 := T_19
+ tot := T_15 \ No newline at end of file
diff --git a/test/chisel3/DirChange.fir b/test/chisel3/DirChange.fir
new file mode 100644
index 00000000..c948dc85
--- /dev/null
+++ b/test/chisel3/DirChange.fir
@@ -0,0 +1,7 @@
+circuit DirChange :
+ module DirChange :
+ input test1 : UInt(5)
+ output test2 : UInt(5)
+ input test3 : UInt(2)[10]
+ output test4 : {output test41 : UInt(5), output test42 : UInt(5)}
+ skip \ No newline at end of file
diff --git a/test/chisel3/EnableShiftRegister.fir b/test/chisel3/EnableShiftRegister.fir
new file mode 100644
index 00000000..aa7d36ae
--- /dev/null
+++ b/test/chisel3/EnableShiftRegister.fir
@@ -0,0 +1,24 @@
+circuit EnableShiftRegister :
+ module EnableShiftRegister :
+ input in : UInt(4)
+ output out : UInt(4)
+ input shift : UInt(1)
+
+ node T_14 : UInt(4) = UInt(0, 4)
+ reg r0 : UInt(4)
+ r0.init := T_14
+ node T_15 : UInt(4) = UInt(0, 4)
+ reg r1 : UInt(4)
+ r1.init := T_15
+ node T_16 : UInt(4) = UInt(0, 4)
+ reg r2 : UInt(4)
+ r2.init := T_16
+ node T_17 : UInt(4) = UInt(0, 4)
+ reg r3 : UInt(4)
+ r3.init := T_17
+ when shift :
+ r0 := in
+ r1 := r0
+ r2 := r1
+ r3 := r2
+ out := r3 \ No newline at end of file
diff --git a/test/chisel3/GCD.fir b/test/chisel3/GCD.fir
new file mode 100644
index 00000000..5b103a6b
--- /dev/null
+++ b/test/chisel3/GCD.fir
@@ -0,0 +1,24 @@
+circuit GCD :
+ module GCD :
+ input b : UInt(16)
+ input a : UInt(16)
+ input e : UInt(1)
+ output z : UInt(16)
+ output v : UInt(1)
+
+ reg x : UInt(16)
+ reg y : UInt(16)
+ node T_17 : UInt(1) = greater(x, y)
+ when T_17 :
+ node T_18 : UInt = sub-mod(x, y)
+ x := T_18
+ else :
+ node T_19 : UInt = sub-mod(y, x)
+ y := T_19
+ when e :
+ x := a
+ y := b
+ z := x
+ node T_20 : UInt(1) = UInt(0, 1)
+ node T_21 : UInt(1) = equal(y, T_20)
+ v := T_21 \ No newline at end of file
diff --git a/test/chisel3/LFSR16.fir b/test/chisel3/LFSR16.fir
new file mode 100644
index 00000000..7e661548
--- /dev/null
+++ b/test/chisel3/LFSR16.fir
@@ -0,0 +1,20 @@
+circuit LFSR16 :
+ module LFSR16 :
+ output out : UInt(16)
+ input inc : UInt(1)
+
+ node T_16 : UInt(16) = UInt(1, 16)
+ reg res : UInt(16)
+ res.init := T_16
+ when inc :
+ node T_17 : UInt(1) = bit(res, 0)
+ node T_18 : UInt(1) = bit(res, 2)
+ node T_19 : UInt(1) = bit-xor(T_17, T_18)
+ node T_20 : UInt(1) = bit(res, 3)
+ node T_21 : UInt(1) = bit-xor(T_19, T_20)
+ node T_22 : UInt(1) = bit(res, 5)
+ node T_23 : UInt(1) = bit-xor(T_21, T_22)
+ node T_24 : UInt = bits(res, 15, 1)
+ node T_25 : UInt(1) = concat(T_23, T_24)
+ res := T_25
+ out := res \ No newline at end of file
diff --git a/test/chisel3/MemorySearch.fir b/test/chisel3/MemorySearch.fir
new file mode 100644
index 00000000..f7a0fb84
--- /dev/null
+++ b/test/chisel3/MemorySearch.fir
@@ -0,0 +1,43 @@
+circuit MemorySearch :
+ module MemorySearch :
+ input target : UInt(4)
+ output address : UInt(3)
+ input en : UInt(1)
+ output done : UInt(1)
+
+ node T_36 : UInt(3) = UInt(0, 3)
+ reg index : UInt(3)
+ index.init := T_36
+ node T_37 : UInt(1) = UInt(0, 1)
+ node T_38 : UInt(3) = UInt(4, 3)
+ node T_39 : UInt(4) = UInt(15, 4)
+ node T_40 : UInt(4) = UInt(14, 4)
+ node T_41 : UInt(2) = UInt(2, 2)
+ node T_42 : UInt(3) = UInt(5, 3)
+ node T_43 : UInt(4) = UInt(13, 4)
+ wire elts : UInt(1)[7]
+ elts.0 := T_37
+ elts.1 := T_38
+ elts.2 := T_39
+ elts.3 := T_40
+ elts.4 := T_41
+ elts.5 := T_42
+ elts.6 := T_43
+ accessor elt = elts[index]
+ node T_44 : UInt(1) = bit-not(en)
+ node T_45 : UInt(1) = equal(elt, target)
+ node T_46 : UInt(3) = UInt(7, 3)
+ node T_47 : UInt(1) = equal(index, T_46)
+ node T_48 : UInt(1) = bit-or(T_45, T_47)
+ node done : UInt(1) = bit-and(T_44, T_48)
+ when en :
+ node T_49 : UInt(1) = UInt(0, 1)
+ index := T_49
+ else :
+ node T_50 : UInt(1) = bit-not(done)
+ when T_50 :
+ node T_51 : UInt(1) = UInt(1, 1)
+ node T_52 : UInt(3) = add(index, T_51)
+ index := T_52
+ done := done
+ address := index \ No newline at end of file
diff --git a/test/chisel3/ModuleVec.fir b/test/chisel3/ModuleVec.fir
new file mode 100644
index 00000000..1372d1f6
--- /dev/null
+++ b/test/chisel3/ModuleVec.fir
@@ -0,0 +1,25 @@
+circuit ModuleVec :
+ module PlusOne :
+ input in : UInt(32)
+ output out : UInt(32)
+
+ node T_34 : UInt(1) = UInt(1, 1)
+ node T_35 : UInt(32) = add(in, T_34)
+ out := T_35
+ module PlusOne_26 :
+ input in : UInt(32)
+ output out : UInt(32)
+
+ node T_36 : UInt(1) = UInt(1, 1)
+ node T_37 : UInt(32) = add(in, T_36)
+ out := T_37
+ module ModuleVec :
+ input ins : UInt(32)[2]
+ output outs : UInt(32)[2]
+
+ instance T_38 of PlusOne
+ instance T_39 of PlusOne_26
+ pluses.0.in := ins.0
+ outs.0 := pluses.0.out
+ pluses.1.in := ins.1
+ outs.1 := pluses.1.out \ No newline at end of file
diff --git a/test/chisel3/Mul.fir b/test/chisel3/Mul.fir
new file mode 100644
index 00000000..f8ba0b78
--- /dev/null
+++ b/test/chisel3/Mul.fir
@@ -0,0 +1,44 @@
+circuit Mul :
+ module Mul :
+ input y : UInt(2)
+ input x : UInt(2)
+ output z : UInt(4)
+
+ node T_44 : UInt(4) = UInt(0, 4)
+ node T_45 : UInt(4) = UInt(0, 4)
+ node T_46 : UInt(4) = UInt(0, 4)
+ node T_47 : UInt(4) = UInt(0, 4)
+ node T_48 : UInt(4) = UInt(0, 4)
+ node T_49 : UInt(4) = UInt(1, 4)
+ node T_50 : UInt(4) = UInt(2, 4)
+ node T_51 : UInt(4) = UInt(3, 4)
+ node T_52 : UInt(4) = UInt(0, 4)
+ node T_53 : UInt(4) = UInt(2, 4)
+ node T_54 : UInt(4) = UInt(4, 4)
+ node T_55 : UInt(4) = UInt(6, 4)
+ node T_56 : UInt(4) = UInt(0, 4)
+ node T_57 : UInt(4) = UInt(3, 4)
+ node T_58 : UInt(4) = UInt(6, 4)
+ node T_59 : UInt(4) = UInt(9, 4)
+ wire tbl : UInt(4)[16]
+ tbl.0 := T_44
+ tbl.1 := T_45
+ tbl.2 := T_46
+ tbl.3 := T_47
+ tbl.4 := T_48
+ tbl.5 := T_49
+ tbl.6 := T_50
+ tbl.7 := T_51
+ tbl.8 := T_52
+ tbl.9 := T_53
+ tbl.10 := T_54
+ tbl.11 := T_55
+ tbl.12 := T_56
+ tbl.13 := T_57
+ tbl.14 := T_58
+ tbl.15 := T_59
+ node T_60 : UInt(2) = UInt(2, 2)
+ node T_61 : UInt(2) = shift-left(x, T_60)
+ node T_62 : UInt(2) = bit-or(T_61, y)
+ accessor T_63 = tbl[T_62]
+ z := T_63 \ No newline at end of file
diff --git a/test/chisel3/Outer.fir b/test/chisel3/Outer.fir
new file mode 100644
index 00000000..e3a67a6e
--- /dev/null
+++ b/test/chisel3/Outer.fir
@@ -0,0 +1,17 @@
+circuit Outer :
+ module Inner :
+ input in : UInt(8)
+ output out : UInt(8)
+
+ node T_15 : UInt(1) = UInt(1, 1)
+ node T_16 : UInt(8) = add(in, T_15)
+ out := T_16
+ module Outer :
+ input in : UInt(8)
+ output out : UInt(8)
+
+ instance T_17 of Inner
+ T_17.in := in
+ node T_18 : UInt(2) = UInt(2, 2)
+ node T_19 : UInt(8) = times(T_17.out, T_18)
+ out := T_19 \ No newline at end of file
diff --git a/test/chisel3/RegisterVecShift.fir b/test/chisel3/RegisterVecShift.fir
new file mode 100644
index 00000000..772c3d54
--- /dev/null
+++ b/test/chisel3/RegisterVecShift.fir
@@ -0,0 +1,34 @@
+circuit RegisterVecShift :
+ module RegisterVecShift :
+ input load : UInt(1)
+ output out : UInt(4)
+ input shift : UInt(1)
+ input ins : UInt(4)[4]
+
+ reg delays : UInt(4)[4]
+ when reset :
+ node T_39 : UInt(4) = UInt(0, 4)
+ node T_40 : UInt(4) = UInt(0, 4)
+ node T_41 : UInt(4) = UInt(0, 4)
+ node T_42 : UInt(4) = UInt(0, 4)
+ wire T_43 : UInt(4)[4]
+ T_43.0 := T_39
+ T_43.1 := T_40
+ T_43.2 := T_41
+ T_43.3 := T_42
+ delays := T_43
+ node T_44 : UInt(3) = UInt(5, 3)
+ node T_45 : UInt(3) = bit-and(T_44, load)
+ node T_46 : UInt(3) = UInt(4, 3)
+ node T_47 : UInt(1) = equal(T_45, T_46)
+ when T_47 :
+ delays.0 := ins.0
+ delays.1 := ins.1
+ delays.2 := ins.2
+ delays.3 := ins.3
+ else : when shift :
+ delays.0 := ins.0
+ delays.1 := delays.0
+ delays.2 := delays.1
+ delays.3 := delays.2
+ out := delays.3 \ No newline at end of file
diff --git a/test/chisel3/Risc.fir b/test/chisel3/Risc.fir
new file mode 100644
index 00000000..1a4d21e5
--- /dev/null
+++ b/test/chisel3/Risc.fir
@@ -0,0 +1,66 @@
+circuit Risc :
+ module Risc :
+ output out : UInt(32)
+ output valid : UInt(1)
+ input boot : UInt(1)
+ input isWr : UInt(1)
+ input wrAddr : UInt(8)
+ input wrData : UInt(32)
+
+ mem file : UInt(32)[256]
+ mem code : UInt(32)[256]
+ node T_51 : UInt(8) = UInt(0, 8)
+ reg pc : UInt(8)
+ pc.init := T_51
+ node add_op : UInt(1) = UInt(0, 1)
+ node imm_op : UInt(1) = UInt(1, 1)
+ accessor inst = code[pc]
+ node op : UInt = bits(inst, 31, 24)
+ node rci : UInt = bits(inst, 23, 16)
+ node rai : UInt = bits(inst, 15, 8)
+ node rbi : UInt = bits(inst, 7, 0)
+ node T_52 : UInt(1) = UInt(0, 1)
+ node T_53 : UInt(1) = equal(rai, T_52)
+ node T_54 : UInt(1) = UInt(0, 1)
+ accessor T_55 = file[rai]
+ node ra : UInt = multiplex(T_53, T_54, T_55)
+ node T_56 : UInt(1) = UInt(0, 1)
+ node T_57 : UInt(1) = equal(rbi, T_56)
+ node T_58 : UInt(1) = UInt(0, 1)
+ accessor T_59 = file[rbi]
+ node rb : UInt = multiplex(T_57, T_58, T_59)
+ wire rc : UInt(32)
+ node T_60 : UInt(1) = UInt(0, 1)
+ valid := T_60
+ node T_61 : UInt(1) = UInt(0, 1)
+ out := T_61
+ node T_62 : UInt(1) = UInt(0, 1)
+ rc := T_62
+ when isWr :
+ accessor T_63 = code[wrAddr]
+ T_63 := wrData
+ else : when boot :
+ node T_64 : UInt(1) = UInt(0, 1)
+ pc := T_64
+ else :
+ node T_65 : UInt(1) = equal(add_op, op)
+ when T_65 :
+ node T_66 : UInt = add-mod(ra, rb)
+ rc := T_66
+ node T_67 : UInt(1) = equal(imm_op, op)
+ when T_67 :
+ node T_68 : UInt = shift-left(rai, 8)
+ node T_69 : UInt = bit-or(T_68, rbi)
+ rc := T_69
+ out := rc
+ node T_70 : UInt(8) = UInt(255, 8)
+ node T_71 : UInt(1) = equal(rci, T_70)
+ when T_71 :
+ node T_72 : UInt(1) = UInt(1, 1)
+ valid := T_72
+ else :
+ accessor T_73 = file[rci]
+ T_73 := rc
+ node T_74 : UInt(1) = UInt(1, 1)
+ node T_75 : UInt = add-mod(pc, T_74)
+ pc := T_75 \ No newline at end of file
diff --git a/test/chisel3/Rom.fir b/test/chisel3/Rom.fir
new file mode 100644
index 00000000..bb4960a4
--- /dev/null
+++ b/test/chisel3/Rom.fir
@@ -0,0 +1,24 @@
+circuit Rom :
+ module Rom :
+ output out : UInt(8)
+ input addr : UInt(8)
+
+ node T_24 : UInt(8) = UInt(0, 8)
+ node T_25 : UInt(8) = UInt(1, 8)
+ node T_26 : UInt(8) = UInt(2, 8)
+ node T_27 : UInt(8) = UInt(3, 8)
+ node T_28 : UInt(8) = UInt(4, 8)
+ node T_29 : UInt(8) = UInt(5, 8)
+ node T_30 : UInt(8) = UInt(6, 8)
+ node T_31 : UInt(8) = UInt(7, 8)
+ wire r : UInt(8)[8]
+ r.0 := T_24
+ r.1 := T_25
+ r.2 := T_26
+ r.3 := T_27
+ r.4 := T_28
+ r.5 := T_29
+ r.6 := T_30
+ r.7 := T_31
+ accessor T_32 = r[addr]
+ out := T_32 \ No newline at end of file
diff --git a/test/chisel3/SIntOps.fir b/test/chisel3/SIntOps.fir
new file mode 100644
index 00000000..b026e1f3
--- /dev/null
+++ b/test/chisel3/SIntOps.fir
@@ -0,0 +1,49 @@
+circuit SIntOps :
+ module SIntOps :
+ input b : UInt(16)
+ input a : UInt(16)
+ output addout : UInt(16)
+ output subout : UInt(16)
+ output timesout : UInt(16)
+ output divout : UInt(16)
+ output modout : UInt(16)
+ output lshiftout : UInt(16)
+ output rshiftout : UInt(16)
+ output lessout : UInt(1)
+ output greatout : UInt(1)
+ output eqout : UInt(1)
+ output noteqout : UInt(1)
+ output lesseqout : UInt(1)
+ output greateqout : UInt(1)
+ output negout : UInt(16)
+
+ node T_35 : UInt = add-mod(a, b)
+ addout := T_35
+ node T_36 : UInt = sub-mod(a, b)
+ subout := T_36
+ node T_37 : UInt = times(a, b)
+ node T_38 : UInt = bits(T_37, 15, 0)
+ timesout := T_38
+ node T_39 : UInt = divide(a, b)
+ divout := T_39
+ node T_40 : UInt = divide(a, b)
+ modout := T_40
+ node T_41 : UInt = shift-left(a, 12)
+ node T_42 : UInt = bits(T_41, 15, 0)
+ lshiftout := T_42
+ node T_43 : UInt = shift-right(a, 8)
+ rshiftout := T_43
+ node T_44 : UInt(1) = less(a, b)
+ lessout := T_44
+ node T_45 : UInt(1) = greater(a, b)
+ greatout := T_45
+ node T_46 : UInt(1) = equal(a, b)
+ eqout := T_46
+ node T_47 : UInt(1) = not-equal(a, b)
+ noteqout := T_47
+ node T_48 : UInt(1) = less-eq(a, b)
+ lesseqout := T_48
+ node T_49 : UInt(1) = greater-eq(a, b)
+ greateqout := T_49
+ node T_50 : UInt = neg(a)
+ negout := T_50 \ No newline at end of file
diff --git a/test/chisel3/Stack.fir b/test/chisel3/Stack.fir
new file mode 100644
index 00000000..15596d0d
--- /dev/null
+++ b/test/chisel3/Stack.fir
@@ -0,0 +1,41 @@
+circuit Stack :
+ module Stack :
+ input push : UInt(1)
+ input pop : UInt(1)
+ input en : UInt(1)
+ output dataOut : UInt(32)
+ input dataIn : UInt(32)
+
+ mem stack_mem : UInt(32)[16]
+ node T_30 : UInt(5) = UInt(0, 5)
+ reg sp : UInt(5)
+ sp.init := T_30
+ node T_31 : UInt(32) = UInt(0, 32)
+ reg out : UInt(32)
+ out.init := T_31
+ when en :
+ node T_32 : UInt(5) = UInt(16, 5)
+ node T_33 : UInt(1) = less(sp, T_32)
+ node T_34 : UInt(1) = bit-and(push, T_33)
+ when T_34 :
+ accessor T_35 = stack_mem[sp]
+ T_35 := dataIn
+ node T_36 : UInt(1) = UInt(1, 1)
+ node T_37 : UInt = add-mod(sp, T_36)
+ sp := T_37
+ else :
+ node T_38 : UInt(1) = UInt(0, 1)
+ node T_39 : UInt(1) = greater(sp, T_38)
+ node T_40 : UInt(1) = bit-and(pop, T_39)
+ when T_40 :
+ node T_41 : UInt(1) = UInt(1, 1)
+ node T_42 : UInt = sub-mod(sp, T_41)
+ sp := T_42
+ node T_43 : UInt(1) = UInt(0, 1)
+ node T_44 : UInt(1) = greater(sp, T_43)
+ when T_44 :
+ node T_45 : UInt(1) = UInt(1, 1)
+ node T_46 : UInt = sub-mod(sp, T_45)
+ accessor T_47 = stack_mem[T_46]
+ out := T_47
+ dataOut := out \ No newline at end of file
diff --git a/test/chisel3/Tbl.fir b/test/chisel3/Tbl.fir
new file mode 100644
index 00000000..273047b0
--- /dev/null
+++ b/test/chisel3/Tbl.fir
@@ -0,0 +1,16 @@
+circuit Tbl :
+ module Tbl :
+ output o : UInt(16)
+ input i : UInt(16)
+ input d : UInt(16)
+ input we : UInt(1)
+
+ mem m : UInt(10)[256]
+ node T_13 : UInt(1) = UInt(0, 1)
+ o := T_13
+ when we :
+ accessor T_14 = m[i]
+ T_14 := d
+ else :
+ accessor T_15 = m[i]
+ o := T_15 \ No newline at end of file
diff --git a/test/chisel3/UIntOps.fir b/test/chisel3/UIntOps.fir
new file mode 100644
index 00000000..8d0e105e
--- /dev/null
+++ b/test/chisel3/UIntOps.fir
@@ -0,0 +1,44 @@
+circuit UIntOps :
+ module UIntOps :
+ input b : UInt(16)
+ input a : UInt(16)
+ output addout : UInt(16)
+ output subout : UInt(16)
+ output timesout : UInt(16)
+ output divout : UInt(16)
+ output modout : UInt(16)
+ output lshiftout : UInt(16)
+ output rshiftout : UInt(16)
+ output lessout : UInt(1)
+ output greatout : UInt(1)
+ output eqout : UInt(1)
+ output noteqout : UInt(1)
+ output lesseqout : UInt(1)
+ output greateqout : UInt(1)
+
+ node T_32 : UInt(16) = add(a, b)
+ addout := T_32
+ node T_33 : UInt(16) = sub(a, b)
+ subout := T_33
+ node T_34 : UInt(16) = times(a, b)
+ timesout := T_34
+ node T_35 : UInt(16) = divide(a, b)
+ divout := T_35
+ node T_36 : UInt(16) = divide(a, b)
+ modout := T_36
+ node T_37 : UInt(16) = shift-left(a, 12)
+ lshiftout := T_37
+ node T_38 : UInt(16) = shift-right(a, 8)
+ rshiftout := T_38
+ node T_39 : UInt(1) = less(a, b)
+ lessout := T_39
+ node T_40 : UInt(1) = greater(a, b)
+ greatout := T_40
+ node T_41 : UInt(1) = equal(a, b)
+ eqout := T_41
+ node T_42 : UInt(1) = not-equal(a, b)
+ noteqout := T_42
+ node T_43 : UInt(1) = less-eq(a, b)
+ lesseqout := T_43
+ node T_44 : UInt(1) = greater-eq(a, b)
+ greateqout := T_44 \ No newline at end of file
diff --git a/test/chisel3/VecApp.fir b/test/chisel3/VecApp.fir
new file mode 100644
index 00000000..6b2bc21d
--- /dev/null
+++ b/test/chisel3/VecApp.fir
@@ -0,0 +1,8 @@
+circuit VecApp :
+ module VecApp :
+ input a : UInt(4)
+ input i : UInt(8)[4]
+ output d : UInt(8)
+
+ accessor T_13 = i[a]
+ d := T_13 \ No newline at end of file
diff --git a/test/chisel3/VecShiftRegister.fir b/test/chisel3/VecShiftRegister.fir
new file mode 100644
index 00000000..86f20796
--- /dev/null
+++ b/test/chisel3/VecShiftRegister.fir
@@ -0,0 +1,19 @@
+circuit VecShiftRegister :
+ module VecShiftRegister :
+ input load : UInt(1)
+ output out : UInt(4)
+ input shift : UInt(1)
+ input ins : UInt(4)[4]
+
+ reg delays : UInt(4)[4]
+ when load :
+ delays.0 := ins.0
+ delays.1 := ins.1
+ delays.2 := ins.2
+ delays.3 := ins.3
+ else : when shift :
+ delays.0 := ins.0
+ delays.1 := delays.0
+ delays.2 := delays.1
+ delays.3 := delays.2
+ out := delays.3 \ No newline at end of file
diff --git a/test/chisel3/VendingMachine.fir b/test/chisel3/VendingMachine.fir
new file mode 100644
index 00000000..4ae94524
--- /dev/null
+++ b/test/chisel3/VendingMachine.fir
@@ -0,0 +1,46 @@
+circuit VendingMachine :
+ module VendingMachine :
+ output valid : UInt(1)
+ input nickel : UInt(1)
+ input dime : UInt(1)
+
+ node T_34 : UInt(3) = UInt(5, 3)
+ wire c : UInt
+ c := T_34
+ node T_35 : UInt(3) = UInt(0, 3)
+ wire sIdle : UInt
+ sIdle := T_35
+ node T_36 : UInt(3) = UInt(1, 3)
+ wire s5 : UInt
+ s5 := T_36
+ node T_37 : UInt(3) = UInt(2, 3)
+ wire s10 : UInt
+ s10 := T_37
+ node T_38 : UInt(3) = UInt(3, 3)
+ wire s15 : UInt
+ s15 := T_38
+ node T_39 : UInt(3) = UInt(4, 3)
+ wire sOk : UInt
+ sOk := T_39
+ reg state : UInt
+ state.init := sIdle
+ node T_40 : UInt(1) = equal(state, sIdle)
+ when T_40 :
+ when nickel : state := s5
+ when dime : state := s10
+ node T_41 : UInt(1) = equal(state, s5)
+ when T_41 :
+ when nickel : state := s10
+ when dime : state := s15
+ node T_42 : UInt(1) = equal(state, s10)
+ when T_42 :
+ when nickel : state := s15
+ when dime : state := sOk
+ node T_43 : UInt(1) = equal(state, s15)
+ when T_43 :
+ when nickel : state := sOk
+ when dime : state := sOk
+ node T_44 : UInt(1) = equal(state, sOk)
+ when T_44 : state := sIdle
+ node T_45 : UInt(1) = equal(state, sOk)
+ valid := T_45 \ No newline at end of file
diff --git a/test/passes/infer-widths/simple.fir b/test/passes/infer-widths/simple.fir
index f98d98da..fcd08ac6 100644
--- a/test/passes/infer-widths/simple.fir
+++ b/test/passes/infer-widths/simple.fir
@@ -3,10 +3,9 @@
;CHECK: Infer Widths
circuit top :
module top :
- wire e : UInt
- wire x : UInt
+ wire e : UInt(30)
reg y : UInt
- y := mux-uu(e, UInt(1), equal-uu(gt-uu(x, x), UInt(0)))
+ y := e
; CHECK: Finished Infer Widths
diff --git a/test/passes/inline/gcd.fir b/test/passes/inline/gcd.fir
new file mode 100644
index 00000000..bf6f87ab
--- /dev/null
+++ b/test/passes/inline/gcd.fir
@@ -0,0 +1,45 @@
+; RUN: firrtl %s abcefghipjkl c | tee %s.out | FileCheck %s
+
+;CHECK: Inline Instances
+circuit top :
+ module subtracter :
+ input x : UInt
+ input y : UInt
+ output q : UInt
+ q := sub-wrap-uu(x, y)
+ module gcd :
+ input a : UInt(16)
+ input b : UInt(16)
+ input e : UInt(1)
+ output z : UInt(16)
+ output v : UInt(1)
+ reg x : UInt
+ reg y : UInt
+ x.init := UInt(0)
+ y.init := UInt(42)
+ when gt-uu(x, y) :
+ inst s of subtracter
+ s.x := x
+ s.y := y
+ x := s.q
+ else :
+ inst s2 of subtracter
+ s2.x := x
+ s2.y := y
+ y := s2.q
+ when e :
+ x := a
+ y := b
+ v := equal-uu(v, UInt(0))
+ z := x
+ module top :
+ input a : UInt(16)
+ input b : UInt(16)
+ output z : UInt
+ inst i of gcd
+ i.a := a
+ i.b := b
+ i.e := UInt(1)
+ z := i.z
+
+; CHECK: Finished Inline Instances
diff --git a/test/passes/split-exp/gcd.fir b/test/passes/split-exp/gcd.fir
new file mode 100644
index 00000000..a659aa07
--- /dev/null
+++ b/test/passes/split-exp/gcd.fir
@@ -0,0 +1,45 @@
+; RUN: firrtl %s abcefghipjklm c | tee %s.out | FileCheck %s
+
+;CHECK: Split Expressions
+circuit top :
+ module subtracter :
+ input x : UInt
+ input y : UInt
+ output q : UInt
+ q := sub-wrap-uu(x, y)
+ module gcd :
+ input a : UInt(16)
+ input b : UInt(16)
+ input e : UInt(1)
+ output z : UInt(16)
+ output v : UInt(1)
+ reg x : UInt
+ reg y : UInt
+ x.init := UInt(0)
+ y.init := UInt(42)
+ when gt-uu(x, y) :
+ inst s of subtracter
+ s.x := x
+ s.y := y
+ x := s.q
+ else :
+ inst s2 of subtracter
+ s2.x := x
+ s2.y := y
+ y := s2.q
+ when e :
+ x := a
+ y := b
+ v := equal-uu(v, UInt(0))
+ z := x
+ module top :
+ input a : UInt(16)
+ input b : UInt(16)
+ output z : UInt
+ inst i of gcd
+ i.a := a
+ i.b := b
+ i.e := UInt(1)
+ z := i.z
+
+; CHECK: Finished Split Expressions
diff --git a/test/passes/to-flo/gcd.fir b/test/passes/to-flo/gcd.fir
new file mode 100644
index 00000000..7a3179bf
--- /dev/null
+++ b/test/passes/to-flo/gcd.fir
@@ -0,0 +1,45 @@
+; RUN: firrtl %s abcefghipjklmno cw | tee %s.out | FileCheck %s
+
+;CHECK: Flo
+circuit top :
+ module subtracter :
+ input x : UInt
+ input y : UInt
+ output q : UInt
+ q := sub-wrap-uu(x, y)
+ module gcd :
+ input a : UInt(16)
+ input b : UInt(16)
+ input e : UInt(1)
+ output z : UInt(16)
+ output v : UInt(1)
+ reg x : UInt
+ reg y : UInt
+ x.init := UInt(0)
+ y.init := UInt(42)
+ when gt-uu(x, y) :
+ inst s of subtracter
+ s.x := x
+ s.y := y
+ x := s.q
+ else :
+ inst s2 of subtracter
+ s2.x := x
+ s2.y := y
+ y := s2.q
+ when e :
+ x := a
+ y := b
+ v := equal-uu(v, UInt(0))
+ z := x
+ module top :
+ input a : UInt(16)
+ input b : UInt(16)
+ output z : UInt
+ inst i of gcd
+ i.a := a
+ i.b := b
+ i.e := UInt(1)
+ z := i.z
+;CHECK: Done!
+