SConscript revision 6998
17087Snate@binkert.org# -*- mode:python -*-
210959Sdavid.hashe@amd.com
37087Snate@binkert.org# Copyright (c) 2004-2005 The Regents of The University of Michigan
47087Snate@binkert.org# All rights reserved.
57087Snate@binkert.org#
67087Snate@binkert.org# Redistribution and use in source and binary forms, with or without
77087Snate@binkert.org# modification, are permitted provided that the following conditions are
87087Snate@binkert.org# met: redistributions of source code must retain the above copyright
97087Snate@binkert.org# notice, this list of conditions and the following disclaimer;
107087Snate@binkert.org# redistributions in binary form must reproduce the above copyright
117087Snate@binkert.org# notice, this list of conditions and the following disclaimer in the
127087Snate@binkert.org# documentation and/or other materials provided with the distribution;
137087Snate@binkert.org# neither the name of the copyright holders nor the names of its
145331Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from
155331Sgblack@eecs.umich.edu# this software without specific prior written permission.
165331Sgblack@eecs.umich.edu#
175331Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
185331Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
195331Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
205331Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
215331Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
225331Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
235331Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245331Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255331Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265331Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
275331Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285331Sgblack@eecs.umich.edu#
295331Sgblack@eecs.umich.edu# Authors: Nathan Binkert
305331Sgblack@eecs.umich.edu
315331Sgblack@eecs.umich.eduimport array
325331Sgblack@eecs.umich.eduimport bisect
335331Sgblack@eecs.umich.eduimport imp
345331Sgblack@eecs.umich.eduimport marshal
355331Sgblack@eecs.umich.eduimport os
365331Sgblack@eecs.umich.eduimport re
375331Sgblack@eecs.umich.eduimport sys
385331Sgblack@eecs.umich.eduimport zlib
395331Sgblack@eecs.umich.edu
405331Sgblack@eecs.umich.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath
415331Sgblack@eecs.umich.edu
424276Sgblack@eecs.umich.eduimport SCons
434276Sgblack@eecs.umich.edu
444276Sgblack@eecs.umich.edu# This file defines how to build a particular configuration of M5
454276Sgblack@eecs.umich.edu# based on variable settings in the 'env' build environment.
4610593Sgabeblack@google.com
4710593Sgabeblack@google.comImport('*')
4810593Sgabeblack@google.com
4910593Sgabeblack@google.com# Children need to see the environment
5010593Sgabeblack@google.comExport('env')
5110593Sgabeblack@google.com
5210593Sgabeblack@google.combuild_env = [(opt, env[opt]) for opt in export_vars]
5310593Sgabeblack@google.com
5410593Sgabeblack@google.com########################################################################
5510593Sgabeblack@google.com# Code for adding source files of various types
5610593Sgabeblack@google.com#
5710593Sgabeblack@google.comclass SourceMeta(type):
5810593Sgabeblack@google.com    def __init__(cls, name, bases, dict):
5910593Sgabeblack@google.com        super(SourceMeta, cls).__init__(name, bases, dict)
6010593Sgabeblack@google.com        cls.all = []
6110593Sgabeblack@google.com        
6210593Sgabeblack@google.com    def get(cls, **kwargs):
6310593Sgabeblack@google.com        for src in cls.all:
6410593Sgabeblack@google.com            for attr,value in kwargs.iteritems():
6510593Sgabeblack@google.com                if getattr(src, attr) != value:
6610593Sgabeblack@google.com                    break
6710593Sgabeblack@google.com            else:
6810593Sgabeblack@google.com                yield src
6910593Sgabeblack@google.com
7010593Sgabeblack@google.comclass SourceFile(object):
715238Sgblack@eecs.umich.edu    __metaclass__ = SourceMeta
7210593Sgabeblack@google.com    def __init__(self, source):
7310593Sgabeblack@google.com        tnode = source
7410593Sgabeblack@google.com        if not isinstance(source, SCons.Node.FS.File):
7510593Sgabeblack@google.com            tnode = File(source)
7610593Sgabeblack@google.com
7710593Sgabeblack@google.com        self.tnode = tnode
7810593Sgabeblack@google.com        self.snode = tnode.srcnode()
7910593Sgabeblack@google.com        self.filename = str(tnode)
8010593Sgabeblack@google.com        self.dirname = dirname(self.filename)
8110593Sgabeblack@google.com        self.basename = basename(self.filename)
8210593Sgabeblack@google.com        index = self.basename.rfind('.')
8310593Sgabeblack@google.com        if index <= 0:
8410593Sgabeblack@google.com            # dot files aren't extensions
8510593Sgabeblack@google.com            self.extname = self.basename, None
8610593Sgabeblack@google.com        else:
8710593Sgabeblack@google.com            self.extname = self.basename[:index], self.basename[index+1:]
8810593Sgabeblack@google.com
896611Sgblack@eecs.umich.edu        for base in type(self).__mro__:
9010593Sgabeblack@google.com            if issubclass(base, SourceFile):
9110593Sgabeblack@google.com                bisect.insort_right(base.all, self)       
9210593Sgabeblack@google.com
9310593Sgabeblack@google.com    def __lt__(self, other): return self.filename < other.filename
9410593Sgabeblack@google.com    def __le__(self, other): return self.filename <= other.filename
9510593Sgabeblack@google.com    def __gt__(self, other): return self.filename > other.filename
966611Sgblack@eecs.umich.edu    def __ge__(self, other): return self.filename >= other.filename
9710593Sgabeblack@google.com    def __eq__(self, other): return self.filename == other.filename
9810593Sgabeblack@google.com    def __ne__(self, other): return self.filename != other.filename
9910593Sgabeblack@google.com        
10010593Sgabeblack@google.comclass Source(SourceFile):
10110593Sgabeblack@google.com    '''Add a c/c++ source file to the build'''
10210593Sgabeblack@google.com    def __init__(self, source, Werror=True, swig=False, bin_only=False,
10310593Sgabeblack@google.com                 skip_lib=False):
1046611Sgblack@eecs.umich.edu        super(Source, self).__init__(source)
1056611Sgblack@eecs.umich.edu
10610593Sgabeblack@google.com        self.Werror = Werror
10710593Sgabeblack@google.com        self.swig = swig
10810593Sgabeblack@google.com        self.bin_only = bin_only
10910593Sgabeblack@google.com        self.skip_lib = bin_only or skip_lib
11010593Sgabeblack@google.com
11110593Sgabeblack@google.comclass PySource(SourceFile):
11210593Sgabeblack@google.com    '''Add a python source file to the named package'''
11310593Sgabeblack@google.com    invalid_sym_char = re.compile('[^A-z0-9_]')
11410593Sgabeblack@google.com    modules = {}
11510593Sgabeblack@google.com    tnodes = {}
11610593Sgabeblack@google.com    symnames = {}
11710593Sgabeblack@google.com    
11810593Sgabeblack@google.com    def __init__(self, package, source):
11910593Sgabeblack@google.com        super(PySource, self).__init__(source)
12010593Sgabeblack@google.com
12110593Sgabeblack@google.com        modname,ext = self.extname
12210593Sgabeblack@google.com        assert ext == 'py'
12310593Sgabeblack@google.com
12410593Sgabeblack@google.com        if package:
1255292Sgblack@eecs.umich.edu            path = package.split('.')
1266611Sgblack@eecs.umich.edu        else:
1275238Sgblack@eecs.umich.edu            path = []
12810593Sgabeblack@google.com
12910593Sgabeblack@google.com        modpath = path[:]
13010593Sgabeblack@google.com        if modname != '__init__':
13110593Sgabeblack@google.com            modpath += [ modname ]
13210593Sgabeblack@google.com        modpath = '.'.join(modpath)
13310593Sgabeblack@google.com
13410593Sgabeblack@google.com        arcpath = path + [ self.basename ]
13510593Sgabeblack@google.com        abspath = self.snode.abspath
13610593Sgabeblack@google.com        if not exists(abspath):
1375789Sgblack@eecs.umich.edu            abspath = self.tnode.abspath
1385789Sgblack@eecs.umich.edu
13910593Sgabeblack@google.com        self.package = package
1405908Sgblack@eecs.umich.edu        self.modname = modname
1414276Sgblack@eecs.umich.edu        self.modpath = modpath
14210593Sgabeblack@google.com        self.arcname = joinpath(*arcpath)
14310593Sgabeblack@google.com        self.abspath = abspath
14410593Sgabeblack@google.com        self.compiled = File(self.filename + 'c')
14510593Sgabeblack@google.com        self.assembly = File(self.filename + '.s')
14610593Sgabeblack@google.com        self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath)
14710593Sgabeblack@google.com
14810593Sgabeblack@google.com        PySource.modules[modpath] = self
14910593Sgabeblack@google.com        PySource.tnodes[self.tnode] = self
15010593Sgabeblack@google.com        PySource.symnames[self.symname] = self
15110593Sgabeblack@google.com
15210593Sgabeblack@google.comclass SimObject(PySource):
15310593Sgabeblack@google.com    '''Add a SimObject python file as a python source object and add
15410593Sgabeblack@google.com    it to a list of sim object modules'''
15510593Sgabeblack@google.com
15610593Sgabeblack@google.com    fixed = False
15710593Sgabeblack@google.com    modnames = []
15810593Sgabeblack@google.com
15910593Sgabeblack@google.com    def __init__(self, source):
16010593Sgabeblack@google.com        super(SimObject, self).__init__('m5.objects', source)
16110593Sgabeblack@google.com        if self.fixed:
16210593Sgabeblack@google.com            raise AttributeError, "Too late to call SimObject now."
16310593Sgabeblack@google.com
16410593Sgabeblack@google.com        bisect.insort_right(SimObject.modnames, self.modname)
16510593Sgabeblack@google.com
16610593Sgabeblack@google.comclass SwigSource(SourceFile):
16710593Sgabeblack@google.com    '''Add a swig file to build'''
16810593Sgabeblack@google.com
16910593Sgabeblack@google.com    def __init__(self, package, source):
17010593Sgabeblack@google.com        super(SwigSource, self).__init__(source)
17110593Sgabeblack@google.com
17210593Sgabeblack@google.com        modname,ext = self.extname
17310593Sgabeblack@google.com        assert ext == 'i'
17410593Sgabeblack@google.com
17510593Sgabeblack@google.com        self.module = modname
17611289Sgabor.dozsa@arm.com        cc_file = joinpath(self.dirname, modname + '_wrap.cc')
17710593Sgabeblack@google.com        py_file = joinpath(self.dirname, modname + '.py')
17810593Sgabeblack@google.com
17910593Sgabeblack@google.com        self.cc_source = Source(cc_file, swig=True)
18010593Sgabeblack@google.com        self.py_source = PySource(package, py_file)
18110593Sgabeblack@google.com
18210593Sgabeblack@google.comunit_tests = []
18310593Sgabeblack@google.comdef UnitTest(target, sources):
18410593Sgabeblack@google.com    if not isinstance(sources, (list, tuple)):
18510593Sgabeblack@google.com        sources = [ sources ]
18610593Sgabeblack@google.com
18710593Sgabeblack@google.com    sources = [ Source(src, skip_lib=True) for src in sources ]
18810593Sgabeblack@google.com    unit_tests.append((target, sources))
18910593Sgabeblack@google.com
19010593Sgabeblack@google.com# Children should have access
19110593Sgabeblack@google.comExport('Source')
19210593Sgabeblack@google.comExport('PySource')
19310593Sgabeblack@google.comExport('SimObject')
19410593Sgabeblack@google.comExport('SwigSource')
19510593Sgabeblack@google.comExport('UnitTest')
19610593Sgabeblack@google.com
19710593Sgabeblack@google.com########################################################################
19810593Sgabeblack@google.com#
19910593Sgabeblack@google.com# Trace Flags
20010593Sgabeblack@google.com#
20110593Sgabeblack@google.comtrace_flags = {}
20210593Sgabeblack@google.comdef TraceFlag(name, desc=None):
20310593Sgabeblack@google.com    if name in trace_flags:
20410593Sgabeblack@google.com        raise AttributeError, "Flag %s already specified" % name
20510593Sgabeblack@google.com    trace_flags[name] = (name, (), desc)
20610593Sgabeblack@google.com
20710593Sgabeblack@google.comdef CompoundFlag(name, flags, desc=None):
20810593Sgabeblack@google.com    if name in trace_flags:
20910593Sgabeblack@google.com        raise AttributeError, "Flag %s already specified" % name
21010593Sgabeblack@google.com
21110593Sgabeblack@google.com    compound = tuple(flags)
21210593Sgabeblack@google.com    trace_flags[name] = (name, compound, desc)
21310593Sgabeblack@google.com
21410593Sgabeblack@google.comExport('TraceFlag')
21510593Sgabeblack@google.comExport('CompoundFlag')
21610593Sgabeblack@google.com
21710593Sgabeblack@google.com########################################################################
21810593Sgabeblack@google.com#
21910593Sgabeblack@google.com# Set some compiler variables
22010593Sgabeblack@google.com#
22110593Sgabeblack@google.com
22210593Sgabeblack@google.com# Include file paths are rooted in this directory.  SCons will
22310593Sgabeblack@google.com# automatically expand '.' to refer to both the source directory and
22410593Sgabeblack@google.com# the corresponding build directory to pick up generated include
22510593Sgabeblack@google.com# files.
22610593Sgabeblack@google.comenv.Append(CPPPATH=Dir('.'))
22710593Sgabeblack@google.com
22810593Sgabeblack@google.comfor extra_dir in extras_dir_list:
22910593Sgabeblack@google.com    env.Append(CPPPATH=Dir(extra_dir))
23010593Sgabeblack@google.com
23111703Smichael.lebeane@amd.com# Workaround for bug in SCons version > 0.97d20071212
23211703Smichael.lebeane@amd.com# Scons bug id: 2006 M5 Bug id: 308 
23311703Smichael.lebeane@amd.comfor root, dirs, files in os.walk(base_dir, topdown=True):
2346616Sgblack@eecs.umich.edu    Dir(root[len(base_dir) + 1:])
2356616Sgblack@eecs.umich.edu
2364276Sgblack@eecs.umich.edu########################################################################
23710593Sgabeblack@google.com#
23810593Sgabeblack@google.com# Walk the tree and execute all SConscripts in subdirectories
23910593Sgabeblack@google.com#
24010593Sgabeblack@google.com
24110593Sgabeblack@google.comhere = Dir('.').srcnode().abspath
24210593Sgabeblack@google.comfor root, dirs, files in os.walk(base_dir, topdown=True):
24310593Sgabeblack@google.com    if root == here:
24410593Sgabeblack@google.com        # we don't want to recurse back into this SConscript
24510593Sgabeblack@google.com        continue
24610593Sgabeblack@google.com
24710593Sgabeblack@google.com    if 'SConscript' in files:
24810593Sgabeblack@google.com        build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:])
24910593Sgabeblack@google.com        SConscript(joinpath(root, 'SConscript'), build_dir=build_dir)
25010593Sgabeblack@google.com
25110593Sgabeblack@google.comfor extra_dir in extras_dir_list:
25210593Sgabeblack@google.com    prefix_len = len(dirname(extra_dir)) + 1
25310593Sgabeblack@google.com    for root, dirs, files in os.walk(extra_dir, topdown=True):
25410593Sgabeblack@google.com        if 'SConscript' in files:
25510593Sgabeblack@google.com            build_dir = joinpath(env['BUILDDIR'], root[prefix_len:])
25610593Sgabeblack@google.com            SConscript(joinpath(root, 'SConscript'), build_dir=build_dir)
25710593Sgabeblack@google.com
25810593Sgabeblack@google.comfor opt in export_vars:
25910593Sgabeblack@google.com    env.ConfigFile(opt)
26010593Sgabeblack@google.com
26110593Sgabeblack@google.comdef makeTheISA(source, target, env):
26210593Sgabeblack@google.com    f = file(str(target[0]), 'w')
26310593Sgabeblack@google.com
26410593Sgabeblack@google.com    isas = [ src.get_contents() for src in source ]
26510593Sgabeblack@google.com    target = env['TARGET_ISA']
26610593Sgabeblack@google.com    def define(isa):
26710593Sgabeblack@google.com        return isa.upper() + '_ISA'
26810593Sgabeblack@google.com    
26910593Sgabeblack@google.com    def namespace(isa):
27010593Sgabeblack@google.com        return isa[0].upper() + isa[1:].lower() + 'ISA' 
27110593Sgabeblack@google.com
27210593Sgabeblack@google.com
27310593Sgabeblack@google.com    print >>f, '#ifndef __CONFIG_THE_ISA_HH__'
27410593Sgabeblack@google.com    print >>f, '#define __CONFIG_THE_ISA_HH__'
27510593Sgabeblack@google.com    print >>f
27610593Sgabeblack@google.com    for i,isa in enumerate(isas):
27710593Sgabeblack@google.com        print >>f, '#define %s %d' % (define(isa), i + 1)
27810593Sgabeblack@google.com    print >>f
27910593Sgabeblack@google.com    print >>f, '#define THE_ISA %s' % (define(target))
28010593Sgabeblack@google.com    print >>f, '#define TheISA %s' % (namespace(target))
28110593Sgabeblack@google.com    print >>f
28210593Sgabeblack@google.com    print >>f, '#endif // __CONFIG_THE_ISA_HH__'  
28310593Sgabeblack@google.com
28410593Sgabeblack@google.comenv.Command('config/the_isa.hh', map(Value, all_isa_list), makeTheISA)
28510593Sgabeblack@google.com
28610593Sgabeblack@google.com########################################################################
28710593Sgabeblack@google.com#
28810593Sgabeblack@google.com# Prevent any SimObjects from being added after this point, they
28910593Sgabeblack@google.com# should all have been added in the SConscripts above
29010593Sgabeblack@google.com#
29110593Sgabeblack@google.comSimObject.fixed = True
29210593Sgabeblack@google.com
29310593Sgabeblack@google.comclass DictImporter(object):
29410593Sgabeblack@google.com    '''This importer takes a dictionary of arbitrary module names that
29510593Sgabeblack@google.com    map to arbitrary filenames.'''
29610593Sgabeblack@google.com    def __init__(self, modules):
29710593Sgabeblack@google.com        self.modules = modules
29810593Sgabeblack@google.com        self.installed = set()
29910593Sgabeblack@google.com
30010593Sgabeblack@google.com    def __del__(self):
30110593Sgabeblack@google.com        self.unload()
30210593Sgabeblack@google.com
30310593Sgabeblack@google.com    def unload(self):
30410593Sgabeblack@google.com        import sys
30510593Sgabeblack@google.com        for module in self.installed:
30610593Sgabeblack@google.com            del sys.modules[module]
30710593Sgabeblack@google.com        self.installed = set()
30810593Sgabeblack@google.com
30910593Sgabeblack@google.com    def find_module(self, fullname, path):
31010593Sgabeblack@google.com        if fullname == 'm5.defines':
31110593Sgabeblack@google.com            return self
31210593Sgabeblack@google.com
31310593Sgabeblack@google.com        if fullname == 'm5.objects':
31410593Sgabeblack@google.com            return self
31510593Sgabeblack@google.com
31610593Sgabeblack@google.com        if fullname.startswith('m5.internal'):
31710593Sgabeblack@google.com            return None
31810593Sgabeblack@google.com
31910593Sgabeblack@google.com        source = self.modules.get(fullname, None)
32010593Sgabeblack@google.com        if source is not None and fullname.startswith('m5.objects'):
32110593Sgabeblack@google.com            return self
32210593Sgabeblack@google.com
32310593Sgabeblack@google.com        return None
32410593Sgabeblack@google.com
32510593Sgabeblack@google.com    def load_module(self, fullname):
32610593Sgabeblack@google.com        mod = imp.new_module(fullname)
32710593Sgabeblack@google.com        sys.modules[fullname] = mod
32810593Sgabeblack@google.com        self.installed.add(fullname)
32910593Sgabeblack@google.com
33010593Sgabeblack@google.com        mod.__loader__ = self
33110593Sgabeblack@google.com        if fullname == 'm5.objects':
33210593Sgabeblack@google.com            mod.__path__ = fullname.split('.')
33310593Sgabeblack@google.com            return mod
33410593Sgabeblack@google.com
33510593Sgabeblack@google.com        if fullname == 'm5.defines':
33610593Sgabeblack@google.com            mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env)
33710593Sgabeblack@google.com            return mod
33810593Sgabeblack@google.com
33910593Sgabeblack@google.com        source = self.modules[fullname]
34010593Sgabeblack@google.com        if source.modname == '__init__':
34110593Sgabeblack@google.com            mod.__path__ = source.modpath
34210593Sgabeblack@google.com        mod.__file__ = source.abspath
34310593Sgabeblack@google.com
34410593Sgabeblack@google.com        exec file(source.abspath, 'r') in mod.__dict__
34510593Sgabeblack@google.com
34610593Sgabeblack@google.com        return mod
34710593Sgabeblack@google.com
34810593Sgabeblack@google.comimport m5.SimObject
34910593Sgabeblack@google.comimport m5.params
35010593Sgabeblack@google.com
35110593Sgabeblack@google.comm5.SimObject.clear()
35210593Sgabeblack@google.comm5.params.clear()
35310593Sgabeblack@google.com
35410593Sgabeblack@google.com# install the python importer so we can grab stuff from the source
35510593Sgabeblack@google.com# tree itself.  We can't have SimObjects added after this point or
35610593Sgabeblack@google.com# else we won't know about them for the rest of the stuff.
35710593Sgabeblack@google.comimporter = DictImporter(PySource.modules)
35810593Sgabeblack@google.comsys.meta_path[0:0] = [ importer ]
35910593Sgabeblack@google.com
36010593Sgabeblack@google.com# import all sim objects so we can populate the all_objects list
36110593Sgabeblack@google.com# make sure that we're working with a list, then let's sort it
36210593Sgabeblack@google.comfor modname in SimObject.modnames:
36310593Sgabeblack@google.com    exec('from m5.objects import %s' % modname)
36410593Sgabeblack@google.com
36510593Sgabeblack@google.com# we need to unload all of the currently imported modules so that they
36610593Sgabeblack@google.com# will be re-imported the next time the sconscript is run
36710593Sgabeblack@google.comimporter.unload()
36810959Sdavid.hashe@amd.comsys.meta_path.remove(importer)
36910959Sdavid.hashe@amd.com
37010959Sdavid.hashe@amd.comsim_objects = m5.SimObject.allClasses
37110959Sdavid.hashe@amd.comall_enums = m5.params.allEnums
37210959Sdavid.hashe@amd.com
37310593Sgabeblack@google.comall_params = {}
37410593Sgabeblack@google.comfor name,obj in sorted(sim_objects.iteritems()):
37510593Sgabeblack@google.com    for param in obj._params.local.values():
37610593Sgabeblack@google.com        # load the ptype attribute now because it depends on the
37710593Sgabeblack@google.com        # current version of SimObject.allClasses, but when scons
37810593Sgabeblack@google.com        # actually uses the value, all versions of
37910593Sgabeblack@google.com        # SimObject.allClasses will have been loaded
38010593Sgabeblack@google.com        param.ptype
38110593Sgabeblack@google.com
38210593Sgabeblack@google.com        if not hasattr(param, 'swig_decl'):
38310593Sgabeblack@google.com            continue
38410593Sgabeblack@google.com        pname = param.ptype_str
38510593Sgabeblack@google.com        if pname not in all_params:
38610593Sgabeblack@google.com            all_params[pname] = param
38710593Sgabeblack@google.com
38810593Sgabeblack@google.com########################################################################
38910593Sgabeblack@google.com#
39010593Sgabeblack@google.com# calculate extra dependencies
39110593Sgabeblack@google.com#
39210593Sgabeblack@google.commodule_depends = ["m5", "m5.SimObject", "m5.params"]
39310593Sgabeblack@google.comdepends = [ PySource.modules[dep].tnode for dep in module_depends ]
39410593Sgabeblack@google.com
39510593Sgabeblack@google.com########################################################################
39610593Sgabeblack@google.com#
39710593Sgabeblack@google.com# Commands for the basic automatically generated python files
39810593Sgabeblack@google.com#
39910593Sgabeblack@google.com
40010593Sgabeblack@google.com# Generate Python file containing a dict specifying the current
40110593Sgabeblack@google.com# buildEnv flags.
40210593Sgabeblack@google.comdef makeDefinesPyFile(target, source, env):
40310593Sgabeblack@google.com    build_env, hg_info = [ x.get_contents() for x in source ]
40410593Sgabeblack@google.com
40510593Sgabeblack@google.com    code = m5.util.code_formatter()
40610593Sgabeblack@google.com    code("""
40710593Sgabeblack@google.comimport m5.internal
40810593Sgabeblack@google.comimport m5.util
40910593Sgabeblack@google.com
41010593Sgabeblack@google.combuildEnv = m5.util.SmartDict($build_env)
41110593Sgabeblack@google.comhgRev = '$hg_info'
41210593Sgabeblack@google.com
41310593Sgabeblack@google.comcompileDate = m5.internal.core.compileDate
41410593Sgabeblack@google.com_globals = globals()
41510593Sgabeblack@google.comfor key,val in m5.internal.core.__dict__.iteritems():
41610593Sgabeblack@google.com    if key.startswith('flag_'):
41710593Sgabeblack@google.com        flag = key[5:]
41810593Sgabeblack@google.com        _globals[flag] = val
41910593Sgabeblack@google.comdel _globals
42010593Sgabeblack@google.com""")
42110593Sgabeblack@google.com    code.write(str(target[0]))
42210593Sgabeblack@google.com
42310593Sgabeblack@google.comdefines_info = [ Value(build_env), Value(env['HG_INFO']) ]
42410593Sgabeblack@google.com# Generate a file with all of the compile options in it
42510593Sgabeblack@google.comenv.Command('python/m5/defines.py', defines_info, makeDefinesPyFile)
42610593Sgabeblack@google.comPySource('m5', 'python/m5/defines.py')
42710593Sgabeblack@google.com
42810593Sgabeblack@google.com# Generate python file containing info about the M5 source code
42910593Sgabeblack@google.comdef makeInfoPyFile(target, source, env):
43010593Sgabeblack@google.com    f = file(str(target[0]), 'w')
43110593Sgabeblack@google.com    for src in source:
43210593Sgabeblack@google.com        data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
43310593Sgabeblack@google.com        print >>f, "%s = %s" % (src, repr(data))
43410593Sgabeblack@google.com    f.close()
43510593Sgabeblack@google.com
43610593Sgabeblack@google.com# Generate a file that wraps the basic top level files
43710593Sgabeblack@google.comenv.Command('python/m5/info.py',
43810593Sgabeblack@google.com            [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
43910593Sgabeblack@google.com            makeInfoPyFile)
44010593Sgabeblack@google.comPySource('m5', 'python/m5/info.py')
44110593Sgabeblack@google.com
44210593Sgabeblack@google.com# Generate the __init__.py file for m5.objects
44310593Sgabeblack@google.comdef makeObjectsInitFile(target, source, env):
44410593Sgabeblack@google.com    f = file(str(target[0]), 'w')
44510593Sgabeblack@google.com    print >>f, 'from params import *'
44610593Sgabeblack@google.com    print >>f, 'from m5.SimObject import *'
44710593Sgabeblack@google.com    for module in source:
44810593Sgabeblack@google.com        print >>f, 'from %s import *' % module.get_contents()
44910593Sgabeblack@google.com    f.close()
45010593Sgabeblack@google.com
45110593Sgabeblack@google.com# Generate an __init__.py file for the objects package
45210593Sgabeblack@google.comenv.Command('python/m5/objects/__init__.py',
45310593Sgabeblack@google.com            map(Value, SimObject.modnames),
45410593Sgabeblack@google.com            makeObjectsInitFile)
45510593Sgabeblack@google.comPySource('m5.objects', 'python/m5/objects/__init__.py')
45610593Sgabeblack@google.com
45710593Sgabeblack@google.com########################################################################
45810593Sgabeblack@google.com#
45910593Sgabeblack@google.com# Create all of the SimObject param headers and enum headers
46010593Sgabeblack@google.com#
46110593Sgabeblack@google.com
46210593Sgabeblack@google.comdef createSimObjectParam(target, source, env):
46310593Sgabeblack@google.com    assert len(target) == 1 and len(source) == 1
46410593Sgabeblack@google.com
46510593Sgabeblack@google.com    hh_file = file(target[0].abspath, 'w')
46610593Sgabeblack@google.com    name = str(source[0].get_contents())
46710593Sgabeblack@google.com    obj = sim_objects[name]
46810593Sgabeblack@google.com
46911160Ssteve.reinhardt@amd.com    print >>hh_file, obj.cxx_decl()
47010593Sgabeblack@google.com    hh_file.close()
47110593Sgabeblack@google.com
47210593Sgabeblack@google.comdef createSwigParam(target, source, env):
47310593Sgabeblack@google.com    assert len(target) == 1 and len(source) == 1
47410593Sgabeblack@google.com
47510593Sgabeblack@google.com    i_file = file(target[0].abspath, 'w')
47610593Sgabeblack@google.com    name = str(source[0].get_contents())
47710593Sgabeblack@google.com    param = all_params[name]
47810593Sgabeblack@google.com
47911160Ssteve.reinhardt@amd.com    for line in param.swig_decl():
48010593Sgabeblack@google.com        print >>i_file, line
48110593Sgabeblack@google.com    i_file.close()
48210593Sgabeblack@google.com
48310593Sgabeblack@google.comdef createEnumStrings(target, source, env):
48410593Sgabeblack@google.com    assert len(target) == 1 and len(source) == 1
48510593Sgabeblack@google.com
48610593Sgabeblack@google.com    cc_file = file(target[0].abspath, 'w')
48710593Sgabeblack@google.com    name = str(source[0].get_contents())
48810593Sgabeblack@google.com    obj = all_enums[name]
48910593Sgabeblack@google.com
49010593Sgabeblack@google.com    print >>cc_file, obj.cxx_def()
49110593Sgabeblack@google.com    cc_file.close()
49210593Sgabeblack@google.com
49310593Sgabeblack@google.comdef createEnumParam(target, source, env):
49410593Sgabeblack@google.com    assert len(target) == 1 and len(source) == 1
49510593Sgabeblack@google.com
49610593Sgabeblack@google.com    hh_file = file(target[0].abspath, 'w')
49710593Sgabeblack@google.com    name = str(source[0].get_contents())
49810593Sgabeblack@google.com    obj = all_enums[name]
49910593Sgabeblack@google.com
50010593Sgabeblack@google.com    print >>hh_file, obj.cxx_decl()
50110593Sgabeblack@google.com    hh_file.close()
50210593Sgabeblack@google.com
50310593Sgabeblack@google.com# Generate all of the SimObject param struct header files
50410593Sgabeblack@google.comparams_hh_files = []
50510593Sgabeblack@google.comfor name,simobj in sorted(sim_objects.iteritems()):
50610593Sgabeblack@google.com    py_source = PySource.modules[simobj.__module__]
50710593Sgabeblack@google.com    extra_deps = [ py_source.tnode ]
50810593Sgabeblack@google.com
50910593Sgabeblack@google.com    hh_file = File('params/%s.hh' % name)
51010593Sgabeblack@google.com    params_hh_files.append(hh_file)
51110593Sgabeblack@google.com    env.Command(hh_file, Value(name), createSimObjectParam)
51210593Sgabeblack@google.com    env.Depends(hh_file, depends + extra_deps)
51310593Sgabeblack@google.com
51410593Sgabeblack@google.com# Generate any parameter header files needed
51510593Sgabeblack@google.comparams_i_files = []
51610593Sgabeblack@google.comfor name,param in all_params.iteritems():
51710593Sgabeblack@google.com    i_file = File('params/%s_%s.i' % (name, param.file_ext))
51810593Sgabeblack@google.com    params_i_files.append(i_file)
51910593Sgabeblack@google.com    env.Command(i_file, Value(name), createSwigParam)
52010593Sgabeblack@google.com    env.Depends(i_file, depends)
52110593Sgabeblack@google.com
52210593Sgabeblack@google.com# Generate all enum header files
52310593Sgabeblack@google.comfor name,enum in sorted(all_enums.iteritems()):
52410593Sgabeblack@google.com    py_source = PySource.modules[enum.__module__]
52510593Sgabeblack@google.com    extra_deps = [ py_source.tnode ]
52610593Sgabeblack@google.com
52710593Sgabeblack@google.com    cc_file = File('enums/%s.cc' % name)
52810593Sgabeblack@google.com    env.Command(cc_file, Value(name), createEnumStrings)
52910593Sgabeblack@google.com    env.Depends(cc_file, depends + extra_deps)
53010593Sgabeblack@google.com    Source(cc_file)
53110593Sgabeblack@google.com
53210593Sgabeblack@google.com    hh_file = File('enums/%s.hh' % name)
53310593Sgabeblack@google.com    env.Command(hh_file, Value(name), createEnumParam)
53410593Sgabeblack@google.com    env.Depends(hh_file, depends + extra_deps)
53510593Sgabeblack@google.com
53610593Sgabeblack@google.com# Build the big monolithic swigged params module (wraps all SimObject
53710593Sgabeblack@google.com# param structs and enum structs)
53810593Sgabeblack@google.comdef buildParams(target, source, env):
53910593Sgabeblack@google.com    names = [ s.get_contents() for s in source ]
54010593Sgabeblack@google.com    objs = [ sim_objects[name] for name in names ]
54110593Sgabeblack@google.com    out = file(target[0].abspath, 'w')
54210593Sgabeblack@google.com
54310593Sgabeblack@google.com    ordered_objs = []
54410593Sgabeblack@google.com    obj_seen = set()
54510593Sgabeblack@google.com    def order_obj(obj):
54610593Sgabeblack@google.com        name = str(obj)
54710593Sgabeblack@google.com        if name in obj_seen:
54810593Sgabeblack@google.com            return
54910593Sgabeblack@google.com
55010593Sgabeblack@google.com        obj_seen.add(name)
55110593Sgabeblack@google.com        if str(obj) != 'SimObject':
55210593Sgabeblack@google.com            order_obj(obj.__bases__[0])
55310593Sgabeblack@google.com
55410593Sgabeblack@google.com        ordered_objs.append(obj)
55510593Sgabeblack@google.com
55610593Sgabeblack@google.com    for obj in objs:
55710593Sgabeblack@google.com        order_obj(obj)
55810593Sgabeblack@google.com
55910593Sgabeblack@google.com    enums = set()
56010593Sgabeblack@google.com    predecls = []
56110593Sgabeblack@google.com    pd_seen = set()
56210593Sgabeblack@google.com
56310593Sgabeblack@google.com    def add_pds(*pds):
56410593Sgabeblack@google.com        for pd in pds:
56510593Sgabeblack@google.com            if pd not in pd_seen:
56610593Sgabeblack@google.com                predecls.append(pd)
56710593Sgabeblack@google.com                pd_seen.add(pd)
56810593Sgabeblack@google.com
56910593Sgabeblack@google.com    for obj in ordered_objs:
57010593Sgabeblack@google.com        params = obj._params.local.values()
57110593Sgabeblack@google.com        for param in params:
57210593Sgabeblack@google.com            ptype = param.ptype
57310593Sgabeblack@google.com            if issubclass(ptype, m5.params.Enum):
57410593Sgabeblack@google.com                if ptype not in enums:
57510593Sgabeblack@google.com                    enums.add(ptype)
57610593Sgabeblack@google.com            pds = param.swig_predecls()
57710593Sgabeblack@google.com            if isinstance(pds, (list, tuple)):
57810593Sgabeblack@google.com                add_pds(*pds)
57910593Sgabeblack@google.com            else:
58010593Sgabeblack@google.com                add_pds(pds)
58110593Sgabeblack@google.com
58210593Sgabeblack@google.com    print >>out, '%module params'
58310593Sgabeblack@google.com
58410593Sgabeblack@google.com    print >>out, '%{'
58510593Sgabeblack@google.com    for obj in ordered_objs:
58610593Sgabeblack@google.com        print >>out, '#include "params/%s.hh"' % obj
58710593Sgabeblack@google.com    print >>out, '%}'
58810593Sgabeblack@google.com
58910593Sgabeblack@google.com    for pd in predecls:
59010593Sgabeblack@google.com        print >>out, pd
59110593Sgabeblack@google.com
59210593Sgabeblack@google.com    enums = list(enums)
59310593Sgabeblack@google.com    enums.sort()
59410593Sgabeblack@google.com    for enum in enums:
59510593Sgabeblack@google.com        print >>out, '%%include "enums/%s.hh"' % enum.__name__
59610593Sgabeblack@google.com    print >>out
59710593Sgabeblack@google.com
59810593Sgabeblack@google.com    for obj in ordered_objs:
59910593Sgabeblack@google.com        if obj.swig_objdecls:
60010593Sgabeblack@google.com            for decl in obj.swig_objdecls:
60110593Sgabeblack@google.com                print >>out, decl
60210593Sgabeblack@google.com            continue
60310593Sgabeblack@google.com
60410593Sgabeblack@google.com        class_path = obj.cxx_class.split('::')
60510593Sgabeblack@google.com        classname = class_path[-1]
60610593Sgabeblack@google.com        namespaces = class_path[:-1]
60710593Sgabeblack@google.com        namespaces.reverse()
60810593Sgabeblack@google.com
60910593Sgabeblack@google.com        code = ''
61010593Sgabeblack@google.com
61110593Sgabeblack@google.com        if namespaces:
61210593Sgabeblack@google.com            code += '// avoid name conflicts\n'
61310593Sgabeblack@google.com            sep_string = '_COLONS_'
61410593Sgabeblack@google.com            flat_name = sep_string.join(class_path)
61510593Sgabeblack@google.com            code += '%%rename(%s) %s;\n' % (flat_name, classname)
61610593Sgabeblack@google.com
61710593Sgabeblack@google.com        code += '// stop swig from creating/wrapping default ctor/dtor\n'
61810593Sgabeblack@google.com        code += '%%nodefault %s;\n' % classname
61910593Sgabeblack@google.com        code += 'class %s ' % classname
62010593Sgabeblack@google.com        if obj._base:
62110593Sgabeblack@google.com            code += ': public %s' % obj._base.cxx_class
62210593Sgabeblack@google.com        code += ' {};\n'
62310593Sgabeblack@google.com
62410593Sgabeblack@google.com        for ns in namespaces:
62510593Sgabeblack@google.com            new_code = 'namespace %s {\n' % ns
62610593Sgabeblack@google.com            new_code += code
62710593Sgabeblack@google.com            new_code += '}\n'
62810593Sgabeblack@google.com            code = new_code
62910593Sgabeblack@google.com
63010593Sgabeblack@google.com        print >>out, code
63110593Sgabeblack@google.com
63210593Sgabeblack@google.com    print >>out, '%%include "src/sim/sim_object_params.hh"' % obj
63310593Sgabeblack@google.com    for obj in ordered_objs:
63410593Sgabeblack@google.com        print >>out, '%%include "params/%s.hh"' % obj
63510593Sgabeblack@google.com
63610593Sgabeblack@google.comparams_file = File('params/params.i')
63710593Sgabeblack@google.comnames = sorted(sim_objects.keys())
63810593Sgabeblack@google.comenv.Command(params_file, map(Value, names), buildParams)
63910593Sgabeblack@google.comenv.Depends(params_file, params_hh_files + params_i_files + depends)
64010593Sgabeblack@google.comSwigSource('m5.objects', params_file)
64110593Sgabeblack@google.com
64210593Sgabeblack@google.com# Build all swig modules
64310593Sgabeblack@google.comfor swig in SwigSource.all:
64410593Sgabeblack@google.com    env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode,
64510593Sgabeblack@google.com                '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
64610593Sgabeblack@google.com                '-o ${TARGETS[0]} $SOURCES')
64710593Sgabeblack@google.com    env.Depends(swig.py_source.tnode, swig.tnode)
64810593Sgabeblack@google.com    env.Depends(swig.cc_source.tnode, swig.tnode)
64910593Sgabeblack@google.com
65010593Sgabeblack@google.com# Generate the main swig init file
65110593Sgabeblack@google.comdef makeSwigInit(target, source, env):
65210593Sgabeblack@google.com    f = file(str(target[0]), 'w')
65310593Sgabeblack@google.com    print >>f, 'extern "C" {'
65410593Sgabeblack@google.com    for module in source:
65510593Sgabeblack@google.com        print >>f, '    void init_%s();' % module.get_contents()
65610593Sgabeblack@google.com    print >>f, '}'
65710593Sgabeblack@google.com    print >>f, 'void initSwig() {'
65810593Sgabeblack@google.com    for module in source:
65910593Sgabeblack@google.com        print >>f, '    init_%s();' % module.get_contents()
66010593Sgabeblack@google.com    print >>f, '}'
66110593Sgabeblack@google.com    f.close()
66210593Sgabeblack@google.com
66310593Sgabeblack@google.comenv.Command('python/swig/init.cc',
66410593Sgabeblack@google.com            map(Value, sorted(s.module for s in SwigSource.all)),
66510593Sgabeblack@google.com            makeSwigInit)
66610593Sgabeblack@google.comSource('python/swig/init.cc')
66710593Sgabeblack@google.com
66810593Sgabeblack@google.comdef getFlags(source_flags):
66910593Sgabeblack@google.com    flagsMap = {}
67010593Sgabeblack@google.com    flagsList = []
67110593Sgabeblack@google.com    for s in source_flags:
67210593Sgabeblack@google.com        val = eval(s.get_contents())
67310593Sgabeblack@google.com        name, compound, desc = val
67410593Sgabeblack@google.com        flagsList.append(val)
67510593Sgabeblack@google.com        flagsMap[name] = bool(compound)
67610593Sgabeblack@google.com    
67710593Sgabeblack@google.com    for name, compound, desc in flagsList:
67810593Sgabeblack@google.com        for flag in compound:
67910593Sgabeblack@google.com            if flag not in flagsMap:
68010593Sgabeblack@google.com                raise AttributeError, "Trace flag %s not found" % flag
68110593Sgabeblack@google.com            if flagsMap[flag]:
68210593Sgabeblack@google.com                raise AttributeError, \
68310593Sgabeblack@google.com                    "Compound flag can't point to another compound flag"
68410593Sgabeblack@google.com
68510593Sgabeblack@google.com    flagsList.sort()
68610593Sgabeblack@google.com    return flagsList
68710593Sgabeblack@google.com
68810593Sgabeblack@google.com
68910593Sgabeblack@google.com# Generate traceflags.py
69010593Sgabeblack@google.comdef traceFlagsPy(target, source, env):
69110593Sgabeblack@google.com    assert(len(target) == 1)
69210593Sgabeblack@google.com
69310593Sgabeblack@google.com    f = file(str(target[0]), 'w')
69410593Sgabeblack@google.com   
69510593Sgabeblack@google.com    allFlags = getFlags(source)
69610593Sgabeblack@google.com
69710593Sgabeblack@google.com    print >>f, 'basic = ['
69810593Sgabeblack@google.com    for flag, compound, desc in allFlags:
69910593Sgabeblack@google.com        if not compound:
70010593Sgabeblack@google.com            print >>f, "    '%s'," % flag
70110593Sgabeblack@google.com    print >>f, "    ]"
70210593Sgabeblack@google.com    print >>f
70310593Sgabeblack@google.com
70410593Sgabeblack@google.com    print >>f, 'compound = ['
70510593Sgabeblack@google.com    print >>f, "    'All',"
70610593Sgabeblack@google.com    for flag, compound, desc in allFlags:
70710593Sgabeblack@google.com        if compound:
70810593Sgabeblack@google.com            print >>f, "    '%s'," % flag
70910593Sgabeblack@google.com    print >>f, "    ]"
71010593Sgabeblack@google.com    print >>f
71110593Sgabeblack@google.com
71210593Sgabeblack@google.com    print >>f, "all = frozenset(basic + compound)"
71310593Sgabeblack@google.com    print >>f
71410593Sgabeblack@google.com
71510593Sgabeblack@google.com    print >>f, 'compoundMap = {'
71610593Sgabeblack@google.com    all = tuple([flag for flag,compound,desc in allFlags if not compound])
71710593Sgabeblack@google.com    print >>f, "    'All' : %s," % (all, )
71810593Sgabeblack@google.com    for flag, compound, desc in allFlags:
71910593Sgabeblack@google.com        if compound:
72010593Sgabeblack@google.com            print >>f, "    '%s' : %s," % (flag, compound)
72110593Sgabeblack@google.com    print >>f, "    }"
72210593Sgabeblack@google.com    print >>f
72310593Sgabeblack@google.com
72410593Sgabeblack@google.com    print >>f, 'descriptions = {'
72510593Sgabeblack@google.com    print >>f, "    'All' : 'All flags',"
72610593Sgabeblack@google.com    for flag, compound, desc in allFlags:
72710593Sgabeblack@google.com        print >>f, "    '%s' : '%s'," % (flag, desc)
72810593Sgabeblack@google.com    print >>f, "    }"
72910593Sgabeblack@google.com
73010593Sgabeblack@google.com    f.close()
73110593Sgabeblack@google.com
73210593Sgabeblack@google.comdef traceFlagsCC(target, source, env):
73310593Sgabeblack@google.com    assert(len(target) == 1)
73410593Sgabeblack@google.com
73510593Sgabeblack@google.com    f = file(str(target[0]), 'w')
73610593Sgabeblack@google.com
73710593Sgabeblack@google.com    allFlags = getFlags(source)
73810593Sgabeblack@google.com
73910593Sgabeblack@google.com    # file header
74010593Sgabeblack@google.com    print >>f, '''
74110593Sgabeblack@google.com/*
74210593Sgabeblack@google.com * DO NOT EDIT THIS FILE! Automatically generated
74310593Sgabeblack@google.com */
74410593Sgabeblack@google.com
74510593Sgabeblack@google.com#include "base/traceflags.hh"
74610593Sgabeblack@google.com
74710593Sgabeblack@google.comusing namespace Trace;
74810593Sgabeblack@google.com
74910593Sgabeblack@google.comconst char *Trace::flagStrings[] =
75010593Sgabeblack@google.com{'''
75110593Sgabeblack@google.com
75210593Sgabeblack@google.com    # The string array is used by SimpleEnumParam to map the strings
75310593Sgabeblack@google.com    # provided by the user to enum values.
75410593Sgabeblack@google.com    for flag, compound, desc in allFlags:
75510593Sgabeblack@google.com        if not compound:
75610593Sgabeblack@google.com            print >>f, '    "%s",' % flag
75710593Sgabeblack@google.com
75810593Sgabeblack@google.com    print >>f, '    "All",'
75910593Sgabeblack@google.com    for flag, compound, desc in allFlags:
76010593Sgabeblack@google.com        if compound:
76110593Sgabeblack@google.com            print >>f, '    "%s",' % flag
76210593Sgabeblack@google.com
76310593Sgabeblack@google.com    print >>f, '};'
76410593Sgabeblack@google.com    print >>f
76510593Sgabeblack@google.com    print >>f, 'const int Trace::numFlagStrings = %d;' % (len(allFlags) + 1)
76610593Sgabeblack@google.com    print >>f
76710593Sgabeblack@google.com
76810593Sgabeblack@google.com    #
76910593Sgabeblack@google.com    # Now define the individual compound flag arrays.  There is an array
77010593Sgabeblack@google.com    # for each compound flag listing the component base flags.
77110593Sgabeblack@google.com    #
77210593Sgabeblack@google.com    all = tuple([flag for flag,compound,desc in allFlags if not compound])
77310593Sgabeblack@google.com    print >>f, 'static const Flags AllMap[] = {'
77410593Sgabeblack@google.com    for flag, compound, desc in allFlags:
77510593Sgabeblack@google.com        if not compound:
77610593Sgabeblack@google.com            print >>f, "    %s," % flag
77710593Sgabeblack@google.com    print >>f, '};'
77810593Sgabeblack@google.com    print >>f
77910593Sgabeblack@google.com
78010593Sgabeblack@google.com    for flag, compound, desc in allFlags:
78110593Sgabeblack@google.com        if not compound:
78210593Sgabeblack@google.com            continue
78310593Sgabeblack@google.com        print >>f, 'static const Flags %sMap[] = {' % flag
78410593Sgabeblack@google.com        for flag in compound:
78510593Sgabeblack@google.com            print >>f, "    %s," % flag
78610593Sgabeblack@google.com        print >>f, "    (Flags)-1"
78710593Sgabeblack@google.com        print >>f, '};'
78810593Sgabeblack@google.com        print >>f
78910593Sgabeblack@google.com
79010593Sgabeblack@google.com    #
79110593Sgabeblack@google.com    # Finally the compoundFlags[] array maps the compound flags
79210593Sgabeblack@google.com    # to their individual arrays/
79310593Sgabeblack@google.com    #
79410593Sgabeblack@google.com    print >>f, 'const Flags *Trace::compoundFlags[] ='
79510593Sgabeblack@google.com    print >>f, '{'
79610593Sgabeblack@google.com    print >>f, '    AllMap,'
79710593Sgabeblack@google.com    for flag, compound, desc in allFlags:
79810593Sgabeblack@google.com        if compound:
79910593Sgabeblack@google.com            print >>f, '    %sMap,' % flag
80010593Sgabeblack@google.com    # file trailer
80110593Sgabeblack@google.com    print >>f, '};'
80210593Sgabeblack@google.com
80310593Sgabeblack@google.com    f.close()
80410593Sgabeblack@google.com
80510593Sgabeblack@google.comdef traceFlagsHH(target, source, env):
80610593Sgabeblack@google.com    assert(len(target) == 1)
80710593Sgabeblack@google.com
80810593Sgabeblack@google.com    f = file(str(target[0]), 'w')
80910593Sgabeblack@google.com
81010593Sgabeblack@google.com    allFlags = getFlags(source)
81110593Sgabeblack@google.com
81210593Sgabeblack@google.com    # file header boilerplate
81310593Sgabeblack@google.com    print >>f, '''
81410593Sgabeblack@google.com/*
81510593Sgabeblack@google.com * DO NOT EDIT THIS FILE!
81610593Sgabeblack@google.com *
81710593Sgabeblack@google.com * Automatically generated from traceflags.py
81810593Sgabeblack@google.com */
81910593Sgabeblack@google.com
82010593Sgabeblack@google.com#ifndef __BASE_TRACE_FLAGS_HH__
82110593Sgabeblack@google.com#define __BASE_TRACE_FLAGS_HH__
82210593Sgabeblack@google.com
82310593Sgabeblack@google.comnamespace Trace {
82410593Sgabeblack@google.com
82510593Sgabeblack@google.comenum Flags {'''
82610593Sgabeblack@google.com
82710593Sgabeblack@google.com    # Generate the enum.  Base flags come first, then compound flags.
82810593Sgabeblack@google.com    idx = 0
82910593Sgabeblack@google.com    for flag, compound, desc in allFlags:
83010593Sgabeblack@google.com        if not compound:
83110593Sgabeblack@google.com            print >>f, '    %s = %d,' % (flag, idx)
83210593Sgabeblack@google.com            idx += 1
83310593Sgabeblack@google.com
83410593Sgabeblack@google.com    numBaseFlags = idx
83510593Sgabeblack@google.com    print >>f, '    NumFlags = %d,' % idx
83610593Sgabeblack@google.com
83710593Sgabeblack@google.com    # put a comment in here to separate base from compound flags
83810593Sgabeblack@google.com    print >>f, '''
83910593Sgabeblack@google.com// The remaining enum values are *not* valid indices for Trace::flags.
84010593Sgabeblack@google.com// They are "compound" flags, which correspond to sets of base
84110593Sgabeblack@google.com// flags, and are used by changeFlag.'''
84210593Sgabeblack@google.com
84310593Sgabeblack@google.com    print >>f, '    All = %d,' % idx
84410593Sgabeblack@google.com    idx += 1
84510593Sgabeblack@google.com    for flag, compound, desc in allFlags:
84610593Sgabeblack@google.com        if compound:
84710593Sgabeblack@google.com            print >>f, '    %s = %d,' % (flag, idx)
84810593Sgabeblack@google.com            idx += 1
84910593Sgabeblack@google.com
85010593Sgabeblack@google.com    numCompoundFlags = idx - numBaseFlags
85110593Sgabeblack@google.com    print >>f, '    NumCompoundFlags = %d' % numCompoundFlags
85210593Sgabeblack@google.com
85310593Sgabeblack@google.com    # trailer boilerplate
85410593Sgabeblack@google.com    print >>f, '''\
85510593Sgabeblack@google.com}; // enum Flags
85610593Sgabeblack@google.com
85710593Sgabeblack@google.com// Array of strings for SimpleEnumParam
85810593Sgabeblack@google.comextern const char *flagStrings[];
85910593Sgabeblack@google.comextern const int numFlagStrings;
86010593Sgabeblack@google.com
86110593Sgabeblack@google.com// Array of arraay pointers: for each compound flag, gives the list of
86210593Sgabeblack@google.com// base flags to set.  Inidividual flag arrays are terminated by -1.
8636576Sgblack@eecs.umich.eduextern const Flags *compoundFlags[];
8646576Sgblack@eecs.umich.edu
86510593Sgabeblack@google.com/* namespace Trace */ }
86610593Sgabeblack@google.com
86710593Sgabeblack@google.com#endif // __BASE_TRACE_FLAGS_HH__
86810593Sgabeblack@google.com'''
86910593Sgabeblack@google.com
8705020Sgblack@eecs.umich.edu    f.close()
8716576Sgblack@eecs.umich.edu
8726576Sgblack@eecs.umich.eduflags = map(Value, trace_flags.values())
87310593Sgabeblack@google.comenv.Command('base/traceflags.py', flags, traceFlagsPy)
8746576Sgblack@eecs.umich.eduPySource('m5', 'base/traceflags.py')
8755020Sgblack@eecs.umich.edu
8766576Sgblack@eecs.umich.eduenv.Command('base/traceflags.hh', flags, traceFlagsHH)
8776576Sgblack@eecs.umich.eduenv.Command('base/traceflags.cc', flags, traceFlagsCC)
87810593Sgabeblack@google.comSource('base/traceflags.cc')
87910593Sgabeblack@google.com
88010593Sgabeblack@google.com# embed python files.  All .py files that have been indicated by a
88110593Sgabeblack@google.com# PySource() call in a SConscript need to be embedded into the M5
88210593Sgabeblack@google.com# library.  To do that, we compile the file to byte code, marshal the
8836576Sgblack@eecs.umich.edu# byte code, compress it, and then generate an assembly file that
8846576Sgblack@eecs.umich.edu# inserts the result into the data section with symbols indicating the
8856576Sgblack@eecs.umich.edu# beginning, and end (and with the size at the end)
88610593Sgabeblack@google.comdef objectifyPyFile(target, source, env):
8876611Sgblack@eecs.umich.edu    '''Action function to compile a .py into a code object, marshal
8886611Sgblack@eecs.umich.edu    it, compress it, and stick it into an asm file so the code appears
8896611Sgblack@eecs.umich.edu    as just bytes with a label in the data section'''
8905020Sgblack@eecs.umich.edu
8914276Sgblack@eecs.umich.edu    src = file(str(source[0]), 'r').read()
89210593Sgabeblack@google.com    dst = file(str(target[0]), 'w')
89310593Sgabeblack@google.com
89410593Sgabeblack@google.com    pysource = PySource.tnodes[source[0]]
8956611Sgblack@eecs.umich.edu    compiled = compile(src, pysource.abspath, 'exec')
8964276Sgblack@eecs.umich.edu    marshalled = marshal.dumps(compiled)
89710593Sgabeblack@google.com    compressed = zlib.compress(marshalled)
89810593Sgabeblack@google.com    data = compressed
89910593Sgabeblack@google.com
90010593Sgabeblack@google.com    # Some C/C++ compilers prepend an underscore to global symbol
90110593Sgabeblack@google.com    # names, so if they're going to do that, we need to prepend that
90210593Sgabeblack@google.com    # leading underscore to globals in the assembly file.
90310593Sgabeblack@google.com    if env['LEADING_UNDERSCORE']:
90410593Sgabeblack@google.com        sym = '_' + pysource.symname
90510593Sgabeblack@google.com    else:
9065059Sgblack@eecs.umich.edu        sym = pysource.symname
9075020Sgblack@eecs.umich.edu
90810593Sgabeblack@google.com    step = 16
90910593Sgabeblack@google.com    print >>dst, ".data"
91010593Sgabeblack@google.com    print >>dst, ".globl %s_beg" % sym
9116576Sgblack@eecs.umich.edu    print >>dst, ".globl %s_end" % sym
9125020Sgblack@eecs.umich.edu    print >>dst, "%s_beg:" % sym
91310593Sgabeblack@google.com    for i in xrange(0, len(data), step):
91410593Sgabeblack@google.com        x = array.array('B', data[i:i+step])
91510632Smaxime.cscs@gmail.com        print >>dst, ".byte", ','.join([str(d) for d in x])
91610593Sgabeblack@google.com    print >>dst, "%s_end:" % sym
91710593Sgabeblack@google.com    print >>dst, ".long %d" % len(marshalled)
91810593Sgabeblack@google.com
91910593Sgabeblack@google.comfor source in PySource.all:
92010593Sgabeblack@google.com    env.Command(source.assembly, source.tnode, objectifyPyFile)
92110593Sgabeblack@google.com    Source(source.assembly)
92210593Sgabeblack@google.com
92310593Sgabeblack@google.com# Generate init_python.cc which creates a bunch of EmbeddedPyModule
92410593Sgabeblack@google.com# structs that describe the embedded python code.  One such struct
92510593Sgabeblack@google.com# contains information about the importer that python uses to get at
92610593Sgabeblack@google.com# the embedded files, and then there's a list of all of the rest that
92710593Sgabeblack@google.com# the importer uses to load the rest on demand.
9286576Sgblack@eecs.umich.edudef pythonInit(target, source, env):
9295020Sgblack@eecs.umich.edu    dst = file(str(target[0]), 'w')
93010593Sgabeblack@google.com
93110593Sgabeblack@google.com    def dump_mod(sym, endchar=','):
93210593Sgabeblack@google.com        pysource = PySource.symnames[sym]
93310593Sgabeblack@google.com        print >>dst, '    { "%s",' % pysource.arcname
93410593Sgabeblack@google.com        print >>dst, '      "%s",' % pysource.modpath
93510593Sgabeblack@google.com        print >>dst, '       %s_beg, %s_end,' % (sym, sym)
93610593Sgabeblack@google.com        print >>dst, '       %s_end - %s_beg,' % (sym, sym)
93710593Sgabeblack@google.com        print >>dst, '       *(int *)%s_end }%s'  % (sym, endchar)
93810593Sgabeblack@google.com    
93910593Sgabeblack@google.com    print >>dst, '#include "sim/init.hh"'
94010593Sgabeblack@google.com
94110593Sgabeblack@google.com    for sym in source:
94210593Sgabeblack@google.com        sym = sym.get_contents()
94310593Sgabeblack@google.com        print >>dst, "extern const char %s_beg[], %s_end[];" % (sym, sym)
94410593Sgabeblack@google.com
94510593Sgabeblack@google.com    print >>dst, "const EmbeddedPyModule embeddedPyImporter = "
94610593Sgabeblack@google.com    dump_mod("PyEMB_importer", endchar=';');
94710593Sgabeblack@google.com    print >>dst
94810593Sgabeblack@google.com
94910593Sgabeblack@google.com    print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {"
95010593Sgabeblack@google.com    for i,sym in enumerate(source):
95110593Sgabeblack@google.com        sym = sym.get_contents()
95210593Sgabeblack@google.com        if sym == "PyEMB_importer":
95310593Sgabeblack@google.com            # Skip the importer since we've already exported it
95410593Sgabeblack@google.com            continue
95510593Sgabeblack@google.com        dump_mod(sym)
95610593Sgabeblack@google.com    print >>dst, "    { 0, 0, 0, 0, 0, 0 }"
95710593Sgabeblack@google.com    print >>dst, "};"
95810593Sgabeblack@google.com
95910593Sgabeblack@google.com
96010593Sgabeblack@google.comenv.Command('sim/init_python.cc',
96110593Sgabeblack@google.com            map(Value, (s.symname for s in PySource.all)),
96210593Sgabeblack@google.com            pythonInit)
96310593Sgabeblack@google.comSource('sim/init_python.cc')
96410593Sgabeblack@google.com
96510593Sgabeblack@google.com########################################################################
96610593Sgabeblack@google.com#
9676576Sgblack@eecs.umich.edu# Define binaries.  Each different build type (debug, opt, etc.) gets
9685020Sgblack@eecs.umich.edu# a slightly different build environment.
96910593Sgabeblack@google.com#
97010593Sgabeblack@google.com
97110593Sgabeblack@google.com# List of constructed environments to pass back to SConstruct
9726584Sgblack@eecs.umich.eduenvList = []
9735020Sgblack@eecs.umich.edu
97410593Sgabeblack@google.comdate_source = Source('base/date.cc', skip_lib=True)
97510593Sgabeblack@google.com
97610593Sgabeblack@google.com# Function to create a new build environment as clone of current
97710593Sgabeblack@google.com# environment 'env' with modified object suffix and optional stripped
97810593Sgabeblack@google.com# binary.  Additional keyword arguments are appended to corresponding
97910593Sgabeblack@google.com# build environment vars.
98010593Sgabeblack@google.comdef makeEnv(label, objsfx, strip = False, **kwargs):
98110593Sgabeblack@google.com    # SCons doesn't know to append a library suffix when there is a '.' in the
98210593Sgabeblack@google.com    # name.  Use '_' instead.
98310593Sgabeblack@google.com    libname = 'm5_' + label
98410593Sgabeblack@google.com    exename = 'm5.' + label
98510593Sgabeblack@google.com
98610593Sgabeblack@google.com    new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
98710593Sgabeblack@google.com    new_env.Label = label
9886584Sgblack@eecs.umich.edu    new_env.Append(**kwargs)
9895020Sgblack@eecs.umich.edu
99010593Sgabeblack@google.com    swig_env = new_env.Clone()
99110593Sgabeblack@google.com    swig_env.Append(CCFLAGS='-Werror')
99210593Sgabeblack@google.com    if env['GCC']:
99310593Sgabeblack@google.com        swig_env.Append(CCFLAGS='-Wno-uninitialized')
99410593Sgabeblack@google.com        swig_env.Append(CCFLAGS='-Wno-sign-compare')
99510593Sgabeblack@google.com        swig_env.Append(CCFLAGS='-Wno-parentheses')
99610593Sgabeblack@google.com
99710593Sgabeblack@google.com    werror_env = new_env.Clone()
99810593Sgabeblack@google.com    werror_env.Append(CCFLAGS='-Werror')
99910593Sgabeblack@google.com
100010593Sgabeblack@google.com    def make_obj(source, static, extra_deps = None):
100110593Sgabeblack@google.com        '''This function adds the specified source to the correct
100210593Sgabeblack@google.com        build environment, and returns the corresponding SCons Object
10034727Sgblack@eecs.umich.edu        nodes'''
100410593Sgabeblack@google.com
100510593Sgabeblack@google.com        if source.swig:
100610593Sgabeblack@google.com            env = swig_env
100710593Sgabeblack@google.com        elif source.Werror:
100810593Sgabeblack@google.com            env = werror_env
100910593Sgabeblack@google.com        else:
101010593Sgabeblack@google.com            env = new_env
101110593Sgabeblack@google.com
101210593Sgabeblack@google.com        if static:
101310593Sgabeblack@google.com            obj = env.StaticObject(source.tnode)
10144727Sgblack@eecs.umich.edu        else:
101510593Sgabeblack@google.com            obj = env.SharedObject(source.tnode)
10164276Sgblack@eecs.umich.edu
101710593Sgabeblack@google.com        if extra_deps:
101810593Sgabeblack@google.com            env.Depends(obj, extra_deps)
101910593Sgabeblack@google.com
102010593Sgabeblack@google.com        return obj
102110593Sgabeblack@google.com
102210593Sgabeblack@google.com    static_objs = [ make_obj(s, True) for s in Source.get(skip_lib=False)]
102310593Sgabeblack@google.com    shared_objs = [ make_obj(s, False) for s in Source.get(skip_lib=False)]
102410593Sgabeblack@google.com
102510593Sgabeblack@google.com    static_date = make_obj(date_source, static=True, extra_deps=static_objs)
102610593Sgabeblack@google.com    static_objs.append(static_date)
10276576Sgblack@eecs.umich.edu    
10285020Sgblack@eecs.umich.edu    shared_date = make_obj(date_source, static=False, extra_deps=shared_objs)
102910593Sgabeblack@google.com    shared_objs.append(shared_date)
103010593Sgabeblack@google.com
103110593Sgabeblack@google.com    # First make a library of everything but main() so other programs can
103210593Sgabeblack@google.com    # link against m5.
103310593Sgabeblack@google.com    static_lib = new_env.StaticLibrary(libname, static_objs)
103410593Sgabeblack@google.com    shared_lib = new_env.SharedLibrary(libname, shared_objs)
103510593Sgabeblack@google.com
103610593Sgabeblack@google.com    for target, sources in unit_tests:
103710593Sgabeblack@google.com        objs = [ make_obj(s, static=True) for s in sources ]
10386593Sgblack@eecs.umich.edu        new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs)
10395020Sgblack@eecs.umich.edu
104010593Sgabeblack@google.com    # Now link a stub with main() and the static library.
104110593Sgabeblack@google.com    bin_objs = [make_obj(s, True) for s in Source.get(bin_only=True) ]
104210593Sgabeblack@google.com    progname = exename
10436576Sgblack@eecs.umich.edu    if strip:
10445020Sgblack@eecs.umich.edu        progname += '.unstripped'
104510593Sgabeblack@google.com
104610593Sgabeblack@google.com    targets = new_env.Program(progname, bin_objs + static_objs)
104710593Sgabeblack@google.com
104810593Sgabeblack@google.com    if strip:
104910593Sgabeblack@google.com        if sys.platform == 'sunos5':
105010593Sgabeblack@google.com            cmd = 'cp $SOURCE $TARGET; strip $TARGET'
105110593Sgabeblack@google.com        else:
105210593Sgabeblack@google.com            cmd = 'strip $SOURCE -o $TARGET'
105310593Sgabeblack@google.com        targets = new_env.Command(exename, progname, cmd)
105410593Sgabeblack@google.com            
105510593Sgabeblack@google.com    new_env.M5Binary = targets[0]
105610593Sgabeblack@google.com    envList.append(new_env)
105710593Sgabeblack@google.com
10585022Sgblack@eecs.umich.edu# Debug binary
105910593Sgabeblack@google.comccflags = {}
106010593Sgabeblack@google.comif env['GCC']:
106110593Sgabeblack@google.com    if sys.platform == 'sunos5':
106210593Sgabeblack@google.com        ccflags['debug'] = '-gstabs+'
106310593Sgabeblack@google.com    else:
106410593Sgabeblack@google.com        ccflags['debug'] = '-ggdb3'
106510593Sgabeblack@google.com    ccflags['opt'] = '-g -O3'
106610593Sgabeblack@google.com    ccflags['fast'] = '-O3'
106710593Sgabeblack@google.com    ccflags['prof'] = '-O3 -g -pg'
106810593Sgabeblack@google.comelif env['SUNCC']:
10695020Sgblack@eecs.umich.edu    ccflags['debug'] = '-g0'
107010593Sgabeblack@google.com    ccflags['opt'] = '-g -O'
10714276Sgblack@eecs.umich.edu    ccflags['fast'] = '-fast'
10724276Sgblack@eecs.umich.edu    ccflags['prof'] = '-fast -g -pg'
107310593Sgabeblack@google.comelif env['ICC']:
10744276Sgblack@eecs.umich.edu    ccflags['debug'] = '-g -O0'
10754276Sgblack@eecs.umich.edu    ccflags['opt'] = '-g -O'
1076    ccflags['fast'] = '-fast'
1077    ccflags['prof'] = '-fast -g -pg'
1078else:
1079    print 'Unknown compiler, please fix compiler options'
1080    Exit(1)
1081
1082makeEnv('debug', '.do',
1083        CCFLAGS = Split(ccflags['debug']),
1084        CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
1085
1086# Optimized binary
1087makeEnv('opt', '.o',
1088        CCFLAGS = Split(ccflags['opt']),
1089        CPPDEFINES = ['TRACING_ON=1'])
1090
1091# "Fast" binary
1092makeEnv('fast', '.fo', strip = True,
1093        CCFLAGS = Split(ccflags['fast']),
1094        CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
1095
1096# Profiled binary
1097makeEnv('prof', '.po',
1098        CCFLAGS = Split(ccflags['prof']),
1099        CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
1100        LINKFLAGS = '-pg')
1101
1102Return('envList')
1103