Esempio n. 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'
Esempio n. 2
0
def run_file(path):
    print(f'Running example {path}')
    example = os.path.splitext(os.path.basename(path))[0]
    cfg_fn = os.path.splitext(path)[0] + '_cfg.py'

    clear()
    runpy.run_path(path)

    if os.path.exists(cfg_fn):
        runpy.run_path(cfg_fn)
    else:
        gear = get_example_gear(example).basename

        for inp in find(f'/{gear}').in_ports:
            reg['debug/trace'].append(inp.name)

        for outp in find(f'/{gear}').out_ports:
            reg['debug/trace'].append(outp.name)

    # reg['results-dir'] = '/tools/home/tmp'
    reg['wavejson/trace_fn'] = os.path.join(examples_dir, f'{example}.json')
    reg['sim/extens'].append(WaveJSON)
    # reg['trace/level'] = 0

    sim()
Esempio n. 3
0
    def sim_vcd_to_json(self):
        graph = dump_json_graph('/')

        if self.multiprocess:
            self.finish_event.set()
            json_vcds = [qin.recv() for qin in self.qin]

            for p in self.p:
                p.join()
        else:
            json_vcds = []
            for top, trace_fn in self.cosim_modules:
                json_vcds.append(vcd_to_json(top, follow(trace_fn)))

            json_vcds.append(vcd_to_json(find('/'), follow(self.vcd_fn)))

        visited_channels = set()
        changes = []
        for json_vcd in json_vcds:
            if json_vcd is None:
                continue
            for p_name in json_vcd:
                p = find(p_name)
                intf_name = p_name
                port_name = None if isinstance(p, Intf) else p.producer.name
                if ((isinstance(p, InPort) or
                     (isinstance(p, OutPort) and node_hierarchical(p.gear)))
                        and len(p.producer.consumers) > 1):
                    for i in range(len(p.producer.consumers)):
                        if p.producer.consumers[i] is p:
                            break

                    if isinstance(p, InPort) and node_hierarchical(p.gear):
                        intf_name = p_name
                    bc_name = f'{p.producer.parent.name}/{p.producer.basename}_bc'
                    port_name = f'{bc_name}.dout{i}'

                if isinstance(p, InPort) and (p.consumer is None or any(
                        isinstance(c, HDLConsumer)
                        for c in p.consumer.consumers)):
                    intf_name = None

                for channel_name in [intf_name, port_name]:
                    if channel_name is not None and channel_name not in visited_channels:
                        changes.append({
                            'channelName': channel_name,
                            'changes': json_vcd[p_name]
                        })
                        visited_channels.add(channel_name)

        return {
            'graphInfo': graph,
            'simulationChanges': {
                'startCycle': 0,
                'endCycle': timestep(),
                'channelChanges': changes
            }
        }
Esempio n. 4
0
def sim_hdl_pid(Kp, Ki, Kd):
    plant = tf([1], [1, 10, 20])

    config['sim/clk_freq'] = 1000
    seq = [0.] * 2 + [1.] * config['sim/clk_freq'] * 2

    set_point = drv(t=Float, seq=seq)

    plant_out = set_point \
        | hdl_pid_sys(Kp=Kp, Ki=Ki, Kd=Kd, plant=plant)

    find('/hdl_pid_sys/plant.x').producer | scope(title="PID Output")
    plant_out | scope(title="Plant Output")

    sim('/tools/home/tmp', timeout=len(seq))
Esempio n. 5
0
def sim_pid_lti_comb(Kp, Ki, Kd, Nfilt):
    plant = tf([1], [1, 10, 20])

    config['sim/clk_freq'] = 1000
    seq = [0.] * 2 + [1.] * config['sim/clk_freq']

    set_point = drv(t=Float, seq=seq)

    plant_out = set_point \
        | pid_lti_comb(Kp=Kp, Ki=Ki, Kd=Kd, Nfilt=Nfilt, plant=plant)

    find('/pid_lti_comb/lti.x').producer | scope(title="PID Input")
    plant_out | scope(title="Plant Output")

    sim(timeout=len(seq))
Esempio n. 6
0
    def __init__(self,
                 trace_fn=Inject('wavejson/trace_fn'),
                 include=Inject('debug/trace'),
                 sim=Inject('sim/simulator'),
                 outdir=Inject('results-dir'),
                 sim_map=Inject('sim/map')):
        super().__init__()
        self.sim = sim
        self.finished = False

        self.outdir = outdir
        self.trace_fn = trace_fn

        if not os.path.isabs(self.trace_fn):
            self.trace_fn = os.path.abspath(os.path.join(
                self.outdir, trace_fn))

        atexit.register(self.finish)

        self.writer = WaveJSONWriter()

        reg['WaveJSONWriter'] = self.writer

        self.handhake = set()

        v = WaveJSONHierVisitor(self.writer, include)
        v.visit(find('/'))
        self.vcd_vars = v.vcd_vars

        for intf in self.vcd_vars:
            intf.events['put'].append(self.intf_put)
            intf.events['ack'].append(self.intf_ack)
Esempio n. 7
0
def ipinst(top, resdir=None):
    if isinstance(top, str):
        top = find(top)

    if resdir is None:
        resdir = os.path.join(CACHE_DIR, 'vivado', 'ipinst')

    prjdir = tempfile.mkdtemp()

    os.makedirs(resdir, exist_ok=True)
    params = {k: v for k, v in top.explicit_params.items() if k[0] != '_'}
    ipname = top.definition.__name__

    hsh_name = hashlib.sha1(
        (ipname +
         json.dumps(params, sort_keys=True)).encode()).hexdigest()[-8:]

    ipinst = f'{ipname}_{hsh_name}'
    ipdir = os.path.join(resdir, ipinst)

    if glob.glob(os.path.join(ipdir, 'synth', f'{ipinst}.*')):
        return ipdir, ipinst

    tclpath = os.path.join(prjdir, 'ippack.tcl')

    with open(tclpath, 'w') as f:
        f.write(load_jenv().snippets.ip_inst_prj(ipinst, ipname, resdir,
                                                 prjdir, params))

    ret = run(tclpath)
    if ret:
        shutil.rmtree(ipdir)
        raise Exception(f"Vivado build failed with code: {ret}")

    return ipdir, ipinst
Esempio n. 8
0
def cosim(top, sim, *args, **kwds):
    if top is None:
        top = reg['gear/root']
    elif isinstance(top, str):
        top_name = top
        top = find(top)

        if top is None:
            raise Exception(f'No gear found on path: "{top_name}"')

    if isinstance(sim, str):
        if sim in ['cadence', 'xsim', 'questa']:
            from .modules import SimSocket
            sim_cls = SimSocket
            kwds['sim'] = sim
        elif sim == 'verilator':
            from .modules import SimVerilated
            from .modules.verilator import build

            kwds['outdir'] = kwds.get('outdir', reg['results-dir'])
            kwds['rebuild'] = kwds.get('rebuild', True)
            sim_cls = SimVerilated
            build(top, **kwds)
            kwds['rebuild'] = False
        else:
            raise Exception(f"Unsupported simulator: {sim}")
    else:
        sim_cls = sim

    if args or kwds:
        top.params['sim_cls'] = partial(sim_cls, *args, **kwds)
    else:
        top.params['sim_cls'] = sim_cls
Esempio n. 9
0
def list_hdl_files(top, outdir, rtl_only=False, wrapper=False, filt=None):

    if isinstance(top, str):
        top = find(top)

    orig_fns = set()
    hdlmods = {}
    for fn in enum_hdl_files(top,
                             outdir,
                             rtl_only=rtl_only,
                             wrapper=wrapper,
                             filt=filt):
        modname, lang = os.path.splitext(os.path.basename(fn))
        hdlmods[(modname, lang[1:])] = fn

    hdltop = reg['hdlgen/map'][top]
    disambig = reg['hdlgen/disambig']
    fns = []
    for (modname, lang), fn in hdlmods.items():
        if lang == hdltop.lang or (modname, hdltop.lang) not in hdlmods:
            fns.append(fn)
            continue

        fn_dis = os.path.join(outdir, f'{modname}_{lang}.{lang}')
        disambig[(modname, lang)] = (fn, fn_dis)

        fns.append(fn_dis)

    return fns
Esempio n. 10
0
    def before_run(self, sim):
        vcd_visitor = VCDHierVisitor(self.include, False)
        vcd_visitor.visit(find('/'))

        if not vcd_visitor.vcd_vars:
            self.deactivate('before_run')
            return True

        self.vcd_vars = {
            p: register_traces_for_intf(p.dtype, scope, self.writer, self.expand_data)
            for p, scope in vcd_visitor.vcd_vars.items()
        }

        self.end_consumers = vcd_visitor.end_consumers

        self.writer.flush()

        for intf in self.end_consumers:
            intf.events['put'].append(self.intf_put)
            intf.events['ack'].append(self.intf_ack)

        vcd_intf_vars = {}
        for p, v in self.vcd_vars.items():
            intf.events['put'].append(self.intf_put)
            intf.events['ack'].append(self.intf_ack)
            vcd_intf_vars[p] = v

        self.vcd_vars = vcd_intf_vars
        self.extend_intfs()
Esempio n. 11
0
def test_uint(cosim_cls):
    res = drv(t=Uint[4], seq=[0xa, 0xb, 0xc, 0xd]) << 4
    assert res.dtype == Uint[8]

    res | check(ref=[0xa0, 0xb0, 0xc0, 0xd0])

    find('/shl').params['sim_cls'] = cosim_cls
    sim()
Esempio n. 12
0
def test_int(sim_cls):
    res = drv(t=Int[5], seq=[-0xa, -0xb, -0xc, -0xd]) << 4
    assert res.dtype == Int[9]

    res | check(ref=[-0xa0, -0xb0, -0xc0, -0xd0])

    find('/shl').params['sim_cls'] = sim_cls
    sim()
Esempio n. 13
0
def test_int_logical(sim_cls):
    inp = drv(t=Int[9], seq=[-0xa1, -0xa2, -0xa3, -0xa4])

    res = (inp >> Uint) >> 4
    res | check(ref=[(-0xa1 & 0x1ff) >> 4] * 4)

    find('/shr').params['sim_cls'] = sim_cls
    sim()
Esempio n. 14
0
def sim_inst(top=None):
    if top is None:
        top = find('/')

    v = SimInstVisitor()
    v.visit(top)

    return top
Esempio n. 15
0
def find_target_intf(gear_name, intf_name):
    gear_mod = find(gear_name)
    rtl_node = reg['rtl/gear_node_map'][gear_mod].node

    intf_name = intf_name[1:]  # spy name always starts with _
    for i in rtl_node.local_interfaces():
        if reg['hdlgen/map'][i].basename == intf_name:
            return i
Esempio n. 16
0
def test_int(sim_cls):
    res = drv(t=Int[9], seq=[-0xa1, -0xa2, -0xa3, -0xa4]) >> 4
    assert res.dtype == Int[5]

    res | check(ref=[-0xb] * 4)

    find('/shr').params['sim_cls'] = sim_cls
    sim()
Esempio n. 17
0
def test_uint(sim_cls):
    res = drv(t=Uint[8], seq=[0xa1, 0xa2, 0xa3, 0xa4]) >> 4
    assert res.dtype == Uint[4]

    res | check(ref=[0xa] * 4)

    find('/shr').params['sim_cls'] = sim_cls
    sim()
Esempio n. 18
0
def get_example_gear(example):
    for c in find('/').child:
        if not c.basename.startswith(example.split('_')[0]):
            continue

        return c

    for c in find('/').child:
        if c.definition.func.__module__ == 'pygears.lib.verif':
            continue

        if (c.basename == 'delay_gen'):
            continue

        if (c.basename == 'ccat') and (not example.startswith('ccat')):
            continue

        return c
Esempio n. 19
0
def test_intf(enable_coverage=True):
    t_din = Queue[Uint[4]]
    t_size = Uint[16]

    din_cp = [
        CoverPoint('val', dtype=t_din[0], bind_dtype=True),
        CoverPoint('qlen_cp',
                   bins=[CoverBin('all')],
                   bind_dtype=True,
                   dtype=t_din)
    ]
    din_cg = CoverGroup('din_cg', t_din, cover_points=din_cp)
    size_cp = [
        CoverPoint('size_cp',
                   bins=[
                       CoverBin('two', enablement=lambda x: x == 2),
                       CoverBin('three', enablement=lambda x: x == 3),
                       CoverBin('four', enablement=lambda x: x == 4)
                   ])
    ]
    size_cg = CoverGroup('size_cg', t_size, cover_points=size_cp)

    directed(drv(t=t_din, seq=[list(range(9)), list(range(3))]),
             drv(t=t_size, seq=[2, 3]),
             f=chop,
             ref=[[0, 1], [2, 3], [4, 5], [6, 7], [8], [0, 1, 2]])

    cover_intf(find('/chop.size').consumer, cg=size_cg)
    cover_intf(find('/chop.din').consumer, cg=din_cg)

    sim()

    # print(size_cg.report())
    # print(din_cg.report())

    # size
    assert size_cg.cover_points[0].bins[0].cover_cnt == 1
    assert size_cg.cover_points[0].bins[1].cover_cnt == 1
    assert size_cg.cover_points[0].bins[2].cover_cnt == 0

    # din
    assert din_cg.cover_points[0].cover_cnt == 12
    assert din_cg.cover_points[1].bins[0].cover_cnt == 2
Esempio n. 20
0
def test_basic():
    @gear
    def qrange_wrp(din):
        return qrange(din)

    directed(drv(t=Uint[4], seq=[4]), f=qrange_wrp, ref=[list(range(4))])

    find('/qrange_wrp/qrange').meta_kwds['hdl']['lang'] = 'v'
    cosim('/qrange_wrp', 'verilator', lang='sv')
    sim()
Esempio n. 21
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']
Esempio n. 22
0
def synth_check_fixt(tmpdir, lang, request):
    skip_ifndef('SYNTH_TEST')

    # lang = 'sv'
    util_ref = request.param[0]
    params = request.param[1]
    tool = request.param[2]
    top = request.param[3]

    if tool == 'vivado':
        skip_ifndef('SYNTH_TEST')

    if tool == 'vivado':
        if not shutil.which('vivado'):
            raise unittest.SkipTest(f"Skipping test, vivado not found")

        params['util'] = True
        params['timing'] = True

    elif tool == 'yosys' and lang == 'v':
        if lang != 'v':
            raise unittest.SkipTest(
                f"Skipping test, unsupported lang for yosys")

        if not shutil.which('yosys'):
            raise unittest.SkipTest(f"Skipping test, yosys not found")

        params['synthcmd'] = 'synth_xilinx'

        # from pygears.hdl.yosys import synth
        # report = synth(tmpdir, top=top, synth_cmd='synth_xilinx', optimize=True)
    else:
        raise unittest.SkipTest(
            f"Skipping test, not appropriate tool not found")

    yield

    if top is None:
        top = find('/').child[0]

    util = synth(tool, outdir=tmpdir, top=top, lang=lang, **params)

    if tool == 'vivado':
        util = util['util']

    print(util)

    for param, value in util_ref.items():
        if callable(value):
            assert value(util[param])
        else:
            assert util[param] == value
Esempio n. 23
0
def cosim(top, sim, *args, **kwds):
    if top is None:
        top = reg['gear/root']
    elif isinstance(top, str):
        top_name = top
        top = find(top)

        if top is None:
            raise Exception(f'No gear found on path: "{top_name}"')

    kwds['outdir'] = expand(kwds.get('outdir', reg['results-dir']))
    kwds['rebuild'] = kwds.get('rebuild', True)

    reg['sim/hook/cosim_build_before'](top, args, kwds)

    if not kwds['rebuild']:
        import sys
        if sys.flags.hash_randomization:
            raise Exception(
                f"Reuse of previous cosim build turned on for module '{top}'.\n"
                " In order to use this feature you need to turn off Python hash randomization.\n"
                " Before running Python, you need to set environment variable 'PYTHONHASHSEED=0'")

    if isinstance(sim, str):
        if sim in ['cadence', 'xsim', 'questa']:
            from .modules import SimSocket
            sim_cls = SimSocket
            kwds['sim'] = sim
        elif sim == 'verilator':
            from .modules import SimVerilated
            from .modules.verilator import build

            timeout = kwds.pop('timeout', 100)
            sim_cls = SimVerilated
            build(top, **kwds)
            kwds['timeout'] = timeout
        else:
            raise Exception(f"Unsupported simulator: {sim}")

        kwds['rebuild'] = False
    else:
        sim_cls = sim

    # TODO: Should we invoke build here even when simulation class is sent
    # directly
    reg['sim/hook/cosim_build_after'](top, args, kwds)

    if args or kwds:
        top.params['sim_cls'] = partial(sim_cls, *args, **kwds)
    else:
        top.params['sim_cls'] = sim_cls
Esempio n. 24
0
def enum_hdl_files(top, outdir, rtl_only=False, wrapper=False, filt=None):
    if isinstance(top, str):
        top = find(top)

    vgen_map = reg[f'hdlgen/map']
    dirs = {}
    for lang in ['v', 'sv', 'vhd']:
        dirs[lang] = reg[f'{lang}gen/include']

    dti_yielded = False

    if reg['hdl/toplang'] == 'sv':
        dti_yielded = True
        yield os.path.join(LIB_SVLIB_DIR, 'dti.sv')

    for node in NodeYielder(filt).visit(top):
        if node not in vgen_map:
            continue

        vinst = vgen_map[node]

        if vinst.lang == 'sv' and not dti_yielded:
            dti_yielded = True
            yield os.path.join(LIB_SVLIB_DIR, 'dti.sv')

        # TODO: What?
        if ((node is top) and wrapper and not rtl_only):
            yield os.path.join(outdir, f'wrap_{vinst.file_basename}')

        if isinstance(node, Gear):
            for f in vinst.files:
                path = find_in_dirs(f, dirs[vinst.lang])
                if path is not None:
                    yield path
                else:
                    yield os.path.join(outdir, f)

        if hasattr(vinst, 'file_basename'):
            file_name = getattr(vinst, 'impl_path', None)
            if file_name:
                yield file_name
            # elif rtl_only is False:
            #     for f in vinst.files:
            #         yield os.path.join(outdir, f)

        elif vinst.is_broadcast:
            if vinst.lang == 'v':
                yield os.path.join(LIB_VLIB_DIR, 'bc.v')
            elif vinst.lang == 'sv':
                yield os.path.join(LIB_SVLIB_DIR, 'bc.sv')
Esempio n. 25
0
    def __init__(self, outdir='timelapse', dpi=60):
        super().__init__()
        self.outdir = os.path.abspath(
            os.path.expandvars(os.path.expanduser(outdir)))
        os.makedirs(self.outdir, exist_ok=True)
        self.g = graphviz.graph(find('/'), edge_fmt='{prod_gear} -> {cons_gear}')
        self.g.set_dpi(dpi)
        self.img_cnt = 0

        for out_port in self.g.prod_edge_map:
            out_port.producer.events['put'].append(self.intf_put)

        for in_port in self.g.cons_edge_map:
            in_port.consumer.events['ack'].append(self.intf_ack)
            in_port.consumer.events['finish'].append(self.intf_finish)
Esempio n. 26
0
def test_update_after_in_loop():
    @gear(hdl={'compile': True})
    async def test(din: Queue[Uint]) -> b'din':
        acc = din.dtype.data(0)

        async for d, eot in din:
            acc = d + acc
            if eot:
                yield acc, eot

    test(Intf(Queue[Uint[8]]))

    ctx, res = translate_gear(find('/test'))

    assert ctx.scope['acc'].reg
Esempio n. 27
0
def comp_pid_pg_comb_lti_comb(Kp, Ki, Kd, Nfilt):
    plant = tf([1], [1, 10, 20])

    config['sim/clk_freq'] = 1000
    seq = [0.] * 2 + [1.] * config['sim/clk_freq']

    set_point = drv(t=Float, seq=seq)

    plant_out = set_point \
        | pid_pg_comb(Kp=Kp, Ki=Ki, Kd=Kd, Nfilt=Nfilt, plant=plant)

    find('/pid_pg_comb/pid.x').producer | scope(title="PID Input")
    find('/pid_pg_comb/pid.dout').consumer | scope(title="PID Output")
    plant_out | scope(title="Plant Output")

    ref_out = set_point \
        | pid_lti_comb(Kp=Kp, Ki=Ki, Kd=Kd, Nfilt=Nfilt, plant=plant)

    ref_out | scope(title="Continuous Reference")

    report = []
    scoreboard(plant_out, ref_out, report=report, tolerance=2e-2)

    sim(timeout=len(seq))
Esempio n. 28
0
def test_optional_loop_assign():
    @gear
    async def test(din: Queue[Bool]) -> b'din':
        flag = False

        async for d, eot in din:
            if d:
                flag = True

        yield flag

    test(Intf(Queue[Bool]))

    ctx, res = translate_gear(find('/test'))

    assert ctx.scope['flag'].reg
Esempio n. 29
0
def ipdir(top, resdir=None, **kwds):
    if isinstance(top, str):
        top = find(top)

    if resdir is None:
        resdir = os.path.join(reg['results-dir'], 'ip')

    params = top.explicit_params
    ipname = top.definition.__name__

    hsh_name = hashlib.sha1(
        (ipname +
         json.dumps(params, sort_keys=True)).encode()).hexdigest()[-8:]

    ipinst = f'{ipname}_{hsh_name}'
    return os.path.join(resdir, ipinst)
Esempio n. 30
0
def test_fn_clash():
    @gear
    def test_v(din):
        return din[0] + din[1]

    @gear
    def test_clash(din):
        return din[0], test_v(din)

    directed(drv(t=Tuple[Uint[4], Uint[4]], seq=[(4, 4)]),
             f=test_clash,
             ref=[[4], [8]])

    find('/test_clash/test_v').meta_kwds['hdl']['lang'] = 'v'
    cosim('/test_clash', 'verilator', lang='sv', rebuild=True)
    sim()