def get_port_def(top, name, axi_name, subintf, parent, axi_conf): for p in top.in_ports + top.out_ports: if p.basename == name: break else: breakpoint() raise Exception( f'Port "{name}" supplied for {subintf} port of the' f' {axi_name} interface, not found') if axi_conf['type'] == 'axi': if p.direction == 'in' and subintf not in ['araddr', 'awaddr', 'wdata']: raise Exception( f'Cannot drive gear port {name} from AXi port {axi_name}.{subintf}') if p.direction == 'out' and subintf not in ['rdata']: raise Exception( f'Cannot drive AXi port {axi_name}.{subintf} from gear port {name}') if subintf == 'awaddr': if typeof(p.dtype, Tuple) and axi_conf.get('wdata', '') == name: return port_conf(parent, subintf, p, 0) if subintf == 'araddr': if typeof(p.dtype, Tuple) and axi_conf.get('wdata', '') == name: return port_conf(parent, subintf, p, 0) if subintf == 'wdata': if typeof(p.dtype, Tuple) and axi_conf.get('awaddr', '') == name: if typeof(p.dtype[1], Union) and axi_conf.get('araddr', '') == name: return port_conf(parent, subintf, p, (1, 0)) else: return port_conf(parent, subintf, p, 1) return port_conf(parent, subintf, p)
def register_traces_for_intf(dtype, scope, writer): vcd_vars = {} if typeof(dtype, TLM): vcd_vars['data'] = writer.register_var(scope, 'data', 'string') else: v = VCDTypeVisitor() 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 visit_SubscriptExpr(self, node): val = self.visit(node.val) if val is None: return None if isinstance(node.index, ir.ResExpr): index = node.index.val index = node.val.dtype.index_norm(index)[0] if isinstance(index, slice): stop = int(index.stop) - 1 start = int(index.start) if isinstance(node.val, (ir.Name, ir.AttrExpr)): return f'{val}[{stop}:{start}]' else: if index == node.val.dtype.keys()[0]: start = 0 else: start = node.val.dtype[:index].width stop = start + node.val.dtype[index].width - 1 index = int(index) if isinstance(node.val, (ir.Name, ir.AttrExpr, ir.Component)): if typeof(node.val.dtype, (Tuple, Union, Queue)): return f'{val}{self.separator}{node.val.dtype.fields[index]}' else: return f'{val}[{index}]' if isinstance(node.val, ir.ResExpr): if typeof(node.val.dtype, Array): return f'{val}[{index}]' elif typeof(node.val.dtype, Integral): return f'{val}[{index}]' elif typeof(node.val.dtype, (Tuple, Union, Queue)): return f'{val}{self.separator}{node.val.dtype.fields[index]}' else: fname = get_slice_func(self.aux_funcs, start, stop, node.val.dtype.width, getattr(node.dtype, 'signed', False)) return f'{fname}({val})' if typeof(node.val.dtype, (Array, Queue, Integer, Tuple, Union)): ind = self.visit(node.index) if isinstance(node.val, ir.Name): return f'{val}[{ind}]' else: fname = get_index_func(self.aux_funcs, node.val.dtype.width, node.index.dtype.width, node.dtype.width, getattr(node.dtype, 'signed', False)) return f'{fname}({val}, {ind})' breakpoint() raise Exception('Unsupported slicing')
def call_int(arg, **kwds): # ignore cast if typeof(arg.dtype, (Uint, Int)): return arg elif typeof(arg.dtype, Integral): if arg.dtype.signed: return ir.CastExpr(arg, cast_to=Int[arg.dtype.width]) else: return ir.CastExpr(arg, cast_to=Uint[arg.dtype.width]) else: return ir.ResExpr(NotImplemented)
def test_pysim_dir(sel, din_t, seq, sim_cls): if seq == 'rand': skip_ifndef('RANDOM_TEST') seq = [(random.randint(1, 100), random.randint(0, 2)) for _ in range(random.randint(10, 50))] if typeof(din_t, Queue): queue_filt_test(din_t, seq, sel, sim_cls) elif typeof(din_t, Union): filt_test(din_t, seq, sel, sim_cls) else: filt_by_test(din_t, seq, sel, sim_cls)
def max_expr(op1, op2): op1_compare = op1 op2_compare = op2 # TODO: Sort this casting out signed = typeof(op1.dtype, Int) or typeof(op2.dtype, Int) if signed and typeof(op1.dtype, Uint): op1_compare = resolve_cast_func(op1, Int) if signed and typeof(op2.dtype, Uint): op2_compare = resolve_cast_func(op2, Int) cond = ir.BinOpExpr((op1_compare, op2_compare), ir.opc.Gt) return ir.ConditionalExpr(cond=cond, operands=(op1, op2))
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 booleq(op1, op2, operator): if operator not in [opc.Eq, opc.NotEq]: return if not (typeof(op1.dtype, (Bool, Uint[1])) and typeof(op2.dtype, (Bool, Uint[1]))): return if op2 == res_true: return op1 if operator == opc.Eq else UnaryOpExpr(op1, opc.Not) if op2 == res_false: return op1 if operator == opc.NotEq else UnaryOpExpr(op1, opc.Not) return None
def integral_type_saturate_resolver(cast_type, dtype): if dtype is not int and not typeof(dtype, Integer): raise TypeError( f"cannot saturate '{repr(dtype)}' to a different base type '{repr(cast_type)}'" ) return cast_type
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 call_tuple(arg): if isinstance(arg, ir.ConcatExpr): return ir.TupleExpr(arg.operands) elif isinstance(arg, ir.TupleExpr): return arg elif isinstance(arg, ir.ResExpr): # TODO: Array is a list, so we have a workaround here if typeof(arg.dtype, (Tuple, Array, Queue)): return arg else: return ir.ResExpr(tuple(arg.val)) elif typeof(arg.dtype, (Array, Tuple)): return ir.ConcatExpr([ir.SubscriptExpr(arg, ir.ResExpr(i)) for i in range(len(arg.dtype))]) else: breakpoint() raise Exception
def __new__(cls, operand, cast_to): if isinstance(cast_to, ResExpr): cast_to = cast_to.val if cast_to == int: cast_to = Uint[operand.dtype.width] if operand.dtype == cast_to: return operand if isinstance(operand, ResExpr): return ResExpr(code(operand.val, cast_to)) if isinstance(operand, ConcatExpr) and typeof( cast_to, (Array, Tuple, Queue, Union)): cast_ops = [ CastExpr(op, cast_t) if op.dtype != cast_t else op for op, cast_t in zip(operand.operands, cast_to) ] operand = ConcatExpr(cast_ops) inst = super().__new__(cls) inst.operand = operand inst.cast_to = cast_to return inst
def put_nb(self, val): put_event = self.events['put'] if self.dtype is not type(val): err = None try: if not typeof(self.dtype, Any): val = self.dtype(val) except (TypeError, ValueError) as e: err = e if err: # TODO: when value cannot be represented, the error report can be terse raise TypeMatchError( f'{str(err)}\n, when converting output data "{repr(val)}"' f' from the "{reg["gear/current_module"].name}"' f' module to the type {repr(self.dtype)}') if put_event: put_event(self, val) for q, c in zip(self.out_queues, self.end_consumers): if c.consumer._done: raise GearDone put_event = c.consumer.events['put'] if put_event: put_event(c.consumer, val) q.put_nowait(val)
async def zip_cat(*din) -> b'zip_type(din)': id_max_lvl, max_lvl = max(enumerate(din), key=lambda p: p[1].dtype.lvl if typeof(p[1].dtype, Queue) else 0) async with gather(*din) as dout: yield (din_data_cat_value(dout), dout[id_max_lvl].eot)
def list_initials(self): for name, obj in self.ctx.scope.items(): if not isinstance(obj, ir.Variable): continue if typeof(obj.dtype, ir.IntfType): # if isinstance(obj.val.producer, HDLProducer): if (self.selected(self.ctx.ref(name, ctx='store')) and obj.dtype.direction == ir.IntfType.iout): yield self.attr(name, 'valid'), '0' # elif len(obj.val.consumers) == 1 and isinstance(obj.val.consumers[0], HDLConsumer): elif self.selected(self.ctx.ref(name, ctx='ready')): if not is_port_intf(name, self.ctx): yield self.attr(name, 'ready'), f"{self.attr(name, 'valid')} ? 0 : 1'bx" elif obj.reg: target = self.ctx.ref(name) if self.selected(target): if name == '_state': yield '_state_en', '0' yield (f'{self.svexpr(self.ctx.ref(name, ctx="store"), self.aux_funcs)}', f'{self.svexpr(self.ctx.ref(name), self.aux_funcs)}') else: pass
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 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 get_class(self): queue_struct_cons = [] queue_size_cons = [] data_cons = [] for c in self.cons: if 'queue.length' in c: queue_size_cons.append(c.replace('queue.length', 'length')) elif 'queue.struct' in c: queue_struct_cons.append(c.replace('queue.struct', 'struct')) else: data_cons.append(c.replace(f'dout.data', 'data')) self.cons = data_cons context = { 'con': self, 'sv_dtype': self.cvars['dout'], 'queue_struct_cons': queue_struct_cons, 'queue_size_cons': queue_size_cons } if typeof(self.dtype.data, Integral): dt = self.dtype.data context[ 'sv_data_dtype'] = f'logic {"signed" if dt.signed else ""} [{dt.width-1}:0]' else: context['sv_data_dtype'] = f'dout_data_t' del self.cvars['dout'] return self.tenv.cons.queue_tcon(**context)
async def zip_sync(*din, outsync=True) -> b'din': lvls = tuple(d.dtype.lvl if typeof(d.dtype, Queue) else 0 for d in din) overlap_lvl = min(lvls) eot_aligned = (1, 1) while (1): din_data = [(await d.pull()) for d in din] if overlap_lvl > 0: eot_overlap = [d.eot[:overlap_lvl] for d in din_data] eot_aligned = (eot_overlap[0] >= eot_overlap[1], eot_overlap[1] >= eot_overlap[0]) else: eot_aligned = (1, 1) eot_overlap = din_data[0].eot if lvls[0] else din_data[1].eot if all(eot_aligned): yield din_data else: await delta() for d, aligned in zip(din, eot_aligned): if (not aligned) or all(eot_aligned): d.ack()
def is_trace_included(port, include, vcd_tlm): if not match(f'{port.gear.name}.{port.basename}', include): return False if (port.dtype is None) or (typeof(port.dtype, TLM) and not vcd_tlm): return False return True
async def cart_sync(*din, outsync=True) -> b'din': async with din[0] as d0: if typeof(din[1].dtype, Queue): async for d1 in quiter_async(din[1]): yield d0, d1 else: async with din[1] as d1: yield d0, d1
def call_signed(val): if val.dtype.signed: return val if typeof(val.dtype, Uint): return resolve_cast_func(val, Int) raise Exception("Unsupported signed cast")
def call_isinstance(arg, dtype): if isinstance(dtype, ir.ResExpr): dtype = dtype.val if isinstance(arg, ir.ResExpr): return isinstance(arg.val, dtype) return ir.ResExpr(typeof(arg.dtype, dtype))
def call_typeof(arg, dtype): if isinstance(dtype, ir.ResExpr): dtype = dtype.val if not isinstance(arg, ir.ResExpr): return ir.res_false return ir.ResExpr(typeof(arg.val, dtype))
def rand_seq(name, cnt=None): randomizer = reg['sim/config/randomizer'] dtype = randomizer.get_dtype_by_name(name) if typeof(dtype, Queue): yield from get_rand(name, cnt, perpetum(queue_rand_seq, dtype, name)) else: yield from get_rand(name, cnt)
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 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)
async def replicate_while(cond: Bool, data: Any) -> Queue['data']: async with data as d: last = False while not last: async with cond as en: last = not en if typeof(data.dtype, Queue): yield (d[0], d[1] @ last) else: yield (d, last)
async def cart_sync(*din, outsync=True) -> b'din': din_t = [d.dtype for d in din] queue_id, single_id = (0, 1) if typeof(din_t[0], Queue) else (1, 0) async with din[single_id] as single_data: async for queue_data in quiter_async(din[queue_id]): dout = [0, 0] dout[single_id] = single_data dout[queue_id] = queue_data yield tuple(dout)
def expand_tuple(din: Tuple) -> b'expand_type(din)': ctrl_lens = [] ctrl_list = [] for i, t in enumerate(din.dtype): if (typeof(t, Union)): ctrl_list.append(din[i][1]) ctrl_lens.append(t[1].width) if not ctrl_list: return din ctrl = ccat(*ctrl_list) ctrl = ctrl >> Uint ctrl_width = sum(ctrl_lens) mux_din = [] data_indices = [] comb_no = 2**ctrl_width for i in range(comb_no): ctrl_bits = format(i, f'0={ctrl_width}b') k = 0 for clen in ctrl_lens: data_indices.append(int(ctrl_bits[k:k + clen], 2)) k += clen data = [] for j, t in enumerate(din.dtype): if (typeof(t, Union)): if (data_indices[0] < len(t.types)): if (t.types[data_indices[0]].width != 0): data.append(din[j][0] >> Uint[t.types[data_indices.pop( 0)].width]) else: data_indices.pop(0) else: data_indices.pop(0) else: data.append(din[j]) mux_din.append(ccat(*data)) return ((ctrl, ccat(*mux_din)) | mux) >> expand_type(din.dtype)