| #Copyright (c) 2020 The Regents of the University of California. |
| #All Rights Reserved |
| # |
| # 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. |
| # |
| |
| |
| """ Script to run GAP Benchmark suites workloads. |
| The workloads have two modes: synthetic and real graphs. |
| """ |
| |
| import sys |
| import time |
| |
| import m5 |
| import m5.ticks |
| from m5.objects import * |
| |
| import argparse |
| |
| from system import * |
| |
| def parse_arguments(): |
| parser = argparse.ArgumentParser(description= |
| "gem5 config file to run GAPBS") |
| parser.add_argument("kernel", type = str, help = "Path to vmlinux") |
| parser.add_argument("disk", type = str, |
| help = "Path to the disk image containing GAPBS") |
| parser.add_argument("cpu_type", type = str, help = "Name of the detailed CPU") |
| parser.add_argument("num_cpus", type = str, help = "Number of CPUs") |
| parser.add_argument("mem_sys", type = str, |
| help = "Memory model, Classic or MI_example") |
| parser.add_argument("benchmark", type = str, |
| help = "Name of the GAPBS") |
| parser.add_argument("synthetic", type = int, |
| help = "1 for synthetic graph, 0 for real graph") |
| parser.add_argument("graph", type = str, |
| help = "synthetic=1: integer number. synthetic=0: graph") |
| parser.add_argument("-z", "--allow-listeners", default = False, |
| action = "store_true", |
| help = "Turn on listeners (e.g. gdb listener port);" |
| "The listeners are off by default") |
| return parser.parse_args() |
| |
| |
| def writeBenchScript(dir, benchmark_name, size, synthetic): |
| """ |
| This method creates a script in dir which will be eventually |
| passed to the simulated system (to run a specific benchmark |
| at bootup). |
| """ |
| input_file_name = '{}/run_{}_{}'.format(dir, benchmark_name, size) |
| if (synthetic): |
| with open(input_file_name,"w") as f: |
| f.write('./{} -g {}\n'.format(benchmark_name, size)) |
| elif(synthetic==0): |
| with open(input_file_name,"w") as f: |
| # The workloads that are copied to the disk image using Packer |
| # should be located in /home/gem5/. |
| # Since the command running the workload will be executed with |
| # pwd = /home/gem5/gapbs, the path to the copied workload is |
| # ../{workload-name} |
| f.write('./{} -sf ../{}'.format(benchmark_name, size)) |
| |
| return input_file_name |
| |
| if __name__ == "__m5_main__": |
| args = parse_arguments() |
| |
| |
| kernel = args.kernel |
| disk = args.disk |
| cpu_type = args.cpu_type |
| num_cpus = int(args.num_cpus) |
| mem_sys = args.mem_sys |
| benchmark_name = args.benchmark |
| benchmark_size = args.graph |
| synthetic = args.synthetic |
| allow_listeners = args.allow_listeners |
| |
| if (mem_sys == "classic"): |
| system = MySystem(kernel, disk, cpu_type, num_cpus) |
| elif (mem_sys == "MI_example" or "MESI_Two_Level"): |
| system = MyRubySystem(kernel, disk, cpu_type, mem_sys, num_cpus) |
| |
| # For workitems to work correctly |
| # This will cause the simulator to exit simulation when the first work |
| # item is reached and when the first work item is finished. |
| system.work_begin_exit_count = 1 |
| system.work_end_exit_count = 1 |
| |
| # Read in the script file passed in via an option. |
| # This file gets read and executed by the simulated system after boot. |
| # Note: The disk image needs to be configured to do this. |
| |
| system.readfile = writeBenchScript(m5.options.outdir, benchmark_name, |
| benchmark_size, synthetic) |
| |
| # set up the root SimObject and start the simulation |
| root = Root(full_system = True, system = system) |
| |
| if system.getHostParallel(): |
| # Required for running kvm on multiple host cores. |
| # Uses gem5's parallel event queue feature |
| # Note: The simulator is quite picky about this number! |
| root.sim_quantum = int(1e9) # 1 ms |
| |
| if not allow_listeners: |
| m5.disableAllListeners() |
| |
| # instantiate all of the objects we've created above |
| m5.instantiate() |
| |
| print("Running the simulation") |
| exit_event = m5.simulate() |
| if exit_event.getCause() == "work started count reach": |
| m5.stats.reset() |
| start_tick = m5.curTick() |
| start_insts = system.totalInsts() |
| # switching to atomic cpu if argument cpu == atomic |
| if cpu_type != 'kvm': |
| system.switchCpus(system.cpu, system.timingCpu) |
| print("Switch to detailed cpu model") |
| else: |
| print("ROI is not annotated!") |
| print('Exiting @ tick {} because {}' |
| .format(m5.curTick(), exit_event.getCause())) |
| exit() |
| |
| exit_event = m5.simulate() |
| |
| if exit_event.getCause() == "work items exit count reached": |
| m5.stats.dump() |
| m5.stats.reset() |
| exit_event = m5.simulate() |
| m5.stats.dump() |
| m5.stats.reset() |
| print('Exiting @ tick {} because {}' |
| .format(m5.curTick(), exit_event.getCause())) |