Example #1
0
    def __init__(self, prefix, persistent, sim_cfg_file_name):
        self._prefix = prefix
        sim_cfg_file_name = abspath(sim_cfg_file_name)
        self._sim_cfg_file_name = sim_cfg_file_name

        prefix = (
            self._prefix
        )  # Avoid circular dependency inhibiting process destruction
        env = self.get_env()

        def create_process(ident):
            return Process(
                [
                    join(prefix, "vsim"),
                    "-c",
                    "-l",
                    join(dirname(sim_cfg_file_name), "transcript%i" % ident),
                    "-do",
                    abspath(join(dirname(__file__), "tcl_read_eval_loop.tcl")),
                ],
                cwd=dirname(sim_cfg_file_name),
                env=env,
            )

        if persistent:
            self._persistent_shell = PersistentTclShell(create_process=create_process)
        else:
            self._persistent_shell = None
Example #2
0
    def __init__(self, prefix, persistent, gui, sim_cfg_file_name):
        self._prefix = prefix
        sim_cfg_file_name = abspath(sim_cfg_file_name)
        self._gui = gui
        self._sim_cfg_file_name = sim_cfg_file_name

        prefix = self._prefix  # Avoid circular dependency inhibiting process destruction

        def create_process(ident):
            return Process([join(prefix, "vsim"), "-c",
                            "-l", join(dirname(sim_cfg_file_name), "transcript%i" % ident),
                            "-do", abspath(join(dirname(__file__), "tcl_read_eval_loop.tcl"))],
                           cwd=dirname(sim_cfg_file_name))

        if persistent:
            self._persistent_shell = PersistentTclShell(create_process=create_process)
        else:
            self._persistent_shell = None
Example #3
0
class VsimSimulatorMixin(object):
    """
    A Mixin class for parts that are common to vsim/TCL based
    simulators such as modelsim and rivierapro
    """

    def __init__(self, prefix, persistent, sim_cfg_file_name):
        self._prefix = prefix
        sim_cfg_file_name = abspath(sim_cfg_file_name)
        self._sim_cfg_file_name = sim_cfg_file_name

        prefix = self._prefix  # Avoid circular dependency inhibiting process destruction
        env = self.get_env()

        def create_process(ident):
            return Process([join(prefix, "vsim"), "-c",
                            "-l", join(dirname(sim_cfg_file_name), "transcript%i" % ident),
                            "-do", abspath(join(dirname(__file__), "tcl_read_eval_loop.tcl"))],
                           cwd=dirname(sim_cfg_file_name),
                           env=env)

        if persistent:
            self._persistent_shell = PersistentTclShell(create_process=create_process)
        else:
            self._persistent_shell = None

    @staticmethod
    def _create_restart_function():
        """"
        Create the vunit_restart function to recompile and restart the simulation

        This function is quite complicated to work around limitations
        of modelsim not being able to change working directory.

        Thus python is called with an explicit command string that in
        turn call the python command we actually wanted but in the
        correct working directory using subprocess.call

        -u flag is needed for continuous output
        """
        recompile_command = [
            sys.executable,
            "-u",
            sys.argv[0],
            "--compile"]

        # Strip --clean from re-compile command
        # Leave other arguments intact since users can add custom CLI options
        recompile_command += [arg for arg in sys.argv[1:]
                              if arg != "--clean"]

        recompile_command_visual = " ".join(recompile_command)

        # stderr is intentionally re-directed to stdout so that the tcl's catch
        # relies on the return code from the python process rather than being
        # tricked by output going to stderr.  See issue #228.
        recompile_command_eval = [
            "%s" % sys.executable,
            "-u",
            "-c",
            ("import sys;"
             "import subprocess;"
             "exit(subprocess.call(%r, "
             "cwd=%r, "
             "bufsize=0, "
             "universal_newlines=True, "
             "stdout=sys.stdout, "
             "stderr=sys.stdout))") % (recompile_command, abspath(os.getcwd()))]
        recompile_command_eval_tcl = " ".join(["{%s}" % part for part in recompile_command_eval])

        tcl = """
proc vunit_compile {} {
    set cmd_show {%s}
    puts "Re-compiling using command ${cmd_show}"

    set chan [open |[list %s] r]

    while {[gets $chan line] >= 0} {
        puts $line
    }

    if {[catch {close $chan} error_msg]} {
        puts "Re-compile failed"
        puts ${error_msg}
        return true
    } else {
        puts "Re-compile finished"
        return false
    }
}

proc vunit_restart {} {
    if {![vunit_compile]} {
        _vunit_sim_restart
        vunit_run
    }
}
""" % (recompile_command_visual, recompile_command_eval_tcl)
        return tcl

    def _create_common_script(self,
                              test_suite_name,
                              config,
                              script_path,
                              output_path):
        """
        Create tcl script with functions common to interactive and batch modes
        """
        tcl = """
proc vunit_help {} {
    puts {List of VUnit commands:}
    puts {vunit_help}
    puts {  - Prints this help}
    puts {vunit_load [vsim_extra_args]}
    puts {  - Load design with correct generics for the test}
    puts {  - Optional first argument are passed as extra flags to vsim}
    puts {vunit_user_init}
    puts {  - Re-runs the user defined init file}
    puts {vunit_run}
    puts {  - Run test, must do vunit_load first}
    puts {vunit_compile}
    puts {  - Recompiles the source files}
    puts {vunit_restart}
    puts {  - Recompiles the source files}
    puts {  - and re-runs the simulation if the compile was successful}
}

proc vunit_run {} {
    if {[catch {_vunit_run} failed_or_err]} {
        echo $failed_or_err
        return true;
    }

    if {![is_test_suite_done]} {
        echo
        echo "Test Run Failed!"
        echo
        _vunit_run_failure;
        return true;
    }

    return false;
}

"""
        tcl += self._create_init_files_after_load(config)
        tcl += self._create_load_function(test_suite_name, config, script_path)
        tcl += get_is_test_suite_done_tcl(get_result_file_name(output_path))
        tcl += self._create_run_function()
        tcl += self._create_restart_function()
        return tcl

    @staticmethod
    def _create_batch_script(common_file_name, load_only=False):
        """
        Create tcl script to run in batch mode
        """
        batch_do = ""
        batch_do += "onerror {quit -code 1}\n"
        batch_do += "source \"%s\"\n" % fix_path(common_file_name)
        batch_do += "set failed [vunit_load]\n"
        batch_do += "if {$failed} {quit -code 1}\n"
        if not load_only:
            batch_do += "set failed [vunit_run]\n"
            batch_do += "if {$failed} {quit -code 1}\n"
        batch_do += "quit -code 0\n"
        return batch_do

    def _create_init_files_after_load(self, config):
        """
        Create the _vunit_source_init_files_after_load function which sources the user defined TCL file in
        simulator_name.init_files.after_load
        """
        opt_name = self.name + ".init_files.after_load"
        init_files = config.sim_options.get(opt_name, [])
        tcl = "proc _vunit_source_init_files_after_load {} {\n"
        for init_file in init_files:
            tcl += self._source_tcl_file(init_file, config, opt_name)
        tcl += "    return 0\n"
        tcl += "}\n"
        return tcl

    def _create_user_init_function(self, config):
        """
        Create the vunit_user_init function which sources the user defined TCL file in
        simulator_name.init_file.gui
        """
        opt_name = self.name + ".init_file.gui"
        init_file = config.sim_options.get(opt_name, None)
        tcl = "proc vunit_user_init {} {\n"
        if init_file is not None:
            tcl += self._source_tcl_file(init_file, config, opt_name)
        tcl += "    return 0\n"
        tcl += "}\n"
        return tcl

    @staticmethod
    def _source_tcl_file(file_name, config, message):
        """
        Create TCL to source a file and catch errors
        Also defines the vunit_tb_path variable as the config.tb_path
        """
        template = """
    set vunit_tb_path "%s"
    set file_name "%s"
    puts "Sourcing file ${file_name} from %s"
    if {[catch {source ${file_name}} error_msg]} {
        puts "Sourcing ${file_name} failed"
        puts ${error_msg}
        return true
    }
"""
        tcl = template % (fix_path(abspath(config.tb_path)),
                          fix_path(abspath(file_name)),
                          message)
        return tcl

    def _create_gui_script(self, common_file_name, config):
        """
        Create the user facing script which loads common functions and prints a help message
        """
        tcl = 'source "%s"\n' % fix_path(common_file_name)
        tcl += self._create_user_init_function(config)
        tcl += "if {![vunit_load]} {\n"
        tcl += "  vunit_user_init\n"
        tcl += "  vunit_help\n"
        tcl += "}\n"
        return tcl

    def _run_batch_file(self, batch_file_name, gui=False):
        """
        Run a test bench in batch by invoking a new vsim process from the command line
        """

        try:
            args = [join(self._prefix, "vsim"), "-gui" if gui else "-c",
                    "-l", join(dirname(batch_file_name), "transcript"),
                    '-do', "source \"%s\"" % fix_path(batch_file_name)]

            proc = Process(args, cwd=dirname(self._sim_cfg_file_name))
            proc.consume_output()
        except Process.NonZeroExitCode:
            return False
        return True

    def _run_persistent(self, common_file_name, load_only=False):
        """
        Run a test bench using the persistent vsim process
        """
        try:
            self._persistent_shell.execute('source "%s"' % fix_path(common_file_name))
            self._persistent_shell.execute("set failed [vunit_load]")
            if self._persistent_shell.read_var("failed") == '1':
                return False

            run_ok = True
            if not load_only:
                self._persistent_shell.execute("set failed [vunit_run]")
                run_ok = self._persistent_shell.read_var("failed") != '1'
            self._persistent_shell.execute("quit -sim")
            return run_ok
        except Process.NonZeroExitCode:
            return False

    def simulate(self, output_path, test_suite_name, config, elaborate_only):
        """
        Run a test bench
        """
        script_path = join(output_path, self.name)

        common_file_name = join(script_path, "common.do")
        gui_file_name = join(script_path, "gui.do")
        batch_file_name = join(script_path, "batch.do")

        write_file(common_file_name,
                   self._create_common_script(test_suite_name,
                                              config,
                                              script_path,
                                              output_path))
        write_file(gui_file_name,
                   self._create_gui_script(common_file_name, config))
        write_file(batch_file_name,
                   self._create_batch_script(common_file_name, elaborate_only))

        if self._gui:
            return self._run_batch_file(gui_file_name, gui=True)

        if self._persistent_shell is not None:
            return self._run_persistent(common_file_name, load_only=elaborate_only)

        return self._run_batch_file(batch_file_name)
Example #4
0
class VsimSimulatorMixin(object):
    """
    A Mixin class for parts that are common to vsim/TCL based
    simulators such as modelsim and rivierapro
    """

    def __init__(self, prefix, persistent, gui, sim_cfg_file_name):
        self._prefix = prefix
        sim_cfg_file_name = abspath(sim_cfg_file_name)
        self._gui = gui
        self._sim_cfg_file_name = sim_cfg_file_name

        prefix = self._prefix  # Avoid circular dependency inhibiting process destruction

        def create_process(ident):
            return Process([join(prefix, "vsim"), "-c",
                            "-l", join(dirname(sim_cfg_file_name), "transcript%i" % ident),
                            "-do", abspath(join(dirname(__file__), "tcl_read_eval_loop.tcl"))],
                           cwd=dirname(sim_cfg_file_name))

        if persistent:
            self._persistent_shell = PersistentTclShell(create_process=create_process)
        else:
            self._persistent_shell = None

    @staticmethod
    def _create_restart_function():
        """"
        Create the vunit_restart function to recompile and restart the simulation

        This function is quite complicated to work around limitations
        of modelsim not being able to change working directory.

        Thus python is called with an explicit command string that in
        turn call the python command we actually wanted but in the
        correct working directory using subprocess.call

        -u flag is needed for continous output
        """
        recompile_command = [
            sys.executable,
            "-u",
            sys.argv[0],
            "--compile"] + sys.argv[1:]
        recompile_command_visual = " ".join(recompile_command)

        recompile_command_eval = [
            "%s" % sys.executable,
            "-u",
            "-c",
            ("import sys;"
             "import subprocess;"
             "exit(subprocess.call(%r, "
             "cwd=%r, "
             "bufsize=0, "
             "universal_newlines=True, "
             "stdout=sys.stdout, "
             "stderr=sys.stderr))") % (recompile_command, abspath(os.getcwd()))]
        recompile_command_eval_tcl = " ".join(["{%s}" % part for part in recompile_command_eval])

        tcl = """
proc vunit_compile {} {
    set cmd_show {%s}
    puts "Re-compiling using command ${cmd_show}"

    set chan [open |[list %s] r]

    while {[gets $chan line] >= 0} {
        puts $line
    }

    if {[catch {close $chan} error_msg]} {
        puts "Re-compile failed"
        puts ${error_msg}
        return 1
    } else {
        puts "Re-compile finished"
        return 0
    }
}

proc vunit_restart {} {
    if {![vunit_compile]} {
        _vunit_sim_restart
        vunit_run
    }
}
""" % (recompile_command_visual, recompile_command_eval_tcl)
        return tcl

    def _create_common_script(self,   # pylint: disable=too-many-arguments
                              library_name, entity_name, architecture_name,
                              config,
                              output_path):
        """
        Create tcl script with functions common to interactive and batch modes
        """
        tcl = """
proc vunit_help {} {
    puts {List of VUnit commands:}
    puts {vunit_help}
    puts {  - Prints this help}
    puts {vunit_load [vsim_extra_args]}
    puts {  - Load design with correct generics for the test}
    puts {  - Optional first argument are passed as extra flags to vsim}
    puts {vunit_run}
    puts {  - Run test, must do vunit_load first}
    puts {vunit_compile}
    puts {  - Recompiles the source files}
    puts {vunit_restart}
    puts {  - Recompiles the source files}
    puts {  - and re-runs the simulation if the compile was successful}
}
"""
        tcl += self._create_load_function(library_name, entity_name, architecture_name,
                                          config, output_path)
        tcl += self._create_run_function(config)
        tcl += self._create_restart_function()
        return tcl

    @staticmethod
    def _create_batch_script(common_file_name, load_only=False):
        """
        Create tcl script to run in batch mode
        """
        batch_do = ""
        batch_do += "onerror {quit -code 1}\n"
        batch_do += "source \"%s\"\n" % fix_path(common_file_name)
        batch_do += "set failed [vunit_load]\n"
        batch_do += "if {$failed} {quit -code 1}\n"
        if not load_only:
            batch_do += "set failed [vunit_run]\n"
            batch_do += "if {$failed} {quit -code 1}\n"
        batch_do += "quit -code 0\n"
        return batch_do

    @staticmethod
    def _create_gui_script(common_file_name):
        """
        Create the user facing script which loads common functions and prints a help message
        """
        tcl = """
source "%s"
if {![vunit_load]} {
  vunit_help
}
""" % fix_path(common_file_name)
        return tcl

    def _run_batch_file(self, batch_file_name, gui=False):
        """
        Run a test bench in batch by invoking a new vsim process from the command line
        """

        try:
            args = [join(self._prefix, "vsim"), "-gui" if gui else "-c",
                    "-l", join(dirname(batch_file_name), "transcript"),
                    '-do', "source \"%s\"" % fix_path(batch_file_name)]

            proc = Process(args, cwd=dirname(self._sim_cfg_file_name))
            proc.consume_output()
        except Process.NonZeroExitCode:
            return False
        return True

    def _run_persistent(self, common_file_name, load_only=False):
        """
        Run a test bench using the persistent vsim process
        """
        try:
            self._persistent_shell.execute('source "%s"' % fix_path(common_file_name))
            self._persistent_shell.execute("set failed [vunit_load]")
            if self._persistent_shell.read_var("failed") == '1':
                return False

            run_ok = True
            if not load_only:
                self._persistent_shell.execute("set failed [vunit_run]")
                run_ok = self._persistent_shell.read_var("failed") != '1'
            self._persistent_shell.execute("quit -sim")
            return run_ok
        except Process.NonZeroExitCode:
            return False

    def simulate(self, output_path,  # pylint: disable=too-many-arguments
                 library_name, entity_name, architecture_name, config, elaborate_only):
        """
        Run a test bench
        """
        sim_output_path = abspath(join(output_path, self.name))
        common_file_name = join(sim_output_path, "common.do")
        gui_file_name = join(sim_output_path, "gui.do")
        batch_file_name = join(sim_output_path, "batch.do")

        write_file(common_file_name,
                   self._create_common_script(library_name,
                                              entity_name,
                                              architecture_name,
                                              config,
                                              output_path))
        write_file(gui_file_name,
                   self._create_gui_script(common_file_name))
        write_file(batch_file_name,
                   self._create_batch_script(common_file_name, elaborate_only))

        if self._gui:
            return self._run_batch_file(gui_file_name, gui=True)
        elif self._persistent_shell is not None:
            return self._run_persistent(common_file_name, load_only=elaborate_only)
        else:
            return self._run_batch_file(batch_file_name)
Example #5
0
class VsimSimulatorMixin(object):
    """
    A Mixin class for parts that are common to vsim/TCL based
    simulators such as modelsim and rivierapro
    """

    def __init__(self, prefix, persistent, sim_cfg_file_name):
        self._prefix = prefix
        sim_cfg_file_name = abspath(sim_cfg_file_name)
        self._sim_cfg_file_name = sim_cfg_file_name

        prefix = self._prefix  # Avoid circular dependency inhibiting process destruction
        env = self.get_env()

        def create_process(ident):
            return Process([join(prefix, "vsim"), "-c",
                            "-l", join(dirname(sim_cfg_file_name), "transcript%i" % ident),
                            "-do", abspath(join(dirname(__file__), "tcl_read_eval_loop.tcl"))],
                           cwd=dirname(sim_cfg_file_name),
                           env=env)

        if persistent:
            self._persistent_shell = PersistentTclShell(create_process=create_process)
        else:
            self._persistent_shell = None

    @staticmethod
    def _create_restart_function():
        """"
        Create the vunit_restart function to recompile and restart the simulation

        This function is quite complicated to work around limitations
        of modelsim not being able to change working directory.

        Thus python is called with an explicit command string that in
        turn call the python command we actually wanted but in the
        correct working directory using subprocess.call

        -u flag is needed for continuous output
        """
        recompile_command = [
            sys.executable,
            "-u",
            sys.argv[0],
            "--compile"]

        # Strip --clean from re-compile command
        # Leave other arguments intact since users can add custom CLI options
        recompile_command += [arg for arg in sys.argv[1:]
                              if arg != "--clean"]

        recompile_command_visual = " ".join(recompile_command)

        # stderr is intentionally re-directed to stdout so that the tcl's catch
        # relies on the return code from the python process rather than being
        # tricked by output going to stderr.  See issue #228.
        recompile_command_eval = [
            "%s" % sys.executable,
            "-u",
            "-c",
            ("import sys;"
             "import subprocess;"
             "exit(subprocess.call(%r, "
             "cwd=%r, "
             "bufsize=0, "
             "universal_newlines=True, "
             "stdout=sys.stdout, "
             "stderr=sys.stdout))") % (recompile_command, abspath(os.getcwd()))]
        recompile_command_eval_tcl = " ".join(["{%s}" % part for part in recompile_command_eval])

        tcl = """
proc vunit_compile {} {
    set cmd_show {%s}
    puts "Re-compiling using command ${cmd_show}"

    set chan [open |[list %s] r]

    while {[gets $chan line] >= 0} {
        puts $line
    }

    if {[catch {close $chan} error_msg]} {
        puts "Re-compile failed"
        puts ${error_msg}
        return true
    } else {
        puts "Re-compile finished"
        return false
    }
}

proc vunit_restart {} {
    if {![vunit_compile]} {
        _vunit_sim_restart
        vunit_run
    }
}
""" % (recompile_command_visual, recompile_command_eval_tcl)
        return tcl

    def _create_common_script(self,
                              test_suite_name,
                              config,
                              script_path,
                              output_path):
        """
        Create tcl script with functions common to interactive and batch modes
        """
        tcl = """
proc vunit_help {} {
    puts {List of VUnit commands:}
    puts {vunit_help}
    puts {  - Prints this help}
    puts {vunit_load [vsim_extra_args]}
    puts {  - Load design with correct generics for the test}
    puts {  - Optional first argument are passed as extra flags to vsim}
    puts {vunit_user_init}
    puts {  - Re-runs the user defined init file}
    puts {vunit_run}
    puts {  - Run test, must do vunit_load first}
    puts {vunit_compile}
    puts {  - Recompiles the source files}
    puts {vunit_restart}
    puts {  - Recompiles the source files}
    puts {  - and re-runs the simulation if the compile was successful}
}

proc vunit_run {} {
    if {[catch {_vunit_run} failed_or_err]} {
        echo $failed_or_err
        return true;
    }

    if {![is_test_suite_done]} {
        echo
        echo "Test Run Failed!"
        echo
        _vunit_run_failure;
        return true;
    }

    return false;
}

"""
        tcl += self._create_init_files_after_load(config)
        tcl += self._create_load_function(test_suite_name, config, script_path)
        tcl += get_is_test_suite_done_tcl(get_result_file_name(output_path))
        tcl += self._create_run_function()
        tcl += self._create_restart_function()
        return tcl

    @staticmethod
    def _create_batch_script(common_file_name, load_only=False):
        """
        Create tcl script to run in batch mode
        """
        batch_do = ""
        batch_do += "onerror {quit -code 1}\n"
        batch_do += "source \"%s\"\n" % fix_path(common_file_name)
        batch_do += "set failed [vunit_load]\n"
        batch_do += "if {$failed} {quit -code 1}\n"
        if not load_only:
            batch_do += "set failed [vunit_run]\n"
            batch_do += "if {$failed} {quit -code 1}\n"
        batch_do += "quit -code 0\n"
        return batch_do

    def _create_init_files_after_load(self, config):
        """
        Create the _vunit_source_init_files_after_load function which sources the user defined TCL file in
        simulator_name.init_files.after_load
        """
        opt_name = self.name + ".init_files.after_load"
        init_files = config.sim_options.get(opt_name, [])
        tcl = "proc _vunit_source_init_files_after_load {} {\n"
        for init_file in init_files:
            tcl += self._source_tcl_file(init_file, config, opt_name)
        tcl += "    return 0\n"
        tcl += "}\n"
        return tcl

    def _create_user_init_function(self, config):
        """
        Create the vunit_user_init function which sources the user defined TCL file in
        simulator_name.init_file.gui
        """
        opt_name = self.name + ".init_file.gui"
        init_file = config.sim_options.get(opt_name, None)
        tcl = "proc vunit_user_init {} {\n"
        if init_file is not None:
            tcl += self._source_tcl_file(init_file, config, opt_name)
        tcl += "    return 0\n"
        tcl += "}\n"
        return tcl

    @staticmethod
    def _source_tcl_file(file_name, config, message):
        """
        Create TCL to source a file and catch errors
        Also defines the vunit_tb_path variable as the config.tb_path
        """
        template = """
    set vunit_tb_path "%s"
    set file_name "%s"
    puts "Sourcing file ${file_name} from %s"
    if {[catch {source ${file_name}} error_msg]} {
        puts "Sourcing ${file_name} failed"
        puts ${error_msg}
        return true
    }
"""
        tcl = template % (fix_path(abspath(config.tb_path)),
                          fix_path(abspath(file_name)),
                          message)
        return tcl

    def _create_gui_script(self, common_file_name, config):
        """
        Create the user facing script which loads common functions and prints a help message
        """
        tcl = 'source "%s"\n' % fix_path(common_file_name)
        tcl += self._create_user_init_function(config)
        tcl += "if {![vunit_load]} {\n"
        tcl += "  vunit_user_init\n"
        tcl += "  vunit_help\n"
        tcl += "}\n"
        return tcl

    def _run_batch_file(self, batch_file_name, gui=False):
        """
        Run a test bench in batch by invoking a new vsim process from the command line
        """

        try:
            args = [join(self._prefix, "vsim"), "-gui" if gui else "-c",
                    "-l", join(dirname(batch_file_name), "transcript"),
                    '-do', "source \"%s\"" % fix_path(batch_file_name)]

            proc = Process(args, cwd=dirname(self._sim_cfg_file_name))
            proc.consume_output()
        except Process.NonZeroExitCode:
            return False
        return True

    def _run_persistent(self, common_file_name, load_only=False):
        """
        Run a test bench using the persistent vsim process
        """
        try:
            self._persistent_shell.execute('source "%s"' % fix_path(common_file_name))
            self._persistent_shell.execute("set failed [vunit_load]")
            if self._persistent_shell.read_var("failed") == '1':
                return False

            run_ok = True
            if not load_only:
                self._persistent_shell.execute("set failed [vunit_run]")
                run_ok = self._persistent_shell.read_var("failed") != '1'
            self._persistent_shell.execute("quit -sim")
            return run_ok
        except Process.NonZeroExitCode:
            return False

    def simulate(self, output_path, test_suite_name, config, elaborate_only):
        """
        Run a test bench
        """
        script_path = join(output_path, self.name)

        common_file_name = join(script_path, "common.do")
        gui_file_name = join(script_path, "gui.do")
        batch_file_name = join(script_path, "batch.do")

        write_file(common_file_name,
                   self._create_common_script(test_suite_name,
                                              config,
                                              script_path,
                                              output_path))
        write_file(gui_file_name,
                   self._create_gui_script(common_file_name, config))
        write_file(batch_file_name,
                   self._create_batch_script(common_file_name, elaborate_only))

        if self._gui:
            return self._run_batch_file(gui_file_name, gui=True)

        if self._persistent_shell is not None:
            return self._run_persistent(common_file_name, load_only=elaborate_only)

        return self._run_batch_file(batch_file_name)