ruby: changed all references to numCPs to num-cp
[gem5.git] / SConstruct
index 849585aa768207babccb983d3d3f4d807845c6d4..c291265fcbf22d78b7346150dcd25b52110d5b03 100755 (executable)
@@ -1,6 +1,6 @@
 # -*- mode:python -*-
 
-# Copyright (c) 2013 ARM Limited
+# Copyright (c) 2013, 2015 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -209,10 +209,11 @@ use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH',
                  'PYTHONPATH', 'RANLIB', 'SWIG', 'TERM' ])
 
 use_prefixes = [
-    "M5",           # M5 configuration (e.g., path to kernels)
-    "DISTCC_",      # distcc (distributed compiler wrapper) configuration
-    "CCACHE_",      # ccache (caching compiler wrapper) configuration
-    "CCC_",         # clang static analyzer configuration
+    "CCACHE_",         # ccache (caching compiler wrapper) configuration
+    "CCC_",            # clang static analyzer configuration
+    "DISTCC_",         # distcc (distributed compiler wrapper) configuration
+    "INCLUDE_SERVER_", # distcc pump server settings
+    "M5",              # M5 configuration (e.g., path to kernels)
     ]
 
 use_env = {}
@@ -221,7 +222,10 @@ for key,val in sorted(os.environ.iteritems()):
             any([key.startswith(prefix) for prefix in use_prefixes]):
         use_env[key] = val
 
-main = Environment(ENV=use_env)
+# Tell scons to avoid implicit command dependencies to avoid issues
+# with the param wrappes being compiled twice (see
+# http://scons.tigris.org/issues/show_bug.cgi?id=2811)
+main = Environment(ENV=use_env, IMPLICIT_COMMAND_DEPENDENCIES=0)
 main.Decider('MD5-timestamp')
 main.root = Dir(".")         # The current directory (where this file lives).
 main.srcdir = Dir("src")     # The source directory
@@ -550,15 +554,12 @@ if main['GCC'] or main['CLANG']:
     # As gcc and clang share many flags, do the common parts here
     main.Append(CCFLAGS=['-pipe'])
     main.Append(CCFLAGS=['-fno-strict-aliasing'])
-    # Enable -Wall and then disable the few warnings that we
-    # consistently violate
-    main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef'])
-    # We always compile using C++11, but only gcc >= 4.7 and clang 3.1
-    # actually use that name, so we stick with c++0x
-    main.Append(CXXFLAGS=['-std=c++0x'])
-    # Add selected sanity checks from -Wextra
-    main.Append(CXXFLAGS=['-Wmissing-field-initializers',
-                          '-Woverloaded-virtual'])
+    # Enable -Wall and -Wextra and then disable the few warnings that
+    # we consistently violate
+    main.Append(CCFLAGS=['-Wall', '-Wundef', '-Wextra',
+                         '-Wno-sign-compare', '-Wno-unused-parameter'])
+    # We always compile using C++11
+    main.Append(CXXFLAGS=['-std=c++11'])
 else:
     print termcap.Yellow + termcap.Bold + 'Error' + termcap.Normal,
     print "Don't know what compiler options to use for your compiler."
@@ -579,13 +580,12 @@ else:
     Exit(1)
 
 if main['GCC']:
-    # Check for a supported version of gcc. >= 4.6 is chosen for its
+    # Check for a supported version of gcc. >= 4.7 is chosen for its
     # level of c++11 support. See
-    # http://gcc.gnu.org/projects/cxx0x.html for details. 4.6 is also
-    # the first version with proper LTO support.
+    # http://gcc.gnu.org/projects/cxx0x.html for details.
     gcc_version = readCommand([main['CXX'], '-dumpversion'], exception=False)
-    if compareVersions(gcc_version, "4.6") < 0:
-        print 'Error: gcc version 4.6 or newer required.'
+    if compareVersions(gcc_version, "4.7") < 0:
+        print 'Error: gcc version 4.7 or newer required.'
         print '       Installed version:', gcc_version
         Exit(1)
 
@@ -596,10 +596,16 @@ if main['GCC']:
     # assemblers detect this as an error, "Error: expecting string
     # instruction after `rep'"
     if compareVersions(gcc_version, "4.8") > 0:
-        as_version = readCommand([main['AS'], '-v', '/dev/null'],
-                                 exception=False).split()
+        as_version_raw = readCommand([main['AS'], '-v', '/dev/null'],
+                                     exception=False).split()
 
-        if not as_version or compareVersions(as_version[-1], "2.23") < 0:
+        # version strings may contain extra distro-specific
+        # qualifiers, so play it safe and keep only what comes before
+        # the first hyphen
+        as_version = as_version_raw[-1].split('-')[0] if as_version_raw \
+            else None
+
+        if not as_version or compareVersions(as_version, "2.23") < 0:
             print termcap.Yellow + termcap.Bold + \
                 'Warning: This combination of gcc and binutils have' + \
                 ' known incompatibilities.\n' + \
@@ -633,29 +639,26 @@ if main['GCC']:
                                   '-fno-builtin-realloc', '-fno-builtin-free'])
 
 elif main['CLANG']:
-    # Check for a supported version of clang, >= 3.0 is needed to
-    # support similar features as gcc 4.6. See
+    # Check for a supported version of clang, >= 3.1 is needed to
+    # support similar features as gcc 4.7. See
     # http://clang.llvm.org/cxx_status.html for details
     clang_version_re = re.compile(".* version (\d+\.\d+)")
     clang_version_match = clang_version_re.search(CXX_version)
     if (clang_version_match):
         clang_version = clang_version_match.groups()[0]
-        if compareVersions(clang_version, "3.0") < 0:
-            print 'Error: clang version 3.0 or newer required.'
+        if compareVersions(clang_version, "3.1") < 0:
+            print 'Error: clang version 3.1 or newer required.'
             print '       Installed version:', clang_version
             Exit(1)
     else:
         print 'Error: Unable to determine clang version.'
         Exit(1)
 
-    # clang has a few additional warnings that we disable,
-    # tautological comparisons are allowed due to unsigned integers
-    # being compared to constants that happen to be 0, and extraneous
+    # clang has a few additional warnings that we disable, extraneous
     # parantheses are allowed due to Ruby's printing of the AST,
     # finally self assignments are allowed as the generated CPU code
     # is relying on this
-    main.Append(CCFLAGS=['-Wno-tautological-compare',
-                         '-Wno-parentheses',
+    main.Append(CCFLAGS=['-Wno-parentheses',
                          '-Wno-self-assign',
                          # Some versions of libstdc++ (4.8?) seem to
                          # use struct hash and class hash
@@ -781,10 +784,15 @@ if main['GCC'] and compareVersions(gcc_version, '4.9') >= 0 and \
 swig_flags=Split('-c++ -python -modern -templatereduce $_CPPINCFLAGS')
 main.Append(SWIGFLAGS=swig_flags)
 
-# Check for 'timeout' from GNU coreutils.  If present, regressions
-# will be run with a time limit.
-TIMEOUT_version = readCommand(['timeout', '--version'], exception=False)
-main['TIMEOUT'] = TIMEOUT_version and TIMEOUT_version.find('timeout') == 0
+# Check for 'timeout' from GNU coreutils. If present, regressions will
+# be run with a time limit. We require version 8.13 since we rely on
+# support for the '--foreground' option.
+timeout_lines = readCommand(['timeout', '--version'],
+                            exception='').splitlines()
+# Get the first line and tokenize it
+timeout_version = timeout_lines[0].split() if timeout_lines else []
+main['TIMEOUT'] =  timeout_version and \
+    compareVersions(timeout_version[-1], '8.13') >= 0
 
 # filter out all existing swig scanners, they mess up the dependency
 # stuff for some reason
@@ -807,32 +815,6 @@ scanners.append(CPPScanner("SwigScan", [ ".i" ], "CPPPATH", swig_inc_re))
 # replace the scanners list that has what we want
 main['SCANNERS'] = scanners
 
-# Add a custom Check function to the Configure context so that we can
-# figure out if the compiler adds leading underscores to global
-# variables.  This is needed for the autogenerated asm files that we
-# use for embedding the python code.
-def CheckLeading(context):
-    context.Message("Checking for leading underscore in global variables...")
-    # 1) Define a global variable called x from asm so the C compiler
-    #    won't change the symbol at all.
-    # 2) Declare that variable.
-    # 3) Use the variable
-    #
-    # If the compiler prepends an underscore, this will successfully
-    # link because the external symbol 'x' will be called '_x' which
-    # was defined by the asm statement.  If the compiler does not
-    # prepend an underscore, this will not successfully link because
-    # '_x' will have been defined by assembly, while the C portion of
-    # the code will be trying to use 'x'
-    ret = context.TryLink('''
-        asm(".globl _x; _x: .byte 0");
-        extern int x;
-        int main() { return x; }
-        ''', extension=".c")
-    context.env.Append(LEADING_UNDERSCORE=ret)
-    context.Result(ret)
-    return ret
-
 # Add a custom Check function to test for structure members.
 def CheckMember(context, include, decl, member, include_quotes="<>"):
     context.Message("Checking for member %s in %s..." %
@@ -859,14 +841,9 @@ conf = Configure(main,
                  conf_dir = joinpath(build_root, '.scons_config'),
                  log_file = joinpath(build_root, 'scons_config.log'),
                  custom_tests = {
-        'CheckLeading' : CheckLeading,
         'CheckMember' : CheckMember,
         })
 
-# Check for leading underscores.  Don't really need to worry either
-# way so don't need to check the return code.
-conf.CheckLeading()
-
 # Check if we should compile a 64 bit binary on Mac OS X/Darwin
 try:
     import platform
@@ -1001,6 +978,21 @@ if not GetOption('without_tcmalloc'):
               "installing tcmalloc (libgoogle-perftools-dev package "\
               "on Ubuntu or RedHat)." + termcap.Normal
 
+
+# Detect back trace implementations. The last implementation in the
+# list will be used by default.
+backtrace_impls = [ "none" ]
+
+if conf.CheckLibWithHeader(None, 'execinfo.h', 'C',
+                           'backtrace_symbols_fd((void*)0, 0, 0);'):
+    backtrace_impls.append("glibc")
+
+if backtrace_impls[-1] == "none":
+    default_backtrace_impl = "none"
+    print termcap.Yellow + termcap.Bold + \
+        "No suitable back trace implementation found." + \
+        termcap.Normal
+
 if not have_posix_clock:
     print "Can't find library for POSIX clocks."
 
@@ -1014,18 +1006,19 @@ if not have_fenv:
 # we rely on exists since version 2.6.36 of the kernel, but somehow
 # the KVM_API_VERSION does not reflect the change. We test for one of
 # the types as a fall back.
-have_kvm = conf.CheckHeader('linux/kvm.h', '<>') and \
-    conf.CheckTypeSize('struct kvm_xsave', '#include <linux/kvm.h>') != 0
+have_kvm = conf.CheckHeader('linux/kvm.h', '<>')
 if not have_kvm:
     print "Info: Compatible header file <linux/kvm.h> not found, " \
         "disabling KVM support."
 
+# x86 needs support for xsave. We test for the structure here since we
+# won't be able to run new tests by the time we know which ISA we're
+# targeting.
+have_kvm_xsave = conf.CheckTypeSize('struct kvm_xsave',
+                                    '#include <linux/kvm.h>') != 0
+
 # Check if the requested target ISA is compatible with the host
 def is_isa_kvm_compatible(isa):
-    isa_comp_table = {
-        "arm" : ( "armv7l" ),
-        "x86" : ( "x86_64" ),
-        }
     try:
         import platform
         host_isa = platform.machine()
@@ -1033,7 +1026,24 @@ def is_isa_kvm_compatible(isa):
         print "Warning: Failed to determine host ISA."
         return False
 
-    return host_isa in isa_comp_table.get(isa, [])
+    if not have_posix_timers:
+        print "Warning: Can not enable KVM, host seems to lack support " \
+            "for POSIX timers"
+        return False
+
+    if isa == "arm":
+        return host_isa in ( "armv7l", "aarch64" )
+    elif isa == "x86":
+        if host_isa != "x86_64":
+            return False
+
+        if not have_kvm_xsave:
+            print "KVM on x86 requires xsave support in kernel headers."
+            return False
+
+        return True
+    else:
+        return False
 
 
 # Check if the exclude_host attribute is available. We want this to
@@ -1055,7 +1065,9 @@ main = conf.Finish()
 
 # Define the universe of supported ISAs
 all_isa_list = [ ]
+all_gpu_isa_list = [ ]
 Export('all_isa_list')
+Export('all_gpu_isa_list')
 
 class CpuModel(object):
     '''The CpuModel class encapsulates everything the ISA parser needs to
@@ -1111,9 +1123,11 @@ for bdir in [ base_dir ] + extras_dir_list:
             SConscript(joinpath(root, 'SConsopts'))
 
 all_isa_list.sort()
+all_gpu_isa_list.sort()
 
 sticky_vars.AddVariables(
     EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
+    EnumVariable('TARGET_GPU_ISA', 'Target GPU ISA', 'hsail', all_gpu_isa_list),
     ListVariable('CPU_MODELS', 'CPU models',
                  sorted(n for n,m in CpuModel.dict.iteritems() if m.default),
                  sorted(CpuModel.dict.keys())),
@@ -1129,14 +1143,17 @@ sticky_vars.AddVariables(
     BoolVariable('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
     BoolVariable('CP_ANNOTATE', 'Enable critical path annotation capability', False),
     BoolVariable('USE_KVM', 'Enable hardware virtualized (KVM) CPU models', have_kvm),
+    BoolVariable('BUILD_GPU', 'Build the compute-GPU model', False),
     EnumVariable('PROTOCOL', 'Coherence protocol for Ruby', 'None',
                   all_protocols),
+    EnumVariable('BACKTRACE_IMPL', 'Post-mortem dump implementation',
+                 backtrace_impls[-1], backtrace_impls)
     )
 
 # These variables get exported to #defines in config/*.hh (see src/SConscript).
-export_vars += ['USE_FENV', 'SS_COMPATIBLE_FP', 'TARGET_ISA', 'CP_ANNOTATE',
-                'USE_POSIX_CLOCK', 'USE_KVM', 'PROTOCOL', 'HAVE_PROTOBUF',
-                'HAVE_PERF_ATTR_EXCLUDE_HOST']
+export_vars += ['USE_FENV', 'SS_COMPATIBLE_FP', 'TARGET_ISA', 'TARGET_GPU_ISA',
+                'CP_ANNOTATE', 'USE_POSIX_CLOCK', 'USE_KVM', 'PROTOCOL',
+                'HAVE_PROTOBUF', 'HAVE_PERF_ATTR_EXCLUDE_HOST']
 
 ###################################################
 #
@@ -1183,9 +1200,9 @@ main.Append(BUILDERS = { 'ConfigFile' : config_builder })
 main.SConscript('ext/libelf/SConscript',
                 variant_dir = joinpath(build_root, 'libelf'))
 
-# gzstream build is shared across all configs in the build root.
-main.SConscript('ext/gzstream/SConscript',
-                variant_dir = joinpath(build_root, 'gzstream'))
+# iostream3 build is shared across all configs in the build root.
+main.SConscript('ext/iostream3/SConscript',
+                variant_dir = joinpath(build_root, 'iostream3'))
 
 # libfdt build is shared across all configs in the build root.
 main.SConscript('ext/libfdt/SConscript',
@@ -1203,6 +1220,10 @@ main.SConscript('ext/dramsim2/SConscript',
 main.SConscript('ext/drampower/SConscript',
                 variant_dir = joinpath(build_root, 'drampower'))
 
+# nomali build is shared across all configs in the build root.
+main.SConscript('ext/nomali/SConscript',
+                variant_dir = joinpath(build_root, 'nomali'))
+
 ###################################################
 #
 # This function is used to set up a directory with switching headers
@@ -1210,6 +1231,7 @@ main.SConscript('ext/drampower/SConscript',
 ###################################################
 
 main['ALL_ISA_LIST'] = all_isa_list
+main['ALL_GPU_ISA_LIST'] = all_gpu_isa_list
 all_isa_deps = {}
 def make_switching_dir(dname, switch_headers, env):
     # Generate the header.  target[0] is the full path of the output
@@ -1242,6 +1264,35 @@ def make_switching_dir(dname, switch_headers, env):
 
 Export('make_switching_dir')
 
+def make_gpu_switching_dir(dname, switch_headers, env):
+    # Generate the header.  target[0] is the full path of the output
+    # header to generate.  'source' is a dummy variable, since we get the
+    # list of ISAs from env['ALL_ISA_LIST'].
+    def gen_switch_hdr(target, source, env):
+        fname = str(target[0])
+
+        isa = env['TARGET_GPU_ISA'].lower()
+
+        try:
+            f = open(fname, 'w')
+            print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
+            f.close()
+        except IOError:
+            print "Failed to create %s" % fname
+            raise
+
+    # Build SCons Action object. 'varlist' specifies env vars that this
+    # action depends on; when env['ALL_ISA_LIST'] changes these actions
+    # should get re-executed.
+    switch_hdr_action = MakeAction(gen_switch_hdr,
+                          Transform("GENERATE"), varlist=['ALL_ISA_GPU_LIST'])
+
+    # Instantiate actions for each header
+    for hdr in switch_headers:
+        env.Command(hdr, [], switch_hdr_action)
+
+Export('make_gpu_switching_dir')
+
 # all-isas -> all-deps -> all-environs -> all_targets
 main.Alias('#all-isas', [])
 main.Alias('#all-deps', '#all-isas')
@@ -1349,10 +1400,6 @@ for variant_path in variant_paths:
         if not have_kvm:
             print "Warning: Can not enable KVM, host seems to lack KVM support"
             env['USE_KVM'] = False
-        elif not have_posix_timers:
-            print "Warning: Can not enable KVM, host seems to lack support " \
-                "for POSIX timers"
-            env['USE_KVM'] = False
         elif not is_isa_kvm_compatible(env['TARGET_ISA']):
             print "Info: KVM support disabled due to unsupported host and " \
                 "target ISA combination"