SConscript revision 5610:0e1e9c186769
1955SN/A# -*- mode:python -*-
2955SN/A
31762SN/A# Copyright (c) 2004-2005 The Regents of The University of Michigan
4955SN/A# All rights reserved.
5955SN/A#
6955SN/A# Redistribution and use in source and binary forms, with or without
7955SN/A# modification, are permitted provided that the following conditions are
8955SN/A# met: redistributions of source code must retain the above copyright
9955SN/A# notice, this list of conditions and the following disclaimer;
10955SN/A# redistributions in binary form must reproduce the above copyright
11955SN/A# notice, this list of conditions and the following disclaimer in the
12955SN/A# documentation and/or other materials provided with the distribution;
13955SN/A# neither the name of the copyright holders nor the names of its
14955SN/A# contributors may be used to endorse or promote products derived from
15955SN/A# this software without specific prior written permission.
16955SN/A#
17955SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18955SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19955SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20955SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21955SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22955SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23955SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24955SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25955SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26955SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27955SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu#
292665Ssaidi@eecs.umich.edu# Authors: Nathan Binkert
30955SN/A
31955SN/Aimport array
32955SN/Aimport imp
33955SN/Aimport marshal
34955SN/Aimport os
352632Sstever@eecs.umich.eduimport re
362632Sstever@eecs.umich.eduimport sys
372632Sstever@eecs.umich.eduimport zlib
382632Sstever@eecs.umich.edu
39955SN/Afrom os.path import basename, exists, isdir, isfile, join as joinpath
402632Sstever@eecs.umich.edu
412632Sstever@eecs.umich.eduimport SCons
422761Sstever@eecs.umich.edu
432632Sstever@eecs.umich.edu# This file defines how to build a particular configuration of M5
442632Sstever@eecs.umich.edu# based on variable settings in the 'env' build environment.
452632Sstever@eecs.umich.edu
462761Sstever@eecs.umich.eduImport('*')
472761Sstever@eecs.umich.edu
482761Sstever@eecs.umich.edu# Children need to see the environment
492632Sstever@eecs.umich.eduExport('env')
502632Sstever@eecs.umich.edu
512761Sstever@eecs.umich.edubuild_env = dict([(opt, env[opt]) for opt in env.ExportOptions])
522761Sstever@eecs.umich.edu
532761Sstever@eecs.umich.edudef sort_list(_list):
542761Sstever@eecs.umich.edu    """return a sorted copy of '_list'"""
552761Sstever@eecs.umich.edu    if isinstance(_list, list):
562632Sstever@eecs.umich.edu        _list = _list[:]
572632Sstever@eecs.umich.edu    else:
582632Sstever@eecs.umich.edu        _list = list(_list)
592632Sstever@eecs.umich.edu    _list.sort()
602632Sstever@eecs.umich.edu    return _list
612632Sstever@eecs.umich.edu
622632Sstever@eecs.umich.educlass PySourceFile(object):
63955SN/A    invalid_sym_char = re.compile('[^A-z0-9_]')
64955SN/A    def __init__(self, package, tnode):
65955SN/A        snode = tnode.srcnode()
66955SN/A        filename = str(tnode)
67955SN/A        pyname = basename(filename)
683918Ssaidi@eecs.umich.edu        assert pyname.endswith('.py')
694202Sbinkertn@umich.edu        name = pyname[:-3]
704678Snate@binkert.org        if package:
71955SN/A            path = package.split('.')
722656Sstever@eecs.umich.edu        else:
732656Sstever@eecs.umich.edu            path = []
742656Sstever@eecs.umich.edu
752656Sstever@eecs.umich.edu        modpath = path[:]
762656Sstever@eecs.umich.edu        if name != '__init__':
772656Sstever@eecs.umich.edu            modpath += [name]
782656Sstever@eecs.umich.edu        modpath = '.'.join(modpath)
792653Sstever@eecs.umich.edu
802653Sstever@eecs.umich.edu        arcpath = path + [ pyname ]
812653Sstever@eecs.umich.edu        arcname = joinpath(*arcpath)
822653Sstever@eecs.umich.edu
832653Sstever@eecs.umich.edu        debugname = snode.abspath
842653Sstever@eecs.umich.edu        if not exists(debugname):
852653Sstever@eecs.umich.edu            debugname = tnode.abspath
862653Sstever@eecs.umich.edu
872653Sstever@eecs.umich.edu        self.tnode = tnode
882653Sstever@eecs.umich.edu        self.snode = snode
892653Sstever@eecs.umich.edu        self.pyname = pyname
901852SN/A        self.package = package
91955SN/A        self.modpath = modpath
92955SN/A        self.arcname = arcname
93955SN/A        self.debugname = debugname
943717Sstever@eecs.umich.edu        self.compiled = File(filename + 'c')
953716Sstever@eecs.umich.edu        self.assembly = File(filename + '.s')
96955SN/A        self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath)
971533SN/A        
983716Sstever@eecs.umich.edu
991533SN/A########################################################################
1004678Snate@binkert.org# Code for adding source files of various types
1014678Snate@binkert.org#
1024678Snate@binkert.orgcc_lib_sources = []
1034678Snate@binkert.orgdef Source(source):
1044678Snate@binkert.org    '''Add a source file to the libm5 build'''
1054678Snate@binkert.org    if not isinstance(source, SCons.Node.FS.File):
1064678Snate@binkert.org        source = File(source)
1074678Snate@binkert.org
1084678Snate@binkert.org    cc_lib_sources.append(source)
1094678Snate@binkert.org
1104678Snate@binkert.orgcc_bin_sources = []
1114678Snate@binkert.orgdef BinSource(source):
1124678Snate@binkert.org    '''Add a source file to the m5 binary build'''
1134678Snate@binkert.org    if not isinstance(source, SCons.Node.FS.File):
1144678Snate@binkert.org        source = File(source)
1154678Snate@binkert.org
1164678Snate@binkert.org    cc_bin_sources.append(source)
1174678Snate@binkert.org
1184678Snate@binkert.orgpy_sources = []
1194678Snate@binkert.orgdef PySource(package, source):
1204678Snate@binkert.org    '''Add a python source file to the named package'''
1214678Snate@binkert.org    if not isinstance(source, SCons.Node.FS.File):
1224678Snate@binkert.org        source = File(source)
1234678Snate@binkert.org
1244678Snate@binkert.org    source = PySourceFile(package, source)
1254678Snate@binkert.org    py_sources.append(source)
1264678Snate@binkert.org
1274678Snate@binkert.orgsim_objects_fixed = False
128955SN/Asim_object_modfiles = set()
129955SN/Adef SimObject(source):
1302632Sstever@eecs.umich.edu    '''Add a SimObject python file as a python source object and add
1312632Sstever@eecs.umich.edu    it to a list of sim object modules'''
132955SN/A
133955SN/A    if sim_objects_fixed:
134955SN/A        raise AttributeError, "Too late to call SimObject now."
135955SN/A
1362632Sstever@eecs.umich.edu    if not isinstance(source, SCons.Node.FS.File):
137955SN/A        source = File(source)
1382632Sstever@eecs.umich.edu
1392632Sstever@eecs.umich.edu    PySource('m5.objects', source)
1402632Sstever@eecs.umich.edu    modfile = basename(str(source))
1412632Sstever@eecs.umich.edu    assert modfile.endswith('.py')
1422632Sstever@eecs.umich.edu    modname = modfile[:-3]
1432632Sstever@eecs.umich.edu    sim_object_modfiles.add(modname)
1442632Sstever@eecs.umich.edu
1453053Sstever@eecs.umich.eduswig_sources = []
1463053Sstever@eecs.umich.edudef SwigSource(package, source):
1473053Sstever@eecs.umich.edu    '''Add a swig file to build'''
1483053Sstever@eecs.umich.edu    if not isinstance(source, SCons.Node.FS.File):
1493053Sstever@eecs.umich.edu        source = File(source)
1503053Sstever@eecs.umich.edu    val = source,package
1513053Sstever@eecs.umich.edu    swig_sources.append(val)
1523053Sstever@eecs.umich.edu
1533053Sstever@eecs.umich.eduunit_tests = []
1543053Sstever@eecs.umich.edudef UnitTest(target, sources):
1553053Sstever@eecs.umich.edu    if not isinstance(sources, (list, tuple)):
1563053Sstever@eecs.umich.edu        sources = [ sources ]
1573053Sstever@eecs.umich.edu    
1583053Sstever@eecs.umich.edu    srcs = []
1593053Sstever@eecs.umich.edu    for source in sources:
1603053Sstever@eecs.umich.edu        if not isinstance(source, SCons.Node.FS.File):
1612632Sstever@eecs.umich.edu            source = File(source)
1622632Sstever@eecs.umich.edu        srcs.append(source)
1632632Sstever@eecs.umich.edu            
1642632Sstever@eecs.umich.edu    unit_tests.append((target, srcs))
1652632Sstever@eecs.umich.edu
1662632Sstever@eecs.umich.edu# Children should have access
1673718Sstever@eecs.umich.eduExport('Source')
1683718Sstever@eecs.umich.eduExport('BinSource')
1693718Sstever@eecs.umich.eduExport('PySource')
1703718Sstever@eecs.umich.eduExport('SimObject')
1713718Sstever@eecs.umich.eduExport('SwigSource')
1723718Sstever@eecs.umich.eduExport('UnitTest')
1733718Sstever@eecs.umich.edu
1743718Sstever@eecs.umich.edu########################################################################
1753718Sstever@eecs.umich.edu#
1763718Sstever@eecs.umich.edu# Trace Flags
1773718Sstever@eecs.umich.edu#
1783718Sstever@eecs.umich.eduall_flags = {}
1793718Sstever@eecs.umich.edutrace_flags = []
1802634Sstever@eecs.umich.edudef TraceFlag(name, desc=''):
1812634Sstever@eecs.umich.edu    if name in all_flags:
1822632Sstever@eecs.umich.edu        raise AttributeError, "Flag %s already specified" % name
1832638Sstever@eecs.umich.edu    flag = (name, (), desc)
1842632Sstever@eecs.umich.edu    trace_flags.append(flag)
1852632Sstever@eecs.umich.edu    all_flags[name] = ()
1862632Sstever@eecs.umich.edu
1872632Sstever@eecs.umich.edudef CompoundFlag(name, flags, desc=''):
1882632Sstever@eecs.umich.edu    if name in all_flags:
1892632Sstever@eecs.umich.edu        raise AttributeError, "Flag %s already specified" % name
1901858SN/A
1913716Sstever@eecs.umich.edu    compound = tuple(flags)
1922638Sstever@eecs.umich.edu    for flag in compound:
1932638Sstever@eecs.umich.edu        if flag not in all_flags:
1942638Sstever@eecs.umich.edu            raise AttributeError, "Trace flag %s not found" % flag
1952638Sstever@eecs.umich.edu        if all_flags[flag]:
1962638Sstever@eecs.umich.edu            raise AttributeError, \
1972638Sstever@eecs.umich.edu                "Compound flag can't point to another compound flag"
1982638Sstever@eecs.umich.edu
1993716Sstever@eecs.umich.edu    flag = (name, compound, desc)
2002634Sstever@eecs.umich.edu    trace_flags.append(flag)
2012634Sstever@eecs.umich.edu    all_flags[name] = compound
202955SN/A
203955SN/AExport('TraceFlag')
204955SN/AExport('CompoundFlag')
205955SN/A
206955SN/A########################################################################
207955SN/A#
208955SN/A# Set some compiler variables
209955SN/A#
2101858SN/A
2111858SN/A# Include file paths are rooted in this directory.  SCons will
2122632Sstever@eecs.umich.edu# automatically expand '.' to refer to both the source directory and
213955SN/A# the corresponding build directory to pick up generated include
2143643Ssaidi@eecs.umich.edu# files.
2153643Ssaidi@eecs.umich.eduenv.Append(CPPPATH=Dir('.'))
2163643Ssaidi@eecs.umich.edu
2173643Ssaidi@eecs.umich.edu# Add a flag defining what THE_ISA should be for all compilation
2183643Ssaidi@eecs.umich.eduenv.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
2193643Ssaidi@eecs.umich.edu
2203643Ssaidi@eecs.umich.edu########################################################################
2213643Ssaidi@eecs.umich.edu#
2224494Ssaidi@eecs.umich.edu# Walk the tree and execute all SConscripts in subdirectories
2234494Ssaidi@eecs.umich.edu#
2243716Sstever@eecs.umich.edu
2251105SN/Afor base_dir in base_dir_list:
2262667Sstever@eecs.umich.edu    here = Dir('.').srcnode().abspath
2272667Sstever@eecs.umich.edu    for root, dirs, files in os.walk(base_dir, topdown=True):
2282667Sstever@eecs.umich.edu        if root == here:
2292667Sstever@eecs.umich.edu            # we don't want to recurse back into this SConscript
2302667Sstever@eecs.umich.edu            continue
2312667Sstever@eecs.umich.edu
2321869SN/A        if 'SConscript' in files:
2331869SN/A            build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:])
2341869SN/A            SConscript(joinpath(root, 'SConscript'), build_dir=build_dir)
2351869SN/A
2361869SN/Afor opt in env.ExportOptions:
2371065SN/A    env.ConfigFile(opt)
2382632Sstever@eecs.umich.edu
2392632Sstever@eecs.umich.edu########################################################################
2403918Ssaidi@eecs.umich.edu#
2413918Ssaidi@eecs.umich.edu# Prevent any SimObjects from being added after this point, they
2423940Ssaidi@eecs.umich.edu# should all have been added in the SConscripts above
2433918Ssaidi@eecs.umich.edu#
2443918Ssaidi@eecs.umich.educlass DictImporter(object):
2453918Ssaidi@eecs.umich.edu    '''This importer takes a dictionary of arbitrary module names that
2463918Ssaidi@eecs.umich.edu    map to arbitrary filenames.'''
2473918Ssaidi@eecs.umich.edu    def __init__(self, modules):
2483918Ssaidi@eecs.umich.edu        self.modules = modules
2493940Ssaidi@eecs.umich.edu        self.installed = set()
2503940Ssaidi@eecs.umich.edu
2513940Ssaidi@eecs.umich.edu    def __del__(self):
2523942Ssaidi@eecs.umich.edu        self.unload()
2533940Ssaidi@eecs.umich.edu
2543918Ssaidi@eecs.umich.edu    def unload(self):
2553918Ssaidi@eecs.umich.edu        import sys
256955SN/A        for module in self.installed:
2571858SN/A            del sys.modules[module]
2583918Ssaidi@eecs.umich.edu        self.installed = set()
2593918Ssaidi@eecs.umich.edu
2603918Ssaidi@eecs.umich.edu    def find_module(self, fullname, path):
2613918Ssaidi@eecs.umich.edu        if fullname == '__scons':
2623940Ssaidi@eecs.umich.edu            return self
2633940Ssaidi@eecs.umich.edu
2643918Ssaidi@eecs.umich.edu        if fullname == 'm5.objects':
2653918Ssaidi@eecs.umich.edu            return self
2663918Ssaidi@eecs.umich.edu
2673918Ssaidi@eecs.umich.edu        if fullname.startswith('m5.internal'):
2683918Ssaidi@eecs.umich.edu            return None
2693918Ssaidi@eecs.umich.edu
2703918Ssaidi@eecs.umich.edu        if fullname in self.modules and exists(self.modules[fullname]):
2713918Ssaidi@eecs.umich.edu            return self
2723918Ssaidi@eecs.umich.edu
2733940Ssaidi@eecs.umich.edu        return None
2743918Ssaidi@eecs.umich.edu
2753918Ssaidi@eecs.umich.edu    def load_module(self, fullname):
2761851SN/A        mod = imp.new_module(fullname)
2771851SN/A        sys.modules[fullname] = mod
2781858SN/A        self.installed.add(fullname)
2792632Sstever@eecs.umich.edu
280955SN/A        mod.__loader__ = self
2813053Sstever@eecs.umich.edu        if fullname == 'm5.objects':
2823053Sstever@eecs.umich.edu            mod.__path__ = fullname.split('.')
2833053Sstever@eecs.umich.edu            return mod
2843053Sstever@eecs.umich.edu
2853053Sstever@eecs.umich.edu        if fullname == '__scons':
2863053Sstever@eecs.umich.edu            mod.__dict__['m5_build_env'] = build_env
2873053Sstever@eecs.umich.edu            return mod
2883053Sstever@eecs.umich.edu
2893053Sstever@eecs.umich.edu        srcfile = self.modules[fullname]
2904742Sstever@eecs.umich.edu        if basename(srcfile) == '__init__.py':
2914742Sstever@eecs.umich.edu            mod.__path__ = fullname.split('.')
2923053Sstever@eecs.umich.edu        mod.__file__ = srcfile
2933053Sstever@eecs.umich.edu
2943053Sstever@eecs.umich.edu        exec file(srcfile, 'r') in mod.__dict__
2953053Sstever@eecs.umich.edu
2963053Sstever@eecs.umich.edu        return mod
2973053Sstever@eecs.umich.edu
2983053Sstever@eecs.umich.edupy_modules = {}
2993053Sstever@eecs.umich.edufor source in py_sources:
3003053Sstever@eecs.umich.edu    py_modules[source.modpath] = source.snode.abspath
3012667Sstever@eecs.umich.edu
3024554Sbinkertn@umich.edu# install the python importer so we can grab stuff from the source
3034554Sbinkertn@umich.edu# tree itself.  We can't have SimObjects added after this point or
3042667Sstever@eecs.umich.edu# else we won't know about them for the rest of the stuff.
3054554Sbinkertn@umich.edusim_objects_fixed = True
3064554Sbinkertn@umich.eduimporter = DictImporter(py_modules)
3074554Sbinkertn@umich.edusys.meta_path[0:0] = [ importer ]
3084554Sbinkertn@umich.edu
3094554Sbinkertn@umich.eduimport m5
3104554Sbinkertn@umich.edu
3114554Sbinkertn@umich.edu# import all sim objects so we can populate the all_objects list
3124554Sbinkertn@umich.edu# make sure that we're working with a list, then let's sort it
3134554Sbinkertn@umich.edusim_objects = list(sim_object_modfiles)
3144554Sbinkertn@umich.edusim_objects.sort()
3152667Sstever@eecs.umich.edufor simobj in sim_objects:
3164554Sbinkertn@umich.edu    exec('from m5.objects import %s' % simobj)
3174554Sbinkertn@umich.edu
3184554Sbinkertn@umich.edu# we need to unload all of the currently imported modules so that they
3194554Sbinkertn@umich.edu# will be re-imported the next time the sconscript is run
3202667Sstever@eecs.umich.eduimporter.unload()
3214554Sbinkertn@umich.edusys.meta_path.remove(importer)
3222667Sstever@eecs.umich.edu
3234554Sbinkertn@umich.edusim_objects = m5.SimObject.allClasses
3244554Sbinkertn@umich.eduall_enums = m5.params.allEnums
3252667Sstever@eecs.umich.edu
3262638Sstever@eecs.umich.eduall_params = {}
3272638Sstever@eecs.umich.edufor name,obj in sim_objects.iteritems():
3282638Sstever@eecs.umich.edu    for param in obj._params.local.values():
3293716Sstever@eecs.umich.edu        if not hasattr(param, 'swig_decl'):
3303716Sstever@eecs.umich.edu            continue
3311858SN/A        pname = param.ptype_str
3323118Sstever@eecs.umich.edu        if pname not in all_params:
3333118Sstever@eecs.umich.edu            all_params[pname] = param
3343118Sstever@eecs.umich.edu
3353118Sstever@eecs.umich.edu########################################################################
3363118Sstever@eecs.umich.edu#
3373118Sstever@eecs.umich.edu# calculate extra dependencies
3383118Sstever@eecs.umich.edu#
3393118Sstever@eecs.umich.edumodule_depends = ["m5", "m5.SimObject", "m5.params"]
3403118Sstever@eecs.umich.edudepends = [ File(py_modules[dep]) for dep in module_depends ]
3413118Sstever@eecs.umich.edu
3423118Sstever@eecs.umich.edu########################################################################
3433716Sstever@eecs.umich.edu#
3443118Sstever@eecs.umich.edu# Commands for the basic automatically generated python files
3453118Sstever@eecs.umich.edu#
3463118Sstever@eecs.umich.edu
3473118Sstever@eecs.umich.edu# Generate Python file containing a dict specifying the current
3483118Sstever@eecs.umich.edu# build_env flags.
3493118Sstever@eecs.umich.edudef makeDefinesPyFile(target, source, env):
3503118Sstever@eecs.umich.edu    f = file(str(target[0]), 'w')
3513118Sstever@eecs.umich.edu    print >>f, "m5_build_env = ", source[0]
3523118Sstever@eecs.umich.edu    f.close()
3533716Sstever@eecs.umich.edu
3543118Sstever@eecs.umich.edu# Generate python file containing info about the M5 source code
3553118Sstever@eecs.umich.edudef makeInfoPyFile(target, source, env):
3563118Sstever@eecs.umich.edu    f = file(str(target[0]), 'w')
3573118Sstever@eecs.umich.edu    for src in source:
3583118Sstever@eecs.umich.edu        data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
3593118Sstever@eecs.umich.edu        print >>f, "%s = %s" % (src, repr(data))
3603118Sstever@eecs.umich.edu    f.close()
3613118Sstever@eecs.umich.edu
3623118Sstever@eecs.umich.edu# Generate the __init__.py file for m5.objects
3633118Sstever@eecs.umich.edudef makeObjectsInitFile(target, source, env):
3643483Ssaidi@eecs.umich.edu    f = file(str(target[0]), 'w')
3653494Ssaidi@eecs.umich.edu    print >>f, 'from params import *'
3663494Ssaidi@eecs.umich.edu    print >>f, 'from m5.SimObject import *'
3673483Ssaidi@eecs.umich.edu    for module in source:
3683483Ssaidi@eecs.umich.edu        print >>f, 'from %s import *' % module.get_contents()
3693483Ssaidi@eecs.umich.edu    f.close()
3703053Sstever@eecs.umich.edu
3713053Sstever@eecs.umich.edu# Generate a file with all of the compile options in it
3723918Ssaidi@eecs.umich.eduenv.Command('python/m5/defines.py', Value(build_env), makeDefinesPyFile)
3733053Sstever@eecs.umich.eduPySource('m5', 'python/m5/defines.py')
3743053Sstever@eecs.umich.edu
3753053Sstever@eecs.umich.edu# Generate a file that wraps the basic top level files
3763053Sstever@eecs.umich.eduenv.Command('python/m5/info.py',
3773053Sstever@eecs.umich.edu            [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
3781858SN/A            makeInfoPyFile)
3791858SN/APySource('m5', 'python/m5/info.py')
3801858SN/A
3811858SN/A# Generate an __init__.py file for the objects package
3821858SN/Aenv.Command('python/m5/objects/__init__.py',
3831858SN/A            [ Value(o) for o in sort_list(sim_object_modfiles) ],
3841859SN/A            makeObjectsInitFile)
3851858SN/APySource('m5.objects', 'python/m5/objects/__init__.py')
3861858SN/A
3871858SN/A########################################################################
3881859SN/A#
3891859SN/A# Create all of the SimObject param headers and enum headers
3901862SN/A#
3913053Sstever@eecs.umich.edu
3923053Sstever@eecs.umich.edudef createSimObjectParam(target, source, env):
3933053Sstever@eecs.umich.edu    assert len(target) == 1 and len(source) == 1
3943053Sstever@eecs.umich.edu
3951859SN/A    hh_file = file(target[0].abspath, 'w')
3961859SN/A    name = str(source[0].get_contents())
3971859SN/A    obj = sim_objects[name]
3981859SN/A
3991859SN/A    print >>hh_file, obj.cxx_decl()
4001859SN/A
4011859SN/Adef createSwigParam(target, source, env):
4021859SN/A    assert len(target) == 1 and len(source) == 1
4031862SN/A
4041859SN/A    i_file = file(target[0].abspath, 'w')
4051859SN/A    name = str(source[0].get_contents())
4061859SN/A    param = all_params[name]
4071858SN/A
4081858SN/A    for line in param.swig_decl():
4092139SN/A        print >>i_file, line
4104202Sbinkertn@umich.edu
4114202Sbinkertn@umich.edudef createEnumStrings(target, source, env):
4122139SN/A    assert len(target) == 1 and len(source) == 1
4132155SN/A
4144202Sbinkertn@umich.edu    cc_file = file(target[0].abspath, 'w')
4154202Sbinkertn@umich.edu    name = str(source[0].get_contents())
4164202Sbinkertn@umich.edu    obj = all_enums[name]
4172155SN/A
4181869SN/A    print >>cc_file, obj.cxx_def()
4191869SN/A    cc_file.close()
4201869SN/A
4211869SN/Adef createEnumParam(target, source, env):
4224202Sbinkertn@umich.edu    assert len(target) == 1 and len(source) == 1
4234202Sbinkertn@umich.edu
4244202Sbinkertn@umich.edu    hh_file = file(target[0].abspath, 'w')
4254202Sbinkertn@umich.edu    name = str(source[0].get_contents())
4264202Sbinkertn@umich.edu    obj = all_enums[name]
4274202Sbinkertn@umich.edu
4284202Sbinkertn@umich.edu    print >>hh_file, obj.cxx_decl()
4294202Sbinkertn@umich.edu
4304202Sbinkertn@umich.edu# Generate all of the SimObject param struct header files
4314202Sbinkertn@umich.eduparams_hh_files = []
4324202Sbinkertn@umich.edufor name,simobj in sim_objects.iteritems():
4334202Sbinkertn@umich.edu    extra_deps = [ File(py_modules[simobj.__module__]) ]
4344202Sbinkertn@umich.edu
4354202Sbinkertn@umich.edu    hh_file = File('params/%s.hh' % name)
4364202Sbinkertn@umich.edu    params_hh_files.append(hh_file)
4374202Sbinkertn@umich.edu    env.Command(hh_file, Value(name), createSimObjectParam)
4384773Snate@binkert.org    env.Depends(hh_file, depends + extra_deps)
4394773Snate@binkert.org
4404773Snate@binkert.org# Generate any parameter header files needed
4414773Snate@binkert.orgparams_i_files = []
4424773Snate@binkert.orgfor name,param in all_params.iteritems():
4434773Snate@binkert.org    if isinstance(param, m5.params.VectorParamDesc):
4444773Snate@binkert.org        ext = 'vptype'
4451869SN/A    else:
4464202Sbinkertn@umich.edu        ext = 'ptype'
4471869SN/A
4482508SN/A    i_file = File('params/%s_%s.i' % (name, ext))
4492508SN/A    params_i_files.append(i_file)
4502508SN/A    env.Command(i_file, Value(name), createSwigParam)
4512508SN/A    env.Depends(i_file, depends)
4524202Sbinkertn@umich.edu
4531869SN/A# Generate all enum header files
4541869SN/Afor name,enum in all_enums.iteritems():
4551869SN/A    extra_deps = [ File(py_modules[enum.__module__]) ]
4561869SN/A
4571869SN/A    cc_file = File('enums/%s.cc' % name)
4581869SN/A    env.Command(cc_file, Value(name), createEnumStrings)
4591965SN/A    env.Depends(cc_file, depends + extra_deps)
4601965SN/A    Source(cc_file)
4611965SN/A
4621869SN/A    hh_file = File('enums/%s.hh' % name)
4631869SN/A    env.Command(hh_file, Value(name), createEnumParam)
4642733Sktlim@umich.edu    env.Depends(hh_file, depends + extra_deps)
4651869SN/A
4661884SN/A# Build the big monolithic swigged params module (wraps all SimObject
4671884SN/A# param structs and enum structs)
4683356Sbinkertn@umich.edudef buildParams(target, source, env):
4693356Sbinkertn@umich.edu    names = [ s.get_contents() for s in source ]
4703356Sbinkertn@umich.edu    objs = [ sim_objects[name] for name in names ]
4714773Snate@binkert.org    out = file(target[0].abspath, 'w')
4724773Snate@binkert.org
4734773Snate@binkert.org    ordered_objs = []
4741869SN/A    obj_seen = set()
4751858SN/A    def order_obj(obj):
4761869SN/A        name = str(obj)
4771869SN/A        if name in obj_seen:
4781869SN/A            return
4791858SN/A
4802761Sstever@eecs.umich.edu        obj_seen.add(name)
4811869SN/A        if str(obj) != 'SimObject':
4822733Sktlim@umich.edu            order_obj(obj.__bases__[0])
4833584Ssaidi@eecs.umich.edu
4841869SN/A        ordered_objs.append(obj)
4851869SN/A
4861869SN/A    for obj in objs:
4871869SN/A        order_obj(obj)
4881869SN/A
4891869SN/A    enums = set()
4901858SN/A    predecls = []
491955SN/A    pd_seen = set()
492955SN/A
4931869SN/A    def add_pds(*pds):
4941869SN/A        for pd in pds:
4951869SN/A            if pd not in pd_seen:
4961869SN/A                predecls.append(pd)
4971869SN/A                pd_seen.add(pd)
4981869SN/A
4991869SN/A    for obj in ordered_objs:
5001869SN/A        params = obj._params.local.values()
5011869SN/A        for param in params:
5021869SN/A            ptype = param.ptype
5031869SN/A            if issubclass(ptype, m5.params.Enum):
5041869SN/A                if ptype not in enums:
5051869SN/A                    enums.add(ptype)
5061869SN/A            pds = param.swig_predecls()
5071869SN/A            if isinstance(pds, (list, tuple)):
5081869SN/A                add_pds(*pds)
5091869SN/A            else:
5101869SN/A                add_pds(pds)
5111869SN/A
5121869SN/A    print >>out, '%module params'
5131869SN/A
5141869SN/A    print >>out, '%{'
5151869SN/A    for obj in ordered_objs:
5161869SN/A        print >>out, '#include "params/%s.hh"' % obj
5171869SN/A    print >>out, '%}'
5181869SN/A
5191869SN/A    for pd in predecls:
5201869SN/A        print >>out, pd
5211869SN/A
5223716Sstever@eecs.umich.edu    enums = list(enums)
5233356Sbinkertn@umich.edu    enums.sort()
5243356Sbinkertn@umich.edu    for enum in enums:
5253356Sbinkertn@umich.edu        print >>out, '%%include "enums/%s.hh"' % enum.__name__
5263356Sbinkertn@umich.edu    print >>out
5273356Sbinkertn@umich.edu
5283356Sbinkertn@umich.edu    for obj in ordered_objs:
5293356Sbinkertn@umich.edu        if obj.swig_objdecls:
5301869SN/A            for decl in obj.swig_objdecls:
5311869SN/A                print >>out, decl
5321869SN/A            continue
5331869SN/A
5341869SN/A        class_path = obj.cxx_class.split('::')
5351869SN/A        class_path.reverse()
5361869SN/A        classname = class_path[0]
5372655Sstever@eecs.umich.edu        namespaces = class_path[1:]
5382655Sstever@eecs.umich.edu
5392655Sstever@eecs.umich.edu        code = ''
5402655Sstever@eecs.umich.edu        code += '// stop swig from creating/wrapping default ctor/dtor\n'
5412655Sstever@eecs.umich.edu        code += '%%nodefault %s;\n' % classname
5422655Sstever@eecs.umich.edu        code += 'class %s ' % classname
5432655Sstever@eecs.umich.edu        if obj._base:
5442655Sstever@eecs.umich.edu            code += ': public %s' % obj._base.cxx_class
5452655Sstever@eecs.umich.edu        code += ' {};\n'
5462655Sstever@eecs.umich.edu
5472655Sstever@eecs.umich.edu        for ns in namespaces:
5482655Sstever@eecs.umich.edu            new_code = 'namespace %s {\n' % ns
5492655Sstever@eecs.umich.edu            new_code += code
5502655Sstever@eecs.umich.edu            new_code += '}\n'
5512655Sstever@eecs.umich.edu            code = new_code
5522655Sstever@eecs.umich.edu
5532655Sstever@eecs.umich.edu        print >>out, code
5542655Sstever@eecs.umich.edu
5552655Sstever@eecs.umich.edu    print >>out, '%%include "src/sim/sim_object_params.hh"' % obj
5562655Sstever@eecs.umich.edu    for obj in ordered_objs:
5572655Sstever@eecs.umich.edu        print >>out, '%%include "params/%s.hh"' % obj
5582655Sstever@eecs.umich.edu
5592655Sstever@eecs.umich.eduparams_file = File('params/params.i')
5602655Sstever@eecs.umich.edunames = sort_list(sim_objects.keys())
5612655Sstever@eecs.umich.eduenv.Command(params_file, [ Value(v) for v in names ], buildParams)
5622655Sstever@eecs.umich.eduenv.Depends(params_file, params_hh_files + params_i_files + depends)
5632634Sstever@eecs.umich.eduSwigSource('m5.objects', params_file)
5642634Sstever@eecs.umich.edu
5652634Sstever@eecs.umich.edu# Build all swig modules
5662634Sstever@eecs.umich.eduswig_modules = []
5672634Sstever@eecs.umich.educc_swig_sources = []
5682634Sstever@eecs.umich.edufor source,package in swig_sources:
5692638Sstever@eecs.umich.edu    filename = str(source)
5702638Sstever@eecs.umich.edu    assert filename.endswith('.i')
5713716Sstever@eecs.umich.edu
5722638Sstever@eecs.umich.edu    base = '.'.join(filename.split('.')[:-1])
5732638Sstever@eecs.umich.edu    module = basename(base)
5741869SN/A    cc_file = base + '_wrap.cc'
5751869SN/A    py_file = base + '.py'
5763546Sgblack@eecs.umich.edu
5773546Sgblack@eecs.umich.edu    env.Command([cc_file, py_file], source,
5783546Sgblack@eecs.umich.edu                '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
5793546Sgblack@eecs.umich.edu                '-o ${TARGETS[0]} $SOURCES')
5804202Sbinkertn@umich.edu    env.Depends(py_file, source)
5813546Sgblack@eecs.umich.edu    env.Depends(cc_file, source)
5823546Sgblack@eecs.umich.edu
5833546Sgblack@eecs.umich.edu    swig_modules.append(Value(module))
5843546Sgblack@eecs.umich.edu    cc_swig_sources.append(File(cc_file))
5853546Sgblack@eecs.umich.edu    PySource(package, py_file)
5863546Sgblack@eecs.umich.edu
5873546Sgblack@eecs.umich.edu# Generate the main swig init file
5883546Sgblack@eecs.umich.edudef makeSwigInit(target, source, env):
5893546Sgblack@eecs.umich.edu    f = file(str(target[0]), 'w')
5903546Sgblack@eecs.umich.edu    print >>f, 'extern "C" {'
5914202Sbinkertn@umich.edu    for module in source:
5923546Sgblack@eecs.umich.edu        print >>f, '    void init_%s();' % module.get_contents()
5933546Sgblack@eecs.umich.edu    print >>f, '}'
5943546Sgblack@eecs.umich.edu    print >>f, 'void initSwig() {'
5953546Sgblack@eecs.umich.edu    for module in source:
5963546Sgblack@eecs.umich.edu        print >>f, '    init_%s();' % module.get_contents()
5973546Sgblack@eecs.umich.edu    print >>f, '}'
5983546Sgblack@eecs.umich.edu    f.close()
5993546Sgblack@eecs.umich.edu
6003546Sgblack@eecs.umich.eduenv.Command('python/swig/init.cc', swig_modules, makeSwigInit)
6013546Sgblack@eecs.umich.eduSource('python/swig/init.cc')
6023546Sgblack@eecs.umich.edu
6033546Sgblack@eecs.umich.edu# Generate traceflags.py
6043546Sgblack@eecs.umich.edudef traceFlagsPy(target, source, env):
6053546Sgblack@eecs.umich.edu    assert(len(target) == 1)
6063546Sgblack@eecs.umich.edu
6073546Sgblack@eecs.umich.edu    f = file(str(target[0]), 'w')
6083546Sgblack@eecs.umich.edu
6093546Sgblack@eecs.umich.edu    allFlags = []
6103546Sgblack@eecs.umich.edu    for s in source:
6113546Sgblack@eecs.umich.edu        val = eval(s.get_contents())
6124202Sbinkertn@umich.edu        allFlags.append(val)
6133546Sgblack@eecs.umich.edu
6143546Sgblack@eecs.umich.edu    print >>f, 'baseFlags = ['
6153546Sgblack@eecs.umich.edu    for flag, compound, desc in allFlags:
616955SN/A        if not compound:
617955SN/A            print >>f, "    '%s'," % flag
618955SN/A    print >>f, "    ]"
619955SN/A    print >>f
6201858SN/A
6211858SN/A    print >>f, 'compoundFlags = ['
6221858SN/A    print >>f, "    'All',"
6232632Sstever@eecs.umich.edu    for flag, compound, desc in allFlags:
6242632Sstever@eecs.umich.edu        if compound:
6254773Snate@binkert.org            print >>f, "    '%s'," % flag
6264773Snate@binkert.org    print >>f, "    ]"
6272632Sstever@eecs.umich.edu    print >>f
6282632Sstever@eecs.umich.edu
6292632Sstever@eecs.umich.edu    print >>f, "allFlags = frozenset(baseFlags + compoundFlags)"
6302634Sstever@eecs.umich.edu    print >>f
6312638Sstever@eecs.umich.edu
6322023SN/A    print >>f, 'compoundFlagMap = {'
6332632Sstever@eecs.umich.edu    all = tuple([flag for flag,compound,desc in allFlags if not compound])
6342632Sstever@eecs.umich.edu    print >>f, "    'All' : %s," % (all, )
6352632Sstever@eecs.umich.edu    for flag, compound, desc in allFlags:
6362632Sstever@eecs.umich.edu        if compound:
6372632Sstever@eecs.umich.edu            print >>f, "    '%s' : %s," % (flag, compound)
6383716Sstever@eecs.umich.edu    print >>f, "    }"
6392632Sstever@eecs.umich.edu    print >>f
6402632Sstever@eecs.umich.edu
6412632Sstever@eecs.umich.edu    print >>f, 'flagDescriptions = {'
6422632Sstever@eecs.umich.edu    print >>f, "    'All' : 'All flags',"
6432632Sstever@eecs.umich.edu    for flag, compound, desc in allFlags:
6442023SN/A        print >>f, "    '%s' : '%s'," % (flag, desc)
6452632Sstever@eecs.umich.edu    print >>f, "    }"
6462632Sstever@eecs.umich.edu
6471889SN/A    f.close()
6481889SN/A
6492632Sstever@eecs.umich.edudef traceFlagsCC(target, source, env):
6502632Sstever@eecs.umich.edu    assert(len(target) == 1)
6512632Sstever@eecs.umich.edu
6522632Sstever@eecs.umich.edu    f = file(str(target[0]), 'w')
6533716Sstever@eecs.umich.edu
6543716Sstever@eecs.umich.edu    allFlags = []
6552632Sstever@eecs.umich.edu    for s in source:
6562632Sstever@eecs.umich.edu        val = eval(s.get_contents())
6572632Sstever@eecs.umich.edu        allFlags.append(val)
6582632Sstever@eecs.umich.edu
6592632Sstever@eecs.umich.edu    # file header
6602632Sstever@eecs.umich.edu    print >>f, '''
6612632Sstever@eecs.umich.edu/*
6622632Sstever@eecs.umich.edu * DO NOT EDIT THIS FILE! Automatically generated
6631888SN/A */
6641888SN/A
6651869SN/A#include "base/traceflags.hh"
6661869SN/A
6671858SN/Ausing namespace Trace;
6682598SN/A
6692598SN/Aconst char *Trace::flagStrings[] =
6702598SN/A{'''
6712598SN/A
6722598SN/A    # The string array is used by SimpleEnumParam to map the strings
6731858SN/A    # provided by the user to enum values.
6741858SN/A    for flag, compound, desc in allFlags:
6751858SN/A        if not compound:
6761858SN/A            print >>f, '    "%s",' % flag
6771858SN/A
6781858SN/A    print >>f, '    "All",'
6791858SN/A    for flag, compound, desc in allFlags:
6801858SN/A        if compound:
6811858SN/A            print >>f, '    "%s",' % flag
6821871SN/A
6831858SN/A    print >>f, '};'
6841858SN/A    print >>f
6851858SN/A    print >>f, 'const int Trace::numFlagStrings = %d;' % (len(allFlags) + 1)
6861858SN/A    print >>f
6871858SN/A
6881858SN/A    #
6891858SN/A    # Now define the individual compound flag arrays.  There is an array
6901858SN/A    # for each compound flag listing the component base flags.
6911858SN/A    #
6921858SN/A    all = tuple([flag for flag,compound,desc in allFlags if not compound])
6931858SN/A    print >>f, 'static const Flags AllMap[] = {'
6941859SN/A    for flag, compound, desc in allFlags:
6951859SN/A        if not compound:
6961869SN/A            print >>f, "    %s," % flag
6971888SN/A    print >>f, '};'
6982632Sstever@eecs.umich.edu    print >>f
6991869SN/A
7001884SN/A    for flag, compound, desc in allFlags:
7011884SN/A        if not compound:
7021884SN/A            continue
7031884SN/A        print >>f, 'static const Flags %sMap[] = {' % flag
7041884SN/A        for flag in compound:
7051884SN/A            print >>f, "    %s," % flag
7061965SN/A        print >>f, "    (Flags)-1"
7071965SN/A        print >>f, '};'
7081965SN/A        print >>f
7092761Sstever@eecs.umich.edu
7101869SN/A    #
7111869SN/A    # Finally the compoundFlags[] array maps the compound flags
7122632Sstever@eecs.umich.edu    # to their individual arrays/
7132667Sstever@eecs.umich.edu    #
7141869SN/A    print >>f, 'const Flags *Trace::compoundFlags[] ='
7151869SN/A    print >>f, '{'
7162929Sktlim@umich.edu    print >>f, '    AllMap,'
7172929Sktlim@umich.edu    for flag, compound, desc in allFlags:
7183716Sstever@eecs.umich.edu        if compound:
7192929Sktlim@umich.edu            print >>f, '    %sMap,' % flag
720955SN/A    # file trailer
7212598SN/A    print >>f, '};'
7222598SN/A
7233546Sgblack@eecs.umich.edu    f.close()
724955SN/A
725955SN/Adef traceFlagsHH(target, source, env):
726955SN/A    assert(len(target) == 1)
7271530SN/A
728955SN/A    f = file(str(target[0]), 'w')
729955SN/A
730955SN/A    allFlags = []
731    for s in source:
732        val = eval(s.get_contents())
733        allFlags.append(val)
734
735    # file header boilerplate
736    print >>f, '''
737/*
738 * DO NOT EDIT THIS FILE!
739 *
740 * Automatically generated from traceflags.py
741 */
742
743#ifndef __BASE_TRACE_FLAGS_HH__
744#define __BASE_TRACE_FLAGS_HH__
745
746namespace Trace {
747
748enum Flags {'''
749
750    # Generate the enum.  Base flags come first, then compound flags.
751    idx = 0
752    for flag, compound, desc in allFlags:
753        if not compound:
754            print >>f, '    %s = %d,' % (flag, idx)
755            idx += 1
756
757    numBaseFlags = idx
758    print >>f, '    NumFlags = %d,' % idx
759
760    # put a comment in here to separate base from compound flags
761    print >>f, '''
762// The remaining enum values are *not* valid indices for Trace::flags.
763// They are "compound" flags, which correspond to sets of base
764// flags, and are used by changeFlag.'''
765
766    print >>f, '    All = %d,' % idx
767    idx += 1
768    for flag, compound, desc in allFlags:
769        if compound:
770            print >>f, '    %s = %d,' % (flag, idx)
771            idx += 1
772
773    numCompoundFlags = idx - numBaseFlags
774    print >>f, '    NumCompoundFlags = %d' % numCompoundFlags
775
776    # trailer boilerplate
777    print >>f, '''\
778}; // enum Flags
779
780// Array of strings for SimpleEnumParam
781extern const char *flagStrings[];
782extern const int numFlagStrings;
783
784// Array of arraay pointers: for each compound flag, gives the list of
785// base flags to set.  Inidividual flag arrays are terminated by -1.
786extern const Flags *compoundFlags[];
787
788/* namespace Trace */ }
789
790#endif // __BASE_TRACE_FLAGS_HH__
791'''
792
793    f.close()
794
795flags = [ Value(f) for f in trace_flags ]
796env.Command('base/traceflags.py', flags, traceFlagsPy)
797PySource('m5', 'base/traceflags.py')
798
799env.Command('base/traceflags.hh', flags, traceFlagsHH)
800env.Command('base/traceflags.cc', flags, traceFlagsCC)
801Source('base/traceflags.cc')
802
803# Generate program_info.cc
804def programInfo(target, source, env):
805    def gen_file(target, rev, node, date):
806        pi_stats = file(target, 'w')
807        print >>pi_stats, 'const char *hgRev = "%s:%s";' %  (rev, node)
808        print >>pi_stats, 'const char *hgDate = "%s";' % date
809        pi_stats.close()
810
811    target = str(target[0])
812    scons_dir = str(source[0].get_contents())
813    try:
814        import mercurial.demandimport, mercurial.hg, mercurial.ui
815        import mercurial.util, mercurial.node
816        if not exists(scons_dir) or not isdir(scons_dir) or \
817               not exists(joinpath(scons_dir, ".hg")):
818            raise ValueError
819        repo = mercurial.hg.repository(mercurial.ui.ui(), scons_dir)
820        rev = mercurial.node.nullrev + repo.changelog.count()
821        changenode = repo.changelog.node(rev)
822        changes = repo.changelog.read(changenode)
823        date = mercurial.util.datestr(changes[2])
824
825        gen_file(target, rev, mercurial.node.hex(changenode), date)
826
827        mercurial.demandimport.disable()
828    except ImportError:
829        gen_file(target, "Unknown", "Unknown", "Unknown")
830
831    except:
832        print "in except"
833        gen_file(target, "Unknown", "Unknown", "Unknown")
834        mercurial.demandimport.disable()
835
836env.Command('base/program_info.cc',
837            Value(str(SCons.Node.FS.default_fs.SConstruct_dir)),
838            programInfo)
839
840# embed python files.  All .py files that have been indicated by a
841# PySource() call in a SConscript need to be embedded into the M5
842# library.  To do that, we compile the file to byte code, marshal the
843# byte code, compress it, and then generate an assembly file that
844# inserts the result into the data section with symbols indicating the
845# beginning, and end (and with the size at the end)
846py_sources_tnodes = {}
847for pysource in py_sources:
848    py_sources_tnodes[pysource.tnode] = pysource
849
850def objectifyPyFile(target, source, env):
851    '''Action function to compile a .py into a code object, marshal
852    it, compress it, and stick it into an asm file so the code appears
853    as just bytes with a label in the data section'''
854
855    src = file(str(source[0]), 'r').read()
856    dst = file(str(target[0]), 'w')
857
858    pysource = py_sources_tnodes[source[0]]
859    compiled = compile(src, pysource.debugname, 'exec')
860    marshalled = marshal.dumps(compiled)
861    compressed = zlib.compress(marshalled)
862    data = compressed
863
864    # Some C/C++ compilers prepend an underscore to global symbol
865    # names, so if they're going to do that, we need to prepend that
866    # leading underscore to globals in the assembly file.
867    if env['LEADING_UNDERSCORE']:
868        sym = '_' + pysource.symname
869    else:
870        sym = pysource.symname
871
872    step = 16
873    print >>dst, ".data"
874    print >>dst, ".globl %s_beg" % sym
875    print >>dst, ".globl %s_end" % sym
876    print >>dst, "%s_beg:" % sym
877    for i in xrange(0, len(data), step):
878        x = array.array('B', data[i:i+step])
879        print >>dst, ".byte", ','.join([str(d) for d in x])
880    print >>dst, "%s_end:" % sym
881    print >>dst, ".long %d" % len(marshalled)
882
883for source in py_sources:
884    env.Command(source.assembly, source.tnode, objectifyPyFile)
885    Source(source.assembly)
886
887# Generate init_python.cc which creates a bunch of EmbeddedPyModule
888# structs that describe the embedded python code.  One such struct
889# contains information about the importer that python uses to get at
890# the embedded files, and then there's a list of all of the rest that
891# the importer uses to load the rest on demand.
892py_sources_symbols = {}
893for pysource in py_sources:
894    py_sources_symbols[pysource.symname] = pysource
895def pythonInit(target, source, env):
896    dst = file(str(target[0]), 'w')
897
898    def dump_mod(sym, endchar=','):
899        pysource = py_sources_symbols[sym]
900        print >>dst, '    { "%s",' % pysource.arcname
901        print >>dst, '      "%s",' % pysource.modpath
902        print >>dst, '       %s_beg, %s_end,' % (sym, sym)
903        print >>dst, '       %s_end - %s_beg,' % (sym, sym)
904        print >>dst, '       *(int *)%s_end }%s'  % (sym, endchar)
905    
906    print >>dst, '#include "sim/init.hh"'
907
908    for sym in source:
909        sym = sym.get_contents()
910        print >>dst, "extern const char %s_beg[], %s_end[];" % (sym, sym)
911
912    print >>dst, "const EmbeddedPyModule embeddedPyImporter = "
913    dump_mod("PyEMB_importer", endchar=';');
914    print >>dst
915
916    print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {"
917    for i,sym in enumerate(source):
918        sym = sym.get_contents()
919        if sym == "PyEMB_importer":
920            # Skip the importer since we've already exported it
921            continue
922        dump_mod(sym)
923    print >>dst, "    { 0, 0, 0, 0, 0, 0 }"
924    print >>dst, "};"
925
926symbols = [Value(s.symname) for s in py_sources]
927env.Command('sim/init_python.cc', symbols, pythonInit)
928Source('sim/init_python.cc')
929
930########################################################################
931#
932# Define binaries.  Each different build type (debug, opt, etc.) gets
933# a slightly different build environment.
934#
935
936# List of constructed environments to pass back to SConstruct
937envList = []
938
939# This function adds the specified sources to the given build
940# environment, and returns a list of all the corresponding SCons
941# Object nodes (including an extra one for date.cc).  We explicitly
942# add the Object nodes so we can set up special dependencies for
943# date.cc.
944def make_objs(sources, env, static):
945    if static:
946        XObject = env.StaticObject
947    else:
948        XObject = env.SharedObject
949
950    objs = [ XObject(s) for s in sources ]
951  
952    # make date.cc depend on all other objects so it always gets
953    # recompiled whenever anything else does
954    date_obj = XObject('base/date.cc')
955
956    # Make the generation of program_info.cc dependend on all 
957    # the other cc files and the compiling of program_info.cc 
958    # dependent on all the objects but program_info.o 
959    pinfo_obj = XObject('base/program_info.cc')
960    env.Depends('base/program_info.cc', sources)
961    env.Depends(date_obj, objs)
962    env.Depends(pinfo_obj, objs)
963    objs.extend([date_obj, pinfo_obj])
964    return objs
965
966# Function to create a new build environment as clone of current
967# environment 'env' with modified object suffix and optional stripped
968# binary.  Additional keyword arguments are appended to corresponding
969# build environment vars.
970def makeEnv(label, objsfx, strip = False, **kwargs):
971    # SCons doesn't know to append a library suffix when there is a '.' in the
972    # name.  Use '_' instead.
973    libname = 'm5_' + label
974    exename = 'm5.' + label
975
976    new_env = env.Copy(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
977    new_env.Label = label
978    new_env.Append(**kwargs)
979
980    swig_env = new_env.Copy()
981    if env['GCC']:
982        swig_env.Append(CCFLAGS='-Wno-uninitialized')
983        swig_env.Append(CCFLAGS='-Wno-sign-compare')
984        swig_env.Append(CCFLAGS='-Wno-parentheses')
985
986    static_objs = make_objs(cc_lib_sources, new_env, static=True)
987    shared_objs = make_objs(cc_lib_sources, new_env, static=False)
988    static_objs += [ swig_env.StaticObject(s) for s in cc_swig_sources ]
989    shared_objs += [ swig_env.SharedObject(s) for s in cc_swig_sources ]
990
991    # First make a library of everything but main() so other programs can
992    # link against m5.
993    static_lib = new_env.StaticLibrary(libname, static_objs + static_objs)
994    shared_lib = new_env.SharedLibrary(libname, shared_objs + shared_objs)
995
996    for target, sources in unit_tests:
997        objs = [ new_env.StaticObject(s) for s in sources ]
998        new_env.Program("unittest/%s.%s" % (target, label), objs + static_lib)
999
1000    # Now link a stub with main() and the static library.
1001    objects = [new_env.Object(s) for s in cc_bin_sources] + static_lib
1002    if strip:
1003        unstripped_exe = exename + '.unstripped'
1004        new_env.Program(unstripped_exe, objects)
1005        if sys.platform == 'sunos5':
1006            cmd = 'cp $SOURCE $TARGET; strip $TARGET'
1007        else:
1008            cmd = 'strip $SOURCE -o $TARGET'
1009        targets = new_env.Command(exename, unstripped_exe, cmd)
1010    else:
1011        targets = new_env.Program(exename, objects)
1012            
1013    new_env.M5Binary = targets[0]
1014    envList.append(new_env)
1015
1016# Debug binary
1017ccflags = {}
1018if env['GCC']:
1019    if sys.platform == 'sunos5':
1020        ccflags['debug'] = '-gstabs+'
1021    else:
1022        ccflags['debug'] = '-ggdb3'
1023    ccflags['opt'] = '-g -O3'
1024    ccflags['fast'] = '-O3'
1025    ccflags['prof'] = '-O3 -g -pg'
1026elif env['SUNCC']:
1027    ccflags['debug'] = '-g0'
1028    ccflags['opt'] = '-g -O'
1029    ccflags['fast'] = '-fast'
1030    ccflags['prof'] = '-fast -g -pg'
1031elif env['ICC']:
1032    ccflags['debug'] = '-g -O0'
1033    ccflags['opt'] = '-g -O'
1034    ccflags['fast'] = '-fast'
1035    ccflags['prof'] = '-fast -g -pg'
1036else:
1037    print 'Unknown compiler, please fix compiler options'
1038    Exit(1)
1039
1040makeEnv('debug', '.do',
1041        CCFLAGS = Split(ccflags['debug']),
1042        CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
1043
1044# Optimized binary
1045makeEnv('opt', '.o',
1046        CCFLAGS = Split(ccflags['opt']),
1047        CPPDEFINES = ['TRACING_ON=1'])
1048
1049# "Fast" binary
1050makeEnv('fast', '.fo', strip = True,
1051        CCFLAGS = Split(ccflags['fast']),
1052        CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
1053
1054# Profiled binary
1055makeEnv('prof', '.po',
1056        CCFLAGS = Split(ccflags['prof']),
1057        CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
1058        LINKFLAGS = '-pg')
1059
1060Return('envList')
1061