def generate(top, outdir, lang, util, timing, prjdir, part, yosys_preproc=True): if lang not in ['sv', 'v']: raise Exception(f"Synth test unknown language: {lang}") if lang == 'sv': yosys_preproc = False hdlgen(top=top, lang=lang, toplang=lang, outdir=outdir) vgen_map = reg['hdlgen/map'] top_name = vgen_map[top].wrap_module_name if not yosys_preproc or not shutil.which('yosys'): files = list_hdl_files(top, outdir, lang, wrapper=True) if lang == 'sv': save_file(f'{top_name}_synth_wrap.sv', outdir, vgen_map[top].get_synth_wrap(reg[f'svgen/templenv'])) top_name = f'{top_name}_synth_wrap' files.append(os.path.join(outdir, f'{top_name}.sv')) else: files = [os.path.join(outdir, 'synth.v')] # files.append(os.path.join(os.path.dirname(__file__), 'yosys_blocks.v')) yosys_synth(outdir=outdir, srcdir=outdir, top=top, synthout=files[0], synthcmd='synth -noalumacc -noabc -run coarse') jinja_context = { 'res_dir': prjdir, 'outdir': outdir, 'files': files, 'top': top_name, 'util': util, 'timing': timing, 'part': part } env = jinja2.Environment(loader=jinja2.FileSystemLoader( searchpath=os.path.dirname(__file__))) if timing: with open(f'{outdir}/synth.xdc', 'w') as f: f.write( f'create_clock -name clk -period {timing} [get_ports clk]\n') env.get_template('synth.j2').stream(jinja_context).dump( f'{outdir}/synth.tcl')
def hdlgen_wspy(rtldir, dut): bind('debug/trace', ['']) bind('svgen/spy_connection_template', signal_spy_connect_t) hdlgen( f"/{dut.name}", outdir=rtldir, wrapper=True, copy_files=True)
def hdl_check_fixt(tmpdir, request): reg['gear/infer_signal_names'] = True yield lang = os.path.splitext(request.param[0][0])[1][1:] register_hdl_paths(tmpdir) hdlgen(lang=lang, outdir=tmpdir, **request.param[1]) for fn in request.param[0]: res_file = os.path.join(tmpdir, fn) ref_file = os.path.join(os.path.splitext(request.fspath)[0], request.function.__name__, fn) assert sv_files_equal(res_file, ref_file)
def compile_gear_body(gear, outdir, template_env): # ctx, hdl_ast = parse_gear_body(gear) from pygears.hls.translate import translate_gear ctx, hdl_ast = translate_gear(gear) subsvmods = [] if ctx.submodules: from pygears.hdl import hdlgen hdlgen_map = reg['hdlgen/map'] for c in ctx.submodules: rtl_top = hdlgen(c.gear, outdir=outdir, generate=False) svmod = hdlgen_map[rtl_top] subsvmods.append(svmod) funcs = [] def _get_funcs_rec(block): for f_ast, f_ctx in block.funcs: funcs.append((f_ast, f_ctx)) _get_funcs_rec(f_ast) _get_funcs_rec(hdl_ast) writer = HDLWriter() write_module(ctx, hdl_ast, writer, subsvmods, funcs, template_env, config=gear.meta_kwds.get('hdl', {})) return '\n'.join(writer.lines), subsvmods
def __init__(self, gear, timeout=100, rebuild=True, run=True, batch=True, **kwds): super().__init__(gear, timeout) self.name = gear.name[1:].replace('/', '_') self.outdir = os.path.abspath( os.path.join(reg['results-dir'], self.name)) self.rebuild = rebuild reg['sim/svsock/run'] = run if not kwds.get('gui', False): kwds['batch'] = batch self.kwds = kwds self.sock = None self.cosim_pid = None self.handlers = {} reg['sim/config/socket'] = self self.srcdir = os.path.join(self.outdir, 'src_gen') self.rtl_node = hdlgen(gear, outdir=self.srcdir, lang='sv') self.svmod = reg['hdlgen/map'][self.rtl_node]
def formal_check_fixt(tmpdir, request): skip_ifndef('FORMAL_TEST') yield outdir = tmpdir disable = request.param[0] if request.param[0] is not None else {} asserts = request.param[1] if request.param[1] is not None else {} assumes = request.param[2] if request.param[2] is not None else [] reg['vgen/formal/asserts'] = asserts reg['vgen/formal/assumes'] = assumes root = find('/') module = hdlgen(root.child[0], lang='v', outdir=outdir, wrapper=False, **request.param[3]) yosis_cmds = [] env = jinja2.Environment(loader=jinja2.FileSystemLoader( searchpath=os.path.dirname(__file__))) jinja_context = {'name': module.basename, 'outdir': outdir} def find_yosis_cmd(name): if name in disable: if disable[name] == 'all': return if disable[name] == 'live': jinja_context['live_task'] = False script_path = f'{outdir}/top_{name}.sby' jinja_context['if_name'] = name.upper() env.get_template('formal.j2').stream(jinja_context).dump(script_path) yosis_cmds.append(f'sby {script_path}') for port in module.in_ports: jinja_context['live_task'] = True find_yosis_cmd(port.basename) for port in module.out_ports: jinja_context['live_task'] = False find_yosis_cmd(port.basename) for cmd in yosis_cmds: assert os.system(cmd) == 0, f'Yosis failed. Cmd: {cmd}'
from pygears.typing import Queue, Uint from pygears.lib.verif import drv from pygears.lib import shred from pygears.hdl import hdlgen from pygears.conf.registry import bind from pygears.synth import list_hdl_files from string import Template signal_spy_connect_t = Template(""" /*verilator tracing_on*/ ${intf_name}_t ${intf_name}_data; logic ${intf_name}_valid; logic ${intf_name}_ready; /*verilator tracing_off*/ assign ${intf_name}_data = ${conn_name}.data; assign ${intf_name}_valid = ${conn_name}.valid; assign ${intf_name}_ready = ${conn_name}.ready; """) din_t = Queue[Uint[8], 2] ii_gen(din=drv(t=din_t, seq=[]), frame_size=(5, 5)) bind('hdl/debug_intfs', ['']) bind('hdl/spy_connection_template', signal_spy_connect_t) hdlgen('/ii_gen', outdir="rtl/build", wrapper=True, copy_files=True) # print(list_hdl_files('/ii_gen', outdir='rtl/build', language='sv', rtl_only=True)) # copy_svlib(list_hdl_files('/ii_gen', outdir='rtl/build', language='sv', rtl_only=True))
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()
def build(top, outdir=None, postsynth=False, lang=None, rebuild=True): if isinstance(top, str): top_name = top top = find(top) if top is None: raise Exception(f'No gear found on path: "{top_name}"') if lang is None: lang = reg['hdl/lang'] if lang != 'v': postsynth = False else: pass # postsynth = True file_struct = get_file_struct(top, outdir) outdir = file_struct['outdir'] if not rebuild and os.path.exists(file_struct['dll_path']): return shutil.rmtree(outdir, ignore_errors=True) reg['svgen/spy_connection_template'] = (signal_spy_connect_hide_interm_t if reg['debug/hide_interm_vals'] else signal_spy_connect_t) synth_src_dir = os.path.join(outdir, 'src') hdlgen(top, outdir=synth_src_dir if postsynth else outdir, generate=True, lang=lang, copy_files=True, toplang='v') hdlmod = reg['hdlgen/map'][top] if postsynth: # TODO: change this to the call of the toplevel synth function from pygears.hdl.yosys import synth synth(outdir=outdir, top=top, synthcmd='synth', srcdir=synth_src_dir, synthout=os.path.join(outdir, hdlmod.file_basename)) tracing_enabled = bool(reg['debug/trace']) context = { 'in_ports': top.in_ports, 'out_ports': top.out_ports, 'top_name': hdlmod.wrap_module_name, 'tracing': tracing_enabled, 'aux_clock': reg['sim/aux_clock'] } jenv = jinja2.Environment(trim_blocks=True, lstrip_blocks=True) jenv.globals.update(int=int) jenv.loader = jinja2.FileSystemLoader([os.path.dirname(__file__)]) c = jenv.get_template('sim_veriwrap.j2').render(context) save_file('sim_main.cpp', outdir, c) verilate(outdir, lang, top, hdlmod.wrap_module_name, tracing_enabled) make(file_struct['objdir'], hdlmod.wrap_module_name)
import os import shutil from pygears_dsp.examples.echo.echo import echo from pygears import Intf from pygears.definitions import LIB_SVLIB_DIR from pygears.hdl import hdlgen from pygears.typing import Fixp from pygears.util.print_hier import print_hier Intf(Fixp[1, 16]) | echo(feedback_gain=0.6, sample_rate=48000, delay=0.25) hdlgen('/echo', outdir='build/echo', wrapper=True) print(f'Generated SystemVerilog files inside {os.path.abspath("build/echo")}') print() print_hier() print() print(f'Creating Vivado project inside {os.path.abspath("build/echo/vivado")}') shutil.rmtree('build/echo/vivado', ignore_errors=True) viv_cmd = (f'vivado -mode batch -source echo_synth.tcl -nolog -nojournal' f' -tclargs {LIB_SVLIB_DIR}') if os.system(viv_cmd) == 0: with open('build/echo/echo_utilization.txt') as f: print(f.read())