defpackage firrtl/primops : import core import verse import firrtl/ir2 import firrtl/ir-utils import firrtl/passes public defn set-primop-type (e:DoPrim) -> DoPrim : ;println-all(["Inferencing primop type: " e]) defn PLUS (w1:Width,w2:Width) -> Width : PlusWidth(w1,w2) defn MAX (w1:Width,w2:Width) -> Width : MaxWidth(list(w1,w2)) defn MINUS (w1:Width,w2:Width) -> Width : MinusWidth(w1,w2) defn POW (w1:Width) -> Width : ExpWidth(w1) val o = op(e) val a = args(e) val c = consts(e) defn t1 () : type(a[0]) defn t2 () : type(a[1]) defn t3 () : type(a[2]) defn w1 () : width!(type(a[0])) defn w2 () : width!(type(a[1])) defn w3 () : width!(type(a[2])) defn c1 () : IntWidth(c[0]) defn c2 () : IntWidth(c[1]) switch {op(e) == _} : ADD-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(PLUS(MAX(w1(),w2()),ONE)) (t1:UIntType, t2:SIntType) : SIntType(PLUS(MAX(w1(),w2()),ONE)) (t1:SIntType, t2:UIntType) : SIntType(PLUS(MAX(w1(),w2()),ONE)) (t1:SIntType, t2:SIntType) : SIntType(PLUS(MAX(w1(),w2()),ONE)) (t1, t2) : UnknownType() SUB-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : SIntType(PLUS(MAX(w1(),w2()),ONE)) (t1:UIntType, t2:SIntType) : SIntType(PLUS(MAX(w1(),w2()),ONE)) (t1:SIntType, t2:UIntType) : SIntType(PLUS(MAX(w1(),w2()),ONE)) (t1:SIntType, t2:SIntType) : SIntType(PLUS(MAX(w1(),w2()),ONE)) (t1, t2) : UnknownType() ADD-WRAP-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(MAX(w1(),w2())) (t1:UIntType, t2:SIntType) : SIntType(MAX(w1(),w2())) (t1:SIntType, t2:UIntType) : SIntType(MAX(w1(),w2())) (t1:SIntType, t2:SIntType) : SIntType(MAX(w1(),w2())) (t1, t2) : UnknownType() SUB-WRAP-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(MAX(w1(),w2())) (t1:UIntType, t2:SIntType) : SIntType(MAX(w1(),w2())) (t1:SIntType, t2:UIntType) : SIntType(MAX(w1(),w2())) (t1:SIntType, t2:SIntType) : SIntType(MAX(w1(),w2())) (t1, t2) : UnknownType() MUL-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(PLUS(w1(),w2())) (t1:UIntType, t2:SIntType) : SIntType(PLUS(w1(),w2())) (t1:SIntType, t2:UIntType) : SIntType(PLUS(w1(),w2())) (t1:SIntType, t2:SIntType) : SIntType(PLUS(w1(),w2())) (t1, t2) : UnknownType() DIV-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(w1()) (t1:UIntType, t2:SIntType) : SIntType(PLUS(w1(),w2())) (t1:SIntType, t2:UIntType) : SIntType(w1()) (t1:SIntType, t2:SIntType) : SIntType(PLUS(w1(),w2())) (t1, t2) : UnknownType() MOD-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(w2()) (t1:UIntType, t2:SIntType) : UIntType(w2()) (t1:SIntType, t2:UIntType) : SIntType(PLUS(w2(),ONE)) (t1:SIntType, t2:SIntType) : SIntType(w2()) (t1, t2) : UnknownType() QUO-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(PLUS(w1(),ONE)) (t1:UIntType, t2:SIntType) : SIntType(w1()) (t1:SIntType, t2:UIntType) : SIntType(PLUS(w1(),ONE)) (t1:SIntType, t2:SIntType) : SIntType(w1()) (t1, t2) : UnknownType() REM-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(w2()) (t1:UIntType, t2:SIntType) : SIntType(w2()) (t1:SIntType, t2:UIntType) : UIntType(PLUS(w2(),ONE)) (t1:SIntType, t2:SIntType) : SIntType(w2()) (t1, t2) : UnknownType() LESS-OP : DoPrim(o,a,c,BoolType()) LESS-EQ-OP : DoPrim(o,a,c,BoolType()) GREATER-OP : DoPrim(o,a,c,BoolType()) GREATER-EQ-OP : DoPrim(o,a,c,BoolType()) EQUAL-OP : DoPrim(o,a,c,BoolType()) NEQUAL-OP : DoPrim(o,a,c,BoolType()) EQUIV-OP : DoPrim(o,a,c,BoolType()) NEQUIV-OP : DoPrim(o,a,c,BoolType()) ;MUX-OP : DoPrim{o,a,c,_} $ ; match(t2(),t3()) : ; (t2:UIntType, t3:UIntType) : UIntType(MAX(w2(),w3())) ; (t2:SIntType, t3:SIntType) : SIntType(MAX(w2(),w3())) ; (t2, t3) : UnknownType() PAD-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(c1()) (t1:SIntType) : SIntType(c1()) (t1) : UnknownType() AS-UINT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(w1()) (t1:SIntType) : UIntType(w1()) (t1) : UnknownType() AS-SINT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : SIntType(w1()) (t1:SIntType) : SIntType(w1()) (t1) : UnknownType() SHIFT-LEFT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(PLUS(w1(),c1())) (t1:SIntType) : SIntType(PLUS(w1(),c1())) (t1) : UnknownType() SHIFT-RIGHT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(MINUS(w1(),c1())) (t1:SIntType) : SIntType(MINUS(w1(),c1())) (t1) : UnknownType() DYN-SHIFT-LEFT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(PLUS(w1(),POW(w2()))) (t1:SIntType) : SIntType(PLUS(w1(),POW(w2()))) (t1) : UnknownType() DYN-SHIFT-RIGHT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(w1()) (t1:SIntType) : SIntType(w1()) (t1) : UnknownType() CONVERT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : SIntType(PLUS(w1(),ONE)) (t1:SIntType) : SIntType(w1()) (t1) : UnknownType() NEG-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : SIntType(PLUS(w1(),ONE)) (t1:SIntType) : SIntType(w1()) (t1) : UnknownType() BIT-NOT-OP : DoPrim(o,a,c,t1()) BIT-AND-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(MAX(w1(),w2())) (t1:SIntType) : SIntType(MAX(w1(),w2())) (t1) : UnknownType() BIT-OR-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(MAX(w1(),w2())) (t1:SIntType) : SIntType(MAX(w1(),w2())) (t1) : UnknownType() BIT-XOR-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(MAX(w1(),w2())) (t1:SIntType) : SIntType(MAX(w1(),w2())) (t1) : UnknownType() BIT-AND-REDUCE-OP : DoPrim(o,a,c,BoolType()) BIT-OR-REDUCE-OP : DoPrim(o,a,c,BoolType()) BIT-XOR-REDUCE-OP : DoPrim(o,a,c,BoolType()) CONCAT-OP : DoPrim(o,a,c,UIntType(PLUS(w1(),w2()))) BIT-SELECT-OP : DoPrim(o,a,c,BoolType()) BITS-SELECT-OP : DoPrim(o,a,c,UIntType(PLUS(MINUS(c1(),c2()),ONE))) ;public defn primop-gen-constraints (e:DoPrim,v:Vector) -> Type : ; defn get-max (i0:Int,i1:Int) -> Width : get-max(list(i0,i1)) ; defn get-max (ls:List) -> Width : ; MaxWidth $ for i in ls map : width!(args(e)[i]) ; defn all-max () -> Width : ; MaxWidth $ for x in args(e) map : width!(x) ; ; println-all-debug(["Looking at " op(e) " with inputs " args(e)]) ; val w* = switch {op(e) == _} : ; ADD-OP : PlusWidth(get-max(0,1),IntWidth(1)) ; SUB-OP : PlusWidth(get-max(0,1),IntWidth(1)) ; MUL-OP : PlusWidth(get-max(0,1),get-max(0,1)) ; DIV-OP : ; match(type(args(e)[0]),type(args(e)[1])) : ; (t0:UIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1)) ; (t0:SIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1)) ; (t0,t1) : width!(args(e)[0]) ; MOD-OP : ; match(type(args(e)[0]),type(args(e)[1])) : ; (t0:SIntType,t1:UIntType) : PlusWidth(width!(args(e)[1]),IntWidth(1)) ; (t0,t1) : width!(args(e)[1]) ; QUO-OP : ; match(type(args(e)[0]),type(args(e)[1])) : ; (t0:UIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1)) ; (t0:SIntType,t1:SIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1)) ; (t0,t1) : width!(args(e)[0]) ; REM-OP : ; match(type(args(e)[0]),type(args(e)[1])) : ; (t0:SIntType,t1:UIntType) : PlusWidth(width!(args(e)[1]),IntWidth(1)) ; (t0,t1) : width!(args(e)[1]) ; ADD-WRAP-OP : get-max(0,1) ; SUB-WRAP-OP : get-max(0,1) ; LESS-OP : IntWidth(1) ; LESS-EQ-OP : IntWidth(1) ; GREATER-OP : IntWidth(1) ; GREATER-EQ-OP : IntWidth(1) ; EQUAL-OP : IntWidth(1) ; NEQUAL-OP : IntWidth(1) ; EQUIV-OP : IntWidth(1) ; NEQUIV-OP : IntWidth(1) ; MUX-OP : ; add(v,WGeq(IntWidth(1),width!(args(e)[0]))) ; add(v,WGeq(width!(args(e)[0]),IntWidth(1))) ; get-max(1,2) ; PAD-OP : IntWidth(consts(e)[0]) ; AS-UINT-OP : width!(args(e)[0]) ; AS-SINT-OP : width!(args(e)[0]) ; SHIFT-LEFT-OP : PlusWidth(width!(args(e)[0]),IntWidth(consts(e)[0])) ; SHIFT-RIGHT-OP : MinusWidth(width!(args(e)[0]),IntWidth(consts(e)[0])) ; DYN-SHIFT-LEFT-OP : PlusWidth(width!(args(e)[0]),ExpWidth(width!(args(e)[1]))) ; DYN-SHIFT-RIGHT-OP : width!(args(e)[0]) ; CONVERT-OP : ; match(type(args(e)[0])) : ; (t0:UIntType) : PlusWidth(width!(args(e)[0]),IntWidth(1)) ; (t0:SIntType) : width!(args(e)[0]) ; NEG-OP : PlusWidth(width!(args(e)[0]),IntWidth(1)) ; BIT-NOT-OP : width!(args(e)[0]) ; BIT-AND-OP : get-max(0,1) ; BIT-OR-OP : get-max(0,1) ; BIT-XOR-OP : get-max(0,1) ; BIT-AND-REDUCE-OP : all-max() ; BIT-OR-REDUCE-OP : all-max() ; BIT-XOR-REDUCE-OP : all-max() ; CONCAT-OP : PlusWidth(width!(args(e)[0]),width!(args(e)[1])) ; BIT-SELECT-OP : IntWidth(1) ; BITS-SELECT-OP : IntWidth(consts(e)[0] - consts(e)[1] + 1) ; ; match(type(e)) : ; (t:UIntType) : UIntType(w*) ; (t:SIntType) : SIntType(w*) ; (t) : error("Shouldn't be here") ;