def test_ufixp_type_cast(): assert cast(Ufixp[8, 16], Int) == Int[9] assert cast(Ufixp[8, 16], Int[16]) == Int[16] assert cast(Ufixp[16, 8], Int) == Int[17] with pytest.raises(TypeError): cast(Ufixp[-1, 16], Int)
def test_supported_type_cast(): for t in [Int[6], Fixp[1, 14], Ufixp[0, 13]]: assert cast(t, Float) == Float for t in [Tuple[Int[2], Uint[2]]]: with pytest.raises(TypeError): cast(t, Float)
def test_tuple_type_cast(): assert cast(Tuple[Uint[4], Uint[2]], Queue) == Queue[Uint[4], 2] with pytest.raises(TypeError): cast(Tuple[Uint[4], Uint[2]], Queue[Uint[2]]) with pytest.raises(TypeError): cast(Tuple[Uint[4], Uint[2]], Queue[Uint[2], 2])
def test_array_type_cast(): assert cast(Array[Uint[4], 3], Tuple) == Tuple[Uint[4], Uint[4], Uint[4]] with pytest.raises(TypeError): cast(Array[Uint[4], 3], Tuple[Uint[4], Uint[4]]) assert cast(Array[Uint[4], 3], Tuple[Int, Int, Int]) == Tuple[Int[5], Int[5], Int[5]] assert cast(Array[Uint[4], 3], Tuple[Int, Uint[4], Int]) == Tuple[Int[5], Uint[4], Int[5]]
def fixp_resolver(opexp, cast_to): cast_to = cast(opexp.dtype, cast_to) val_dtype = opexp.dtype if typeof(val_dtype, Integer): other_cls = Fixp if val_dtype.signed else Ufixp val_dtype = other_cls[val_dtype.width, val_dtype.width] if cast_to is Fixpnumber: return ir.CastExpr(opexp, val_dtype) val_fract = val_dtype.fract fract = cast_to.fract if val_dtype.signed: opexp = ir.CastExpr(opexp, Int[val_dtype.width]) else: opexp = ir.CastExpr(opexp, Uint[val_dtype.width]) if fract > val_fract: shift = ir.BinOpExpr( [opexp, ir.ResExpr(Uint(fract - val_fract))], ir.opc.LShift) else: shift = ir.BinOpExpr( [opexp, ir.ResExpr(Uint(val_fract - fract))], ir.opc.RShift) return ir.CastExpr(shift, cast_to)
def forward_value(target, val): if isinstance(target, ir.Name): if self.res_expr_only and not isinstance(val, ir.ResExpr): return False # if isinstance(val, ir.ResExpr) and getattr( # val.val, 'unknown', False): # return False self.forwarded[target.name] = val return True elif isinstance(target, ir.ConcatExpr): for i, t in enumerate(target.operands): forward_value(t, ir.SubscriptExpr(val, ir.ResExpr(i))) elif isinstance(target, ir.SubscriptExpr): if (isinstance(target.index, ir.ResExpr) and isinstance(val, ir.ResExpr)): base_val = get_forward_value(target.val) if isinstance(base_val, ir.ResExpr): base_val.val[target.index.val] = cast( val.val, base_val.dtype[target.index.val]) return True del_forward_subvalue(target)
def qrange_out_type(cfg): if typeof(cfg, Tuple): base = Int if any(c.signed for c in cfg) else Uint return cast(max(cfg[0], cfg[1]), base) return cfg
def tuple_resolver(opexp, cast_to): cast_to = cast(opexp.dtype, cast_to) cast_fields = [] for i in range(len(opexp.dtype)): field = subscript(opexp, i) cast_fields.append(resolve_cast_func(field, cast_to[i])) return ir.ConcatExpr(cast_fields)
def uint_resolver(opexp, cast_to): cast_to = cast(opexp.dtype, cast_to) if typeof(opexp.dtype, Ufixp): if opexp.dtype.fract >= 0: opexp = ir.BinOpExpr((opexp, ir.ResExpr(opexp.dtype.fract)), ir.opc.RShift) else: opexp = ir.BinOpExpr((opexp, ir.ResExpr(-opexp.dtype.fract)), ir.opc.LShift) return ir.CastExpr(opexp, cast_to)
def test_tuple_type_cast(): assert cast(Tuple[Uint[4], Uint[4], Uint[4]], Array) == Array[Uint[4], 3] with pytest.raises(TypeError): cast(Tuple[Uint[4], Uint[5], Uint[6]], Array) assert cast(Tuple[Uint[6], Uint[4], Uint[4]], Array) == Array[Uint[6], 3] assert cast(Tuple[Uint[4], Uint[4], Uint[4]], Array[Uint[6]]) == Array[Uint[6], 3] with pytest.raises(TypeError): cast(Tuple[Uint[4], Uint[4], Uint[4]], Array[Uint[2]]) assert cast(Tuple[Uint[4], Uint[4], Uint[4]], Array[Uint[6], 3]) == Array[Uint[6], 3] with pytest.raises(TypeError): cast(Tuple[Uint[4], Uint[4], Uint[4]], Array[Uint[4], 2])
def test_uint_type_cast(): assert cast(Uint[8], Int) == Int[9] assert cast(Uint[8], Int[16]) == Int[16] with pytest.raises(TypeError): cast(Uint[8], Int[8]) assert cast(Int[8], Int) == Int[8] assert cast(Int[8], Int[16]) == Int[16] with pytest.raises(TypeError): cast(Int[8], Int[4])
def queue_resolver(opexp, cast_to): cast_to = cast(opexp.dtype, cast_to) if cast_to == opexp.dtype: return opexp return ir.CastExpr( ir.ConcatExpr([ resolve_cast_func(subscript(opexp, 0), cast_to.data), subscript(opexp, 1) ]), cast_to)
def test_queue_type_cast(): assert cast(Queue[Uint[8], 2], Tuple) == Tuple[Uint[8], Uint[2]] assert cast(Queue[Ufixp[8, 16], 2], Tuple[Uint, Uint]) == Tuple[Uint[8], Uint[2]] assert cast(Queue[Ufixp[8, 16], 2], Tuple[Uint[16], Uint]) == Tuple[Uint[16], Uint[2]] with pytest.raises(TypeError): cast(Queue[Ufixp[8, 16], 2], Tuple[Uint]) with pytest.raises(TypeError): cast(Queue[Ufixp[8, 16], 2], Tuple[Uint[4], Uint]) with pytest.raises(TypeError): cast(Queue[Ufixp[8, 16], 2], Tuple[Uint[4], Uint[1]])
def test_ufixp_type_cast(): assert cast(Ufixp[8, 16], Uint) == Uint[8] assert cast(Ufixp[8, 16], Uint[16]) == Uint[16] assert cast(Ufixp[16, 8], Uint) == Uint[16] with pytest.raises(TypeError): cast(Ufixp[8, 16], Uint[4]) with pytest.raises(TypeError): cast(Ufixp[-1, 16], Uint)
def resolve_cast_func(opexp, dtype): if opexp.dtype == dtype: return opexp for templ in resolvers: try: get_match_conds(dtype, templ) return resolvers[templ](opexp, dtype) except TypeMatchError: continue return ir.CastExpr(operand=opexp, cast_to=cast(opexp.dtype, dtype))
def resolve_out_types(out_intfs, out_dtype, gear_inst): if out_intfs and (not out_dtype): out_dtype = tuple(intf.dtype for intf in out_intfs) return out_intfs, out_dtype if out_intfs: if len(out_intfs) != len(out_dtype): relation = 'smaller' if len(out_intfs) < len( out_dtype) else 'larger' raise TypeMatchError( f"Number of actual output interfaces ({len(out_intfs)}) is {relation} " f"than the number of specified output types: ({tuple(getattr(i, 'dtype', type(i)) for i in out_intfs)})" f" vs {repr(out_dtype)}") casted_out_intfs = list(out_intfs) # Try casting interface types upfront to get better error messaging for i, (intf, t) in enumerate(zip(out_intfs, out_dtype)): err = None try: if intf.dtype != t: cast(intf.dtype, t) except (TypeError, TypeMatchError) as e: err = type(e)( f"{str(e)}, when casting type for output port {i}") if err: raise err # If no exceptions occured, do it for real for i, (intf, t) in enumerate(zip(out_intfs, out_dtype)): if intf.dtype != t: from pygears.lib.cast import cast as cast_gear casted_out_intfs[i] = cast_gear(intf, t=t) out_intfs = tuple(casted_out_intfs) return out_intfs, out_dtype return out_intfs, out_dtype
def maybe_resolver(opexp, cast_to): cast_to = cast(opexp.dtype, cast_to) if typeof(opexp.dtype, Tuple): data = resolve_cast_func(ir.SubscriptExpr(opexp, ir.ResExpr(0)), cast_to.dtype) ctrl = resolve_cast_func(ir.SubscriptExpr(opexp, ir.ResExpr(1)), cast_to[1]) return ir.CastExpr(ir.ConcatExpr([data, ctrl]), cast_to) elif typeof(opexp.dtype, Union): return ir.CastExpr(opexp, cast_to) else: breakpoint()
def test_ufixp_value_cast(): assert cast(Ufixp[8, 16](2.15), Uint) == Uint[8](2) assert cast(Ufixp[8, 16](2.15), Uint[16]) == Uint[16](2) with pytest.raises(TypeError): cast(Ufixp[-1, 16](0.15), Uint) assert cast(Ufixp[-1, 16](0.15), Uint[16]) == Uint[16](0) with pytest.raises(TypeError): cast(Ufixp[8, 16](56.15), Uint[4])
def union_resolver(opexp, cast_to): cast_to = cast(opexp.dtype, cast_to) op_data = subscript(opexp, 0) op_ctrl = subscript(opexp, 1) cast_fields = [] uint_data = ir.CastExpr(op_data, Uint[op_data.dtype.width]) cast_fields.append(resolve_cast_func(uint_data, cast_to.data)) cast_fields.append(resolve_cast_func(op_ctrl, cast_to.ctrl)) return ir.CastExpr(ir.ConcatExpr(cast_fields), cast_to)
def test_uint_value_cast(): assert cast(Uint[8](128), Uint[16]) == Uint[16](128) with pytest.raises(TypeError): cast(Uint[16](128), Uint[4]) assert cast(2.15, Uint[4]) == Uint[4](2) assert cast(15, Uint[4]) == Uint[4](15) with pytest.raises(ValueError): cast(27, Uint[4])
def __new__(cls, val): if isinstance(val, Expr): return val inst = super().__new__(cls) # TODO: Think about this automatic casting. For example when register # is inferred based on this value, it might be wrong. ex. "cnt = 0" if not is_type(type(val)) and isinstance(val, (int, float)): val = cast(val, Integer) inst.val = val return inst
def array_resolver(opexp, cast_to): cast_to = cast(opexp.dtype, cast_to) dlen, clen = len(opexp.dtype), len(cast_to) if dlen == clen: cast_fields = [] for i in range(len(opexp.dtype)): field = subscript(opexp, i) cast_fields.append(resolve_cast_func(field, cast_to.data)) else: elen = len(cast_to.data) cast_fields = [] for i in range(len(cast_to)): field = subscript(opexp, slice(elen * i, elen * (i + 1))) cast_fields.append(resolve_cast_func(field, cast_to.data)) return ir.ConcatExpr(cast_fields)
def forward_value(target, val, scope): if isinstance(target, ir.Name): scope[target.name] = val return True elif isinstance(target, ir.Component): scope[f'{target.val.name}.{target.field}'] = val return True elif isinstance(target, ir.ConcatExpr): for i, t in enumerate(target.operands): forward_value(t, ir.SubscriptExpr(val, ir.ResExpr(i)), scope) elif isinstance(target, ir.SubscriptExpr): if (isinstance(target.index, ir.ResExpr) and isinstance(val, ir.ResExpr)): base_val = get_forward_value(target.val, scope) if isinstance(base_val, ir.ResExpr): base_val.val[target.index.val] = cast(val.val, base_val.dtype[target.index.val]) return True else: scope[target.val.name] = target.val
def forward_nonreg_value(target, val, scope): if isinstance(target, ir.Name): if not target.obj.reg or isinstance(val, ir.ResExpr): scope[target.name] = val else: scope[target.name] = ir.Name(target.name, target.obj, ctx='load') return True elif isinstance(target, ir.ConcatExpr): for i, t in enumerate(target.operands): forward_nonreg_value(t, ir.SubscriptExpr(val, ir.ResExpr(i)), scope) elif isinstance(target, ir.SubscriptExpr): if (isinstance(target.index, ir.ResExpr) and isinstance(val, ir.ResExpr)): base_val = get_forward_value(target.val, scope) if isinstance(base_val, ir.ResExpr): base_val.val[target.index.val] = cast(val.val, base_val.dtype[target.index.val]) return True if isinstance(target.index, ir.ResExpr) and target.ctx == 'store': scope[f'{target.val.name}[{int(target.index.val)}]'] = val return True scope[target.val.name] = target.val
def test_tuple_type_cast(): assert cast(Tuple[Uint[4], Uint[1]], Union) == Union[Uint[4], Uint[4]]
def _(node, ctx: Context): if isinstance(node.value, (int, float)): return ir.ResExpr(cast(node.n, Integer)) else: return ir.ResExpr(node.value)
def num(node, ctx: Context): return ir.ResExpr(cast(node.n, Integer))
def test_maybe_type_cast(): assert cast(Union[Unit, Uint[4]], Maybe) == Maybe[Uint[4]]
def uint_resolver(opexp, cast_to): return expr.CastExpr(opexp, cast(opexp.dtype, cast_to))
def int_resolver(opexp, cast_to): cast_to = cast(opexp.dtype, cast_to) if typeof(opexp.dtype, Uint): opexp = ir.CastExpr(opexp, Uint[cast_to.width]) return ir.CastExpr(opexp, cast_to)