arm: disable GIC extensions
[gem5.git] / SConstruct
index 45cfb0b897b698bb6d5d07b9d867400b4247cf15..f8eac47e6d049a7d57b9c04a70c54abff91fc277 100755 (executable)
@@ -1,6 +1,6 @@
 # -*- mode:python -*-
 
-# Copyright (c) 2013, 2015 ARM Limited
+# Copyright (c) 2013, 2015, 2016 ARM Limited
 # All rights reserved.
 #
 # The license below extends only to copyright in the software and shall
@@ -112,6 +112,7 @@ For more details, see:
 import itertools
 import os
 import re
+import shutil
 import subprocess
 import sys
 
@@ -194,6 +195,8 @@ AddLocalOption('--without-tcmalloc', dest='without_tcmalloc',
                help='Disable linking against tcmalloc')
 AddLocalOption('--with-ubsan', dest='with_ubsan', action='store_true',
                help='Build with Undefined Behavior Sanitizer if available')
+AddLocalOption('--with-asan', dest='with_asan', action='store_true',
+               help='Build with Address Sanitizer if available')
 
 termcap = get_termcap(GetOption('use_colors'))
 
@@ -209,6 +212,7 @@ use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH',
                  'PYTHONPATH', 'RANLIB', 'SWIG', 'TERM' ])
 
 use_prefixes = [
+    "ASAN_",           # address sanitizer symbolizer path and settings
     "CCACHE_",         # ccache (caching compiler wrapper) configuration
     "CCC_",            # clang static analyzer configuration
     "DISTCC_",         # distcc (distributed compiler wrapper) configuration
@@ -257,21 +261,33 @@ main.AppendENVPath('PYTHONPATH', extra_python_paths)
 
 hgdir = main.root.Dir(".hg")
 
-mercurial_style_message = """
+
+style_message = """
 You're missing the gem5 style hook, which automatically checks your code
-against the gem5 style rules on hg commit and qrefresh commands.  This
-script will now install the hook in your .hg/hgrc file.
+against the gem5 style rules on %s.
+This script will now install the hook in your %s.
+Press enter to continue, or ctrl-c to abort: """
+
+mercurial_style_message = style_message % ("hg commit and qrefresh commands",
+                                           ".hg/hgrc file")
+git_style_message = style_message % ("'git commit'",
+                                     ".git/hooks/ directory")
+
+mercurial_style_upgrade_message = """
+Your Mercurial style hooks are not up-to-date. This script will now
+try to automatically update them. A backup of your hgrc will be saved
+in .hg/hgrc.old.
 Press enter to continue, or ctrl-c to abort: """
 
 mercurial_style_hook = """
 # The following lines were automatically added by gem5/SConstruct
 # to provide the gem5 style-checking hooks
 [extensions]
-style = %s/util/style.py
+hgstyle = %s/util/hgstyle.py
 
 [hooks]
-pretxncommit.style = python:style.check_style
-pre-qrefresh.style = python:style.check_style
+pretxncommit.style = python:hgstyle.check_style
+pre-qrefresh.style = python:hgstyle.check_style
 # End of SConstruct additions
 
 """ % (main.root.abspath)
@@ -283,20 +299,58 @@ hook. It is important.
 """
 
 # Check for style hook and prompt for installation if it's not there.
-# Skip this if --ignore-style was specified, there's no .hg dir to
-# install a hook in, or there's no interactive terminal to prompt.
-if not GetOption('ignore_style') and hgdir.exists() and sys.stdin.isatty():
+# Skip this if --ignore-style was specified, there's no interactive
+# terminal to prompt, or no recognized revision control system can be
+# found.
+ignore_style = GetOption('ignore_style') or not sys.stdin.isatty()
+
+# Try wire up Mercurial to the style hooks
+if not ignore_style and hgdir.exists():
     style_hook = True
+    style_hooks = tuple()
+    hgrc = hgdir.File('hgrc')
+    hgrc_old = hgdir.File('hgrc.old')
     try:
         from mercurial import ui
         ui = ui.ui()
-        ui.readconfig(hgdir.File('hgrc').abspath)
-        style_hook = ui.config('hooks', 'pretxncommit.style', None) and \
-                     ui.config('hooks', 'pre-qrefresh.style', None)
+        ui.readconfig(hgrc.abspath)
+        style_hooks = (ui.config('hooks', 'pretxncommit.style', None),
+                       ui.config('hooks', 'pre-qrefresh.style', None))
+        style_hook = all(style_hooks)
+        style_extension = ui.config('extensions', 'style', None)
     except ImportError:
         print mercurial_lib_not_found
 
-    if not style_hook:
+    if "python:style.check_style" in style_hooks:
+        # Try to upgrade the style hooks
+        print mercurial_style_upgrade_message
+        # continue unless user does ctrl-c/ctrl-d etc.
+        try:
+            raw_input()
+        except:
+            print "Input exception, exiting scons.\n"
+            sys.exit(1)
+        shutil.copyfile(hgrc.abspath, hgrc_old.abspath)
+        re_style_hook = re.compile(r"^([^=#]+)\.style\s*=\s*([^#\s]+).*")
+        re_style_extension = re.compile("style\s*=\s*([^#\s]+).*")
+        old, new = open(hgrc_old.abspath, 'r'), open(hgrc.abspath, 'w')
+        for l in old:
+            m_hook = re_style_hook.match(l)
+            m_ext = re_style_extension.match(l)
+            if m_hook:
+                hook, check = m_hook.groups()
+                if check != "python:style.check_style":
+                    print "Warning: %s.style is using a non-default " \
+                        "checker: %s" % (hook, check)
+                if hook not in ("pretxncommit", "pre-qrefresh"):
+                    print "Warning: Updating unknown style hook: %s" % hook
+
+                l = "%s.style = python:hgstyle.check_style\n" % hook
+            elif m_ext and m_ext.group(1) == style_extension:
+                l = "hgstyle = %s/util/hgstyle.py\n" % main.root.abspath
+
+            new.write(l)
+    elif not style_hook:
         print mercurial_style_message,
         # continue unless user does ctrl-c/ctrl-d etc.
         try:
@@ -307,13 +361,54 @@ if not GetOption('ignore_style') and hgdir.exists() and sys.stdin.isatty():
         hgrc_path = '%s/.hg/hgrc' % main.root.abspath
         print "Adding style hook to", hgrc_path, "\n"
         try:
-            hgrc = open(hgrc_path, 'a')
-            hgrc.write(mercurial_style_hook)
-            hgrc.close()
+            with open(hgrc_path, 'a') as f:
+                f.write(mercurial_style_hook)
         except:
             print "Error updating", hgrc_path
             sys.exit(1)
 
+def install_git_style_hooks():
+    try:
+        gitdir = Dir(readCommand(
+            ["git", "rev-parse", "--git-dir"]).strip("\n"))
+    except Exception, e:
+        print "Warning: Failed to find git repo directory: %s" % e
+        return
+
+    git_hooks = gitdir.Dir("hooks")
+    git_pre_commit_hook = git_hooks.File("pre-commit")
+    git_style_script = File("util/git-pre-commit.py")
+
+    if git_pre_commit_hook.exists():
+        return
+
+    print git_style_message,
+    try:
+        raw_input()
+    except:
+        print "Input exception, exiting scons.\n"
+        sys.exit(1)
+
+    if not git_hooks.exists():
+        mkdir(git_hooks.get_abspath())
+
+    # Use a relative symlink if the hooks live in the source directory
+    if git_pre_commit_hook.is_under(main.root):
+        script_path = os.path.relpath(
+            git_style_script.get_abspath(),
+            git_pre_commit_hook.Dir(".").get_abspath())
+    else:
+        script_path = git_style_script.get_abspath()
+
+    try:
+        os.symlink(script_path, git_pre_commit_hook.get_abspath())
+    except:
+        print "Error updating git pre-commit hook"
+        raise
+
+# Try to wire up git to the style hooks
+if not ignore_style and main.root.Entry(".git").exists():
+    install_git_style_hooks()
 
 ###################################################
 #
@@ -554,14 +649,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'])
+    # 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'])
-    # Add selected sanity checks from -Wextra
-    main.Append(CXXFLAGS=['-Wmissing-field-initializers',
-                          '-Woverloaded-virtual'])
 else:
     print termcap.Yellow + termcap.Bold + 'Error' + termcap.Normal,
     print "Don't know what compiler options to use for your compiler."
@@ -582,12 +675,12 @@ else:
     Exit(1)
 
 if main['GCC']:
-    # Check for a supported version of gcc. >= 4.7 is chosen for its
+    # Check for a supported version of gcc. >= 4.8 is chosen for its
     # level of c++11 support. See
     # http://gcc.gnu.org/projects/cxx0x.html for details.
     gcc_version = readCommand([main['CXX'], '-dumpversion'], exception=False)
-    if compareVersions(gcc_version, "4.7") < 0:
-        print 'Error: gcc version 4.7 or newer required.'
+    if compareVersions(gcc_version, "4.8") < 0:
+        print 'Error: gcc version 4.8 or newer required.'
         print '       Installed version:', gcc_version
         Exit(1)
 
@@ -597,23 +690,21 @@ if main['GCC']:
     # to avoid performance penalties on certain AMD chips. Older
     # assemblers detect this as an error, "Error: expecting string
     # instruction after `rep'"
-    if compareVersions(gcc_version, "4.8") > 0:
-        as_version_raw = readCommand([main['AS'], '-v', '/dev/null'],
-                                     exception=False).split()
-
-        # 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' + \
-                '         If you encounter build problems, please update ' + \
-                'binutils to 2.23.' + \
-                termcap.Normal
+    as_version_raw = readCommand([main['AS'], '-v', '/dev/null'],
+                                 exception=False).split()
+
+    # 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' + \
+            '         If you encounter build problems, please update ' + \
+            'binutils to 2.23.' + \
+            termcap.Normal
 
     # Make sure we warn if the user has requested to compile with the
     # Undefined Benahvior Sanitizer and this version of gcc does not
@@ -640,9 +731,13 @@ if main['GCC']:
     main.Append(TCMALLOC_CCFLAGS=['-fno-builtin-malloc', '-fno-builtin-calloc',
                                   '-fno-builtin-realloc', '-fno-builtin-free'])
 
+    # add option to check for undeclared overrides
+    if compareVersions(gcc_version, "5.0") > 0:
+        main.Append(CCFLAGS=['-Wno-error=suggest-override'])
+
 elif main['CLANG']:
     # Check for a supported version of clang, >= 3.1 is needed to
-    # support similar features as gcc 4.7. See
+    # support similar features as gcc 4.8. 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)
@@ -656,14 +751,11 @@ elif main['CLANG']:
         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
@@ -983,6 +1075,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."
 
@@ -1055,7 +1162,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 +1220,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 +1240,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 +1297,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',
@@ -1214,6 +1328,7 @@ main.SConscript('ext/nomali/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
@@ -1246,6 +1361,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')