def test_outsig(lang): @gear(signals=[InSig('clk', 1), InSig('rst', 1), OutSig('flush', 1)]) 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) @gear def hier(din: Bool): din | local_rst drv(t=Bool, seq=[False, True]) | hier cosim('/hier', 'verilator', lang=lang) sim()
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']
from pygears import gear from pygears.hdl import hdlgen from pygears.typing import Uint from pygears.typing.math import ceil_chunk from pygears.core.gear import InSig from pygears import Intf from pygears_vivado.ipinst import ipinst from pygears_vivado.vivmod import SVVivModuleInst @gear( hdl={'hdlgen_cls': SVVivModuleInst}, sigmap={ 's_axis_aresetn': '~rst', 's_axis_aclk': 'clk' }, signals=[InSig('s_axis_aresetn', 1), InSig('s_axis_aclk', 1)], ) async def axis_data_fifo( s_axis: Uint['W'], *, tdata_num_bytes=b'W//8', fifo_depth=b'depth' ) -> { 'm_axis': b's_axis' }: pass @gear def viv_fifo(din, *, depth):
from pygears.lib.verif import directed, drv from pygears.core.gear import InSig, OutSig @pytest.fixture(autouse=True) def configure(): reg['hdl/include'].append( os.path.join(os.path.dirname(__file__), 'test_signals')) @gear(signals=[OutSig('dout_sig', 16)]) async def bc_sig(din) -> b'din': pass @gear(signals=[InSig('din_sig', 16)]) async def add_sig(din) -> b'din': pass def test_local_signal(): @gear def dut(din): return din \ | bc_sig(sigmap={'dout_sig': 'sig'}) \ | add_sig(sigmap={'din_sig': 'sig'}) directed(drv(t=Uint[16], seq=list(range(3))), f=dut(sim_cls=SimVerilated), ref=(list(range(0, 6, 2))))
def generate(top, intfdef): files = set() if isinstance(top, str): top = find(top) modinst = reg['hdlgen/map'][top] sigs = [] for s in top.signals.values(): if s.name == 'clk': sigs.append(InSig('aclk', 1)) elif s.name == 'rst': sigs.append(InSig('aresetn', 1)) else: sigs.append(s) intfs = {p['name']: p for p in get_port_intfs(top)} for i in intfs.values(): dtype = i['type'] w_data = i['width'] w_eot = 0 if typeof(dtype, Queue): w_data = dtype.data.width w_eot = int(dtype.eot) i['w_data'] = w_data i['w_eot'] = w_eot defs = [] for name, p in intfdef.items(): if p.t == 'axidma': params = {n: c.params for n, c in p.comp.items()} defs.extend( axi_intfs.port_def(axi_intfs.AXI_MASTER, name, **params)) params = { n: c.params for n, c in intfdef[f'{name}_ctrl'].comp.items() } defs.extend( axi_intfs.port_def(axi_intfs.AXIL_SLAVE, f'{name}_ctrl', **params)) files.update({'sfifo.v', 'axi_addr.v', 'skidbuffer.v'}) if 'rdata' in p.comp: files.add('aximm2s.v') if 'wdata' in p.comp: files.add('axis2mm.v') elif p.t in ['bram', 'bram.req', 'axi']: params = {n: c.params for n, c in p.comp.items()} pdefs = axi_intfs.port_def(axi_intfs.AXI_SLAVE, name, **params) if 'rdata' in params: files.add('axi_slave_read.v') if 'wdata' in params: files.add('axi_slave_write.v') if 'rdata' in params or 'wdata' in params: files.update({'sfifo.v', 'axi_addr.v', 'skidbuffer.v'}) defs.extend(pdefs) elif p.t == 'axis': if p.direction == 'w': tmplt = axi_intfs.AXIS_SLAVE else: tmplt = axi_intfs.AXIS_MASTER params = {n: c.params for n, c in p.comp.items()} pdefs = axi_intfs.port_def(tmplt, name, **params) defs.extend(pdefs) context = { 'wrap_module_name': f'wrap_{modinst.module_name}', 'module_name': modinst.wrap_module_name, 'inst_name': modinst.wrap_module_name, 'intfs': intfs, 'sigs': sigs, 'param_map': modinst.params if not modinst.wrapped else {}, 'port_def': defs, 'ports': intfdef } context['pg_clk'] = 'aclk' tmplt = 'wrapper.j2' base_addr = os.path.dirname(__file__) lang_dir = os.path.join(os.path.dirname(base_addr), 'sv') env = TemplateEnv(lang_dir) env.jenv.globals.update(zip=zip, ceil_pow2=ceil_pow2, ceil_div=ceil_div, bitw=bitw, ceil_chunk=ceil_chunk, axi_intfs=axi_intfs) return env.render(base_addr, tmplt, context), files
def generate(top, outdir, lang, intfdef, prjdir, presynth=False, rst=True, drvgen=False): dirs = get_folder_struct(outdir) create_folder_struct(dirs) drv_files = [] if presynth: hdl_lang = 'v' srcdir = os.path.join(dirs['root'], 'src') else: hdl_lang = lang srcdir = dirs['hdl'] top = hdlgen(top, outdir=srcdir, wrapper=False, copy_files=True, lang=hdl_lang, toplang=lang, generate=True) topinst = reg['hdlgen/map'][top] if topinst.wrapped: try: shutil.copy(os.path.join(srcdir, f'{topinst.wrap_module_name}.sv'), dirs['hdl']) except shutil.SameFileError: pass if presynth: if lang == 'sv': # TODO: Use some general file finder (as in hdl resolver) shutil.copy(os.path.join(srcdir, 'dti.sv'), dirs['hdl']) v = IPHierVisitor() v.visit(top) blackbox = [ip.node.name for ip in v.ips] synth('yosys', top=top, outdir=dirs['hdl'], lang=hdl_lang, synthcmd=None, synthout=os.path.join(dirs['hdl'], topinst.file_basename), blackbox=','.join(blackbox), srcdir=srcdir) sigs = [] for s in top.signals.values(): if s.name == 'clk': sigs.append(InSig('aclk', 1)) elif s.name == 'rst': sigs.append(InSig('aresetn', 1)) else: sigs.append(s) if drvgen: drv_files = drvgen(top, intfdef, dirs['driver']) else: drv_files = None wrp, files = generate_wrap(top, intfdef, rst=rst) for p in intfdef.values(): if p.t == 'axi': from pygears.lib.strb_combiner import strb_combiner from pygears import Intf, find from pygears.typing import Tuple, Array, Uint num = p.comp['wdata'].params['wstrb'] # strb_combiner generation requires deeper recursion limit for large buses import sys sys.setrecursionlimit(1500) cur = reg['gear/current_module'] reg['gear/current_module'] = top strb_combiner(Intf(Tuple[Array[Uint[8], num], Uint[num]]), name=f'{p.name}_strb_combiner') reg['gear/current_module'] = cur hdlgen(f'{top.name}/{p.name}_strb_combiner', outdir=srcdir, wrapper=False, copy_files=True, lang=hdl_lang, toplang=lang, generate=True) ippack(top, dirs, intfdef=intfdef, lang=lang, prjdir=prjdir, files=files, drv_files=drv_files) preproc_hdl(dirs['hdl'], mapping=default_preproc) save_file(f'wrap_{os.path.basename(topinst.inst_name)}.{lang}', dirs['hdl'], wrp) # TODO: Remove this when memoization gets smarter. Right now this removes # the problem where memoization can make one IP rely on files stored in # another IP without proper copying reg['hdlgen/map'].clear()
import os import math from pygears import gear from pygears.typing import Fixp, Tuple from pygears_vivado.vivmod import SVVivModuleInst from pygears.core.gear import InSig # TODO: Make it work properly with widths that are not multiple of 8 @gear(hdl={'hdlgen_cls': SVVivModuleInst}, sigmap={'aclk': 'clk'}, signals=[InSig('aclk', 1)]) async def cordic( s_axis_phase: Fixp[3, 'W'], *, output_width=b'input_width', input_width=b'W', functional_selection="Sin_and_Cos", architectural_configuration="Word_Serial", # Word_Serial, Parallel pipelining_mode="Optimal", # Optimal, Maximum phase_format="Scaled_Radians", flow_control="Blocking", # NonBlocking, Blocking out_tready=True, data_format="SignedFraction", _w_out=b'((W+7)//8)*8' ) -> { 'm_axis_dout': Tuple[Fixp[2, '_w_out'], Fixp[2, '_w_out']] }: async with s_axis_phase as p: yield (Fixp[2, output_width](math.cos(math.pi * float(p))),