def signed(dtype_or_val): if dtype_or_val.signed: return dtype_or_val if is_type(dtype_or_val): if typeof(dtype_or_val, Uint): return cast(dtype_or_val, Int)
def tuple_value_cast_resolver(val, cast_type): if (isinstance(val, (list, tuple, dict)) and not is_type(type(val)) and not cast_type.specified): return cast_type(val) val_type = type(val) cast_type = tuple_type_cast_resolver(val_type, cast_type) return cast_type(tuple(cast(v, ct) for v, ct in zip(val, cast_type)))
def __new__(cls, operands: typing.Sequence[Expr]): if all(isinstance(v, ResExpr) for v in operands): if (all(is_type(v.dtype) for v in operands) and not any(isinstance(v.val, EmptyType) for v in operands)): return ResExpr(Tuple[tuple(v.dtype for v in operands)](tuple( v.val for v in operands))) else: return ResExpr(tuple(v.val for v in operands)) inst = super().__new__(cls) inst.operands = operands return inst
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 type_is_specified(t): if is_type(t): return t.specified if t is None: return True elif isinstance(t, dict): return all(type_is_specified(subt) for subt in t.values()) elif is_type_iterable(t): return all(type_is_specified(subt) for subt in t) elif isinstance(t, bytes): return False else: return True
def int_value_cast_resolver(val, cast_type): val_type = type(val) if not is_type(val_type) and isinstance(val, (int, float)): return cast_type(int(val)) cast_type = int_type_cast_resolver(val_type, cast_type) if typeof(val_type, Fixpnumber): if val_type.fract >= 0: return cast_type.decode(val.code() >> val_type.fract) else: return cast_type.decode(val.code() << (-val_type.fract)) if typeof(val_type, Integer): return cast_type(val) raise get_value_error(val, cast_type)
def dtype(self): if isinstance(self.val, EmptyType): if type(self.val).dtype is None: return EmptyType else: return type(self.val).dtype # if is_type(type(self.val)): # return type(self.val) if not is_type(type(self.val)) and isinstance(self.val, int): return type(Integer(self.val)) # TODO: Remove this if unecessary if isinstance(self.val, Intf): return IntfType[self.val.dtype] return type(self.val)
def register_traces_for_intf(dtype, scope, writer, expand_data=True): # TODO: Refactor this into a class vcd_vars = {'srcs': [], 'srcs_active': [], 'dtype': dtype} if typeof(dtype, TLM) or not is_type(dtype): vcd_vars['data'] = writer.register_var(scope, 'data', 'string') else: if not expand_data: try: vcd_vars['data'] = writer.register_var(scope, 'data', var_type='wire', size=max(dtype.width, 1)) except: vcd_vars['data'] = writer.register_var(scope, 'data', 'string') else: v = VCDTypeVisitor(max_level=10) v.visit(dtype, 'data') for name, t in v.fields.items(): field_scope, _, basename = name.rpartition('.') if field_scope: field_scope = '.'.join((scope, field_scope)) else: field_scope = scope if typeof(t, Float): vcd_vars[name] = writer.register_var(field_scope, basename, var_type='real', size=32) else: vcd_vars[name] = writer.register_var(field_scope, basename, var_type='wire', size=max(t.width, 1)) for sig in ('valid', 'ready'): vcd_vars[sig] = writer.register_var(scope, sig, 'wire', size=1, init=0) return vcd_vars
def cast(data, cast_type): if is_type(data): return type_cast(data, cast_type) else: return value_cast(data, cast_type)
def infer_ftypes(params, args, namespace={}): # Add all registered objects (types and transformations) to the namespace namespace = dict(namespace) namespace.update(reg['gear/type_arith']) def is_postponed(name, val): if isinstance(val, bytes): return True if (name in args): return True if (name == 'return'): return not type_is_specified(val) return False postponed = {name: val for name, val in params.items() if is_postponed(name, val)} match = {name: val for name, val in params.items() if name not in postponed} substituted = True final_check = False # Allow for keyword argument values to be templates and provide # a mechanism to resolve these template arguments while substituted or final_check: substituted = False # Loops until none of the parameters has been additionally resolved for name, val in postponed.copy().items(): if name in args: try: templ = val if isinstance(val, bytes): templ = templ.decode() match_update, res = get_match_conds(args[name], templ, match) match.update(match_update) args[name] = res if type_is_specified(res): if is_type(res): res = copy_field_names(res, params[name]) args[name] = res match[name] = res del postponed[name] substituted = True break else: postponed[name] = res except TypeMatchError as e: err = TypeMatchError( f'{str(e)}\n - when deducing type for argument ' f'"{name}"') err.params = match raise err else: try: substituted, new_p = resolve_param(val, match, namespace) if substituted and (name == 'return'): substituted = type_is_specified(new_p) if substituted: if name == 'return': substituted = type_is_specified(new_p) match[name] = new_p del postponed[name] break elif final_check: if new_p is not None: raise TypeMatchError(f'Incomplete type: {repr(new_p)}') else: raise TypeMatchError(f'Incomplete type: {repr(val)}') except Exception as e: if final_check: try: arg_repr = str(e.args[0]) except: arg_repr = repr(e.args[0]) if isinstance(val, bytes): val_repr = val.decode() else: try: val_repr = str(val) except: val_repr = repr(val) if name == 'return': err = type(e)( f'{arg_repr}\n - when resolving ' f'return type "{val_repr}"') else: err = type(e)( f'{arg_repr}\n - when resolving ' f'parameter "{name}": "{val_repr}"') err.params = match raise err final_check = not substituted and not final_check # print('Final postponed: ', postponed) # print('Final match: ', match) for name, val in args.items(): get_match_conds(val, match[name], {}) if postponed: name, value = next(iter(postponed.items())) err = TypeMatchError(f'Parameter "{name}" unresolved: {value}') err.params = match raise err return match