def infer_dtype(val, dtype): if is_type(type(val)): return type(val) if not is_type(dtype) or typeof(dtype, Any): if isinstance(val, int): if val < 0: return type(Int(val)) else: return type(Uint(val)) if dtype.specified: return dtype return type(dtype.base(val))
def fixp_type_trunc_resolver(cast_type: FixpnumberType, dtype): if not is_type(dtype) or dtype.base != cast_type.base: raise TypeError( f"cannot truncate type '{repr(dtype)}' to a type '{repr(cast_type)}'" f" of a different base type") return cast_type
def pipeline(din, *, length, feedback=False, init=None) -> b'din': if init is None: init = [] if is_type(init) or not isinstance(init, (list, tuple)): init = [init] * length if feedback: if init: stage_init = init[0] init.pop(0) else: stage_init = None din = decouple(din, init=stage_init) length -= 1 inputs = [din] for i in range(length): if init: stage_init = init[0] init.pop(0) else: stage_init = None dout = dreg(inputs.pop(0), init=stage_init) inputs.append(dout) return inputs.pop(0)
def _(node, ctx: Context): targets = visit_ast(node.target, ctx) annotation = visit_ast(node.annotation, ctx) if not (isinstance(annotation, ir.ResExpr) or isinstance(annotation.val, type) or is_type(annotation.val)): raise SyntaxError( f'Variable annotation has to be a type, not "{annotation}"') if node.value is None: output_port_shadow_check(targets.name, ctx) ctx.scope[targets.name] = ir.Variable(targets.name, annotation.val) return if node.value: init = visit_ast(node.value, ctx) init_cast = ir.CastExpr(init, annotation.val) stmts = assign_targets(ctx, targets, init_cast) if not isinstance(stmts, list): stmts = [stmts] # for s in stmts: # s.target.obj.val = s.val # if init.val is None or getattr(init.val, 'unknown', False): # s.target.obj.any_init = True return stmts
def infer_targets(ctx, target, source): dtype = source.dtype if isinstance(target, ir.Name): ctx.alias_map[target.name] = source if target.name not in ctx.scope: var = ir.Variable(target.name, dtype, reg=target.name in ctx.registers) ctx.scope[target.name] = var target.obj = var else: output_port_shadow_check(target.name, ctx) elif isinstance(target, ir.ConcatExpr): # We can only make this check if the value is recognized PyGears type. # If it is some random Python type, just hope for the best if is_type(dtype) and len(dtype) != len(target.operands): raise SyntaxError( f'Cannot unpack value of type "{dtype!r}" with {len(dtype)} component(s) into {len(target.operands)} variables: ' f'"{target}".') for i, t in enumerate(target.operands): infer_targets(ctx, t, ir.SubscriptExpr(source, ir.ResExpr(i))) elif isinstance(target, ir.SubscriptExpr): # # TODO: can we do some check here? if isinstance(target.val, ir.Name): ctx.alias_map[target.val.name] = ctx.ref(target.val.name) else: breakpoint()
def shr_or_code(x, y): if is_type(y): if typeof(y, Uint) and (not y.specified): y = Uint[x.dtype.width] return code(x, t=y) else: return shr(x, shamt=y)
def integer_type_trunc_resolver(cast_type: IntegerType, dtype): if dtype is int: return cast_type if not is_type(dtype) or dtype.base != cast_type.base: raise TypeError( f"cannot truncate type '{repr(dtype)}' to a type '{repr(cast_type)}'" f" of a different base type") return cast_type
def dtype(self): # 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)) if isinstance(self.val, Intf): return IntfType[self.val.dtype] return type(self.val)
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): 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 dtype(self): # 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 vgen_signal(dtype, vtype, name, direction, hier=True): if isinstance(dtype, str): return f'{dtype} {name};' if is_type(dtype) and dtype.width == 0: return f'{vtype} [0:0] {name};' if not hier: if is_type(dtype): width = dtype.width sign = 'signed' if getattr(dtype, 'signed', False) else '' elif isinstance(dtype, (tuple, list)): width = sum(d.width for d in dtype) sign = '' return f'{vtype} {sign} [{width-1}:0] {name}; // {dtype}' vis = VGenTypeVisitor(name, basic_type=vtype, direction=direction, hier=hier) return '\n'.join(vis.visit(type_=dtype, field=name))
def field_names_eq(a, b): if not hasattr(a, 'fields'): return True if a.fields != b.fields: return False for aa, ab in zip(a.args, b.args): if not is_type(aa): continue if not field_names_eq(aa, ab): return False return True
def description(self): tooltip = '<b>{}</b><br/><br/>'.format(self.name) pp = pprint.PrettyPrinter(indent=4, width=30) fmt = pp.pformat def _pprint_list(self, object, stream, indent, allowance, context, level): if len(object) > 5: object = object[:5] + ['...'] pprint.PrettyPrinter._pprint_list(self, object, stream, indent, allowance, context, level) pp._dispatch[list.__repr__] = _pprint_list table = [] for name, val in self.rtl.params.items(): name_style = 'style="font-weight:bold" nowrap' val_style = '' if name == 'definition': val = val.func.__name__ val_style = 'style="font-weight:bold"' elif inspect.isclass(val) and not is_type(val): val = val.__name__ elif name not in registry('gear/params/extra').keys(): # if isinstance(val, (list, tuple)) and len(val) > 5: # val = fmt(val[:2]) + '\n...' val = highlight(fmt(val), 'py', add_style=False) else: continue table.append([(name_style, name), (val_style, val)]) table_style = """ <style> td { padding-left: 10px; padding-right: 10px; } </style> """ tooltip += table_style tooltip += tabulate(table, 'style="padding-right: 10px;"') return tooltip
def visit_SubscriptExpr(self, node): val = self.visit(node.val) if isinstance(node.index, slice): return f'{val}[{int(node.index.stop) - 1}:{node.index.start}]' dtype = node.val.dtype if typeof(dtype, Array): index = self.visit(node.index) return f'{val}_arr[{index}]' elif typeof(dtype, Number): return f'{val}[{self.visit(node.index)}]' elif is_type(dtype): return f'{val}_{dtype.fields[node.index]}' else: raise Exception('Unable to subscript')
def svgen_typedef(dtype, name, depth=4): # TODO: if a variable is called "wr", of the type that has a composite # field "data", than struct for that field will be called "wr_data_t". If # there is a variable "wr_data" in same module, it will also have the type # called "wr_data_t". This can be in conflict when the type definitions are # added for verilator debugging. Maybe think of a different scheme to name # subtypes if isinstance(dtype, str): return f'typedef {dtype} {name}_t;' assert is_type(dtype) if dtype.width == 0: return f'typedef logic [0:0] {name}_t;' vis = SVGenTypeVisitor(name, depth=depth) vis.visit(type_=dtype, field=name) return '\n'.join(vis.struct_array)
def integral_saturate_resolver(t, data: Integral, limits=None): if not is_type(type(data)) and isinstance(data, int): conv_data = Integer(data) else: conv_data = data idin = code(data) if type(conv_data).signed == t.signed and type(conv_data).width <= t.width: if type(conv_data).signed: sign = code(data, int) >> (type(conv_data).width - 1) sign_exten = Uint[t.width - type(conv_data).width].max if sign else 0 return t.decode((sign_exten << type(conv_data).width) | code(data, int)) else: return code(conv_data, t) elif type(conv_data).signed and not t.signed: if idin[t.width:] == 0: return code(conv_data, t) elif conv_data < 0: return 0 else: return t.max elif type(conv_data).signed and t.signed: # TODO: This 0 is not typecast, check why that happens if ((idin[t.width - 1:] == 0) or (idin[t.width - 1:] == Uint[type(conv_data).width - t.width + 1].max)): return code(conv_data, t) elif idin[-1]: return t.min else: return t.max else: if type(conv_data).width <= t.width or idin[t.width:] == 0: return code(conv_data, t) else: return t.max
def params(self): if not self.impl_params: return {} params = {} for k, v in self.node.params.items(): param_name = k.upper() param_valid_name = f'{param_name}_VALID' if (param_name in self.impl_params): if v is None: if param_valid_name in self.impl_params: params[param_valid_name] = 0 continue if is_type(v): v = max(v.width, 1) err = None try: v = code(v, int) except: err = ValueError( f'Cannot encode value "{v}" as integer, passed for HDL parameter "{param_name}"\n' f' - when instantiating module "{self.node.name}"') if err: raise err if (code(v, int) != int(self.impl_params[param_name]['val'])): params[param_name] = code(v, int) if param_valid_name in self.impl_params: params[param_valid_name] = 1 return params
def resolve_func(func, args, kwds, ctx): if is_type(func): if const_func_args(args, kwds): return resolve_compile_time(func, args, kwds) return resolve_cast_func(args[0], func) hashable_func = hashable(func) if isinstance(func, partial): args = func.args + tuple(args) func = func.func elif not inspect.isbuiltin(func) and hasattr(func, '__self__'): if func is super: if not isinstance(ctx, FuncContext): raise Exception(f'super() called outside a method function') f = ctx.funcref.func obj = ctx.ref('self') cls = get_class_that_defined_method(f).__base__ return ir.ResExpr(Super(cls, obj)) elif getattr(func, '__func__', None) in reg['hls/ir_builtins']: val = func.__self__ for name, v in ctx.scope.items(): if val is v.val: val = ctx.ref(name) break return reg['hls/ir_builtins'][func.__func__](val, *args, **kwds) elif const_func_args(args, kwds): return resolve_compile_time(func, args, kwds) elif is_type(func.__self__): if func.__name__ == 'decode': return ir.CastExpr(args[0], ir.ResExpr(func.__self__)) else: breakpoint() raise Exception else: breakpoint() raise Exception if hashable_func and func not in reg['hls/ir_builtins']: if func in special_funcs: return resolve_func(getattr(args[0].dtype, special_funcs[func]), args, kwds, ctx) if isinstance(func, Partial): intf, stmts = call_gear(func, *form_gear_args(args, kwds, func), ctx) ctx.ir_parent_block.stmts.extend(stmts) return intf if hashable_func and func in compile_time_builtins and const_func_args(args, kwds): return resolve_compile_time(func, args, kwds) if hashable_func and func in reg['hls/ir_builtins']: try: return reg['hls/ir_builtins'][func](*args, **kwds) except TypeError as e: raise SyntaxError(str(e).replace('<lambda>()', repr(func))) if const_func_args(args, kwds): return resolve_compile_time(func, args, kwds) elif hasattr(func, 'dispatch'): return resolve_func(func.dispatch(args[0].dtype), args, kwds, ctx) else: return parse_func_call(func, args, kwds, ctx)
def call_is_type(arg): if not isinstance(arg, ir.ResExpr): return ir.res_false return ir.ResExpr(is_type(arg.val))
def trunc(data, t): if is_type(data): return type_trunc(t, data) else: return value_trunc(type_trunc(t, type(data)), data)
def saturate(data, t, limits=None): if is_type(data): return type_saturate(t, data) else: return value_saturate(type_saturate(t, type(data)), data, limits)