;Copyright (c) 2014 - 2016 The Regents of the University of ;California (Regents). All Rights Reserved. Redistribution and use in ;source and binary forms, with or without modification, are permitted ;provided that the following conditions are met: ; * Redistributions of source code must retain the above ; copyright notice, this list of conditions and the following ; two paragraphs of disclaimer. ; * Redistributions in binary form must reproduce the above ; copyright notice, this list of conditions and the following ; two paragraphs of disclaimer in the documentation and/or other materials ; provided with the distribution. ; * Neither the name of the Regents nor the names of its contributors ; may be used to endorse or promote products derived from this ; software without specific prior written permission. ;IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, ;SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ;ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ;REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT ;LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ;A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ;ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION ;TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR ;MODIFICATIONS. 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) defn MIN (w1:Width,w2:Width) -> Width : MinWidth(list(w1,w2)) 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() 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(),ONE)) (t1:SIntType, t2:UIntType) : SIntType(w1()) (t1:SIntType, t2:SIntType) : SIntType(PLUS(w1(),ONE)) (t1, t2) : UnknownType() REM-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType, t2:UIntType) : UIntType(MIN(w1(),w2())) (t1:UIntType, t2:SIntType) : UIntType(MIN(w1(),w2())) (t1:SIntType, t2:UIntType) : SIntType(MIN(w1(),PLUS(w2(),ONE))) (t1:SIntType, t2:SIntType) : SIntType(MIN(w1(),w2())) (t1, t2) : UnknownType() LESS-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : BoolType() (t1, t2) : UnknownType() LESS-EQ-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : BoolType() (t1, t2) : UnknownType() GREATER-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : BoolType() (t1, t2) : UnknownType() GREATER-EQ-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : BoolType() (t1, t2) : UnknownType() EQUAL-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : BoolType() (t1, t2) : UnknownType() NEQUAL-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : BoolType() (t1, t2) : UnknownType() PAD-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(MAX(w1(),c1())) (t1:SIntType) : SIntType(MAX(w1(),c1())) (t1) : UnknownType() AS-UINT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : UIntType(w1()) (t1:SIntType) : UIntType(w1()) (t1:ClockType) : UIntType(ONE) (t1) : UnknownType() AS-SINT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : SIntType(w1()) (t1:SIntType) : SIntType(w1()) (t1:ClockType) : SIntType(ONE) (t1) : UnknownType() AS-CLOCK-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType) : ClockType() (t1:SIntType) : ClockType() (t1:ClockType) : ClockType() (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(PLUS(w1(),ONE)) (t1) : UnknownType() NOT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType|SIntType) : UIntType(w1()) (t1) : UnknownType() AND-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : UIntType(MAX(w1(),w2())) (t1,t2) : UnknownType() OR-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : UIntType(MAX(w1(),w2())) (t1,t2) : UnknownType() XOR-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : UIntType(MAX(w1(),w2())) (t1,t2) : UnknownType() AND-REDUCE-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType|SIntType) : BoolType() (t1) : UnknownType() OR-REDUCE-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType|SIntType) : BoolType() (t1) : UnknownType() XOR-REDUCE-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType|SIntType) : BoolType() (t1) : UnknownType() CONCAT-OP : DoPrim{o,a,c,_} $ match(t1(),t2()) : (t1:UIntType|SIntType, t2:UIntType|SIntType) : UIntType(PLUS(w1(),w2())) (t1, t2) : UnknownType() BITS-SELECT-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType|SIntType) : UIntType(PLUS(MINUS(c1(),c2()),ONE)) (t1) : UnknownType() HEAD-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType|SIntType) : UIntType(c1()) (t1) : UnknownType() TAIL-OP : DoPrim{o,a,c,_} $ match(t1()) : (t1:UIntType|SIntType) : UIntType(MINUS(w1(),c1())) (t1) : UnknownType() ;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]) ; 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]) ; 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") ;