text: #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 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":
          print("Done booting Linux")
          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()))
  