aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--notes/primop-inference.txt73
-rw-r--r--src/main/stanza/firrtl-ir.stanza82
-rw-r--r--src/main/stanza/passes.stanza302
-rw-r--r--test/passes/infer-types/primops.fir114
4 files changed, 415 insertions, 156 deletions
diff --git a/notes/primop-inference.txt b/notes/primop-inference.txt
new file mode 100644
index 00000000..ec704ba6
--- /dev/null
+++ b/notes/primop-inference.txt
@@ -0,0 +1,73 @@
+The design of the primitive operations follows the following principles:
+(1) if operand types are known (i.e. FIRRTL front-end), primops whose return type is statically known (no future type introspection needed) are available
+(2) if operand types are not known (i.e. hand-writing FIRRTL pass), generic primops can be used, and a future pass will perform type introspection to replace the generic with the specific primop
+(3) the FIRRTL's lowered form will never contain any generic primops
+(4) resultant widths are always large enough to represent any possible output
+(5) specific primops do not grow widths (e.g. add-wrap, sub-wrap) and should be used if that behavior is desired
+(6) except for mux, mux-u, and mux-s, all primops can accept operands of differing width to enable optimizations in the backend
+(7) autopadding on connect is not allowed, and one should use the pad!/-u/-s expression to autopad
+
+TODO:
+rederive div,mod,quo,rem widths.
+Write explanations in terms of formulas.
+Reread all explanations.
+Finish adding primops.
+
+add
+ adduu(a,b) -> u, max(a.w,b.w) + 1
+ addus(a,b) -> s, max(a.w,b.w) + 1
+ addsu(a,b) -> s, max(a.w,b.w) + 1
+ addss(a,b) -> s, max(a.w,b.w) + 1
+
+sub
+ subuu(a,b) -> s, max(a.w,b.w) + 1 ; 0@<UInt,3> - 7@<UInt,3> = -7@<SInt,4>
+ subus(a,b) -> s, max(a.w,b.w) + 1 ; 7@<UInt,3> - -8@<SInt,4> = 15@<SInt,5>
+ subsu(a,b) -> s, max(a.w,b.w) + 1 ; -8@<SInt,4> - 7@<UInt,3> = -15@<SInt,5>
+ subss(a,b) -> s, max(a.w,b.w) + 1 ; -8@<UInt,4> - 7@<SInt,4> = -15@<SInt,5>
+
+mul
+ muluu(a,b) -> u,a.w+b.w
+ mulus(a,b) -> s,a.w+b.w
+ mulsu(a,b) -> s,a.w+b.w
+ mulss(a,b) -> s,a.w+b.w
+
+div
+ divuu(a,b) -> u,a.w ; if divide by 1
+ divus(a,b) -> s,a.w+1 ; if divide by -1
+ divsu(a,b) -> s,a.w ; if divide by 1
+ divss(a,b) -> s,a.w+1 ; if divide by -1
+
+mod
+ moduu(a,d) -> u,d.w
+ modus(a,d) -> u,d.w-1
+ modsu(a,d) -> u,d.w
+ modss(a,d) -> u,d.w-1
+
+rem
+ remuu(a,b) -> u,min(a.w,b.w) ; 15 % 16 = 15. All remainders must be less than b or a.
+ remus(a,b) -> u,b.w ; -1 % 32 = 31. Remainder can be larger than abs(a), but not larger than b.
+ remsu(a,b) -> s,b.w ; 1 % -32 = -31. abs(rem) can be larger than abs(a), but not larger than abs(b).
+ remss(a,b) -> s,b.w ; strictly superset of us and su.
+
+add-mod
+ add-moduu(a,b) -> u, a.w
+ add-modus(a,b) -> u, a.w
+ add-modsu(a,b) -> s, a.w
+ add-modss(a,b) -> s, a.w
+
+sub-mod
+ sub-moduu(a,b) -> u, a.w
+ sub-modus(a,b) -> u, a.w
+ sub-modsu(a,b) -> s, a.w
+ sub-modss(a,b) -> s, a.w
+
+
+Proof:
+add-moduu -> u
+take inverse:
+sub-moduu -> u
+add-modus -> u
+add-modsu -> s with width of first operand
+
+add-mod and sub-mod always return the type and width of the first operand.
+
diff --git a/src/main/stanza/firrtl-ir.stanza b/src/main/stanza/firrtl-ir.stanza
index 259bba10..206401d8 100644
--- a/src/main/stanza/firrtl-ir.stanza
+++ b/src/main/stanza/firrtl-ir.stanza
@@ -14,27 +14,89 @@ public defstruct IntWidth <: Width :
public defstruct PrimOp
public val ADD-OP = PrimOp()
-public val ADD-MOD-OP = PrimOp()
+public val ADD-UU-OP = PrimOp()
+public val ADD-US-OP = PrimOp()
+public val ADD-SU-OP = PrimOp()
+public val ADD-SS-OP = PrimOp()
public val SUB-OP = PrimOp()
-public val SUB-MOD-OP = PrimOp()
+public val SUB-UU-OP = PrimOp()
+public val SUB-US-OP = PrimOp()
+public val SUB-SU-OP = PrimOp()
+public val SUB-SS-OP = PrimOp()
public val TIMES-OP = PrimOp()
+public val TIMES-UU-OP = PrimOp()
+public val TIMES-US-OP = PrimOp()
+public val TIMES-SU-OP = PrimOp()
+public val TIMES-SS-OP = PrimOp()
public val DIVIDE-OP = PrimOp()
+public val DIVIDE-UU-OP = PrimOp()
+public val DIVIDE-US-OP = PrimOp()
+public val DIVIDE-SU-OP = PrimOp()
+public val DIVIDE-SS-OP = PrimOp()
public val MOD-OP = PrimOp()
-public val SHIFT-LEFT-OP = PrimOp()
-public val SHIFT-RIGHT-OP = PrimOp()
+public val MOD-UU-OP = PrimOp()
+public val MOD-US-OP = PrimOp()
+public val MOD-SU-OP = PrimOp()
+public val MOD-SS-OP = PrimOp()
+public val ADD-WRAP-OP = PrimOp()
+public val ADD-WRAP-UU-OP = PrimOp()
+public val ADD-WRAP-US-OP = PrimOp()
+public val ADD-WRAP-SU-OP = PrimOp()
+public val ADD-WRAP-SS-OP = PrimOp()
+public val SUB-WRAP-OP = PrimOp()
+public val SUB-WRAP-UU-OP = PrimOp()
+public val SUB-WRAP-US-OP = PrimOp()
+public val SUB-WRAP-SU-OP = PrimOp()
+public val SUB-WRAP-SS-OP = PrimOp()
+public val LESS-OP = PrimOp()
+public val LESS-UU-OP = PrimOp()
+public val LESS-US-OP = PrimOp()
+public val LESS-SU-OP = PrimOp()
+public val LESS-SS-OP = PrimOp()
+public val LESS-EQ-OP = PrimOp()
+public val LESS-EQ-UU-OP = PrimOp()
+public val LESS-EQ-US-OP = PrimOp()
+public val LESS-EQ-SU-OP = PrimOp()
+public val LESS-EQ-SS-OP = PrimOp()
+public val GREATER-OP = PrimOp()
+public val GREATER-UU-OP = PrimOp()
+public val GREATER-US-OP = PrimOp()
+public val GREATER-SU-OP = PrimOp()
+public val GREATER-SS-OP = PrimOp()
+public val GREATER-EQ-OP = PrimOp()
+public val GREATER-EQ-UU-OP = PrimOp()
+public val GREATER-EQ-US-OP = PrimOp()
+public val GREATER-EQ-SU-OP = PrimOp()
+public val GREATER-EQ-SS-OP = PrimOp()
+public val EQUAL-OP = PrimOp()
+public val EQUAL-UU-OP = PrimOp()
+public val EQUAL-SS-OP = PrimOp()
+public val MULTIPLEX-OP = PrimOp()
+public val MULTIPLEX-UU-OP = PrimOp()
+public val MULTIPLEX-SS-OP = PrimOp()
public val PAD-OP = PrimOp()
+public val PAD-U-OP = PrimOp()
+public val PAD-S-OP = PrimOp()
+public val AS-UINT-OP = PrimOp()
+public val AS-UINT-U-OP = PrimOp()
+public val AS-UINT-S-OP = PrimOp()
+public val AS-SINT-OP = PrimOp()
+public val AS-SINT-U-OP = PrimOp()
+public val AS-SINT-S-OP = PrimOp()
+public val SHIFT-LEFT-OP = PrimOp()
+public val SHIFT-LEFT-U-OP = PrimOp()
+public val SHIFT-LEFT-S-OP = PrimOp()
+public val SHIFT-RIGHT-U-OP = PrimOp()
+public val SHIFT-RIGHT-S-OP = PrimOp()
+public val CONVERT-OP = PrimOp()
+public val CONVERT-U-OP = PrimOp()
+public val CONVERT-S-OP = PrimOp()
public val BIT-AND-OP = PrimOp()
public val BIT-OR-OP = PrimOp()
public val BIT-XOR-OP = PrimOp()
public val CONCAT-OP = PrimOp()
public val BIT-SELECT-OP = PrimOp()
public val BITS-SELECT-OP = PrimOp()
-public val MULTIPLEX-OP = PrimOp()
-public val LESS-OP = PrimOp()
-public val LESS-EQ-OP = PrimOp()
-public val GREATER-OP = PrimOp()
-public val GREATER-EQ-OP = PrimOp()
-public val EQUAL-OP = PrimOp()
public definterface Expression
public defmulti type (e:Expression) -> Type
diff --git a/src/main/stanza/passes.stanza b/src/main/stanza/passes.stanza
index 25ce27bd..6a518e49 100644
--- a/src/main/stanza/passes.stanza
+++ b/src/main/stanza/passes.stanza
@@ -342,155 +342,173 @@ defn initialize-registers (c:Circuit) :
; Type errors are not checked in this pass, as this is
; postponed for a later/earlier pass.
-defmethod type (v:UIntValue) :
- UIntType(width(v))
-
-defmethod type (v:SIntValue) :
- SIntType(width(v))
-
-defn put-type (e:Expression, t:Type) -> Expression :
+defn get-primop-rettype (e:DoPrim) -> Type :
+ defn u() = UIntType(UnknownWidth())
+ defn s() = SIntType(UnknownWidth())
match(e) :
- (e:WRef) : WRef(name(e), t, kind(e), dir(e))
- (e:WField) : WField(exp(e), name(e), t, dir(e))
- (e:WIndex) : WIndex(exp(e), value(e), t, dir(e))
- (e:DoPrim) : DoPrim(op(e), args(e), consts(e), t)
- (e:ReadPort) : ReadPort(mem(e), index(e), t)
- (e) : e
-
-defn lookup-port (ports: Streamable<Port>, port-name: Symbol) :
- for port in ports find :
- name(port) == port-name
-
-defn infer (op:PrimOp, arg-types: List<Type>) -> Type :
- defn wipe-width (t:Type) :
- match(t) :
- (t:UIntType) : UIntType(UnknownWidth())
- (t:SIntType) : SIntType(UnknownWidth())
-
- defn arg0 () : wipe-width(arg-types[0])
- defn arg1 () : wipe-width(arg-types[1])
- ; TODO subtle, not entirely figured out
- switch {op == _} :
- ADD-OP : arg0()
- ADD-MOD-OP : arg0()
- SUB-OP : arg0()
- SUB-MOD-OP : arg0()
- TIMES-OP : arg0()
- DIVIDE-OP : arg0()
- MOD-OP : arg0()
- SHIFT-LEFT-OP : arg0()
- SHIFT-RIGHT-OP : arg0()
- PAD-OP : arg0()
- BIT-AND-OP : arg0()
- BIT-OR-OP : arg0()
- BIT-XOR-OP : arg0()
- CONCAT-OP : arg0()
- BIT-SELECT-OP : UIntType(UnknownWidth())
- BITS-SELECT-OP : arg0()
- MULTIPLEX-OP : arg0()
- LESS-OP : UIntType(UnknownWidth())
- LESS-EQ-OP : UIntType(UnknownWidth())
- GREATER-OP : UIntType(UnknownWidth())
- GREATER-EQ-OP : UIntType(UnknownWidth())
- EQUAL-OP : UIntType(UnknownWidth())
-
-defn bundle-field-type (t:Type, n:Symbol) -> Type :
- match(t) :
- (t:BundleType) :
- match(lookup-port(ports(t), n)) :
- (p:Port) : type(p)
- (p) : UnknownType()
- (t) : UnknownType()
-
-defn vector-elem-type (t:Type) -> Type :
- match(t) :
- (t:VectorType) : type(t)
- (t) : UnknownType()
-
-;e is the environment that contains all definitions seen so far.
-defn infer (c:Stmt, e:List<KeyValue<Symbol, Type>>) -> [Stmt, List<KeyValue<Symbol,Type>>] :
- defn infer-exp (e:Expression, env:List<KeyValue<Symbol,Type>>) :
- match(map(infer-exp{_, env}, e)) :
- (e:WRef) :
- put-type(e, lookup!(env, name(e)))
- (e:WField) :
- put-type(e, bundle-field-type(type(exp(e)), name(e)))
- (e:WIndex) :
- put-type(e, vector-elem-type(type(exp(e))))
- (e:UIntValue) : e
- (e:SIntValue) : e
- (e:DoPrim) :
- put-type(e, infer(op(e), map(type, args(e))))
- (e:ReadPort) :
- put-type(e, vector-elem-type(type(mem(e))))
- (e:Null) : e
-
- defn element-type (e:Element, env:List<KeyValue<Symbol,Type>>) :
- match(e) :
- (e:Instance) :
- val t = type(infer-exp(module(e), env))
- match(t) :
- (t:BundleType) :
- BundleType $ to-list $
- for p in ports(t) filter :
- direction(p) == OUTPUT
- (t) : UnknownType()
- (e) : type(e)
-
- match(c) :
- (c:LetRec) :
- val e* = append(elem-types, e) where :
- val elem-types =
- for entry in entries(c) map :
- key(entry) => element-type(value(entry), e)
- val c* = map(infer-exp{_, e*}, c)
- val [body*, be] = infer(body(c*), e*)
- [LetRec(entries(c*), body*), e]
- (c) :
- match(map(infer-exp{_, e}, c)) :
- (c:DefWire) :
- [c, List(entry, e)] where :
- val entry = name(c) => type(c)
- (c:DefRegister) :
- [c, List(entry, e)] where :
- val entry = name(c) => type(c)
- (c:DefInstance) :
- [c, List(entry, e)] where :
- val entry = name(c) => type(module(c))
- (c:DefMemory) :
- [c, List(entry, e)] where :
- val entry = name(c) => type(c)
- (c:WDefAccessor) :
- [c, List(entry, e)] where :
- val src-type = type(source(c))
- val entry = name(c) => vector-elem-type(src-type)
- (c:Begin) :
- var current-e: List<KeyValue<Symbol,Type>> = e
- val body* = for c in body(c) map :
- val [c*, e*] = infer(c, current-e)
- current-e = e*
- c*
- [Begin(body*), current-e]
- (c) :
- defn infer-comm (c:Stmt) :
- val [c* e*] = infer(c, e)
- c*
- val c* = map(infer-comm, c)
- [c*, e]
-
-defn infer (m:Module, e:List<KeyValue<Symbol, Type>>) -> Module :
- val env = append{_, e} $
+ (e:ADD-OP ) : u()
+ (e:ADD-UU-OP ) : u()
+ (e:ADD-US-OP ) : s()
+ (e:ADD-SU-OP ) : s()
+ (e:ADD-SS-OP ) : s()
+ (e:SUB-OP ) : s()
+ (e:SUB-UU-OP ) : s()
+ (e:SUB-US-OP ) : s()
+ (e:SUB-SU-OP ) : s()
+ (e:SUB-SS-OP ) : s()
+ (e:TIMES-OP ) : u()
+ (e:TIMES-UU-OP ) : u()
+ (e:TIMES-US-OP ) : s()
+ (e:TIMES-SU-OP ) : s()
+ (e:TIMES-SS-OP ) : s()
+ (e:DIVIDE-OP ) : u()
+ (e:DIVIDE-UU-OP ) : u()
+ (e:DIVIDE-US-OP ) : s()
+ (e:DIVIDE-SU-OP ) : s()
+ (e:DIVIDE-SS-OP ) : s()
+ (e:MOD-OP ) : u()
+ (e:MOD-UU-OP ) : s()
+ (e:MOD-US-OP ) : s()
+ (e:MOD-SU-OP ) : s()
+ (e:MOD-SS-OP ) : s()
+ (e:QUOTIENT-OP ) : u()
+ (e:QUOTIENT-UU-OP ) : u()
+ (e:QUOTIENT-US-OP ) : s()
+ (e:QUOTIENT-SU-OP ) : s()
+ (e:QUOTIENT-SS-OP ) : s()
+ (e:REMAINDER-OP ) : u()
+ (e:REMAINDER-UU-OP ) : u()
+ (e:REMAINDER-US-OP ) : s()
+ (e:REMAINDER-SU-OP ) : u()
+ (e:REMAINDER-SS-OP ) : s()
+ (e:ADD-WRAP-OP ) : u()
+ (e:ADD-WRAP-UU-OP ) : u()
+ (e:ADD-WRAP-US-OP ) : s()
+ (e:ADD-WRAP-SU-OP ) : s()
+ (e:ADD-WRAP-SS-OP ) : s()
+ (e:SUB-WRAP-OP ) : u()
+ (e:SUB-WRAP-UU-OP ) : u()
+ (e:SUB-WRAP-US-OP ) : s()
+ (e:SUB-WRAP-SU-OP ) : s()
+ (e:SUB-WRAP-SS-OP ) : s()
+ (e:LESS-OP ) : u()
+ (e:LESS-UU-OP ) : u()
+ (e:LESS-US-OP ) : u()
+ (e:LESS-SU-OP ) : u()
+ (e:LESS-SS-OP ) : u()
+ (e:LESS-EQ-OP ) : u()
+ (e:LESS-EQ-UU-OP ) : u()
+ (e:LESS-EQ-US-OP ) : u()
+ (e:LESS-EQ-SU-OP ) : u()
+ (e:LESS-EQ-SS-OP ) : u()
+ (e:GREATER-OP ) : u()
+ (e:GREATER-UU-OP ) : u()
+ (e:GREATER-US-OP ) : u()
+ (e:GREATER-SU-OP ) : u()
+ (e:GREATER-SS-OP ) : u()
+ (e:GREATER-EQ-OP ) : u()
+ (e:GREATER-EQ-UU-OP ) : u()
+ (e:GREATER-EQ-US-OP ) : u()
+ (e:GREATER-EQ-SU-OP ) : u()
+ (e:GREATER-EQ-SS-OP ) : u()
+ (e:EQUAL-OP ) : u()
+ (e:EQUAL-UU-OP ) : u()
+ (e:EQUAL-SS-OP ) : u()
+ (e:MULTIPLEX-OP ) : u()
+ (e:MULTIPLEX-UU-OP ) : u()
+ (e:MULTIPLEX-SS-OP ) : s()
+ (e:PAD-OP ) : u()
+ (e:PAD-U-OP ) : u()
+ (e:PAD-S-OP ) : s()
+ (e:AS-UINT-OP ) : u()
+ (e:AS-UINT-U-OP ) : u()
+ (e:AS-UINT-S-OP ) : u()
+ (e:AS-SINT-OP ) : s()
+ (e:AS-SINT-U-OP ) : s()
+ (e:AS-SINT-S-OP ) : s()
+ (e:SHIFT-LEFT-OP ) : u()
+ (e:SHIFT-LEFT-U-OP ) : u()
+ (e:SHIFT-LEFT-S-OP ) : s()
+ (e:SHIFT-RIGHT-OP ) : u()
+ (e:SHIFT-RIGHT-U-OP ) : u()
+ (e:SHIFT-RIGHT-S-OP ) : u()
+ (e:CONVERT-OP ) : u()
+ (e:CONVERT-U-OP ) : u()
+ (e:CONVERT-S-OP ) : u()
+ (e:BIT-AND-OP ) : u()
+ (e:BIT-OR-OP ) : u()
+ (e:BIT-XOR-OP ) : u()
+ (e:CONCAT-OP ) : u()
+ (e:BIT-SELECT-OP ) : u()
+ (e:BITS-SELECT-OP ) : u()
+
+defn type (m:Module) -> Type :
+ BundleType(ports(module(s)))
+
+defn get-type (b:Symbol,l:List<KeyValue<Symbol,Type>>) -> Type :
+ val contains? = for kv in l any? : b == key(kv)
+ if contains? :
+ label<Type> myret :
+ for kv in l do :
+ if b == key(kv) : myret(value(kv))
+ else : UnknownType()
+
+defn get-bundle-subtype (v:Type,s:Symbol) -> Type :
+ match(v) :
+ (v:BundleType) :
+ val contains? = for p in ports(v) any? : name(p) == s
+ if contains? :
+ label<Type> myret :
+ for p in ports(v) do :
+ if b == name(p) : myret(type(p))
+ else : UnknownType()
+ (v) : UnknownType()
+
+defn get-vector-subtype (v:Type) -> Type :
+ match(v) :
+ (v:VectorType) : type(v)
+ (v) : UnknownType()
+
+defn infer-types (e:Expression, l:List<KeyValue<Symbol,Type>>) -> Expression :
+ match(map(infer-types{_,l},e)) :
+ (e:WRef) : WRef(name(e), get-type(name(e),l))
+ (e:WField) : WField(exp(e),name(e), get-bundle-subtype(type(exp(e))))
+ (e:WIndex) : WIndex(exp(e),name(e), get-vector-subtype(type(exp(e))))
+ (e:DoPrim) : DoPrim(op(e),args(e),consts(e),get-primop-rettype(e))
+ (e:ReadPort) : ReadPort(mem(e),index(e),get-vector-subtype(type(mem(e))))
+ (e:UIntValue|SIntValue|Null) : e
+
+defn infer-types (s:Stmt, l:List<KeyValue<Symbol,Type>>) -> [Stmt, List<KeyValue<Symbol,Type>>]
+ match(map(infer-types{_,l},s)) :
+ (s:LetRec) : [s,l] ;TODO, this is wrong but we might be getting rid of letrecs?
+ (s:Begin) :
+ var env = l
+ val body* =
+ for s in body(s) map :
+ val [s*,l*] = infer-types(s,env)
+ env = l*
+ s*
+ [Begin(body*),env]
+ (s:DefWire|DefRegister|DefMemory) : [s,List(name(s) => type(s),l)]
+ (s:DefInstance) : [s, List(name(s) => type(module(s)),l)]
+ (s:DefNode) : [s, List(name(s) => type(value(s)),l)]
+ (s:WDefAccessor) : [s, List(name(s) => type(source(s)),l)]
+ (s:Conditionally|Connect|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)
- val [body*, e*] = infer(body(m), env)
- Module(name(m), ports(m), body*)
+ infer-types(body(m),append(ptypes, l))
defn infer-types (c:Circuit) -> Circuit :
- val env =
+ val l =
for m in modules(c) map :
name(m) => BundleType(ports(m))
- Circuit(map(infer{_, env}, modules(c)),
- main(c))
+ Circuit{ _, main(c) } $
+ for m in modules(c) map :
+ infer-types(m,l)
+
;============= INFER DIRECTIONS ============================
defn flip (d:Direction) :
diff --git a/test/passes/infer-types/primops.fir b/test/passes/infer-types/primops.fir
index 244853cf..2a29efbf 100644
--- a/test/passes/infer-types/primops.fir
+++ b/test/passes/infer-types/primops.fir
@@ -3,8 +3,114 @@
;CHECK: Infer Types
circuit top :
module top :
- wire io : {input x : UInt, output y : UInt}
- node a = io.x
-;CHECK: wire io : {input x : UInt@<t:UInt>, output y : UInt@<t:UInt>}@<t:{input x : UInt@<t:UInt>, output y : UInt@<t:UInt>}>
-;CHECK: node a = io@<t:{input x : UInt@<t:UInt>, output y : UInt@<t:UInt>}>.x@<t:UInt>
+ wire a : UInt(16)
+ wire b : UInt(8)
+ wire c : SInt(16)
+ wire d : SInt(8)
+
+ ;add
+ module add :
+ node w = adduu(a,b) ;CHECK: node w = adduu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = addus(a,d) ;CHECK: node x = addus(a@<t:UInt>,d@<t:SInt>)@<t:SInt>
+ node y = addsu(c,b) ;CHECK: node y = addsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = addss(c,d) ;CHECK: node z = addss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;sub
+ module sub :
+ node w = subuu(a,b) ;CHECK: node w = subuu(a@<t:UInt>,b@<t:UInt>)@<t:SInt>
+ node x = subus(a,d) ;CHECK: node x = subus(a@<t:UInt>,d@<t:SInt>)@<t:SInt>
+ node y = subsu(c,b) ;CHECK: node y = subsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = subss(c,d) ;CHECK: node z = subss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;mul
+ module mul :
+ node w = muluu(a,b) ;CHECK: node w = muluu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = mulus(a,d) ;CHECK: node x = mulus(a@<t:UInt>,d@<t:SInt>)@<t:SInt>
+ node y = mulsu(c,b) ;CHECK: node y = mulsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = mulss(c,d) ;CHECK: node z = mulss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;div
+ module div :
+ node w = divuu(a,b) ;CHECK: node w = divuu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = divus(a,d) ;CHECK: node x = divus(a@<t:UInt>,d@<t:SInt>)@<t:SInt>
+ node y = divsu(c,b) ;CHECK: node y = divsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = divss(c,d) ;CHECK: node z = divss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;mod
+ module mod :
+ node w = moduu(a,b) ;CHECK: node w = moduu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = modus(a,d) ;CHECK: node x = modus(a@<t:UInt>,d@<t:SInt>)@<t:SInt>
+ node y = modsu(c,b) ;CHECK: node y = modsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = modss(c,d) ;CHECK: node z = modss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;rem
+ module rem :
+ node w = remuu(a,b) ;CHECK: node w = remuu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = remus(a,d) ;CHECK: node x = remus(a@<t:UInt>,d@<t:SInt>)@<t:SInt>
+ node y = remsu(c,b) ;CHECK: node y = remsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = remss(c,d) ;CHECK: node z = remss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;add-mod
+ module add-mod :
+ node w = add-moduu(a,b) ;CHECK: node w = add-moduu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = add-modus(a,d) ;CHECK: node x = add-modus(a@<t:UInt>,d@<t:SInt>)@<t:UInt>
+ node y = add-modsu(c,b) ;CHECK: node y = add-modsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = add-modss(c,d) ;CHECK: node z = add-modss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;sub-mod
+ module sub-mod :
+ node w = sub-moduu(a,b) ;CHECK: node w = sub-moduu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = sub-modus(a,d) ;CHECK: node x = sub-modus(a@<t:UInt>,d@<t:SInt>)@<t:UInt>
+ node y = sub-modsu(c,b) ;CHECK: node y = sub-modsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = sub-modss(c,d) ;CHECK: node z = sub-modss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;lt
+ module lt :
+ node w = ltuu(a,b) ;CHECK: node w = ltuu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = ltus(a,d) ;CHECK: node x = ltus(a@<t:UInt>,d@<t:SInt>)@<t:UInt>
+ node y = ltsu(c,b) ;CHECK: node y = ltsu(c@<t:SInt>,b@<t:UInt>)@<t:UInt>
+ node z = ltss(c,d) ;CHECK: node z = ltss(c@<t:SInt>,d@<t:SInt>)@<t:UInt>
+ ;leq
+ module leq :
+ node w = lequu(a,b) ;CHECK: node w = lequu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = lequs(a,d) ;CHECK: node x = lequs(a@<t:UInt>,d@<t:SInt>)@<t:UInt>
+ node y = leqsu(c,b) ;CHECK: node y = leqsu(c@<t:SInt>,b@<t:UInt>)@<t:UInt>
+ node z = leqss(c,d) ;CHECK: node z = leqss(c@<t:SInt>,d@<t:SInt>)@<t:UInt>
+ ;gt
+ module gt :
+ node w = gtuu(a,b) ;CHECK: node w = gtuu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = gtus(a,d) ;CHECK: node x = gtus(a@<t:UInt>,d@<t:SInt>)@<t:UInt>
+ node y = gtsu(c,b) ;CHECK: node y = gtsu(c@<t:SInt>,b@<t:UInt>)@<t:UInt>
+ node z = gtss(c,d) ;CHECK: node z = gtss(c@<t:SInt>,d@<t:SInt>)@<t:UInt>
+ ;geq
+ module geq :
+ node w = gequu(a,b) ;CHECK: node w = gequu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = gequs(a,d) ;CHECK: node x = gequs(a@<t:UInt>,d@<t:SInt>)@<t:UInt>
+ node y = geqsu(c,b) ;CHECK: node y = geqsu(c@<t:SInt>,b@<t:UInt>)@<t:UInt>
+ node z = geqss(c,d) ;CHECK: node z = geqss(c@<t:SInt>,d@<t:SInt>)@<t:UInt>
+ ;pad
+ module pad :
+ node w = paduu(a,b) ;CHECK: node w = paduu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = padus(a,d) ;CHECK: node x = padus(a@<t:UInt>,d@<t:SInt>)@<t:UInt>
+ node y = padsu(c,b) ;CHECK: node y = padsu(c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = padss(c,d) ;CHECK: node z = padss(c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;and
+ module and :
+ node w = and(a,b) ;CHECK: node w = and(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ module or :
+ node w = or(a,b) ;CHECK: node w = or(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ module xor :
+ node w = xor(a,b) ;CHECK: node w = xor(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ ;concat
+ node w = concat(a,b) ;CHECK: node w = concat(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ ;equal
+ node w = equaluu(a,b) ;CHECK: node w = equaluu(a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = equalus(a,d) ;CHECK: node x = equalus(a@<t:UInt>,d@<t:SInt>)@<t:UInt>
+ node y = equalsu(c,b) ;CHECK: node y = equalsu(c@<t:SInt>,b@<t:UInt>)@<t:UInt>
+ node z = equalss(c,d) ;CHECK: node z = equalss(c@<t:SInt>,d@<t:SInt>)@<t:UInt>
+ ;mux
+ node w = muxuu(e,a,b) ;CHECK: node w = muxuu(e@<t:UInt>,a@<t:UInt>,b@<t:UInt>)@<t:UInt>
+ node x = muxus(e,a,d) ;CHECK: node x = muxus(e@<t:UInt>,a@<t:UInt>,d@<t:SInt>)@<t:SInt>
+ node y = muxsu(e,c,b) ;CHECK: node y = muxsu(e@<t:UInt>,c@<t:SInt>,b@<t:UInt>)@<t:SInt>
+ node z = muxss(e,c,d) ;CHECK: node z = muxss(e@<t:UInt>,c@<t:SInt>,d@<t:SInt>)@<t:SInt>
+ ;shl
+ ;shr
+ ;bit
+ ;bits
+
+
+
+
;CHECK: Finished Infer Types