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()
Beispiel #2
0
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()