diff --git a/configs/example/arm/etrace_se.py b/configs/example/arm/etrace_se.py new file mode 100644 index 0000000000..8fa971ff84 --- /dev/null +++ b/configs/example/arm/etrace_se.py @@ -0,0 +1,191 @@ +# Copyright (c) 2016-2017, 2022-2023 Arm Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +import os +import m5 +from m5.util import addToPath +from m5.objects import * +import argparse +import shlex + +m5.util.addToPath("../..") + +from common import ObjectList + +import devices + + +def get_processes(cmd): + """Interprets commands to run and returns a list of processes""" + + cwd = os.getcwd() + multiprocesses = [] + for idx, c in enumerate(cmd): + argv = shlex.split(c) + + process = Process(pid=100 + idx, cwd=cwd, cmd=argv, executable=argv[0]) + process.gid = os.getgid() + + print("info: %d. command and arguments: %s" % (idx + 1, process.cmd)) + multiprocesses.append(process) + + return multiprocesses + + +def create(args): + """Create and configure the system object.""" + + system = devices.SimpleSeSystem( + mem_mode="timing", + ) + + # Add CPUs to the system. A cluster of CPUs typically have + # private L1 caches and a shared L2 cache. + system.cpu_cluster = devices.ArmCpuCluster( + system, + args.num_cores, + args.cpu_freq, + "1.2V", + ObjectList.cpu_list.get("O3_ARM_v7a_3_Etrace"), + devices.L1I, + devices.L1D, + devices.L2, + ) + + # Attach the elastic trace probe listener to every CPU in the cluster + for cpu in system.cpu_cluster: + cpu.attach_probe_listener(args.inst_trace_file, args.data_trace_file) + + # As elastic trace generation is enabled, make sure the memory system is + # minimal so that compute delays do not include memory access latencies. + # Configure the compulsory L1 caches for the O3CPU, do not configure + # any more caches. + system.addCaches(True, last_cache_level=1) + + # For elastic trace, over-riding Simple Memory latency to 1ns." + system.memory = SimpleMemory( + range=AddrRange(start=0, size=args.mem_size), + latency="1ns", + port=system.membus.mem_side_ports, + ) + + # Parse the command line and get a list of Processes instances + # that we can pass to gem5. + processes = get_processes(args.commands_to_run) + if len(processes) != args.num_cores: + print( + "Error: Cannot map %d command(s) onto %d CPU(s)" + % (len(processes), args.num_cores) + ) + sys.exit(1) + + system.workload = SEWorkload.init_compatible(processes[0].executable) + + # Assign one workload to each CPU + for cpu, workload in zip(system.cpu_cluster.cpus, processes): + cpu.workload = workload + + return system + + +def main(): + parser = argparse.ArgumentParser(epilog=__doc__) + + parser.add_argument( + "commands_to_run", + metavar="command(s)", + nargs="+", + help="Command(s) to run", + ) + parser.add_argument( + "--inst-trace-file", + action="store", + type=str, + help="""Instruction fetch trace file input to + Elastic Trace probe in a capture simulation and + Trace CPU in a replay simulation""", + default="fetchtrace.proto.gz", + ) + parser.add_argument( + "--data-trace-file", + action="store", + type=str, + help="""Data dependency trace file input to + Elastic Trace probe in a capture simulation and + Trace CPU in a replay simulation""", + default="deptrace.proto.gz", + ) + parser.add_argument("--cpu-freq", type=str, default="4GHz") + parser.add_argument( + "--num-cores", type=int, default=1, help="Number of CPU cores" + ) + parser.add_argument( + "--mem-size", + action="store", + type=str, + default="2GB", + help="Specify the physical memory size", + ) + + args = parser.parse_args() + + # Create a single root node for gem5's object hierarchy. There can + # only exist one root node in the simulator at any given + # time. Tell gem5 that we want to use syscall emulation mode + # instead of full system mode. + root = Root(full_system=False) + + # Populate the root node with a system. A system corresponds to a + # single node with shared memory. + root.system = create(args) + + # Instantiate the C++ object hierarchy. After this point, + # SimObjects can't be instantiated anymore. + m5.instantiate() + + # Start the simulator. This gives control to the C++ world and + # starts the simulator. The returned event tells the simulation + # script why the simulator exited. + event = m5.simulate() + + # Print the reason for the simulation exit. Some exit codes are + # requests for service (e.g., checkpoints) from the simulation + # script. We'll just ignore them here and exit. + print(f"{event.getCause()} ({event.getCode()}) @ {m5.curTick()}") + + +if __name__ == "__m5_main__": + main()