Esempio n. 1
0
    def __init__(self):
        requires(
            isa_required=ISA.X86,
            coherence_protocol_required=CoherenceProtocol.MESI_TWO_LEVEL,
        )

        warn("The X86DemoBoard is solely for demonstration purposes. "
             "This board is not known to be be representative of any "
             "real-world system. Use with caution.")

        memory = SingleChannelDDR3_1600(size="2GB")
        processor = SimpleProcessor(cpu_type=CPUTypes.TIMING, num_cores=4)
        cache_hierarchy = MESITwoLevelCacheHierarchy(
            l1d_size="32kB",
            l1d_assoc=8,
            l1i_size="32kB",
            l1i_assoc=8,
            l2_size="1MB",
            l2_assoc=16,
            num_l2_banks=1,
        )

        super().__init__(
            clk_freq="3GHz",
            processor=processor,
            memory=memory,
            cache_hierarchy=cache_hierarchy,
        )
Esempio n. 2
0
    def run(self, max_ticks: int = m5.MaxTick) -> None:
        """
        This function will start or continue the simulator run and handle exit
        events accordingly.

        :param max_ticks: The maximum number of ticks to execute per simulation
        run. If this max_ticks value is met, a MAX_TICK exit event is
        received, if another simulation exit event is met the tick count is
        reset. This is the **maximum number of ticks per simululation run**.
        """

        # We instantiate the board if it has not already been instantiated.
        self._instantiate()

        # This while loop will continue until an a generator yields True.
        while True:

            self._last_exit_event = m5.simulate(max_ticks)

            # Translate the exit event cause to the exit event enum.
            exit_enum = ExitEvent.translate_exit_status(
                self.get_last_exit_event_cause())

            # Check to see the run is corresponding to the expected execution
            # order (assuming this check is demanded by the user).
            if self._expected_execution_order:
                expected_enum = self._expected_execution_order[
                    self._exit_event_count]
                if exit_enum.value != expected_enum.value:
                    raise Exception(
                        f"Expected a '{expected_enum.value}' exit event but a "
                        f"'{exit_enum.value}' exit event was encountered.")

            # Record the current tick and exit event enum.
            self._tick_stopwatch.append((exit_enum, self.get_current_tick()))

            try:
                # If the user has specified their own generator for this exit
                # event, use it.
                exit_on_completion = next(self._on_exit_event[exit_enum])
            except StopIteration:
                # If the user's generator has ended, throw a warning and use
                # the default generator for this exit event.
                warn("User-specified generator for the exit event "
                     f"'{exit_enum.value}' has ended. Using the default "
                     "generator.")
                exit_on_completion = next(
                    self._default_on_exit_dict[exit_enum])
            except KeyError:
                # If the user has not specified their own generator for this
                # exit event, use the default.
                exit_on_completion = next(
                    self._default_on_exit_dict[exit_enum])

            self._exit_event_count += 1

            # If the generator returned True we will return from the Simulator
            # run loop.
            if exit_on_completion:
                return
Esempio n. 3
0
def fromSeconds(value):
    import _m5.core

    if not isinstance(value, float):
        raise TypeError("can't convert '%s' to type tick" % type(value))

    # once someone needs to convert to seconds, the global frequency
    # had better be fixed
    if not _m5.core.clockFrequencyFixed():
        raise AttributeError(
              "In order to do conversions, the global frequency must be fixed")

    if value == 0:
        return 0

    # convert the value from time to ticks
    value *= _m5.core.getClockFrequency()

    int_value = int(
            decimal.Decimal(value).to_integral_value( decimal.ROUND_HALF_UP))
    err = (value - int_value) / value
    if err > frequency_tolerance:
        warn("rounding error > tolerance\n    %f rounded to %d", value,
            int_value)
    return int_value
Esempio n. 4
0
    def incorporate_processor(self, board: AbstractBoard) -> None:
        if self._cpu_type == CPUTypes.KVM:
            board.kvm_vm = self.kvm_vm

        # Set the memory mode.
        if self._cpu_type == CPUTypes.TIMING or self._cpu_type == CPUTypes.O3:
            board.set_mem_mode(MemMode.TIMING)
        elif self._cpu_type == CPUTypes.KVM:
            board.set_mem_mode(MemMode.ATOMIC_NONCACHING)
        elif self._cpu_type == CPUTypes.ATOMIC:
            if board.get_cache_hierarchy().is_ruby():
                warn(
                    "Using an atomic core with Ruby will result in "
                    "'atomic_noncaching' memory mode. This will skip caching "
                    "completely."
                )
            else:
                board.set_mem_mode(MemMode.ATOMIC)
        else:
            raise NotImplementedError

        if self._cpu_type == CPUTypes.KVM:
            # To get the KVM CPUs to run on different host CPUs
            # Specify a different event queue for each CPU
            for i, core in enumerate(self.cores):
                for obj in core.get_simobject().descendants():
                    obj.eventq_index = 0
                core.get_simobject().eventq_index = i + 1
Esempio n. 5
0
def create_network(options, ruby):

    # Allow legacy users to use garnet through garnet2.0 option
    # until next gem5 release.
    if options.network == "garnet2.0":
        warn("Usage of option 'garnet2.0' will be depracated. " \
            "Please use 'garnet' for using the latest garnet " \
            "version. Current version: 3.0")
        options.network = "garnet"

    # Set the network classes based on the command line options
    if options.network == "garnet":
        NetworkClass = GarnetNetwork
        IntLinkClass = GarnetIntLink
        ExtLinkClass = GarnetExtLink
        RouterClass = GarnetRouter
        InterfaceClass = GarnetNetworkInterface

    else:
        NetworkClass = SimpleNetwork
        IntLinkClass = SimpleIntLink
        ExtLinkClass = SimpleExtLink
        RouterClass = Switch
        InterfaceClass = None

    # Instantiate the network object
    # so that the controllers can connect to it.
    network = NetworkClass(ruby_system=ruby,
                           topology=options.topology,
                           routers=[],
                           ext_links=[],
                           int_links=[],
                           netifs=[])

    return (network, IntLinkClass, ExtLinkClass, RouterClass, InterfaceClass)
def fromSeconds(value):
    if not isinstance(value, float):
        raise TypeError, "can't convert '%s' to type tick" % type(value)

    # once someone needs to convert to seconds, the global frequency
    # had better be fixed
    if not tps_fixed:
        raise AttributeError, \
              "In order to do conversions, the global frequency must be fixed"

    if value == 0:
        return 0

    # convert the value from time to ticks
    value *= tps

    int_value = int(round(value))
    err = (value - int_value) / value

    if "GEM5SIMTYPE" in environ:
        if environ["GEM5SIMTYPE"] == "GarnetStandalone":
            # Hide warn message for GarnetStandalone
            return int_value

    if err > frequency_tolerance:
        warn("rounding error > tolerance\n    %f rounded to %d", value,
             int_value)

    return int_value
Esempio n. 7
0
def _do_dot(network, outdir, dotFilename):
    callgraph = pydot.Dot(graph_type='graph', rankdir='LR')
    _dot_create(network, callgraph)
    dot_filename = os.path.join(outdir, dotFilename)
    callgraph.write(dot_filename)
    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        callgraph.write_svg(dot_filename + ".svg", prog='neato')
        callgraph.write_pdf(dot_filename + ".pdf", prog='neato')
    except:
        warn("failed to generate dot output from %s", dot_filename)
Esempio n. 8
0
def do_dot(root, outdir, dotFilename):
    if not pydot:
        return
    callgraph = pydot.Dot(graph_type='digraph')
    dot_create_nodes(root, callgraph)
    dot_create_edges(root, callgraph)
    dot_filename = os.path.join(outdir, dotFilename)
    callgraph.write(dot_filename)
    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        callgraph.write_pdf(dot_filename + ".pdf")
    except:
        warn("failed to generate pdf output from %s", dot_filename)
Esempio n. 9
0
def do_dot(root, outdir, dotFilename):
    if not pydot:
        return
    callgraph = pydot.Dot(graph_type='digraph')
    dot_create_nodes(root, callgraph)
    dot_create_edges(root, callgraph)
    dot_filename = os.path.join(outdir, dotFilename)
    callgraph.write(dot_filename)
    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        callgraph.write_pdf(dot_filename + ".pdf")
    except:
        warn("failed to generate pdf output from %s", dot_filename)
Esempio n. 10
0
    def incorporate_processor(self, board: AbstractBoard) -> None:
        if self._cpu_type == CPUTypes.KVM:
            board.kvm_vm = self.kvm_vm

        # Set the memory mode.
        if self._cpu_type == CPUTypes.TIMING or self._cpu_type == CPUTypes.O3:
            board.set_mem_mode(MemMode.TIMING)
        elif self._cpu_type == CPUTypes.KVM:
            board.set_mem_mode(MemMode.ATOMIC_NONCACHING)
        elif self._cpu_type == CPUTypes.ATOMIC:
            if is_ruby(get_runtime_coherence_protocol()):
                warn("Using an atomic core with Ruby will result in "
                     "'atomic_noncaching' memory mode. This will skip caching "
                     "completely.")
            else:
                board.set_mem_mode(MemMode.ATOMIC)
        else:
            raise NotImplementedError
Esempio n. 11
0
def do_dot(root, outdir, dotFilename):
    if not pydot:
        return
    # * use ranksep > 1.0 for for vertical separation between nodes
    # especially useful if you need to annotate edges using e.g. visio
    # which accepts svg format
    # * no need for hoizontal separation as nothing moves horizonally
    callgraph = pydot.Dot(graph_type='digraph', ranksep='1.3')
    dot_create_nodes(root, callgraph)
    dot_create_edges(root, callgraph)
    dot_filename = os.path.join(outdir, dotFilename)
    callgraph.write(dot_filename)
    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        callgraph.write_svg(dot_filename + ".svg")
        callgraph.write_pdf(dot_filename + ".pdf")
    except:
        warn("failed to generate dot output from %s", dot_filename)
Esempio n. 12
0
def do_dot(root, outdir, dotFilename):
    if not pydot:
        return
    # * use ranksep > 1.0 for for vertical separation between nodes
    # especially useful if you need to annotate edges using e.g. visio
    # which accepts svg format
    # * no need for hoizontal separation as nothing moves horizonally
    callgraph = pydot.Dot(graph_type='digraph', ranksep='1.3')
    dot_create_nodes(root, callgraph)
    dot_create_edges(root, callgraph)
    dot_filename = os.path.join(outdir, dotFilename)
    callgraph.write(dot_filename)
    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        callgraph.write_svg(dot_filename + ".svg")
        callgraph.write_pdf(dot_filename + ".pdf")
    except:
        warn("failed to generate dot output from %s", dot_filename)
Esempio n. 13
0
def do_dvfs_dot(root, outdir, dotFilename):
    if not pydot:
        warn("No dot file generated. " +
             "Please install pydot to generate the dot file and pdf.")
        return

    # There is a chance that we are unable to resolve the clock or
    # voltage domains. If so, we fail silently.
    try:
        dvfsgraph = pydot.Dot(graph_type='digraph', ranksep='1.3')
        dot_create_dvfs_nodes(root, dvfsgraph)
        dot_create_edges(root, dvfsgraph)
        dot_filename = os.path.join(outdir, dotFilename)
        dvfsgraph.write(dot_filename)
    except:
        warn("Failed to generate dot graph for DVFS domains")
        return

    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        dvfsgraph.write_svg(dot_filename + ".svg")
        dvfsgraph.write_pdf(dot_filename + ".pdf")
    except:
        warn("failed to generate dot output from %s", dot_filename)
Esempio n. 14
0
def fromSeconds(value):
    if not isinstance(value, float):
        raise TypeError, "can't convert '%s' to type tick" % type(value)

    # once someone needs to convert to seconds, the global frequency
    # had better be fixed
    if not tps_fixed:
        raise AttributeError, \
              "In order to do conversions, the global frequency must be fixed"

    if value == 0:
        return 0

    # convert the value from time to ticks
    value *= tps

    int_value = int(round(value))
    err = (value - int_value) / value
    if err > frequency_tolerance:
        warn("rounding error > tolerance\n    %f rounded to %d", value,
            int_value)
    return int_value
Esempio n. 15
0
def do_dvfs_dot(root, outdir, dotFilename):
    if not pydot:
        return

    # There is a chance that we are unable to resolve the clock or
    # voltage domains. If so, we fail silently.
    try:
        dvfsgraph = pydot.Dot(graph_type='digraph', ranksep='1.3')
        dot_create_dvfs_nodes(root, dvfsgraph)
        dot_create_edges(root, dvfsgraph)
        dot_filename = os.path.join(outdir, dotFilename)
        dvfsgraph.write(dot_filename)
    except:
        warn("Failed to generate dot graph for DVFS domains")
        return

    try:
        # dot crashes if the figure is extremely wide.
        # So avoid terminating simulation unnecessarily
        dvfsgraph.write_svg(dot_filename + ".svg")
        dvfsgraph.write_pdf(dot_filename + ".pdf")
    except:
        warn("failed to generate dot output from %s", dot_filename)
Esempio n. 16
0
                        options.ethernet_linkspeed,
                        options.ethernet_linkdelay,
                        options.etherdump);
elif len(bm) == 1:
    root = Root(full_system=True, system=test_sys)
else:
    print("Error I don't know how to create more than 2 systems.")
    sys.exit(1)

if options.timesync:
    root.time_sync_enable = True

if options.frame_capture:
    VncServer.frame_capture = True

if buildEnv['TARGET_ISA'] == "arm" and not options.bare_metal \
        and not options.dtb_filename:
    if options.machine_type not in ["VExpress_GEM5", "VExpress_GEM5_V1"]:
        warn("Can only correctly generate a dtb for VExpress_GEM5_V1 " \
             "platforms, unless custom hardware models have been equipped "\
             "with generation functionality.")

    # Generate a Device Tree
    for sysname in ('system', 'testsys', 'drivesys'):
        if hasattr(root, sysname):
            sys = getattr(root, sysname)
            sys.generateDtb(m5.options.outdir, '%s.dtb' % sysname)

Simulation.setWorkCountOptions(test_sys, options)
Simulation.run(options, root, test_sys, FutureClass)
Esempio n. 17
0
    root.sim_quantum = int(1e9)  # 1 ms

if args.timesync:
    root.time_sync_enable = True

if args.frame_capture:
    VncServer.frame_capture = True

if buildEnv['TARGET_ISA'] == "arm" and not args.bare_metal \
        and not args.dtb_filename:
    if args.machine_type not in [
            "VExpress_GEM5", "VExpress_GEM5_V1", "VExpress_GEM5_V2",
            "VExpress_GEM5_Foundation"
    ]:
        warn("Can only correctly generate a dtb for VExpress_GEM5_* " \
             "platforms, unless custom hardware models have been equipped "\
             "with generation functionality.")

    # Generate a Device Tree
    for sysname in ('system', 'testsys', 'drivesys'):
        if hasattr(root, sysname):
            sys = getattr(root, sysname)
            sys.workload.dtb_filename = \
                os.path.join(m5.options.outdir, '%s.dtb' % sysname)
            sys.generateDtb(sys.workload.dtb_filename)

if args.wait_gdb:
    test_sys.workload.wait_for_remote_gdb = True

Simulation.setWorkCountOptions(test_sys, args)
Simulation.run(args, root, test_sys, FutureClass)
Esempio n. 18
0
    type=str,
    required=True,
    help="Sumulation size the benchmark program.",
    choices=size_choices,
)

args = parser.parse_args()

# We expect the user to input the full path of the disk-image.
if args.image[0] != "/":
    # We need to get the absolute path to this file. We assume that the file is
    # present on the current working directory.
    args.image = os.path.abspath(args.image)

if not os.path.exists(args.image):
    warn("Disk image not found!")
    print("Instructions on building the disk image can be found at: ")
    print(
        "https://gem5art.readthedocs.io/en/latest/tutorials/spec-tutorial.html"
    )
    fatal("The disk-image is not found at {}".format(args.image))

# Setting up all the fixed system parameters here
# Caches: MESI Two Level Cache Hierarchy

from gem5.components.cachehierarchies.ruby.\
    mesi_two_level_cache_hierarchy import(
    MESITwoLevelCacheHierarchy,
)

cache_hierarchy = MESITwoLevelCacheHierarchy(
Esempio n. 19
0
    def __init__(
        self,
        board: AbstractBoard,
        full_system: bool = True,
        on_exit_event: Optional[Dict[Union[str, ExitEvent],
                                     Generator[Optional[bool], None,
                                               None]]] = None,
        expected_execution_order: Optional[List[ExitEvent]] = None,
    ) -> None:
        """
        :param board: The board to be simulated.
        :param full_system: Whether to run in full-system simulation or not. If
        False, the simulation will run in Syscall-Execution mode. True by
        default.
        :param on_exit_event: An optional map to specify the generator to
        execute on each exit event. The generator may yield a boolean which,
        if True, will have the Simulator exit the run loop.
        :param expected_execution_order: May be specified to check the exit
        events come in a specified order. If the order specified is not
        encountered (e.g., 'Workbegin', 'Workend', then 'Exit'), an Exception
        is thrown. If this parameter is not specified, any ordering of exit
        events is valid.

        `on_exit_event` usage notes
        ---------------------------

        The `on_exit_event` parameter specifies a Python generator for each
        exit event. `next(<generator>)` is run each time an exit event. The
        generator may yield a boolean. If this value of this boolean is True
        the Simulator run loop will exit, otherwise
        the Simulator run loop will continue execution. If the generator has
        finished (i.e. a `StopIteration` exception is thrown when
        `next(<generator>)` is executed), then the default behavior for that
        exit event is run.

        As an example, a user may specify their own exit event setup like so:

        ```
        def unique_exit_event():
            processor.switch()
            yield False
            m5.stats.dump()
            yield False
            yield True

        simulator = Simulator(
            board=board
            on_exit_event = {
                ExitEvent.Exit : unique_exit_event(),
            },
        )
        ```

        This will execute `processor.switch()` the first time an exit event is
        encountered, will dump gem5 statistics the second time an exit event is
        encountered, and will terminate the Simulator run loop the third time.

        Each exit event has a default behavior if none is specified by the
        user. These are as follows:

            * ExitEvent.EXIT:  default_exit_list
            * ExitEvent.CHECKPOINT: default_exit_list
            * ExitEvent.FAIL : default_exit_list
            * ExitEvent.SWITCHCPU: default_switch_list
            * ExitEvent.WORKBEGIN: default_workbegin_list
            * ExitEvent.WORKEND: default_workend_list
            * ExitEvent.USER_INTERRUPT: default_exit_generator
            * ExitEvent.MAX_TICK: default_exit_generator()

        These generators can be found in the `exit_event_generator.py` module.

        """

        warn("The simulate package is still in a beta state. The gem5 "
             "project does not guarantee the APIs within this package will "
             "remain consistent across upcoming releases.")

        # We specify a dictionary here outlining the default behavior for each
        # exit event. Each exit event is mapped to a generator.
        self._default_on_exit_dict = {
            ExitEvent.EXIT:
            default_exit_generator(),
            # TODO: Something else should be done here for CHECKPOINT
            ExitEvent.CHECKPOINT:
            default_exit_generator(),
            ExitEvent.FAIL:
            default_exit_generator(),
            ExitEvent.SWITCHCPU:
            default_switch_generator(processor=board.get_processor()),
            ExitEvent.WORKBEGIN:
            default_workbegin_generator(),
            ExitEvent.WORKEND:
            default_workend_generator(),
            ExitEvent.USER_INTERRUPT:
            default_exit_generator(),
            ExitEvent.MAX_TICK:
            default_exit_generator(),
        }

        if on_exit_event:
            self._on_exit_event = on_exit_event
        else:
            self._on_exit_event = self._default_on_exit_dict

        self._instantiated = False
        self._board = board
        self._full_system = full_system
        self._expected_execution_order = expected_execution_order
        self._tick_stopwatch = []

        self._last_exit_event = None
        self._exit_event_count = 0
Esempio n. 20
0
parser.add_argument(
    "--ticks",
    type = int,
    help = "Optionally put the maximum number of ticks to execute during the "\
        "ROI. It accepts an integer value."
)

args = parser.parse_args()

# The simulation may fail in the case of `mg` with class C as it uses 3.3 GB
# of memory (more information is availabe at https://arxiv.org/abs/2010.13216).
# We warn the user here.

if args.benchmark == "mg" and args.size == "C":
    warn("mg.C uses 3.3 GB of memory. Currently we are simulating 3 GB\
    of main memory in the system.")

# The simulation will fail in the case of `ft` with class C. We warn the user
# here.
elif args.benchmark == "ft" and args.size == "C":
    warn("There is not enough memory for ft.C. Currently we are\
    simulating 3 GB of main memory in the system.")

# Checking for the maximum number of instructions, if provided by the user.

# Setting up all the fixed system parameters here
# Caches: MESI Two Level Cache Hierarchy

from gem5.components.cachehierarchies.ruby.\
    mesi_two_level_cache_hierarchy import(
    MESITwoLevelCacheHierarchy,
Esempio n. 21
0
def build_test_system(np):
    cmdline = cmd_line_template()
    if buildEnv['TARGET_ISA'] == "alpha":
        test_sys = makeLinuxAlphaSystem(test_mem_mode,
                                        bm[0],
                                        options.ruby,
                                        cmdline=cmdline)
    elif buildEnv['TARGET_ISA'] == "mips":
        test_sys = makeLinuxMipsSystem(test_mem_mode, bm[0], cmdline=cmdline)
    elif buildEnv['TARGET_ISA'] == "sparc":
        test_sys = makeSparcSystem(test_mem_mode, bm[0], cmdline=cmdline)
    elif buildEnv['TARGET_ISA'] == "x86":
        test_sys = makeLinuxX86System(test_mem_mode,
                                      options.num_cpus,
                                      bm[0],
                                      options.ruby,
                                      cmdline=cmdline)
    elif buildEnv['TARGET_ISA'] == "arm":
        test_sys = makeArmSystem(
            test_mem_mode,
            options.machine_type,
            options.membus_width,
            options,
            options.num_cpus,
            bm[0],
            options.dtb_filename,
            bare_metal=options.bare_metal,
            cmdline=cmdline,
            ignore_dtb=options.generate_dtb,
            external_memory=options.external_memory_system,
            ruby=options.ruby,
            security=options.enable_security_extensions)
        if options.enable_context_switch_stats_dump:
            test_sys.enable_context_switch_stats_dump = True
    else:
        fatal("Incapable of building %s full system!", buildEnv['TARGET_ISA'])

    # Set the cache line size for the entire system
    test_sys.cache_line_size = options.cacheline_size

    # Create a top-level voltage domain
    test_sys.voltage_domain = VoltageDomain(voltage=options.sys_voltage)

    # Create a source clock for the system and set the clock period
    test_sys.clk_domain = SrcClockDomain(
        clock=options.sys_clock, voltage_domain=test_sys.voltage_domain)

    # Create a CPU voltage domain
    test_sys.cpu_voltage_domain = VoltageDomain()

    # Create a source clock for the CPUs and set the clock period
    test_sys.cpu_clk_domain = SrcClockDomain(
        clock=options.cpu_clock, voltage_domain=test_sys.cpu_voltage_domain)

    if options.kernel is not None:
        test_sys.kernel = binary(options.kernel)

    if options.script is not None:
        test_sys.readfile = options.script

    if options.lpae:
        test_sys.have_lpae = True

    if options.virtualisation:
        test_sys.have_virtualization = True

    test_sys.init_param = options.init_param

    # For now, assign all the CPUs to the same clock domain
    test_sys.cpu = [
        TestCPUClass(clk_domain=test_sys.cpu_clk_domain, cpu_id=i)
        for i in xrange(np)
    ]

    if is_kvm_cpu(TestCPUClass) or is_kvm_cpu(FutureClass):
        test_sys.kvm_vm = KvmVM()

    if options.ruby:
        bootmem = getattr(test_sys, 'bootmem', None)
        Ruby.create_system(options, True, test_sys, test_sys.iobus,
                           test_sys._dma_ports, bootmem)

        # Create a seperate clock domain for Ruby
        test_sys.ruby.clk_domain = SrcClockDomain(
            clock=options.ruby_clock, voltage_domain=test_sys.voltage_domain)

        # Connect the ruby io port to the PIO bus,
        # assuming that there is just one such port.
        test_sys.iobus.master = test_sys.ruby._io_port.slave

        for (i, cpu) in enumerate(test_sys.cpu):
            #
            # Tie the cpu ports to the correct ruby system ports
            #
            cpu.clk_domain = test_sys.cpu_clk_domain
            cpu.createThreads()
            cpu.createInterruptController()

            cpu.icache_port = test_sys.ruby._cpu_ports[i].slave
            cpu.dcache_port = test_sys.ruby._cpu_ports[i].slave

            if buildEnv['TARGET_ISA'] in ("x86", "arm"):
                cpu.itb.walker.port = test_sys.ruby._cpu_ports[i].slave
                cpu.dtb.walker.port = test_sys.ruby._cpu_ports[i].slave

            if buildEnv['TARGET_ISA'] in "x86":
                cpu.interrupts[0].pio = test_sys.ruby._cpu_ports[i].master
                cpu.interrupts[0].int_master = test_sys.ruby._cpu_ports[
                    i].slave
                cpu.interrupts[0].int_slave = test_sys.ruby._cpu_ports[
                    i].master

    else:
        if options.caches or options.l2cache:
            # By default the IOCache runs at the system clock
            test_sys.iocache = IOCache(addr_ranges=test_sys.mem_ranges)
            test_sys.iocache.cpu_side = test_sys.iobus.master
            test_sys.iocache.mem_side = test_sys.membus.slave
        elif not options.external_memory_system:
            test_sys.iobridge = Bridge(delay='50ns',
                                       ranges=test_sys.mem_ranges)
            test_sys.iobridge.slave = test_sys.iobus.master
            test_sys.iobridge.master = test_sys.membus.slave

        # Sanity check
        if options.fastmem:
            if TestCPUClass != AtomicSimpleCPU:
                fatal("Fastmem can only be used with atomic CPU!")
            if (options.caches or options.l2cache):
                fatal("You cannot use fastmem in combination with caches!")

        if options.simpoint_profile:
            if not options.fastmem:
                # Atomic CPU checked with fastmem option already
                fatal(
                    "SimPoint generation should be done with atomic cpu and fastmem"
                )
            if np > 1:
                fatal(
                    "SimPoint generation not supported with more than one CPUs"
                )

        for i in xrange(np):
            if options.fastmem:
                test_sys.cpu[i].fastmem = True
            if options.simpoint_profile:
                test_sys.cpu[i].addSimPointProbe(options.simpoint_interval)
            if options.checker:
                test_sys.cpu[i].addCheckerCpu()
            test_sys.cpu[i].createThreads()

        # If elastic tracing is enabled when not restoring from checkpoint and
        # when not fast forwarding using the atomic cpu, then check that the
        # TestCPUClass is DerivO3CPU or inherits from DerivO3CPU. If the check
        # passes then attach the elastic trace probe.
        # If restoring from checkpoint or fast forwarding, the code that does this for
        # FutureCPUClass is in the Simulation module. If the check passes then the
        # elastic trace probe is attached to the switch CPUs.
        if options.elastic_trace_en and options.checkpoint_restore == None and \
            not options.fast_forward:
            CpuConfig.config_etrace(TestCPUClass, test_sys.cpu, options)

        if buildEnv['TARGET_ISA'] != "arm" and options.workload_automation_vio:
            warn("Ignoring --workload-automation-vio. It is unsupported on "
                 "non-ARM systems.")
        elif options.workload_automation_vio:
            from m5.objects import PciVirtIO, VirtIO9PDiod
            viopci = PciVirtIO(
                pci_bus=0,
                pci_dev=test_sys.realview._num_pci_dev,
                pci_func=0,
                InterruptPin=1,
                InterruptLine=test_sys.realview._num_pci_int_line)

            test_sys.realview._num_pci_dev = test_sys.realview._num_pci_dev + 1
            test_sys.realview._num_pci_int_line = test_sys.realview._num_pci_int_line + 1

            viopci.vio = VirtIO9PDiod()
            viopci.vio.root = options.workload_automation_vio
            viopci.vio.socketPath = "/home/yqureshi/shares/local/scrap/temp"
            test_sys.realview.viopci = viopci
            test_sys.realview.viopci.dma = test_sys.iobus.slave
            test_sys.realview.viopci.pio = test_sys.iobus.master

        CacheConfig.config_cache(options, test_sys)

        MemConfig.config_mem(options, test_sys)

    return test_sys