def __init__(self, scfg: StructureConfig): super().__init__(trim_blocks=True, lstrip_blocks=True) ##################################################### # Create module interface ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="clk_gen") module.add_inputs(scfg.clk_i) module.add_output(scfg.dbg_clk) module.add_output(scfg.emu_clk_2x) module.add_outputs(scfg.clk_independent) module.generate_header() ##################################################### # Instantiate clk wizard ##################################################### self.clk_wiz_inst = SVAPI() clk_wiz = ModuleInst(api=self.clk_wiz_inst, name='clk_wiz_0') clk_wiz.add_inputs(scfg.clk_i, connections=scfg.clk_i) # handled by emu clk generator for k, port in enumerate([scfg.emu_clk_2x] + [scfg.dbg_clk] + scfg.clk_independent): clk_wiz.add_output(DigitalSignal(abspath=None, width=1, name=f'clk_out{k + 1}'), connection=port) clk_wiz.add_input(DigitalSignal(abspath=None, width=1, name='reset'), connection=r"1'b0") clk_wiz.add_output(DigitalSignal(abspath=None, width=1, name='locked'), DigitalSignal(abspath=None, width=1, name='locked')) clk_wiz.generate_instantiation() ##################################################### # Create independent clks for simulation case ##################################################### self.emu_clk = scfg.emu_clk self.independent_clks = scfg.clk_independent
def __init__(self, scfg: StructureConfig): super().__init__(trim_blocks=True, lstrip_blocks=True) probes = scfg.digital_probes + scfg.analog_probes + [scfg.time_probe] + [scfg.dec_cmp] ##################################################### # Define module ios ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="trace_port_gen") # Add probe signals module.add_inputs(probes) # Add master clk module.add_input(scfg.emu_clk) module.generate_header() ##################################################### # CPU sim control section - add dump statements ##################################################### self.probe_dumps = SVAPI() self.probe_dumps.indent() self.probe_dumps.writeln(f'initial begin') self.probe_dumps.indent() self.probe_dumps.writeln('#0;') for probe in probes: self.probe_dumps.writeln(f'$dumpvars(0, {probe.name});') self.probe_dumps.dedent() self.probe_dumps.writeln(f'end') ##################################################### # FPGA sim control section - Instantiate ila core ##################################################### # Instantiate ila core self.ila_wiz_inst = SVAPI() ila_wiz = ModuleInst(api=self.ila_wiz_inst, name="ila_0") for k, signal in enumerate(probes): # Add probe signals ila_wiz.add_input(DigitalSignal(name=f'probe{k}', abspath=None, width=signal.width), connection=signal) ila_wiz.add_input(DigitalSignal(name='clk', abspath=None, width=1), connection=scfg.emu_clk) # Add master clk ila_wiz.generate_instantiation()
def __init__(self, ps_vlnv='xilinx.com:ip:processing_system7:5.5', gpio_vlnv='xilinx.com:ip:axi_gpio:2.0', design_name='zynq_gpio', ultra_ps_vlnv='xilinx.com:ip:zynq_ultra_ps_e:3.3', is_ultrascale=False): # call the super constructor super().__init__(trim_blocks=False, lstrip_blocks=False) # save settings self.design_name = design_name self.ps_vlnv = ps_vlnv self.gpio_vlnv = gpio_vlnv self.ultra_ps_vlnv = ultra_ps_vlnv self.is_ultrascale = is_ultrascale # save IO that are used by the emulator self.o_ctrl = DigitalSignal(name='o_ctrl', width=32, abspath=None) self.o_data = DigitalSignal(name='o_data', width=32, abspath=None) self.i_ctrl = DigitalSignal(name='i_ctrl', width=32, abspath=None) self.i_data = DigitalSignal(name='i_data', width=32, abspath=None)
class TemplZynqGPIO(JinjaTempl): def __init__(self, ps_vlnv='xilinx.com:ip:processing_system7:5.5', gpio_vlnv='xilinx.com:ip:axi_gpio:2.0', design_name='zynq_gpio', ultra_ps_vlnv='xilinx.com:ip:zynq_ultra_ps_e:3.3', is_ultrascale=False): # call the super constructor super().__init__(trim_blocks=False, lstrip_blocks=False) # save settings self.design_name = design_name self.ps_vlnv = ps_vlnv self.gpio_vlnv = gpio_vlnv self.ultra_ps_vlnv = ultra_ps_vlnv self.is_ultrascale = is_ultrascale # save IO that are used by the emulator self.o_ctrl = DigitalSignal(name='o_ctrl', width=32, abspath=None) self.o_data = DigitalSignal(name='o_data', width=32, abspath=None) self.i_ctrl = DigitalSignal(name='i_ctrl', width=32, abspath=None) self.i_data = DigitalSignal(name='i_data', width=32, abspath=None) # generate text TEMPLATE_TEXT = '''\ ############################ # Create the block diagram # ############################ # Initialize create_bd_design "{{subst.design_name}}" # Instantiate IPs {% if subst.is_ultrascale %} create_bd_cell -type ip -vlnv {{subst.ultra_ps_vlnv}} zynq_ultra_ps_e_0 {% else %} create_bd_cell -type ip -vlnv {{subst.ps_vlnv}} processing_system7_0 {% endif %} create_bd_cell -type ip -vlnv {{subst.gpio_vlnv}} axi_gpio_0 create_bd_cell -type ip -vlnv {{subst.gpio_vlnv}} axi_gpio_1 # Configure IPs set_property \\ -dict [list \\ CONFIG.C_IS_DUAL {1} \\ CONFIG.C_ALL_OUTPUTS {1} \\ CONFIG.C_ALL_INPUTS_2 {1} \\ ] \\ [get_bd_cells axi_gpio_0] set_property \\ -dict [list \\ CONFIG.C_IS_DUAL {1} \\ CONFIG.C_ALL_OUTPUTS {1} \\ CONFIG.C_ALL_OUTPUTS_2 {1} \\ ] \\ [get_bd_cells axi_gpio_1] # Create ports create_bd_port -dir O -from 31 -to 0 o_ctrl create_bd_port -dir I -from 31 -to 0 o_data create_bd_port -dir O -from 31 -to 0 i_ctrl create_bd_port -dir O -from 31 -to 0 i_data # Wire up IPs {% if not subst.is_ultrascale %} connect_bd_net \\ [get_bd_pins processing_system7_0/FCLK_CLK0] \\ [get_bd_pins processing_system7_0/M_AXI_GP0_ACLK] {% endif %} connect_bd_net \\ [get_bd_ports o_ctrl] \\ [get_bd_pins axi_gpio_0/gpio_io_o] connect_bd_net \\ [get_bd_ports o_data] \\ [get_bd_pins axi_gpio_0/gpio2_io_i] connect_bd_net \\ [get_bd_ports i_ctrl] \\ [get_bd_pins axi_gpio_1/gpio_io_o] connect_bd_net \\ [get_bd_ports i_data] \\ [get_bd_pins axi_gpio_1/gpio2_io_o] #################### # Apply automation # #################### # processing system automation {% if subst.is_ultrascale %} apply_bd_automation \\ -rule xilinx.com:bd_rule:zynq_ultra_ps_e \\ -config { \\ apply_board_preset "1" \\ } \\ [get_bd_cells zynq_ultra_ps_e_0] {% else %} apply_bd_automation \\ -rule xilinx.com:bd_rule:processing_system7 \\ -config { \\ make_external "FIXED_IO, DDR" \\ apply_board_preset "1" \\ Master "Disable" \\ Slave "Disable" \\ } \\ [get_bd_cells processing_system7_0] {% endif %} # axi_gpio_0 automation {% if subst.is_ultrascale %} apply_bd_automation \\ -rule xilinx.com:bd_rule:axi4 \\ -config { \\ Clk_master {Auto} \\ Clk_slave {Auto} \\ Clk_xbar {Auto} \\ Master {/zynq_ultra_ps_e_0/M_AXI_HPM0_FPD} \\ Slave {/axi_gpio_0/S_AXI} \\ ddr_seg {Auto} \\ intc_ip {New AXI Interconnect} \\ master_apm {0}\\ } \\ [get_bd_intf_pins axi_gpio_0/S_AXI] {% else %} apply_bd_automation \\ -rule xilinx.com:bd_rule:axi4 \\ -config { \\ Clk_master {/processing_system7_0/FCLK_CLK0 (100 MHz)} \\ Clk_slave {Auto} \\ Clk_xbar {Auto} \\ Master {/processing_system7_0/M_AXI_GP0} \\ Slave {/axi_gpio_0/S_AXI} \\ intc_ip {New AXI Interconnect} \\ master_apm {0}\\ } \\ [get_bd_intf_pins axi_gpio_0/S_AXI] {% endif %} # axi_gpio_1 automation {% if subst.is_ultrascale %} apply_bd_automation \\ -rule xilinx.com:bd_rule:axi4 \\ -config { \\ Clk_master {Auto} \\ Clk_slave {Auto} \\ Clk_xbar {Auto} \\ Master {/zynq_ultra_ps_e_0/M_AXI_HPM0_FPD} \\ Slave {/axi_gpio_1/S_AXI} \\ ddr_seg {Auto} \\ intc_ip {New AXI Interconnect} \\ master_apm {0}\\ } \\ [get_bd_intf_pins axi_gpio_1/S_AXI] {% else %} apply_bd_automation \\ -rule xilinx.com:bd_rule:axi4 \\ -config { \\ Clk_master {/processing_system7_0/FCLK_CLK0 (100 MHz)} \\ Clk_slave {Auto} \\ Clk_xbar {Auto} \\ Master {/processing_system7_0/M_AXI_GP0} \\ Slave {/axi_gpio_1/S_AXI} \\ intc_ip {New AXI Interconnect} \\ master_apm {0}\\ } \\ [get_bd_intf_pins axi_gpio_1/S_AXI] {% endif %} # other automation {% if subst.is_ultrascale %} apply_bd_automation \\ -rule xilinx.com:bd_rule:axi4 \\ -config { \\ Clk_master {Auto} \\ Clk_slave {/zynq_ultra_ps_e_0/pl_clk0 (99 MHz)} \\ Clk_xbar {/zynq_ultra_ps_e_0/pl_clk0 (99 MHz)} \\ Master {/zynq_ultra_ps_e_0/M_AXI_HPM1_FPD} \\ Slave {/axi_gpio_0/S_AXI} \\ ddr_seg {Auto} \\ intc_ip {/ps8_0_axi_periph} \\ master_apm {0}\\ } \\ [get_bd_intf_pins zynq_ultra_ps_e_0/M_AXI_HPM1_FPD] {% endif %} validate_bd_design ''' # save external IOs that need to be wired to the top EXT_IOS = [ DigitalSignal(name='DDR_addr', width=15, abspath=None), DigitalSignal(name='DDR_ba', width=3, abspath=None), DigitalSignal(name='DDR_cas_n', width=1, abspath=None), DigitalSignal(name='DDR_ck_n', width=1, abspath=None), DigitalSignal(name='DDR_ck_p', width=1, abspath=None), DigitalSignal(name='DDR_cke', width=1, abspath=None), DigitalSignal(name='DDR_cs_n', width=1, abspath=None), DigitalSignal(name='DDR_dm', width=4, abspath=None), DigitalSignal(name='DDR_dq', width=32, abspath=None), DigitalSignal(name='DDR_dqs_n', width=4, abspath=None), DigitalSignal(name='DDR_dqs_p', width=4, abspath=None), DigitalSignal(name='DDR_odt', width=1, abspath=None), DigitalSignal(name='DDR_ras_n', width=1, abspath=None), DigitalSignal(name='DDR_reset_n', width=1, abspath=None), DigitalSignal(name='DDR_we_n', width=1, abspath=None), DigitalSignal(name='FIXED_IO_ddr_vrn', width=1, abspath=None), DigitalSignal(name='FIXED_IO_ddr_vrp', width=1, abspath=None), DigitalSignal(name='FIXED_IO_mio', width=54, abspath=None), DigitalSignal(name='FIXED_IO_ps_clk', width=1, abspath=None), DigitalSignal(name='FIXED_IO_ps_porb', width=1, abspath=None), DigitalSignal(name='FIXED_IO_ps_srstb', width=1, abspath=None) ]
def __init__(self, scfg: StructureConfig, pcfg: EmuConfig): super().__init__(trim_blocks=True, lstrip_blocks=True) gated_clks = [] ##################################################### # Create module interface ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="gen_emu_clks") module.add_input(scfg.emu_clk_2x) module.add_output(scfg.emu_clk) for derived_clk in scfg.clk_derived: if derived_clk.abspath_gated_clk is not None: gated_clks.append(derived_clk.name) # add IOs for default oscillator if used self.use_default_oscillator = scfg.use_default_oscillator if scfg.use_default_oscillator: module.add_input( DigitalSignal(name=f'clk_val_default_osc', width=1, abspath='')) module.add_output( DigitalSignal(name=f'clk_default_osc', width=1, abspath='')) for gated_clk in gated_clks: module.add_input( DigitalSignal(name=f'clk_val_{gated_clk}', width=1, abspath='')) module.add_output( DigitalSignal(name=f'clk_{gated_clk}', width=1, abspath='')) module.generate_header() ##################################################### # Generate other clks ##################################################### self.generated_clks = SVAPI() if gated_clks: for gated_clk in gated_clks: self.generated_clks.gen_signal(DigitalSignal( name=f'clk_unbuf_{gated_clk}', width=1, abspath=''), default_value=0) self.generated_clks.writeln(f'always @(posedge emu_clk_2x) begin') self.generated_clks.indent() for gated_clk in gated_clks: self.generated_clks.writeln( f"if (emu_clk_unbuf == 1'b0) begin") self.generated_clks.indent() self.generated_clks.writeln( f'clk_unbuf_{gated_clk} <= clk_val_{gated_clk};') self.generated_clks.dedent() self.generated_clks.writeln(f'end else begin') self.generated_clks.indent() self.generated_clks.writeln( f"clk_unbuf_{gated_clk} <= clk_unbuf_{gated_clk};") self.generated_clks.dedent() self.generated_clks.writeln(f'end') self.generated_clks.dedent() self.generated_clks.writeln(f'end') self.generated_clks.writeln(f'') self.generated_clks.writeln(f'`ifndef SIMULATION_MODE_MSDSL') self.generated_clks.indent() for k, gated_clk in enumerate(gated_clks): self.generated_clks.writeln( f'BUFG buf_{k} (.I(clk_unbuf_{gated_clk}), .O(clk_{gated_clk}));' ) self.generated_clks.dedent() self.generated_clks.writeln(f'`else') self.generated_clks.indent() for gated_clk in gated_clks: self.generated_clks.writeln( f'assign clk_{gated_clk} = clk_unbuf_{gated_clk};') self.generated_clks.dedent() self.generated_clks.writeln(f'`endif')
def _read_simctrlfile(self): """ Read all lines from simulation control file simctrl.yaml and store in structure config attributes. """ if os.path.isfile(self._simctrl_file_path): try: sigs = yaml.safe_load(open(self._simctrl_file_path, "r")) except yaml.YAMLError as exc: raise Exception(exc) else: print('No simctrl.yaml file existing, no additional probes will be available for this simulation.') return if sigs is None: print('No signals specified in simctrl.yaml.') return # Add analog probes to structure config if 'analog_probes' in sigs: print(f'Analog Probes: {list(sigs["analog_probes"].keys())}') for name, analog_probe in sigs['analog_probes'].items(): self.analog_probes.append(AnalogProbe.from_dict(name, analog_probe)) else: print(f'No Analog Probes provided.') # Add digital probes to structure config if 'digital_probes' in sigs: print(f'Digital Probes: {list(sigs["digital_probes"].keys())}') for name, digital_probe in sigs['digital_probes'].items(): self.digital_probes.append(DigitalSignal.from_dict(name, digital_probe)) else: print(f'No Digital Probes provided.') # Add digital ctrl inputs to structure config if sigs.get('digital_ctrl_inputs', None) is not None: print(f'Digital Ctrl Inputs: {list(sigs["digital_ctrl_inputs"].keys())}') for name, d_ctrl_in in sigs['digital_ctrl_inputs'].items(): d_ctrl_i = DigitalCtrlInput.from_dict(name, d_ctrl_in) d_ctrl_i.i_addr = self._assign_i_addr() self.digital_ctrl_inputs.append(d_ctrl_i) else: print(f'No Digital Ctrl Input provided.') # Add digital ctrl outputs to structure config if sigs.get('digital_ctrl_outputs', None) is not None: print(f'Digital Ctrl Outputs: {list(sigs["digital_ctrl_outputs"].keys())}') for name, d_ctrl_out in sigs['digital_ctrl_outputs'].items(): d_ctrl_o = DigitalCtrlOutput.from_dict(name, d_ctrl_out) d_ctrl_o.o_addr = self._assign_o_addr() self.digital_ctrl_outputs.append(d_ctrl_o) else: print(f'No Digital Ctrl Outputs provided.') # Add analog ctrl inputs to structure config if sigs.get('analog_ctrl_inputs', None) is not None: print(f'Analog Ctrl Inputs: {list(sigs["analog_ctrl_inputs"].keys())}') for name, a_ctrl_in in sigs['analog_ctrl_inputs'].items(): a_ctrl_i = AnalogCtrlInput.from_dict(name, a_ctrl_in) a_ctrl_i.i_addr = self._assign_i_addr() self.analog_ctrl_inputs.append(a_ctrl_i) else: print(f'No Analog Ctrl Input provided.') # Add analog ctrl outputs to structure config if sigs.get('analog_ctrl_outputs', None) is not None: print(f'Analog Ctrl Outputs: {list(sigs["analog_ctrl_outputs"].keys())}') for name, a_ctrl_out in sigs['analog_ctrl_outputs'].items(): a_ctrl_o = AnalogCtrlOutput.from_dict(name, a_ctrl_out) a_ctrl_o.o_addr = self._assign_o_addr() self.analog_ctrl_outputs.append(a_ctrl_o) else: print(f'No Analog Ctrl Outputs provided.')
def __init__(self, prj_cfg: EmuConfig, simctrl_path, can_use_default_oscillator=True): # Internal variables self.i_addr_counter = 0 self.o_addr_counter = 0 # Path to clks.yaml file self._clks_file_path = os.path.join(prj_cfg.root, 'clks.yaml') # Path to simctrl.yaml file self._simctrl_file_path = simctrl_path self.cfg = Config(prj_cfg=prj_cfg) self.cfg.update_config() ######################################################### # Manage clks ######################################################### self.emu_clk = ClkIndependent(name='emu_clk', freq=float(prj_cfg.cfg.emu_clk_freq)) self.emu_clk_2x = ClkIndependent(name='emu_clk_2x', freq=float(prj_cfg.cfg.emu_clk_freq) * 2) # multiplied by two, as emu_clk_2x is twice as fast as emu_clk self.dbg_clk = ClkIndependent(name='dbg_hub_clk', freq=float(prj_cfg.board.dbg_hub_clk_freq)) # add clk_in self.clk_i_num = len(prj_cfg.board.clk_pin) # clk_in names cannot be changed if self.clk_i_num == 2: self.clk_i = [DigitalSignal(abspath=None, width=1, name='clk_in1_p'), DigitalSignal(abspath=None, width=1, name='clk_in1_n')] elif self.clk_i_num == 1: self.clk_i = [DigitalSignal(abspath=None, width=1, name='clk_in1')] else: raise ValueError( f"Wrong number of pins for boards param 'clk_pin', expecting 1 or 2, provided:{self.clk_i_num}") # Add independent clks, that will be implemented via clk_wiz IP core for FPGA self.clk_independent = [] """ type : [ClkIndependent]""" # Add derived clks; those are aligned with emu_clk self.clk_derived = [] """ type : [ClkDerived]""" # Number of gated clks self.num_gated_clks = 0 # Number of dt requests self.num_dt_reqs = 0 self._read_clksfile() # add a default derived clock if needed if (self.num_dt_reqs == 0) and can_use_default_oscillator: self.use_default_oscillator = True else: self.use_default_oscillator = False # make note of whether this is an UltraScale board self.is_ultrascale = prj_cfg.board.is_ultrascale ######################################################### # Simulation control interfaces ######################################################### # CtrlIOs self.digital_ctrl_inputs = [] self.digital_ctrl_outputs = [] self.analog_ctrl_inputs = [] self.analog_ctrl_outputs = [] self.analog_probes = [] self.digital_probes = [] # annotate special control signals that should not # be routed to sim_ctrl self.special_ctrl_ios = set() # Add time signal representing current simulated time self.time_probe = DigitalSignal( name='emu_time', width=prj_cfg.cfg.time_width, abspath='' ) # Add DigitalCtrlInput for reset self.reset_ctrl = DigitalCtrlInput( abspath=None, name='emu_rst', width=1) self.reset_ctrl.i_addr = self._assign_i_addr() self.digital_ctrl_inputs += [self.reset_ctrl] self.special_ctrl_ios.add(self.reset_ctrl.name) # Add DigitalCtrlInput for control signal 'emu_dec_thr' to manage decimation # ratio for capturing probe samples self.dec_thr_ctrl = DigitalCtrlInput( abspath=None, name='emu_dec_thr', width=int(prj_cfg.cfg.dec_bits) ) self.dec_thr_ctrl.i_addr = self._assign_i_addr() self.digital_ctrl_inputs += [self.dec_thr_ctrl] self.special_ctrl_ios.add(self.dec_thr_ctrl.name) # Add DigitalCtrlInput for control signal 'emu_time_tgt' to run for # a specific amount of time self.emu_ctrl_data = DigitalCtrlInput( name='emu_ctrl_data', width=int(prj_cfg.cfg.time_width), abspath = None ) self.emu_ctrl_data.i_addr = self._assign_i_addr() self.digital_ctrl_inputs += [self.emu_ctrl_data] self.special_ctrl_ios.add(self.emu_ctrl_data.name) # Add DigitalCtrlInput for control signal 'emu_ctrl_mode' to run for # a specific amount of time self.emu_ctrl_mode = DigitalCtrlInput( name='emu_ctrl_mode', width=2, abspath = None ) self.emu_ctrl_mode.i_addr = self._assign_i_addr() self.digital_ctrl_inputs += [self.emu_ctrl_mode] self.special_ctrl_ios.add(self.emu_ctrl_mode.name) # Add DigitalCtrlOutput for reading the emulation time self.emu_time_vio = DigitalCtrlOutput( name='emu_time_vio', width=prj_cfg.cfg.time_width, abspath = 'emu_time' ) self.emu_time_vio.i_addr = self._assign_o_addr() self.digital_ctrl_outputs += [self.emu_time_vio] self.special_ctrl_ios.add(self.emu_time_vio.name) # Add DigitalSignal for control of signal 'emu_dec_cmp' to trigger sampling # for the ila depending on 'emu_dec_thr' self.dec_cmp = DigitalSignal( name='emu_dec_cmp', abspath='emu_dec_cmp_probe', width=1 ) self._read_simctrlfile()
def __init__(self, scfg: StructureConfig, pcfg: EmuConfig, plugin_includes: list): super().__init__(trim_blocks=True, lstrip_blocks=True) self.num_dt_reqs = scfg.num_dt_reqs self.dt_value = pcfg.cfg.dt ##################################################### # 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}') ##################################################### # Create module interface ##################################################### self.module_ifc = SVAPI() module = ModuleInst(api=self.module_ifc, name="gen_time_manager") module.add_input(scfg.emu_clk) module.add_input(scfg.reset_ctrl) module.add_output(scfg.time_probe) module.add_output( DigitalSignal(name=f'emu_dt', abspath='', width=pcfg.cfg.dt_width, signed=False)) # add inputs for external timestep requests dt_reqs = [] for derived_clk in scfg.clk_derived: if derived_clk.abspath_dt_req is not None: dt_req = DigitalSignal(name=f'dt_req_{derived_clk.name}', abspath='', width=pcfg.cfg.dt_width, signed=False) module.add_input(dt_req) dt_reqs.append(dt_req) # add input for anasymod control dt request signal dt_req = DigitalSignal(name=f'dt_req_stall', abspath='', width=pcfg.cfg.dt_width, signed=False) module.add_input(dt_req) dt_reqs.append(dt_req) # add input for dt request signal, in case a default oscillator is used if scfg.use_default_oscillator: dt_req = DigitalSignal(name=f'dt_req_default_osc', abspath='', width=pcfg.cfg.dt_width, signed=False) module.add_input(dt_req) dt_reqs.append(dt_req) module.generate_header() # generate a bit of code to take the minimum of the timestep requests self.codegen = SVAPI() self.codegen.indent() # take minimum of the timestep requests if len(dt_reqs) == 0: # Convert dt value to integer considering dt_scale dt_as_int = int(float(pcfg.cfg.dt) / float(pcfg.cfg.dt_scale)) # Represent as binary and expand to dt_width dt_as_bin = bin(dt_as_int).replace('b', '').zfill(pcfg.cfg.dt_width) # assign to the emulator timestep output self.codegen.writeln( f"assign emu_dt = {pcfg.cfg.dt_width}'b{dt_as_bin};") else: prev_min = None for k, curr_sig in enumerate(dt_reqs): if k == 0: prev_min = curr_sig.name else: # create a signal to hold temporary min result curr_min = f'__dt_req_min_{k - 1}' self.codegen.writeln( f'(* dont_touch = "true" *) logic [((`DT_WIDTH)-1):0] {curr_min};' ) # take the minimum of the previous minimum and the current signal curr_min_val = self.vlog_min(curr_sig.name, prev_min) self.codegen.writeln( f'assign {curr_min} = {curr_min_val};') # mark the current minimum as the previous minimum for the next # iteration of the loop prev_min = curr_min # assign to the emulator timestep output self.codegen.writeln(f'assign emu_dt = {prev_min};')
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()
def __init__(self, scfg): super().__init__(trim_blocks=True, lstrip_blocks=True) crtl_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() module = ModuleInst(api=self.module_ifc, name="reg_map") # Add clock clk = DigitalSignal(name='clk', width=1, abspath=None) module.add_input(io_obj=clk) o_ctrl = DigitalSignal(name='o_ctrl', width=32, abspath=None) module.add_input(io_obj=o_ctrl) o_data = DigitalSignal(name='o_data', width=32, abspath=None) module.add_output(io_obj=o_data) i_ctrl = DigitalSignal(name='i_ctrl', width=32, abspath=None) module.add_input(io_obj=i_ctrl) i_data = DigitalSignal(name='i_data', width=32, abspath=None) module.add_input(io_obj=i_data) # Add I/Os to Design (probes and Conrol Parameters) module.add_outputs(io_objs=crtl_inputs, connections=crtl_inputs) module.add_inputs(io_objs=ctrl_outputs, connections=ctrl_outputs) module.generate_header() ##################################################### # Initialize Default Values for ControlInfrastructure Parameters ##################################################### self.init_ctrlios = SVAPI() for parameter in crtl_inputs: default_signal = deepcopy(parameter) default_signal.name = str(default_signal.name) + '_def' self.init_ctrlios.gen_signal(io_obj=default_signal) self.init_ctrlios.assign_to(io_obj=default_signal, exp=default_signal.init_value) ##################################################### # Combo mux for Probes section ##################################################### # instantiation of register map module self.probes_combomux_cases = SVAPI() self.probes_combomux_cases.indent(quantity=3) for probe in ctrl_outputs: if probe.o_addr is not None: self.probes_combomux_cases.writeln(f"'d{probe.o_addr}: o_data_reg = {probe.name};") ##################################################### # Combo mux for Probes section ##################################################### # instantiation of register map module self.params_regmap = SVAPI() for param in crtl_inputs: # create a reg signal reg_signal = deepcopy(param) reg_signal.name = f'{param.name}_reg' self.params_regmap.gen_signal(reg_signal) # assign to the reg signal self.params_regmap.writeln(f'assign {param.name} = {param.name}_reg;') # update the reg signal self.params_regmap.writeln(f'''\ always @(posedge clk) begin if (i_rst == 'b1) begin {param.name}_reg <= {param.name}_def; // use VIO defaults end else if ((i_valid == 1'b1) && (i_addr == 'd{param.i_addr})) begin {param.name}_reg <= i_data; end else begin {param.name}_reg <= {param.name}_reg; end end''')
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' )
def digsig(name, width=1, signed=False): # convenience function to return a digital signal return DigitalSignal(name=f'{name}', width=width, signed=signed, abspath='')
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()