resources: Replace SimpleOpts to argparse in NPB configs

Change-Id: If70cb0144c5486084091dd8fb2ed1cdcb2144138
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5-resources/+/48160
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Tested-by: Bobby R. Bruce <bbruce@ucdavis.edu>
diff --git a/src/npb/configs/run_npb.py b/src/npb/configs/run_npb.py
index 12b43de..07f4822 100755
--- a/src/npb/configs/run_npb.py
+++ b/src/npb/configs/run_npb.py
@@ -35,6 +35,7 @@
     number of instructions executed in the ROI. It also tracks how much
     wallclock and simulated time.
 """
+import argparse
 import errno
 import os
 import sys
@@ -43,9 +44,6 @@
 import m5.ticks
 from m5.objects import *
 
-sys.path.append('gem5/configs/common/') # For the next line...
-import SimpleOpts
-
 from system import *
 
 def writeBenchScript(dir, bench):
@@ -66,32 +64,80 @@
     bench_file.close()
     return file_name
 
-if __name__ == "__m5_main__":
-    (opts, args) = SimpleOpts.parse_args()
-    kernel, disk, cpu, mem_sys, benchmark, num_cpus = args
+supported_protocols = ["classic", "MI_example", "MESI_Two_Level",
+                        "MOESI_CMP_directory"]
+supported_cpu_types = ['kvm', 'atomic', 'timing']
+benchmark_choices = ['bt.A.x', 'cg.A.x', 'ep.A.x', 'ft.A.x',
+                     'is.A.x', 'lu.A.x', 'mg.A.x', 'sp.A.x',
+                     'bt.B.x', 'cg.B.x', 'ep.B.x', 'ft.B.x',
+                     'is.B.x', 'lu.B.x', 'mg.B.x', 'sp.B.x',
+                     'bt.C.x', 'cg.C.x', 'ep.C.x', 'ft.C.x',
+                     'is.C.x', 'lu.C.x', 'mg.C.x', 'sp.C.x',
+                     'bt.D.x', 'cg.D.x', 'ep.D.x', 'ft.D.x',
+                     'is.D.x', 'lu.D.x', 'mg.D.x', 'sp.D.x',
+                     'bt.F.x', 'cg.F.x', 'ep.F.x', 'ft.F.x',
+                     'is.F.x', 'lu.F.x', 'mg.F.x', 'sp.F.x']
 
-    if not cpu in ['atomic', 'kvm', 'timing']:
-        m5.fatal("cpu not supported")
+def parse_options():
+
+    parser = argparse.ArgumentParser(description='For use with gem5. This '
+                'runs a NAS Parallel Benchmark application. This only works '
+                'with x86 ISA.')
+
+    # The manditry position arguments.
+    parser.add_argument("kernel", type=str,
+                        help="Path to the kernel binary to boot")
+    parser.add_argument("disk", type=str,
+                        help="Path to the disk image to boot")
+    parser.add_argument("cpu", type=str, choices=supported_cpu_types,
+                        help="The type of CPU to use in the system")
+    parser.add_argument("mem_sys", type=str, choices=supported_protocols,
+                        help="Type of memory system or coherence protocol")
+    parser.add_argument("benchmark", type=str, choices=benchmark_choices,
+                        help="The NPB application to run")
+    parser.add_argument("num_cpus", type=int, help="Number of CPU cores")
+
+    # The optional arguments.
+    parser.add_argument("--no_host_parallel", action="store_true",
+                        help="Do NOT run gem5 on multiple host threads "
+                              "(kvm only)")
+    parser.add_argument("--second_disk", type=str,
+                        help="The second disk image to mount (/dev/hdb)")
+    parser.add_argument("--no_prefetchers", action="store_true",
+                        help="Enable prefectchers on the caches")
+    parser.add_argument("--l1i_size", type=str, default='32kB',
+                        help="L1 instruction cache size. Default: 32kB")
+    parser.add_argument("--l1d_size", type=str, default='32kB',
+                        help="L1 data cache size. Default: 32kB")
+    parser.add_argument("--l2_size", type=str, default = "256kB",
+                        help="L2 cache size. Default: 256kB")
+    parser.add_argument("--l3_size", type=str, default = "4MB",
+                        help="L2 cache size. Default: 4MB")
+
+    return parser.parse_args()
+
+if __name__ == "__m5_main__":
+    args = parse_options()
+
 
     # create the system we are going to simulate
-    system = MySystem(kernel, disk, int(num_cpus), opts, no_kvm=False)
+    system = MySystem(args.kernel, args.disk, args.num_cpus, args,
+                      no_kvm=False)
 
 
-    ruby_protocols = [ "MI_example", "MESI_Two_Level", "MOESI_CMP_directory"]
-
-    if mem_sys == "classic":
-        system = MySystem(kernel, disk, int(num_cpus), opts, no_kvm=False)
-    elif mem_sys in ruby_protocols:
-        system = MyRubySystem(kernel, disk, mem_sys, int(num_cpus), opts)
+    if args.mem_sys == "classic":
+        system = MySystem(args.kernel, args.disk, args.num_cpus, args,
+                          no_kvm=False)
     else:
-        m5.fatal("Bad option for mem_sys")
+        system = MyRubySystem(args.kernel, args.disk, args.mem_sys,
+                              args.num_cpus, args)
 
     # Exit from guest on workbegin/workend
     system.exit_on_work_items = True
 
     # Create and pass a script to the simulated system to run the reuired
     # benchmark
-    system.readfile = writeBenchScript(m5.options.outdir, benchmark)
+    system.readfile = writeBenchScript(m5.options.outdir, args.benchmark)
 
     # set up the root SimObject and start the simulation
     root = Root(full_system = True, system = system)
@@ -111,7 +157,7 @@
     globalStart = time.time()
 
     print("Running the simulation")
-    print("Using cpu: {}".format(cpu))
+    print("Using cpu: {}".format(args.cpu))
     exit_event = m5.simulate()
 
     if exit_event.getCause() == "workbegin":
@@ -124,9 +170,9 @@
         start_tick = m5.curTick()
         start_insts = system.totalInsts()
         # switching cpu if argument cpu == atomic or timing
-        if cpu == 'atomic':
+        if args.cpu == 'atomic':
             system.switchCpus(system.cpu, system.atomicCpu)
-        if cpu == 'timing':
+        if args.cpu == 'timing':
             system.switchCpus(system.cpu, system.timingCpu)
     else:
         print("Unexpected termination of simulation !")
@@ -149,18 +195,17 @@
     # switching back to simulate the remaining
     # part
 
-    if mem_sys in ruby_protocols:
-        print("Ruby Mem: Not Switching back to KVM!")
-
-    if mem_sys == 'classic':
+    if args.mem_sys == 'classic':
         # switch cpu back to kvm if atomic/timing was used for ROI
-        if cpu == 'atomic':
+        if args.cpu == 'atomic':
             system.switchCpus(system.atomicCpu, system.cpu)
-        if cpu == 'timing':
+        if args.cpu == 'timing':
             system.switchCpus(system.timingCpu, system.cpu)
 
         # Simulate the remaning part of the benchmark
         exit_event = m5.simulate()
+    else:
+        print("Ruby Mem: Not Switching back to KVM!")
 
     print("Done with the simulation")
     print()
diff --git a/src/npb/configs/system/caches.py b/src/npb/configs/system/caches.py
index 3751926..dd45722 100755
--- a/src/npb/configs/system/caches.py
+++ b/src/npb/configs/system/caches.py
@@ -39,17 +39,12 @@
 from m5.params import AddrRange, AllMemory, MemorySize
 from m5.util.convert import toMemorySize
 
-import SimpleOpts
 
 # Some specific options for caches
 # For all options see src/mem/cache/BaseCache.py
 
 class PrefetchCache(Cache):
 
-    SimpleOpts.add_option("--no_prefetchers", default=False,
-                          action="store_true",
-                          help="Enable prefectchers on the caches")
-
     def __init__(self, options):
         super(PrefetchCache, self).__init__()
         if not options or options.no_prefetchers:
@@ -83,12 +78,6 @@
 class L1ICache(L1Cache):
     """Simple L1 instruction cache with default values"""
 
-    # Set the default size
-    size = '32kB'
-
-    SimpleOpts.add_option('--l1i_size',
-                        help="L1 instruction cache size. Default: %s" % size)
-
     def __init__(self, opts=None):
         super(L1ICache, self).__init__(opts)
         if not opts or not opts.l1i_size:
@@ -102,12 +91,6 @@
 class L1DCache(L1Cache):
     """Simple L1 data cache with default values"""
 
-    # Set the default size
-    size = '32kB'
-
-    SimpleOpts.add_option('--l1d_size',
-                          help="L1 data cache size. Default: %s" % size)
-
     def __init__(self, opts=None):
         super(L1DCache, self).__init__(opts)
         if not opts or not opts.l1d_size:
@@ -149,7 +132,6 @@
     """Simple L2 Cache with default values"""
 
     # Default parameters
-    size = '256kB'
     assoc = 16
     tag_latency = 10
     data_latency = 10
@@ -158,9 +140,6 @@
     tgts_per_mshr = 12
     writeback_clean = True
 
-    SimpleOpts.add_option('--l2_size',
-                          help="L2 cache size. Default: %s" % size)
-
     def __init__(self, opts=None):
         super(L2Cache, self).__init__(opts)
         if not opts or not opts.l2_size:
@@ -179,9 +158,6 @@
        be used as a standalone L3 cache.
     """
 
-    SimpleOpts.add_option('--l3_size', default = '4MB',
-                          help="L3 cache size. Default: 4MB")
-
     # Default parameters
     assoc = 32
     tag_latency = 40
diff --git a/src/npb/configs/system/system.py b/src/npb/configs/system/system.py
index e7a0753..6c81433 100755
--- a/src/npb/configs/system/system.py
+++ b/src/npb/configs/system/system.py
@@ -36,13 +36,6 @@
 
 class MySystem(System):
 
-    SimpleOpts.add_option("--no_host_parallel", default=False,
-                action="store_true",
-                help="Do NOT run gem5 on multiple host threads (kvm only)")
-
-    SimpleOpts.add_option("--second_disk", default='',
-                          help="The second disk image to mount (/dev/hdb)")
-
     def __init__(self, kernel, disk, num_cpus, opts, no_kvm=False):
         super(MySystem, self).__init__()
         self._opts = opts