Exemple #1
0
def test_intf_name_inference():
    reg['gear/infer_signal_names'] = True

    @gear
    def fsub1(din1, din2) -> Tuple['din1', 'din2']:
        pass

    @gear
    def fsub2(din) -> b'din':
        pass

    @gear
    def fgear(din1, din2):
        var1 = fsub1(din1, din2)
        var2 = fsub2(var1)

        return var2

    fgear(Intf(Uint[1]), Intf(Uint[2]))

    fsub1_inst = find('/fgear/fsub1')
    fsub2_inst = find('/fgear/fsub2')

    assert fsub1_inst.outputs[0].var_name == 'var1'
    assert fsub2_inst.outputs[0].var_name == 'var2'
Exemple #2
0
def test_hier():
    @gear
    def func1(arg1, arg2, arg3) -> Uint[4]:
        pass

    @gear
    def func2(arg1) -> Uint[2]:
        pass

    @gear
    def func_hier(arg1, arg2, arg3):
        return func1(arg1, arg2, arg3) | func2

    iout = func_hier(Intf(Uint[1]), Intf(Uint[2]), Intf(Uint[3]))

    assert isinstance(iout, Intf)
    assert iout.dtype == Uint[2]

    root = reg['gear/root']
    assert len(root.child) == 1

    assert root['func_hier'].tout == Uint[2]
    for i in range(3):
        arg_intf = root['func_hier'].in_ports[i].consumer
        assert arg_intf.consumers[0] == root['func_hier/func1'].in_ports[i]

    assert root['func_hier/func1'].tout == Uint[4]
    iout1 = root['func_hier/func1'].outputs[0]
    assert iout1.producer == root['func_hier/func1'].out_ports[0]

    assert root['func_hier/func2'].tout == Uint[2]
    iout2 = root['func_hier/func2'].outputs[0]
    assert iout1.consumers == [root['func_hier/func2'].in_ports[0]]
    assert iout2.producer == root['func_hier/func2'].out_ports[0]
Exemple #3
0
def test_le():
    @gear
    def test(a: Fixp, b: Int):
        return a <= b

    test(Intf(Fixp[1, 16]), Intf(Int[16]))

    assert call(test, Fixp[1, 16](0), Int[16](0))[0] == 1
    assert call(test, Fixp[1, 16](-0.01), Int[16](0))[0] == 1
    assert call(test, Fixp[1, 16](0.01), Int[16](0))[0] == 0
Exemple #4
0
def test_consumer_lower():
    @gear
    def func(din, channeled) -> Tuple['din', 'channeled']:
        pass

    @gear
    def hier(din, *, f):
        return din | f

    hier(Intf(Uint[2]), f=func(channeled=Intf(Uint[1])))
Exemple #5
0
def test_when():

    @gear
    def ph_neg(data):
        return data + 1

    @gear
    def ph_pos(data):
        return data + 1

    return Intf(Uint[8]) | when(Intf(Uint[1]), f=ph_neg, fe=ph_pos)
Exemple #6
0
def insert_module(port_name, module):
    port = find(port_name)

    post_intf = port.consumer
    post_intf.disconnect(port)
    if hasattr(post_intf, 'var_name'):
        post_intf.var_name += '_' + module.definition.__name__

    pre_intf = Intf(post_intf.dtype)
    pre_intf.source(port)

    module(pre_intf, intfs=[post_intf])
Exemple #7
0
def test_cordic_first_stage_vivado():
    pw = 19
    iw = 12
    ow = 12

    pw, ww, nstages, cordic_angles_l, gain = cordic_params(iw=iw, ow=ow, pw=pw)

    cordic_first_stage(Intf(Int[iw]),
                       Intf(Int[iw]),
                       Intf(Uint[pw]),
                       iw=iw,
                       ww=ww,
                       pw=pw)
Exemple #8
0
def test_consumer_lower_multilevel():
    @gear
    def func(din, channeled) -> Tuple['din', 'channeled']:
        pass

    @gear
    def hier1(din, *, f):
        return din | f

    @gear
    def hier0(din, *, f):
        return din | f, din | f, hier1(din, f=f)

    hier0(Intf(Uint[2]), f=func(channeled=Intf(Uint[1])))
Exemple #9
0
def test_hier_module_gen():
    @gear
    def fgear(arg1, arg2) -> {'ret': Uint[2]}:
        pass

    @gear(outnames=['top_ret1', 'top_ret2'])
    def hier(top_din1, top_din2):

        ret1 = fgear(top_din1, top_din2)
        ret2 = fgear(ret1, top_din2)

        return ret1, ret2

    hier(Intf(Uint[1]), Intf(Uint[2]))
Exemple #10
0
def test_alternatives():
    @gear(version=0)
    def fgear(arg1: Queue['T', 3], *, lvl=3) -> Tuple['T', Uint['lvl']]:
        pass

    @alternative(fgear)
    @gear(version=1)
    def fgear2(arg1: Queue['T', 2], *, lvl=2) -> Tuple['T', Uint['lvl']]:
        pass

    @alternative(fgear)
    @gear(version=2)
    def fgear1(arg1: Queue['T', 1], *, lvl=1) -> Tuple['T', Uint['lvl']]:
        pass

    @alternative(fgear)
    @gear(version=3)
    def fgear0(arg1: Uint['w'], *, lvl=0) -> Uint['w']:
        pass

    @alternative(fgear)
    @gear(version=4)
    def fgear01(arg1: Tuple['T1', 'T2'], *, lvl=0) -> b'T2':
        pass

    root = reg['gear/root']

    iout = Intf(Uint[1]) | fgear
    assert iout.dtype == Uint[1]
    assert root['fgear'].params['lvl'] == 0

    iout = Intf(Queue[Uint[1], 3]) | fgear
    assert iout.dtype == Tuple[Uint[1], Uint[3]]
    assert root['fgear1'].params['lvl'] == 3

    iout = Intf(Queue[Uint[1], 1]) | fgear
    assert iout.dtype == Tuple[Uint[1], Uint[1]]
    assert root['fgear2'].params['lvl'] == 1

    iout = Intf(Queue[Uint[1], 2]) | fgear
    assert iout.dtype == Tuple[Uint[1], Uint[2]]
    assert root['fgear3'].params['lvl'] == 2

    iout = Intf(Tuple[Uint[1], Uint[2]]) | fgear
    assert iout.dtype == Uint[2]
    assert root['fgear4'].params['lvl'] == 0
    assert root['fgear4'].meta_kwds['version'] == 4

    assert len(root.child) == 5
Exemple #11
0
def test_unionmap_simple_asymmetric():
    @gear
    def test(din: Uint['size']) -> Uint['size+1']:
        pass

    iout = fmap(Intf(Union[Uint[8], Uint[8]]), f=(test, None))
    assert iout.dtype == Union[Uint[9], Uint[8]]
Exemple #12
0
def test_unionmap_simple():
    @gear
    def test(din: Uint['size']) -> Uint['size+1']:
        pass

    iout = fmap(Intf(Union[Uint[1], Uint[2]]), f=(test, test))
    assert iout.dtype == Union[Uint[2], Uint[3]]
def moving_average(cfg: TCfg, din: TDin, *, w_data=b'w_data'):

    second_operand = Intf(dtype=Int[w_data])

    din_window = din \
        | Int[w_data] \
        | fifo(depth=8)

    initial_load = ccat(cfg['average_window'], const(val=0, tout=Int[w_data])) \
        | replicate \
        | Int[w_data]

    delayed_din = (initial_load, din_window) \
        | priority_mux \
        | union_collapse

    accum = din \
        | fmap(f=accumulator(second_operand,
                             delayed_din,
                             w_data=w_data), lvl=din.dtype.lvl)

    accum_reg = accum | decoupler

    second_operand |= priority_mux(accum_reg | Int[w_data], const(val=0, tout=Int[w_data])) \
        | union_collapse

    return accum
Exemple #14
0
def test_queuemap_simple():
    @gear
    def test(din: Uint[4]) -> Uint[2]:
        pass

    iout = fmap(Intf(Queue[Uint[4], 2]), f=test, lvl=2)
    assert iout.dtype == Queue[Uint[2], 2]
Exemple #15
0
def test_queuemap_tuplemap():
    @gear
    def test(din: Uint['size']) -> Uint['size+1']:
        pass

    iout = fmap(Intf(Queue[Tuple[Uint[1], Uint[2]], 2]), f=(test, test), lvl=3)
    assert iout.dtype == Queue[Tuple[Uint[2], Uint[3]], 2]
Exemple #16
0
def dualcycle_wrap_thin(din) -> b'din[0][0]':
    middle = Intf(din.dtype[0])

    return dualcycle(din,
                     middle,
                     intfs={'dout0': middle},
                     sim_cls=partial(SimVerilated, timeout=1))
Exemple #17
0
def reduce2(din, cfg: TCfg, *, f, max_size):
    """Similar to the Python reduce function, applies a rolling computation to
    sequential pairs of values in a list. The ``din`` input is of type
    :class:`Queue` which holds the values to be used for computation while the
    ``cfg`` input is a :class:`Tuple` consisting of a ``reduce_size`` field and
    the ``init`` field holding the inital value.

    Args:
        f: Function to be performed
        max_size: Maximal length of the input `Queue` which is the depth of the
          FIFO used for storing intermediate values

    Returns:
        The result of the reduce operation
    """

    acctype = cfg.dtype['init']

    qtype = Queue[acctype, din.dtype.lvl - 1]

    temp_res = Intf(dtype=qtype)
    cfg_rep = cfg | replicate
    sec_opnd = (cfg_rep, temp_res) \
        | priority_mux \
        | fmap(f=union_collapse, fcat=czip, lvl=1)

    result = czip(din, sec_opnd) | decouple | fmap(f=f, fcat=czip, lvl=2)
    acc, fin_res = result | Union[qtype, qtype] | demux
    acc | fifo(intfs=[temp_res], depth=max_size)

    return fin_res
Exemple #18
0
def test_mux_demux_redux_yosys(branches):
    TDin = Union[tuple(Uint[i] for i in range(1, branches + 1))]

    @gear
    def test(din):
        return demux_ctrl(din) | mux

    test(Intf(TDin))
Exemple #19
0
def hdl_i(din, *, Ki):

    accum_s = Intf(Fixp[5, 28])
    gain = din * Ki

    dout = gain + accum_s
    accum_s |= dout | dreg

    return dout
Exemple #20
0
def dualcycle_wrap_comb_middle(din) -> b'din[0][0]':
    middle = Intf(din.dtype[0])

    middle_back = (middle | fmap(f=(add(0), add(0)))) >> din.dtype[0]

    return dualcycle(din,
                     middle_back,
                     intfs={'dout0': middle},
                     sim_cls=partial(SimVerilated, timeout=1))
Exemple #21
0
def iir_2tsos(din, *, a, b, gain):
    din = din * gain
    y = Intf(din.dtype * 5)
    a1 = ((din * b[2]) - (y * a[2]))
    z1 = a1 | dreg(init=0)
    z2 = ((din * b[1]) + z1 - (y * a[1])) | decouple(init=0)
    y |= (din * b[0]) + z2

    return y
Exemple #22
0
def dualcycle_wrap_decouple_middle(din) -> b'din[0][0]':
    middle = Intf(din.dtype[0])

    middle_back = middle | decouple

    return dualcycle(din,
                     middle_back,
                     intfs={'dout0': middle},
                     sim_cls=partial(SimVerilated, timeout=1))
Exemple #23
0
def sim_compile_resolver(func, *args, **kwds):
    ctx = reg['gear/exec_context']
    if ctx == 'sim':
        reg['gear/exec_context'] = 'compile'

        local_in = []
        for a in args:
            if isinstance(a, Intf):
                a.consumers.clear()
                local_in.append(a)
            else:
                from pygears.lib.const import get_literal_type
                local_in.append(Intf(get_literal_type(a)))
                local_in[-1].producer = HDLProducer()

        reg['gear/exec_context'] = 'sim'

        outputs = gear_base_resolver(func, *local_in, **kwds)

        # TODO: Support multiple outputs

        if isinstance(outputs, tuple):
            raise Exception("Not yet supported")

        outputs.connect(HDLConsumer())

        gear_inst = outputs.producer.gear

        def is_async_gen(func):
            return bool(func.__code__.co_flags & inspect.CO_ASYNC_GENERATOR)

        if not is_async_gen(gear_inst.func):
            raise Exception("Not yet supported")

        import asyncio
        for intf, a in zip(local_in, args):
            if isinstance(a, Intf):
                continue

            intf._in_queue = asyncio.Queue(maxsize=1,
                                           loop=reg['sim/simulator'])
            intf.put_nb(a)

        simulator = reg['sim/simulator']
        cur_sim = reg['gear/current_sim']
        sim_map = reg['sim/map']

        sim_gear = SimGear(gear_inst)
        sim_map[gear_inst] = sim_gear
        cur_sim.child.append(sim_gear)
        simulator.forward_ready.add(sim_gear)
        simulator.tasks[sim_gear] = sim_gear.run()
        simulator.task_data[sim_gear] = None

        return outputs
    else:
        return gear_base_resolver(func, *args, **kwds)
Exemple #24
0
def test_cordic_stage_freduce_vivado():
    pw = 19
    iw = 12
    ow = 12

    cordic_stage(Intf(Tuple[Int[ow], Int[iw], Uint[pw]]),
                 i=10,
                 cordic_angle=Uint[pw](0x4fd9),
                 ww=iw,
                 pw=pw)
Exemple #25
0
def test_cordic_pipeline_freduce_yosys():
    pw = 19
    iw = 12
    ow = 12

    cordic_stages(Intf(Tuple[Int[ow], Int[iw], Uint[pw]]),
                  nstages=3,
                  cordic_angles=[Uint[pw](0x4fd9)] * 3,
                  ww=iw,
                  pw=pw)
Exemple #26
0
def test_cordic_sin_cos_s():
    pw = 19
    iw = 12
    ow = 12

    cordic_sin_cos(Intf(Uint[pw]),
                   ow=ow,
                   iw=iw,
                   norm_gain_sin=False,
                   norm_gain_cos=False)
Exemple #27
0
def test_queuemap_balance():
    @gear
    def bal(din: 'tdin') -> b'tdin':
        pass

    @gear
    def test(din: Uint['size']) -> Uint['size-1']:
        pass

    iout = fmap(Intf(Queue[Uint[4], 2]), f=test, lvl=2, balance=bal)
    assert iout.dtype == Queue[Uint[3], 2]
Exemple #28
0
def test_incomplete_argument():
    @gear
    def test(din) -> b'din':
        pass

    expected_err_text = """Input argument "din" has unresolved type "Integer"\n - when instantiating "test" """

    with pytest.raises(GearArgsNotSpecified) as excinfo:
        test(Intf(Integer))

    assert equal_on_nonspace(str(excinfo.value), expected_err_text)
Exemple #29
0
def test_clk_channeling():
    @gear
    def dut(din):
        return din \
            | gear_clk2

    Intf(Uint[16]) | dut

    mod_dut = find('/dut')

    assert InSig('clk2', 1) in mod_dut.meta_kwds['signals']
Exemple #30
0
def test_unionmap_balance():
    @gear
    def bal(din: 'tdin') -> b'tdin':
        pass

    @gear
    def test(din: Uint['size']) -> Uint['size+1']:
        pass

    iout = fmap(Intf(Union[Uint[1], Uint[2]]), f=(test, test), balance=bal)
    assert iout.dtype == Union[Uint[2], Uint[3]]