def __init__(self, scfg: StructureConfig, plugin_includes: list): super().__init__(trim_blocks=True, lstrip_blocks=True) ctrl_inputs = scfg.analog_ctrl_inputs + scfg.digital_ctrl_inputs ctrl_outputs = scfg.analog_ctrl_outputs + scfg.digital_ctrl_outputs ##################################################### # Add plugin specific includes ##################################################### self.plugin_includes = SVAPI() for plugin in plugin_includes: for include_statement in plugin.include_statements: self.plugin_includes.writeln(f'{include_statement}') ##################################################### # Define module ios ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="sim_ctrl_gen") module.add_inputs(ctrl_outputs) module.add_outputs(ctrl_inputs) module.add_input(scfg.emu_clk) module.generate_header() ##################################################### # PC sim control section ##################################################### ## Custom control IOs for pc sim control module self.pc_sim_crtl_ifc = SVAPI() # Only generate instantiation if there is any ctrl signal available, that is not a special control signal has_custom_ctrl_signal = False for ctrl_signal in (ctrl_outputs + ctrl_inputs): if ctrl_signal.name not in scfg.special_ctrl_ios: has_custom_ctrl_signal = True break if has_custom_ctrl_signal: sim_ctrl_module = ModuleInst(api=self.pc_sim_crtl_ifc, name="sim_ctrl") for ctrl_output in ctrl_outputs: if ctrl_output.name not in scfg.special_ctrl_ios: sim_ctrl_module.add_input(ctrl_output, connection=ctrl_output) for ctrl_input in ctrl_inputs: if ctrl_input.name not in scfg.special_ctrl_ios: sim_ctrl_module.add_output(ctrl_input, connection=ctrl_input) sim_ctrl_module.generate_instantiation() # set number of clk cycles for initial reset self.rst_clkcycles = scfg.cfg.rst_clkcycles ##################################################### # FPGA sim control section - Instantiate vio wizard ##################################################### self.vio_wiz_inst = SVAPI() vio_wiz = ModuleInst(api=self.vio_wiz_inst, name="vio_0") for k, input in enumerate(ctrl_outputs): if isinstance(input, AnalogCtrlOutput): width = '`LONG_WIDTH_REAL' elif isinstance(input, DigitalCtrlOutput): width = input.width else: raise Exception( f"Provided signal type:{type(input)} is not supported!") vio_i = DigitalSignal(name=f'probe_in{k}', width=width, abspath=None) vio_wiz.add_input(io_obj=vio_i, connection=input) for k, output in enumerate(ctrl_inputs): if isinstance(output, AnalogCtrlInput): width = '`LONG_WIDTH_REAL' elif isinstance(output, DigitalCtrlInput): width = output.width else: raise Exception( f"Provided signal type:{type(output)} is not supported!") vio_o = DigitalSignal(name=f'probe_out{k}', width=width, abspath=None) vio_wiz.add_output(io_obj=vio_o, connection=output) vio_wiz.add_input(io_obj=DigitalSignal(name='clk', width=1, abspath=None), connection=scfg.emu_clk) vio_wiz.generate_instantiation()
class ModuleTop(JinjaTempl): """ This is the generator for top.sv. """ def __init__(self, target): super().__init__(trim_blocks=True, lstrip_blocks=True) scfg = target.str_cfg """ :type: StructureConfig """ pcfg = target.prj_cfg """ :type: EmuConfig """ self.result_path_raw = back2fwd(target.result_path_raw) ##################################################### # Add plugin specific includes ##################################################### self.plugin_includes = SVAPI() for plugin in target.plugins: for include_statement in plugin.include_statements: self.plugin_includes.writeln(f'{include_statement}') ##################################################### # Create module interface ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name='top') module.add_inputs(scfg.clk_i) if ((target.cfg.fpga_sim_ctrl is not None) and (target.cfg.fpga_sim_ctrl == FPGASimCtrl.UART_ZYNQ) and (not pcfg.board.is_ultrascale)): module.add_inouts(TemplZynqGPIO.EXT_IOS) module.generate_header() ##################################################### # Manage clks ##################################################### # Add clk in signals for simulation case self.clk_in_sim_sigs = SVAPI() for clk_i in scfg.clk_i: self.clk_in_sim_sigs.gen_signal(io_obj=clk_i) # Add dbg clk signals self.dbg_clk_sigs = SVAPI() self.dbg_clk_sigs.gen_signal(io_obj=scfg.dbg_clk) # Instantiation of clk_gen wrapper self.clk_gen_ifc = SVAPI() clk_gen = ModuleInst(api=self.clk_gen_ifc, name='clk_gen') clk_gen.add_inputs(scfg.clk_i, connections=scfg.clk_i) clk_gen.add_output(scfg.emu_clk_2x, connection=scfg.emu_clk_2x) clk_gen.add_output(scfg.dbg_clk, connection=scfg.dbg_clk) clk_gen.add_outputs(scfg.clk_independent, connections=scfg.clk_independent) clk_gen.generate_instantiation() # Absolute path assignments for derived clks self.derived_clk_assigns = SVAPI() for k, clk in enumerate(scfg.clk_derived): self.derived_clk_assigns.writeln(f'// derived clock: {clk.name}') if clk.abspath_emu_dt is not None: self.derived_clk_assigns.writeln( f'assign {clk.abspath_emu_dt} = emu_dt;') if clk.abspath_emu_clk is not None: self.derived_clk_assigns.writeln( f'assign {clk.abspath_emu_clk} = emu_clk;') if clk.abspath_emu_rst is not None: self.derived_clk_assigns.writeln( f'assign {clk.abspath_emu_rst} = emu_rst;') if clk.abspath_dt_req is not None: self.derived_clk_assigns.writeln( f'assign dt_req_{clk.name} = {clk.abspath_dt_req};') if clk.abspath_gated_clk is not None: self.derived_clk_assigns.writeln( f'assign clk_val_{clk.name} = {clk.abspath_gated_clk_req};' ) self.derived_clk_assigns.writeln( f'assign {clk.abspath_gated_clk} = clk_{clk.name};') self.num_dt_reqs = scfg.num_dt_reqs self.num_gated_clks = scfg.num_gated_clks ##################################################### # Manage Ctrl Module ##################################################### # provide information if default oscillator was used for template evaluation self.use_default_oscillator = scfg.use_default_oscillator ctrl_ios = scfg.analog_ctrl_inputs + scfg.analog_ctrl_outputs + scfg.digital_ctrl_inputs + \ scfg.digital_ctrl_outputs ## Instantiate all ctrl signals self.inst_itl_ctlsigs = SVAPI() for ctrl_io in ctrl_ios: self.inst_itl_ctlsigs.gen_signal(io_obj=ctrl_io) ## Instantiate ctrl module self.sim_ctrl_inst_ifc = SVAPI() sim_ctrl_inst = ModuleInst(api=self.sim_ctrl_inst_ifc, name='sim_ctrl_gen') sim_ctrl_inst.add_inputs( scfg.analog_ctrl_outputs + scfg.digital_ctrl_outputs, connections=scfg.analog_ctrl_outputs + scfg.digital_ctrl_outputs) sim_ctrl_inst.add_outputs( scfg.analog_ctrl_inputs + scfg.digital_ctrl_inputs, connections=scfg.analog_ctrl_inputs + scfg.digital_ctrl_inputs) ## Wire through Zynq connections if needed if ((target.cfg.fpga_sim_ctrl is not None) and (target.cfg.fpga_sim_ctrl == FPGASimCtrl.UART_ZYNQ) and (not pcfg.board.is_ultrascale)): sim_ctrl_inst.add_inouts(TemplZynqGPIO.EXT_IOS, connections=TemplZynqGPIO.EXT_IOS) # add master clk to ctrl module emu_clk_sig = DigitalSignal(name='emu_clk', width=1, abspath=None) sim_ctrl_inst.add_input(emu_clk_sig, emu_clk_sig) sim_ctrl_inst.generate_instantiation() ## Assign custom ctrl signals via abs paths into design self.assign_custom_ctlsigs = SVAPI() for ctrl_input in scfg.digital_ctrl_inputs + scfg.analog_ctrl_inputs: if ctrl_input.abs_path is not None: self.assign_custom_ctlsigs.assign_to( io_obj=ctrl_input.abs_path, exp=ctrl_input.name) for ctrl_output in scfg.digital_ctrl_outputs + scfg.analog_ctrl_outputs: self.assign_custom_ctlsigs.assign_to(io_obj=ctrl_output.name, exp=ctrl_output.abs_path) ###################################################### # Manage trace port Module ###################################################### probes = scfg.digital_probes + scfg.analog_probes + [ scfg.time_probe ] + [scfg.dec_cmp] ## Instantiate all probe signals self.inst_probesigs = SVAPI() for probe in probes: self.inst_probesigs.gen_signal(probe) ## Instantiate traceport module self.num_probes = len(probes) self.trap_inst_ifc = SVAPI() trap_inst = ModuleInst(api=self.trap_inst_ifc, name='trace_port_gen') trap_inst.add_inputs(probes, connections=probes) trap_inst.add_input(scfg.emu_clk, connection=scfg.emu_clk) trap_inst.generate_instantiation() ## Assign probe signals via abs paths into design except for time probe self.assign_probesigs = SVAPI() for probe in scfg.digital_probes + scfg.analog_probes: self.assign_probesigs.assign_to(io_obj=probe, exp=probe.abs_path) ###################################################### # Manage emulation clks Module ###################################################### ## Instantiate all emulation clk signals self.inst_emu_clk_sigs = SVAPI() clk_io_pairs = [] for derived_clk in scfg.clk_derived: if derived_clk.abspath_gated_clk is None: continue clk_val = digsig(f'clk_val_{derived_clk.name}') clk = digsig(f'clk_{derived_clk.name}') self.inst_emu_clk_sigs.gen_signal(clk_val) self.inst_emu_clk_sigs.gen_signal(clk) clk_io_pairs.append((clk_val, clk)) # add default oscillator signals, in case default oscillator was used if self.use_default_oscillator: clk_val = digsig(f'clk_val_default_osc') clk = digsig(f'clk_default_osc') self.inst_emu_clk_sigs.gen_signal(clk_val) self.inst_emu_clk_sigs.gen_signal(clk) clk_io_pairs.append((clk_val, clk)) ## Instantiate gen emulation clk module self.emu_clks_inst_ifc = SVAPI() emu_clks_inst = ModuleInst(api=self.emu_clks_inst_ifc, name="gen_emu_clks") emu_clks_inst.add_input(scfg.emu_clk_2x, connection=scfg.emu_clk_2x) emu_clks_inst.add_output(scfg.emu_clk, connection=scfg.emu_clk) for clk_val, clk in clk_io_pairs: emu_clks_inst.add_input(clk_val, connection=clk_val) emu_clks_inst.add_output(clk, connection=clk) emu_clks_inst.generate_instantiation() ###################################################### # Manage default oscillator module ###################################################### emu_dt = digsig('emu_dt', width=pcfg.cfg.dt_width) dt_req_default_osc = DigitalSignal(name=f'dt_req_default_osc', abspath='', width=pcfg.cfg.dt_width, signed=False) if scfg.use_default_oscillator: # instantiate API self.def_osc_api = SVAPI() # generate clock and reset signals # instantiate the default oscillator def_osc_inst = ModuleInst(api=self.def_osc_api, name='osc_model_anasymod', inst_name='def_osc_i') emu_dt_req = digsig('emu_dt_req', width=pcfg.cfg.dt_width) def_osc_inst.add_output(scfg.emu_clk, connection=scfg.emu_clk) def_osc_inst.add_output(scfg.reset_ctrl, connection=scfg.reset_ctrl) def_osc_inst.add_output(emu_dt, connection=emu_dt) def_osc_inst.add_output(emu_dt_req, connection=dt_req_default_osc) def_osc_inst.add_output(digsig('cke'), connection=digsig('clk_val_default_osc')) def_osc_inst.generate_instantiation() else: self.def_osc_api = None ###################################################### # Manage time manager Module ###################################################### ## Instantiate all time manager signals self.inst_timemanager_sigs = SVAPI() self.inst_timemanager_sigs.gen_signal(emu_dt) dt_reqs = [] for derived_clk in scfg.clk_derived: if derived_clk.abspath_dt_req is None: continue dt_req_sig = digsig(f'dt_req_{derived_clk.name}', width=pcfg.cfg.dt_width) self.inst_timemanager_sigs.gen_signal(dt_req_sig) dt_reqs.append(dt_req_sig) # add input for anasymod control dt request signal dt_req_stall = DigitalSignal(name=f'dt_req_stall', abspath='', width=pcfg.cfg.dt_width, signed=False) dt_reqs.append(dt_req_stall) # add input for dt request signal, in case a default oscillator is used if scfg.use_default_oscillator: dt_reqs.append(dt_req_default_osc) ## Instantiate time manager module self.time_manager_inst_ifc = SVAPI() time_manager_inst = ModuleInst(api=self.time_manager_inst_ifc, name='gen_time_manager') time_manager_inst.add_input(scfg.emu_clk, connection=scfg.emu_clk) time_manager_inst.add_input(scfg.reset_ctrl, connection=scfg.reset_ctrl) time_manager_inst.add_output(scfg.time_probe, scfg.time_probe) time_manager_inst.add_output(emu_dt, emu_dt) for dt_req_sig in dt_reqs: time_manager_inst.add_input(dt_req_sig, connection=dt_req_sig) time_manager_inst.generate_instantiation() ###################################################### # Control module ###################################################### self.ctrl_anasymod_inst_ifc = SVAPI() ctrl_anasymod_inst = ModuleInst(api=self.ctrl_anasymod_inst_ifc, name='ctrl_anasymod', inst_name='ctrl_anasymod_i') ctrl_anasymod_inst.add_input(scfg.emu_ctrl_data, connection=scfg.emu_ctrl_data) ctrl_anasymod_inst.add_input(scfg.emu_ctrl_mode, connection=scfg.emu_ctrl_mode) ctrl_anasymod_inst.add_input(scfg.time_probe, connection=scfg.time_probe) ctrl_anasymod_inst.add_input(scfg.dec_thr_ctrl, connection=scfg.dec_thr_ctrl) ctrl_anasymod_inst.add_input(scfg.emu_clk, connection=scfg.emu_clk) ctrl_anasymod_inst.add_input(scfg.reset_ctrl, connection=scfg.reset_ctrl) ctrl_anasymod_inst.add_output(scfg.dec_cmp, connection=scfg.dec_cmp) ctrl_anasymod_inst.add_output(dt_req_stall, connection=dt_req_stall) ctrl_anasymod_inst.generate_instantiation() # indicate whether TSTOP_MSDSL should be used self.use_tstop = target.cfg.tstop is not None ##################################################### # Instantiate testbench ##################################################### self.tb_inst_ifc = SVAPI() tb_inst = ModuleInst(api=self.tb_inst_ifc, name='tb') tb_inst.add_inputs(scfg.clk_independent, connections=scfg.clk_independent) tb_inst.generate_instantiation() ##################################################### # CPU debug mode ##################################################### self.dump_debug_signals = SVAPI() if pcfg.cfg.cpu_debug_mode: dbg_mods_list = pcfg.cfg.cpu_debug_hierarchies if isinstance(dbg_mods_list, list): for dbg_module in dbg_mods_list: if isinstance(dbg_module, list): self.dump_debug_signals.writeln( f'$dumpvars({dbg_module[0]}, {dbg_module[1]});') elif isinstance(dbg_module, int) and len( dbg_mods_list ) == 2: # only one single debug module was provided self.dump_debug_signals.writeln( f'$dumpvars({dbg_mods_list[0]}, {dbg_mods_list[1]});' ) break else: raise Exception( f'ERROR: unexpected format for cpu_debug_hierarchies attribute of ' f'project_config: {dbg_mods_list}, expecting a list including <depth>, ' f'<path_to_module> or a lists of such a list.') elif not dbg_mods_list: self.dump_debug_signals.writeln(f'$dumpvars(0, top.tb_i);') else: raise Exception( f'ERROR: unexpected format for cpu_debug_hierarchies attribute of ' f'project_config: {dbg_mods_list}, expecting tuple, list or None' ) TEMPLATE_TEXT = '''
def __init__(self, scfg: StructureConfig): super().__init__(trim_blocks=True, lstrip_blocks=True) ctrl_inputs = scfg.analog_ctrl_inputs + scfg.digital_ctrl_inputs ctrl_outputs = scfg.analog_ctrl_outputs + scfg.digital_ctrl_outputs ##################################################### # Define module ios ##################################################### self.module_ifc = SVAPI() self.zynq_gpio = TemplZynqGPIO() module = ModuleInst(api=self.module_ifc, name="sim_ctrl_gen") module.add_inputs(ctrl_outputs) module.add_outputs(ctrl_inputs) module.add_input(scfg.emu_clk) if not scfg.is_ultrascale: module.add_inouts(TemplZynqGPIO.EXT_IOS) module.generate_header() ctrl_inputs = scfg.analog_ctrl_inputs + scfg.digital_ctrl_inputs ctrl_outputs = scfg.analog_ctrl_outputs + scfg.digital_ctrl_outputs ##################################################### # PC sim control section ##################################################### ## Custom control IOs for pc sim control module self.pc_sim_crtl_ifc = SVAPI() # Only generate instantiation if there is any custom ctrl signal available ctrl_signals = ctrl_outputs + ctrl_inputs custom_ctrl_signals = [] for ctrl_signal in ctrl_signals: if not ctrl_signal.name in scfg.special_ctrl_ios: custom_ctrl_signals.append(ctrl_signal) if len(custom_ctrl_signals) != 0: sim_ctrl_module = ModuleInst(api=self.pc_sim_crtl_ifc, name="sim_ctrl") for ctrl_output in ctrl_outputs: if ctrl_output.name not in scfg.special_ctrl_ios: sim_ctrl_module.add_input(ctrl_output, connection=ctrl_output) for ctrl_input in ctrl_inputs: if ctrl_input.name not in scfg.special_ctrl_ios: sim_ctrl_module.add_output(ctrl_input, connection=ctrl_input) sim_ctrl_module.generate_instantiation() # set number of clk cycles for initial reset self.rst_clkcycles = scfg.cfg.rst_clkcycles ##################################################### # FPGA sim control section ##################################################### # instantiation of register map module self.reg_map_inst = SVAPI() reg_map = ModuleInst(api=self.reg_map_inst, name="reg_map") reg_map.add_input(io_obj=DigitalSignal(name='clk', width=1, abspath=None), connection=DigitalSignal(name='emu_clk', width=1, abspath=None)) reg_map.add_input(io_obj=self.zynq_gpio.o_ctrl, connection=self.zynq_gpio.o_ctrl) reg_map.add_output(io_obj=self.zynq_gpio.o_data, connection=self.zynq_gpio.o_data) reg_map.add_input(io_obj=self.zynq_gpio.i_ctrl, connection=self.zynq_gpio.i_ctrl) reg_map.add_input(io_obj=self.zynq_gpio.i_data, connection=self.zynq_gpio.i_data) reg_map.add_outputs(io_objs=ctrl_inputs, connections=ctrl_inputs) reg_map.add_inputs(io_objs=ctrl_outputs, connections=ctrl_outputs) reg_map.generate_instantiation() # instantiation of bd self.bd_inst = SVAPI() bd = ModuleInst(api=self.bd_inst, name=self.zynq_gpio.design_name) bd.add_output(io_obj=self.zynq_gpio.o_ctrl, connection=self.zynq_gpio.o_ctrl) bd.add_input(io_obj=self.zynq_gpio.o_data, connection=self.zynq_gpio.o_data) bd.add_output(io_obj=self.zynq_gpio.i_ctrl, connection=self.zynq_gpio.i_ctrl) bd.add_output(io_obj=self.zynq_gpio.i_data, connection=self.zynq_gpio.i_data) if not scfg.is_ultrascale: bd.add_inouts(io_objs=TemplZynqGPIO.EXT_IOS, connections=TemplZynqGPIO.EXT_IOS) bd.generate_instantiation()