async def decouple_din(din, *, depth, init) -> None: try: async with din as d: await module().queue.put(d) while (module().queue.full()): await delta() except GearDone: if module().queue.empty(): await module().queue.put(None) raise GearDone
def dtype_rnd_seq(t, outdir=None, cons=None): if cons is not None: if not outdir: outdir = os.path.join(artifacts_dir(), module().basename) scvlib = scv_compile(outdir, module().basename, cons) scvlib.randomize_seed() else: scvlib = None yield SCVTypeSeqVisitor(scvlib).visit(t)
async def decouple_dout(*, t, depth) -> b't': queue = module().decouple_din.queue while queue.empty(): if reg['sim/map'][module().decouple_din].done: raise GearDone await clk() yield queue.get_nowait() queue.task_done() await clk()
async def demux( din: Union, *, use_dflt=True, mapping=b'dflt_map(din)', _full_mapping=b'full_mapping(din, mapping, use_dflt)', ) -> b'demux_type(din, _full_mapping)': async with din as (data, ctrl): dout = [None] * len(module().tout) ctrl = _full_mapping[int(ctrl)] dout[ctrl] = module().tout[int(ctrl)].decode(int(data)) yield tuple(dout)
def drvrnd(*, t, cnt=None, cons=None, params=None): return drv(t=t, seq=randomize(t, module().basename, cnt=cnt, cons=cons, params=params))
async def sample(din, *, latency=1, hold=1, init=None) -> b"din": data = din.dtype() if init is None else din.dtype(init) valid = init is not None dout = module().dout while True: if latency == 0: try: data = din.get_nb() valid = True except IntfEmpty: pass if valid and dout.ready_nb(): dout.put_nb(data) if not hold: valid = False if latency == 1: try: data = din.get_nb() valid = True except IntfEmpty: pass await clk()
async def pipe(din, *, length) -> b'din': data = [None] * length dout = module().dout while True: if dout.ready_nb() and data[-1] is not None: dout.put_nb(data[-1]) await delta() if dout.ready_nb(): data[-1] = None if all(d is None for d in data) and din.done: raise GearDone for i in range(length - 1, 0, -1): if data[i] is None: data[i] = data[i - 1] data[i - 1] = None if not din.empty() and data[0] is None: data[0] = din.get_nb() await clk()
async def quenvelope(din: Queue['din_t', 'din_lvl'], *, lvl) -> Queue[Unit, 'lvl']: """Extracts the queue structure of desired level called the envelope If there are more eot levels then forwarded to the output, those eot excess levels are called subenvelope (which is not passed to the output). When there is a subenvelope, the number of data the output transactions (envelope) will contain is lowered by contracting each input transactions within subenvelope to the length of 1. This is done in order that the envelope can be correctly used within cartesian concatenations. """ dout = module().dout sub_lvl = din.dtype.lvl - lvl out_data = None async for data in quiter_async(din): if out_data is None: out_data = (Unit(), data.eot[-lvl:]) dout.put_nb(out_data) if sub_lvl > 0: subelem = data.sub(sub_lvl) if subelem.last: out_data = None else: out_data = None await dout.ready()
async def fifo(din, *, depth=2, threshold=0, regout=False) -> b'din': '''For this implementation depth must be a power of 2''' data = [] out_data = False dout = module().dout while (1): if len(data) <= threshold and din.done: raise GearDone # TODO: Make fifo work correctly in corner case when it is full, but # consumer is ready if len(data) < depth: if not din.empty(): data.insert(0, din.get_nb()) if len(data) > threshold and not out_data and dout.ready_nb(): dout.put_nb(data[-1]) out_data = True await delta() if out_data and dout.ready_nb(): data.pop() out_data = False await clk()
async def tdp_port1(req, *, depth) -> b'req["data"].data': ram = module().port0.ram async with req as (addr, (data, ctrl)): if ctrl: ram[addr] = data else: yield ram[addr]
def qround(din, *, fract=0, cut_bits=b'get_cut_bits(din, fract)', signed=b'din.signed') -> b'get_out_type(din, fract)': res = code(din, Int if signed else Uint) + (Bool(1) << (cut_bits - 1)) return code(res >> cut_bits, module().tout)
async def local_rst(din): sig = module().signals['flush'] sig.write(0) async with din as d: if d: sig.write(1) else: sig.write(0)
async def sdp_rd_port(addr, *, t, depth) -> b't': ram = module().sdp_wr_port.ram while True: a = await addr.get() dout = ram[int(a)] await clk() yield dout
async def qrange_start_stop_inclusive( cfg: Tuple[{ 'start': Integer, 'stop': Integer }], *, inclusive, ) -> Queue['qrange_out_type(cfg)']: cnt: module().tout.data = None last: Bool async with cfg as c: last = False cnt = module().tout.data(c[0]) while not last: last = cnt == c[1] yield cnt, last cnt += 1
async def qrange_start_stop( cfg: Tuple[{ 'start': Integer, 'stop': Integer }], *, inclusive=False, ) -> Queue['qrange_out_type(cfg)']: cnt: module().tout.data = None cur_cnt: cfg.dtype[0] last: Bool async with cfg as c: cnt = module().tout.data(c[0]) last = False while not last: cur_cnt = cnt cnt += 1 last = cnt == c[1] yield cur_cnt, cnt == c[1]
async def state_dout(*rd, t) -> b't': dout = [None] * len(rd) for i, rd_req in enumerate(rd): if not rd_req.empty(): dout[i] = t(module().state_din.val) if len(rd) > 1: yield tuple(dout) else: yield dout[0] for i, rd_req in enumerate(rd): if dout[i] is not None: rd_req.get_nb()
async def decouple_dout(*, t, depth) -> b't': din = module().decouple_din if din.queue.empty() and (din not in reg['sim/map'] or reg['sim/map'][din].done): raise GearDone queue = din.queue data = await queue.get() yield data queue.task_done() await clk()
async def decouple_dout(*, t, depth, latency) -> b't': din = module().decouple_din sim_map = reg['sim/map'] sim_din = sim_map[din] while True: if din.queue.empty() and (din not in sim_map or sim_din.done): raise GearDone queue = din.queue data = await queue.get() yield data queue.task_done() await clk()
async def sieve(din, *, key) -> b'din[key]': """Outputs a slice of the ``din`` input interface. Can be instantiated with the slicing statement: ``din[key]``. Args: key: A single key or a sequence of keys with which to slice the input interface. Returns: A sliced interface Which keys are exactly supported depends on the type of the ``din`` input interface, so checkout the __getitem__ method of the specific type. If for an example we have an interface of the type :class:`Uint[8] <Uint>` :: din = Intf(Uint[8]) we could slice it using Python index operator to obtain a high nibble: >>> din[4:] Intf(Uint[4]) which outputs an interface of the type :class:`Uint[4] <Uint>`. The same would be achieved if the ``sieve`` gear were instantiated explicitly: >>> sieve(din, key=slice(4, None, None)) Intf(Uint[4]) """ async with din as d: dout = [] for i in key: dout.append(d[i]) if len(key) == 1: dout = dout[0] yield module().tout(dout)
async def decouple_din(din, *, depth, init) -> None: async with din as d: await module().queue.put(d) while (module().queue.full()): await delta()
def expand_tuple_single_end_union(din: Tuple) -> b'expand_type(din)': return din >> module().tout
async def scope(*xs, clk_freq=None, title=None, scale=None, method=None, live=None, dump=None, transaction=False): if clk_freq is None: clk_freq = reg['sim/clk_freq'] if method is None: method = ['plot'] * len(xs) if len(method) != len(xs): raise Exception( f'Number of plotting methods ({method}) needs to match the number of inputs ({len(xs)})' ) if title is None: title = module().name parallel_steps = max( len(x.dtype) if typeof(x.dtype, Array) else 1 for x in xs) backends = [] kwds = { 'method': method, 'clk_freq': clk_freq * parallel_steps, 'title': title, 'scale': scale, 'transaction': transaction } if live or (live is None and dump is None): backends.append(plot_live(**kwds)) if dump: backends.append(plot_dump(dump, **kwds)) for b in backends: b.send(None) try: while True: for ch, x in enumerate(xs): if x.done: raise GearDone if x.empty(): continue async with x as x_data: if isinstance(x_data, Queue): x_data, eot = x_data else: eot = 0 if not isinstance(x_data, Array): x_data = [x_data] for i, v in enumerate(x_data): point = (ch, (timestep() + i / len(x_data)) / clk_freq, float(v), int(eot)) for b in backends: b.send(point) await clk() except GearDone: for b in backends: b.close() raise GearDone
def shr(din: Integral, *, shamt) -> b'din >> shamt': return module().tout(din >> shamt)
def shl(din: Integral, *, shamt) -> b'din << shamt': return module().tout(din << shamt)
async def state_din(din, *, init) -> None: async with din as data: pass await delta() module().val = data
async def sdp_wr_port(din, *, depth) -> None: async with din as (addr, data): module().ram[int(addr)] = data
async def sdp_rd_port(addr, *, t, depth) -> b't': ram = module().sdp_wr_port.ram async with addr as a: yield ram[int(a)]