ARM: Add support for interworking branch ALU instructions.
[gem5.git] / SConstruct
index a3cae0fc9f10fb6401f3a8c269112ba4ce7b31ea..55cf71876a79909cacf248b81b6e383d45e7d15e 100644 (file)
@@ -96,6 +96,7 @@ For more details, see:
 """
     raise
 
 """
     raise
 
+# Global Python includes
 import os
 import re
 import subprocess
 import os
 import re
 import subprocess
@@ -106,71 +107,39 @@ from os.path import abspath, basename, dirname, expanduser, normpath
 from os.path import exists,  isdir, isfile
 from os.path import join as joinpath, split as splitpath
 
 from os.path import exists,  isdir, isfile
 from os.path import join as joinpath, split as splitpath
 
+# SCons includes
 import SCons
 import SCons.Node
 
 import SCons
 import SCons.Node
 
-def read_command(cmd, **kwargs):
-    """run the command cmd, read the results and return them
-    this is sorta like `cmd` in shell"""
-    from subprocess import Popen, PIPE, STDOUT
-
-    if isinstance(cmd, str):
-        cmd = cmd.split()
-
-    no_exception = 'exception' in kwargs
-    exception = kwargs.pop('exception', None)
+extra_python_paths = [
+    Dir('src/python').srcnode().abspath, # M5 includes
+    Dir('ext/ply').srcnode().abspath, # ply is used by several files
+    ]
     
     
-    kwargs.setdefault('shell', False)
-    kwargs.setdefault('stdout', PIPE)
-    kwargs.setdefault('stderr', STDOUT)
-    kwargs.setdefault('close_fds', True)
-    try:
-        subp = Popen(cmd, **kwargs)
-    except Exception, e:
-        if no_exception:
-            return exception
-        raise
-
-    return subp.communicate()[0]
-
-# helper function: compare arrays or strings of version numbers.
-# E.g., compare_version((1,3,25), (1,4,1)')
-# returns -1, 0, 1 if v1 is <, ==, > v2
-def compare_versions(v1, v2):
-    def make_version_list(v):
-        if isinstance(v, (list,tuple)):
-            return v
-        elif isinstance(v, str):
-            return map(lambda x: int(re.match('\d+', x).group()), v.split('.'))
-        else:
-            raise TypeError
-
-    v1 = make_version_list(v1)
-    v2 = make_version_list(v2)
-    # Compare corresponding elements of lists
-    for n1,n2 in zip(v1, v2):
-        if n1 < n2: return -1
-        if n1 > n2: return  1
-    # all corresponding values are equal... see if one has extra values
-    if len(v1) < len(v2): return -1
-    if len(v1) > len(v2): return  1
-    return 0
+sys.path[1:1] = extra_python_paths
+
+from m5.util import compareVersions, readCommand
 
 ########################################################################
 #
 
 ########################################################################
 #
-# Set up the base build environment.
+# Set up the main build environment.
 #
 ########################################################################
 #
 ########################################################################
-use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'PATH', 'RANLIB' ])
+use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH', 'PATH',
+                 'PYTHONPATH', 'RANLIB' ])
 
 use_env = {}
 for key,val in os.environ.iteritems():
     if key in use_vars or key.startswith("M5"):
         use_env[key] = val
 
 
 use_env = {}
 for key,val in os.environ.iteritems():
     if key in use_vars or key.startswith("M5"):
         use_env[key] = val
 
-env = Environment(ENV=use_env)
-env.root = Dir(".")          # The current directory (where this file lives).
-env.srcdir = Dir("src")      # The source directory
+main = Environment(ENV=use_env)
+main.root = Dir(".")         # The current directory (where this file lives).
+main.srcdir = Dir("src")     # The source directory
+
+# add useful python code PYTHONPATH so it can be used by subprocesses
+# as well
+main.AppendENVPath('PYTHONPATH', extra_python_paths)
 
 ########################################################################
 #
 
 ########################################################################
 #
@@ -181,7 +150,7 @@ env.srcdir = Dir("src")      # The source directory
 #
 ########################################################################
 
 #
 ########################################################################
 
-hgdir = env.root.Dir(".hg")
+hgdir = main.root.Dir(".hg")
 
 mercurial_style_message = """
 You're missing the M5 style hook.
 
 mercurial_style_message = """
 You're missing the M5 style hook.
@@ -196,7 +165,7 @@ style = %s/util/style.py
 
 [hooks]
 pretxncommit.style = python:style.check_whitespace
 
 [hooks]
 pretxncommit.style = python:style.check_whitespace
-""" % (env.root)
+""" % (main.root)
 
 mercurial_bin_not_found = """
 Mercurial binary cannot be found, unfortunately this means that we
 
 mercurial_bin_not_found = """
 Mercurial binary cannot be found, unfortunately this means that we
@@ -211,17 +180,15 @@ If you are actually a M5 developer, please fix this and
 run the style hook. It is important.
 """
 
 run the style hook. It is important.
 """
 
+hg_info = "Unknown"
 if hgdir.exists():
     # 1) Grab repository revision if we know it.
     cmd = "hg id -n -i -t -b"
     try:
 if hgdir.exists():
     # 1) Grab repository revision if we know it.
     cmd = "hg id -n -i -t -b"
     try:
-        hg_info = read_command(cmd, cwd=env.root.abspath).strip()
+        hg_info = readCommand(cmd, cwd=main.root.abspath).strip()
     except OSError:
     except OSError:
-        hg_info = "Unknown"
         print mercurial_bin_not_found
 
         print mercurial_bin_not_found
 
-    env['HG_INFO'] = hg_info
-
     # 2) Ensure that the style hook is in place.
     try:
         ui = None
     # 2) Ensure that the style hook is in place.
     try:
         ui = None
@@ -241,6 +208,8 @@ if hgdir.exists():
 else:
     print ".hg directory not found"
 
 else:
     print ".hg directory not found"
 
+main['HG_INFO'] = hg_info
+
 ###################################################
 #
 # Figure out which configurations to set up based on the path(s) of
 ###################################################
 #
 # Figure out which configurations to set up based on the path(s) of
@@ -273,7 +242,7 @@ if COMMAND_LINE_TARGETS:
                     COMMAND_LINE_TARGETS]
 else:
     # Default targets are relative to root of tree
                     COMMAND_LINE_TARGETS]
 else:
     # Default targets are relative to root of tree
-    abs_targets = [ normpath(joinpath(ROOT, str(x))) for x in \
+    abs_targets = [ normpath(joinpath(main.root.abspath, str(x))) for x in \
                     DEFAULT_TARGETS]
 
 
                     DEFAULT_TARGETS]
 
 
@@ -304,15 +273,15 @@ for t in abs_targets:
 if not isdir(build_root):
     mkdir(build_root)
 
 if not isdir(build_root):
     mkdir(build_root)
 
-Export('env')
+Export('main')
 
 
-env.SConsignFile(joinpath(build_root, "sconsign"))
+main.SConsignFile(joinpath(build_root, "sconsign"))
 
 # Default duplicate option is to use hard links, but this messes up
 # when you use emacs to edit a file in the target dir, as emacs moves
 # file to file~ then copies to file, breaking the link.  Symbolic
 # (soft) links work better.
 
 # Default duplicate option is to use hard links, but this messes up
 # when you use emacs to edit a file in the target dir, as emacs moves
 # file to file~ then copies to file, breaking the link.  Symbolic
 # (soft) links work better.
-env.SetOption('duplicate', 'soft-copy')
+main.SetOption('duplicate', 'soft-copy')
 
 #
 # Set up global sticky variables... these are common to an entire build
 
 #
 # Set up global sticky variables... these are common to an entire build
@@ -339,13 +308,14 @@ global_sticky_vars_file = joinpath(build_root, 'variables.global')
 global_sticky_vars = Variables(global_sticky_vars_file, args=ARGUMENTS)
 
 global_sticky_vars.AddVariables(
 global_sticky_vars = Variables(global_sticky_vars_file, args=ARGUMENTS)
 
 global_sticky_vars.AddVariables(
-    ('CC', 'C compiler', environ.get('CC', env['CC'])),
-    ('CXX', 'C++ compiler', environ.get('CXX', env['CXX'])),
+    ('CC', 'C compiler', environ.get('CC', main['CC'])),
+    ('CXX', 'C++ compiler', environ.get('CXX', main['CXX'])),
     ('BATCH', 'Use batch pool for build and tests', False),
     ('BATCH_CMD', 'Batch pool submission command name', 'qdo'),
     ('EXTRAS', 'Add Extra directories to the compilation', '',
     ('BATCH', 'Use batch pool for build and tests', False),
     ('BATCH_CMD', 'Batch pool submission command name', 'qdo'),
     ('EXTRAS', 'Add Extra directories to the compilation', '',
-     PathListAllExist, PathListMakeAbsolute)
-    )    
+     PathListAllExist, PathListMakeAbsolute),
+    BoolVariable('RUBY', 'Build with Ruby', False),
+    )
 
 # base help text
 help_text = '''
 
 # base help text
 help_text = '''
@@ -354,80 +324,83 @@ Usage: scons [scons options] [build options] [target(s)]
 Global sticky options:
 '''
 
 Global sticky options:
 '''
 
-help_text += global_sticky_vars.GenerateHelpText(env)
+# Update main environment with values from ARGUMENTS & global_sticky_vars_file
+global_sticky_vars.Update(main)
 
 
-# Update env with values from ARGUMENTS & file global_sticky_vars_file
-global_sticky_vars.Update(env)
+help_text += global_sticky_vars.GenerateHelpText(main)
 
 # Save sticky variable settings back to current variables file
 
 # Save sticky variable settings back to current variables file
-global_sticky_vars.Save(global_sticky_vars_file, env)
+global_sticky_vars.Save(global_sticky_vars_file, main)
 
 # Parse EXTRAS variable to build list of all directories where we're
 # look for sources etc.  This list is exported as base_dir_list.
 
 # Parse EXTRAS variable to build list of all directories where we're
 # look for sources etc.  This list is exported as base_dir_list.
-base_dir = env.srcdir.abspath
-if env['EXTRAS']:
-    extras_dir_list = env['EXTRAS'].split(':')
+base_dir = main.srcdir.abspath
+if main['EXTRAS']:
+    extras_dir_list = main['EXTRAS'].split(':')
 else:
     extras_dir_list = []
 
 Export('base_dir')
 Export('extras_dir_list')
 
 else:
     extras_dir_list = []
 
 Export('base_dir')
 Export('extras_dir_list')
 
-# M5_PLY is used by isa_parser.py to find the PLY package.
-env.Append(ENV = { 'M5_PLY' : str(Dir('ext/ply')) })
+# the ext directory should be on the #includes path
+main.Append(CPPPATH=[Dir('ext')])
 
 
-CXX_version = read_command([env['CXX'],'--version'], exception=False)
-CXX_V = read_command([env['CXX'],'-V'], exception=False)
+CXX_version = readCommand([main['CXX'],'--version'], exception=False)
+CXX_V = readCommand([main['CXX'],'-V'], exception=False)
 
 
-env['GCC'] = CXX_version and CXX_version.find('g++') >= 0
-env['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
-env['ICC'] = CXX_V and CXX_V.find('Intel') >= 0
-if env['GCC'] + env['SUNCC'] + env['ICC'] > 1:
+main['GCC'] = CXX_version and CXX_version.find('g++') >= 0
+main['SUNCC'] = CXX_V and CXX_V.find('Sun C++') >= 0
+main['ICC'] = CXX_V and CXX_V.find('Intel') >= 0
+if main['GCC'] + main['SUNCC'] + main['ICC'] > 1:
     print 'Error: How can we have two at the same time?'
     Exit(1)
 
 # Set up default C++ compiler flags
     print 'Error: How can we have two at the same time?'
     Exit(1)
 
 # Set up default C++ compiler flags
-if env['GCC']:
-    env.Append(CCFLAGS='-pipe')
-    env.Append(CCFLAGS='-fno-strict-aliasing')
-    env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
-    env.Append(CXXFLAGS='-Wno-deprecated')
-elif env['ICC']:
+if main['GCC']:
+    main.Append(CCFLAGS='-pipe')
+    main.Append(CCFLAGS='-fno-strict-aliasing')
+    main.Append(CCFLAGS=['-Wall', '-Wno-sign-compare', '-Wundef'])
+    main.Append(CXXFLAGS='-Wno-deprecated')
+elif main['ICC']:
     pass #Fix me... add warning flags once we clean up icc warnings
     pass #Fix me... add warning flags once we clean up icc warnings
-elif env['SUNCC']:
-    env.Append(CCFLAGS='-Qoption ccfe')
-    env.Append(CCFLAGS='-features=gcc')
-    env.Append(CCFLAGS='-features=extensions')
-    env.Append(CCFLAGS='-library=stlport4')
-    env.Append(CCFLAGS='-xar')
-    #env.Append(CCFLAGS='-instances=semiexplicit')
+elif main['SUNCC']:
+    main.Append(CCFLAGS='-Qoption ccfe')
+    main.Append(CCFLAGS='-features=gcc')
+    main.Append(CCFLAGS='-features=extensions')
+    main.Append(CCFLAGS='-library=stlport4')
+    main.Append(CCFLAGS='-xar')
+    #main.Append(CCFLAGS='-instances=semiexplicit')
 else:
     print 'Error: Don\'t know what compiler options to use for your compiler.'
     print '       Please fix SConstruct and src/SConscript and try again.'
     Exit(1)
 
 else:
     print 'Error: Don\'t know what compiler options to use for your compiler.'
     print '       Please fix SConstruct and src/SConscript and try again.'
     Exit(1)
 
+# Set up common yacc/bison flags (needed for Ruby)
+main['YACCFLAGS'] = '-d'
+main['YACCHXXFILESUFFIX'] = '.hh'
+
 # Do this after we save setting back, or else we'll tack on an
 # extra 'qdo' every time we run scons.
 # Do this after we save setting back, or else we'll tack on an
 # extra 'qdo' every time we run scons.
-if env['BATCH']:
-    env['CC']     = env['BATCH_CMD'] + ' ' + env['CC']
-    env['CXX']    = env['BATCH_CMD'] + ' ' + env['CXX']
-    env['AS']     = env['BATCH_CMD'] + ' ' + env['AS']
-    env['AR']     = env['BATCH_CMD'] + ' ' + env['AR']
-    env['RANLIB'] = env['BATCH_CMD'] + ' ' + env['RANLIB']
+if main['BATCH']:
+    main['CC']     = main['BATCH_CMD'] + ' ' + main['CC']
+    main['CXX']    = main['BATCH_CMD'] + ' ' + main['CXX']
+    main['AS']     = main['BATCH_CMD'] + ' ' + main['AS']
+    main['AR']     = main['BATCH_CMD'] + ' ' + main['AR']
+    main['RANLIB'] = main['BATCH_CMD'] + ' ' + main['RANLIB']
 
 if sys.platform == 'cygwin':
     # cygwin has some header file issues...
 
 if sys.platform == 'cygwin':
     # cygwin has some header file issues...
-    env.Append(CCFLAGS=Split("-Wno-uninitialized"))
-env.Append(CPPPATH=[Dir('ext/dnet')])
+    main.Append(CCFLAGS="-Wno-uninitialized")
 
 # Check for SWIG
 
 # Check for SWIG
-if not env.has_key('SWIG'):
+if not main.has_key('SWIG'):
     print 'Error: SWIG utility not found.'
     print '       Please install (see http://www.swig.org) and retry.'
     Exit(1)
 
 # Check for appropriate SWIG version
     print 'Error: SWIG utility not found.'
     print '       Please install (see http://www.swig.org) and retry.'
     Exit(1)
 
 # Check for appropriate SWIG version
-swig_version = read_command(('swig', '-version'), exception='').split()
+swig_version = readCommand(('swig', '-version'), exception='').split()
 # First 3 words should be "SWIG Version x.y.z"
 if len(swig_version) < 3 or \
         swig_version[0] != 'SWIG' or swig_version[1] != 'Version':
 # First 3 words should be "SWIG Version x.y.z"
 if len(swig_version) < 3 or \
         swig_version[0] != 'SWIG' or swig_version[1] != 'Version':
@@ -435,19 +408,19 @@ if len(swig_version) < 3 or \
     Exit(1)
 
 min_swig_version = '1.3.28'
     Exit(1)
 
 min_swig_version = '1.3.28'
-if compare_versions(swig_version[2], min_swig_version) < 0:
+if compareVersions(swig_version[2], min_swig_version) < 0:
     print 'Error: SWIG version', min_swig_version, 'or newer required.'
     print '       Installed version:', swig_version[2]
     Exit(1)
 
 # Set up SWIG flags & scanner
 swig_flags=Split('-c++ -python -modern -templatereduce $_CPPINCFLAGS')
     print 'Error: SWIG version', min_swig_version, 'or newer required.'
     print '       Installed version:', swig_version[2]
     Exit(1)
 
 # Set up SWIG flags & scanner
 swig_flags=Split('-c++ -python -modern -templatereduce $_CPPINCFLAGS')
-env.Append(SWIGFLAGS=swig_flags)
+main.Append(SWIGFLAGS=swig_flags)
 
 # filter out all existing swig scanners, they mess up the dependency
 # stuff for some reason
 scanners = []
 
 # filter out all existing swig scanners, they mess up the dependency
 # stuff for some reason
 scanners = []
-for scanner in env['SCANNERS']:
+for scanner in main['SCANNERS']:
     skeys = scanner.skeys
     if skeys == '.i':
         continue
     skeys = scanner.skeys
     if skeys == '.i':
         continue
@@ -463,7 +436,7 @@ swig_inc_re = '^[ \t]*[%,#][ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")'
 scanners.append(CPPScanner("SwigScan", [ ".i" ], "CPPPATH", swig_inc_re))
 
 # replace the scanners list that has what we want
 scanners.append(CPPScanner("SwigScan", [ ".i" ], "CPPPATH", swig_inc_re))
 
 # replace the scanners list that has what we want
-env['SCANNERS'] = scanners
+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
 
 # Add a custom Check function to the Configure context so that we can
 # figure out if the compiler adds leading underscores to global
@@ -493,7 +466,7 @@ def CheckLeading(context):
 
 # Platform-specific configuration.  Note again that we assume that all
 # builds under a given build root run on the same host platform.
 
 # Platform-specific configuration.  Note again that we assume that all
 # builds under a given build root run on the same host platform.
-conf = Configure(env,
+conf = Configure(main,
                  conf_dir = joinpath(build_root, '.scons_config'),
                  log_file = joinpath(build_root, 'scons_config.log'),
                  custom_tests = { 'CheckLeading' : CheckLeading })
                  conf_dir = joinpath(build_root, '.scons_config'),
                  log_file = joinpath(build_root, 'scons_config.log'),
                  custom_tests = { 'CheckLeading' : CheckLeading })
@@ -506,12 +479,12 @@ conf.CheckLeading()
 try:
     import platform
     uname = platform.uname()
 try:
     import platform
     uname = platform.uname()
-    if uname[0] == 'Darwin' and compare_versions(uname[2], '9.0.0') >= 0:
-        if int(read_command('sysctl -n hw.cpu64bit_capable')[0]):
-            env.Append(CCFLAGS='-arch x86_64')
-            env.Append(CFLAGS='-arch x86_64')
-            env.Append(LINKFLAGS='-arch x86_64')
-            env.Append(ASFLAGS='-arch x86_64')
+    if uname[0] == 'Darwin' and compareVersions(uname[2], '9.0.0') >= 0:
+        if int(readCommand('sysctl -n hw.cpu64bit_capable')[0]):
+            main.Append(CCFLAGS='-arch x86_64')
+            main.Append(CFLAGS='-arch x86_64')
+            main.Append(LINKFLAGS='-arch x86_64')
+            main.Append(ASFLAGS='-arch x86_64')
 except:
     pass
 
 except:
     pass
 
@@ -532,7 +505,7 @@ if not conf:
         def __getattr__(self, mname):
             return NullCheck
 
         def __getattr__(self, mname):
             return NullCheck
 
-    conf = NullConf(env)
+    conf = NullConf(main)
 
 # Find Python include and library directories for embedding the
 # interpreter.  For consistency, we will use the same Python
 
 # Find Python include and library directories for embedding the
 # interpreter.  For consistency, we will use the same Python
@@ -551,21 +524,22 @@ py_includes = [ py_general_include ]
 if py_platform_include != py_general_include:
     py_includes.append(py_platform_include)
 
 if py_platform_include != py_general_include:
     py_includes.append(py_platform_include)
 
-py_lib_path = []
+py_lib_path = [ py_getvar('LIBDIR') ]
 # add the prefix/lib/pythonX.Y/config dir, but only if there is no
 # shared library in prefix/lib/.
 if not py_getvar('Py_ENABLE_SHARED'):
 # add the prefix/lib/pythonX.Y/config dir, but only if there is no
 # shared library in prefix/lib/.
 if not py_getvar('Py_ENABLE_SHARED'):
-    py_lib_path.append('-L' + py_getvar('LIBPL'))
+    py_lib_path.append(py_getvar('LIBPL'))
 
 py_libs = []
 for lib in py_getvar('LIBS').split() + py_getvar('SYSLIBS').split():
 
 py_libs = []
 for lib in py_getvar('LIBS').split() + py_getvar('SYSLIBS').split():
+    assert lib.startswith('-l')
+    lib = lib[2:]   
     if lib not in py_libs:
         py_libs.append(lib)
     if lib not in py_libs:
         py_libs.append(lib)
-py_libs.append('-l' + py_version)
+py_libs.append(py_version)
 
 
-env.Append(CPPPATH=py_includes)
-env.Append(LIBPATH=py_lib_path)
-#env.Append(LIBS=py_libs)
+main.Append(CPPPATH=py_includes)
+main.Append(LIBPATH=py_lib_path)
 
 # verify that this stuff works
 if not conf.CheckHeader('Python.h', '<>'):
 
 # verify that this stuff works
 if not conf.CheckHeader('Python.h', '<>'):
@@ -573,8 +547,6 @@ if not conf.CheckHeader('Python.h', '<>'):
     Exit(1)
 
 for lib in py_libs:
     Exit(1)
 
 for lib in py_libs:
-    assert lib.startswith('-l')
-    lib = lib[2:]
     if not conf.CheckLib(lib):
         print "Error: can't find library %s required by python" % lib
         Exit(1)
     if not conf.CheckLib(lib):
         print "Error: can't find library %s required by python" % lib
         Exit(1)
@@ -608,9 +580,9 @@ have_mysql = bool(mysql_config)
 
 # Check MySQL version.
 if have_mysql:
 
 # Check MySQL version.
 if have_mysql:
-    mysql_version = read_command(mysql_config + ' --version')
+    mysql_version = readCommand(mysql_config + ' --version')
     min_mysql_version = '4.1'
     min_mysql_version = '4.1'
-    if compare_versions(mysql_version, min_mysql_version) < 0:
+    if compareVersions(mysql_version, min_mysql_version) < 0:
         print 'Warning: MySQL', min_mysql_version, 'or newer required.'
         print '         Version', mysql_version, 'detected.'
         have_mysql = False
         print 'Warning: MySQL', min_mysql_version, 'or newer required.'
         print '         Version', mysql_version, 'detected.'
         have_mysql = False
@@ -629,23 +601,45 @@ if have_mysql:
 #
 # Finish the configuration
 #
 #
 # Finish the configuration
 #
-env = conf.Finish()
+main = conf.Finish()
 
 ######################################################################
 #
 # Collect all non-global variables
 #
 
 
 ######################################################################
 #
 # Collect all non-global variables
 #
 
-Export('env')
-
 # Define the universe of supported ISAs
 all_isa_list = [ ]
 Export('all_isa_list')
 
 # Define the universe of supported ISAs
 all_isa_list = [ ]
 Export('all_isa_list')
 
-# Define the universe of supported CPU models
-all_cpu_list = [ ]
-default_cpus = [ ]
-Export('all_cpu_list', 'default_cpus')
+class CpuModel(object):
+    '''The CpuModel class encapsulates everything the ISA parser needs to
+    know about a particular CPU model.'''
+
+    # Dict of available CPU model objects.  Accessible as CpuModel.dict.
+    dict = {}
+    list = []
+    defaults = []
+
+    # Constructor.  Automatically adds models to CpuModel.dict.
+    def __init__(self, name, filename, includes, strings, default=False):
+        self.name = name           # name of model
+        self.filename = filename   # filename for output exec code
+        self.includes = includes   # include files needed in exec file
+        # The 'strings' dict holds all the per-CPU symbols we can
+        # substitute into templates etc.
+        self.strings = strings
+
+        # This cpu is enabled by default
+        self.default = default
+
+        # Add self to dict
+        if name in CpuModel.dict:
+            raise AttributeError, "CpuModel '%s' already registered" % name
+        CpuModel.dict[name] = self
+        CpuModel.list.append(name)
+
+Export('CpuModel')
 
 # Sticky variables get saved in the variables file so they persist from
 # one invocation to the next (unless overridden, in which case the new
 
 # Sticky variables get saved in the variables file so they persist from
 # one invocation to the next (unless overridden, in which case the new
@@ -653,6 +647,10 @@ Export('all_cpu_list', 'default_cpus')
 sticky_vars = Variables(args=ARGUMENTS)
 Export('sticky_vars')
 
 sticky_vars = Variables(args=ARGUMENTS)
 Export('sticky_vars')
 
+# Sticky variables that should be exported
+export_vars = []
+Export('export_vars')
+
 # Non-sticky variables only apply to the current build.
 nonsticky_vars = Variables(args=ARGUMENTS)
 Export('nonsticky_vars')
 # Non-sticky variables only apply to the current build.
 nonsticky_vars = Variables(args=ARGUMENTS)
 Export('nonsticky_vars')
@@ -666,13 +664,13 @@ for bdir in [ base_dir ] + extras_dir_list:
             SConscript(joinpath(root, 'SConsopts'))
 
 all_isa_list.sort()
             SConscript(joinpath(root, 'SConsopts'))
 
 all_isa_list.sort()
-all_cpu_list.sort()
-default_cpus.sort()
 
 sticky_vars.AddVariables(
     EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
     BoolVariable('FULL_SYSTEM', 'Full-system support', False),
 
 sticky_vars.AddVariables(
     EnumVariable('TARGET_ISA', 'Target ISA', 'alpha', all_isa_list),
     BoolVariable('FULL_SYSTEM', 'Full-system support', False),
-    ListVariable('CPU_MODELS', 'CPU models', default_cpus, all_cpu_list),
+    ListVariable('CPU_MODELS', 'CPU models',
+                 sorted(n for n,m in CpuModel.dict.iteritems() if m.default),
+                 sorted(CpuModel.list)),
     BoolVariable('NO_FAST_ALLOC', 'Disable fast object allocator', False),
     BoolVariable('FAST_ALLOC_DEBUG', 'Enable fast object allocator debugging',
                  False),
     BoolVariable('NO_FAST_ALLOC', 'Disable fast object allocator', False),
     BoolVariable('FAST_ALLOC_DEBUG', 'Enable fast object allocator debugging',
                  False),
@@ -697,10 +695,9 @@ nonsticky_vars.AddVariables(
     )
 
 # These variables get exported to #defines in config/*.hh (see src/SConscript).
     )
 
 # These variables get exported to #defines in config/*.hh (see src/SConscript).
-env.ExportVariables = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
-                       'USE_MYSQL', 'NO_FAST_ALLOC', 'FAST_ALLOC_DEBUG', \
-                       'FAST_ALLOC_STATS', 'SS_COMPATIBLE_FP', \
-                       'USE_CHECKER', 'TARGET_ISA', 'CP_ANNOTATE']
+export_vars += ['FULL_SYSTEM', 'USE_FENV', 'USE_MYSQL',
+                'NO_FAST_ALLOC', 'FAST_ALLOC_DEBUG', 'FAST_ALLOC_STATS',
+                'SS_COMPATIBLE_FP', 'USE_CHECKER', 'TARGET_ISA', 'CP_ANNOTATE']
 
 ###################################################
 #
 
 ###################################################
 #
@@ -746,15 +743,15 @@ def config_emitter(target, source, env):
 
 config_builder = Builder(emitter = config_emitter, action = config_action)
 
 
 config_builder = Builder(emitter = config_emitter, action = config_action)
 
-env.Append(BUILDERS = { 'ConfigFile' : config_builder })
+main.Append(BUILDERS = { 'ConfigFile' : config_builder })
 
 # libelf build is shared across all configs in the build root.
 
 # libelf build is shared across all configs in the build root.
-env.SConscript('ext/libelf/SConscript',
-               variant_dir = joinpath(build_root, 'libelf'))
+main.SConscript('ext/libelf/SConscript',
+                variant_dir = joinpath(build_root, 'libelf'))
 
 # gzstream build is shared across all configs in the build root.
 
 # gzstream build is shared across all configs in the build root.
-env.SConscript('ext/gzstream/SConscript',
-               variant_dir = joinpath(build_root, 'gzstream'))
+main.SConscript('ext/gzstream/SConscript',
+                variant_dir = joinpath(build_root, 'gzstream'))
 
 ###################################################
 #
 
 ###################################################
 #
@@ -762,24 +759,17 @@ env.SConscript('ext/gzstream/SConscript',
 #
 ###################################################
 
 #
 ###################################################
 
-env['ALL_ISA_LIST'] = all_isa_list
+main['ALL_ISA_LIST'] = all_isa_list
 def make_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])
 def make_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])
-        bname = basename(fname)
         f = open(fname, 'w')
         f = open(fname, 'w')
-        f.write('#include "arch/isa_specific.hh"\n')
-        cond = '#if'
-        for isa in all_isa_list:
-            f.write('%s THE_ISA == %s_ISA\n#include "%s/%s/%s"\n'
-                    % (cond, isa.upper(), dname, isa, bname))
-            cond = '#elif'
-        f.write('#else\n#error "THE_ISA not set"\n#endif\n')
+        isa = env['TARGET_ISA'].lower()
+        print >>f, '#include "%s/%s/%s"' % (dname, isa, basename(fname))
         f.close()
         f.close()
-        return 0
 
     # String to print when generating header
     def gen_switch_hdr_string(target, source, env):
 
     # String to print when generating header
     def gen_switch_hdr_string(target, source, env):
@@ -802,14 +792,11 @@ Export('make_switching_dir')
 #
 ###################################################
 
 #
 ###################################################
 
-# rename base env
-base_env = env
-
 for variant_path in variant_paths:
     print "Building in", variant_path
 
     # Make a copy of the build-root environment to use for this config.
 for variant_path in variant_paths:
     print "Building in", variant_path
 
     # Make a copy of the build-root environment to use for this config.
-    env = base_env.Clone()
+    env = main.Clone()
     env['BUILDDIR'] = variant_path
 
     # variant_dir is the tail component of build path, and is used to
     env['BUILDDIR'] = variant_path
 
     # variant_dir is the tail component of build path, and is used to