SConscript revision 11370
19793Sakash.bagdia@arm.com# -*- mode:python -*- 29518SAndreas.Sandberg@ARM.com 311320Ssteve.reinhardt@amd.com# Copyright (c) 2004-2005 The Regents of The University of Michigan 49518SAndreas.Sandberg@ARM.com# All rights reserved. 59518SAndreas.Sandberg@ARM.com# 69518SAndreas.Sandberg@ARM.com# Redistribution and use in source and binary forms, with or without 79518SAndreas.Sandberg@ARM.com# modification, are permitted provided that the following conditions are 89518SAndreas.Sandberg@ARM.com# met: redistributions of source code must retain the above copyright 99518SAndreas.Sandberg@ARM.com# notice, this list of conditions and the following disclaimer; 109518SAndreas.Sandberg@ARM.com# redistributions in binary form must reproduce the above copyright 119518SAndreas.Sandberg@ARM.com# notice, this list of conditions and the following disclaimer in the 129518SAndreas.Sandberg@ARM.com# documentation and/or other materials provided with the distribution; 135347Ssaidi@eecs.umich.edu# neither the name of the copyright holders nor the names of its 147534Ssteve.reinhardt@amd.com# contributors may be used to endorse or promote products derived from 153395Shsul@eecs.umich.edu# this software without specific prior written permission. 163395Shsul@eecs.umich.edu# 173395Shsul@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 183395Shsul@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 193395Shsul@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 203395Shsul@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 213395Shsul@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 223395Shsul@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 233395Shsul@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 243395Shsul@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 253395Shsul@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 263395Shsul@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 273395Shsul@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 283395Shsul@eecs.umich.edu# 293395Shsul@eecs.umich.edu# Authors: Nathan Binkert 303395Shsul@eecs.umich.edu 313395Shsul@eecs.umich.eduimport array 323395Shsul@eecs.umich.eduimport bisect 333395Shsul@eecs.umich.eduimport imp 343395Shsul@eecs.umich.eduimport marshal 353395Shsul@eecs.umich.eduimport os 363395Shsul@eecs.umich.eduimport re 373395Shsul@eecs.umich.eduimport sys 383395Shsul@eecs.umich.eduimport zlib 393395Shsul@eecs.umich.edu 403395Shsul@eecs.umich.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath 413395Shsul@eecs.umich.edu 429457Svilanova@ac.upc.eduimport SCons 433395Shsul@eecs.umich.edu 443509Shsul@eecs.umich.edu# This file defines how to build a particular configuration of gem5 456654Snate@binkert.org# based on variable settings in the 'env' build environment. 4611688Sandreas.hansson@arm.com 4711688Sandreas.hansson@arm.comImport('*') 489520SAndreas.Sandberg@ARM.com 493395Shsul@eecs.umich.edu# Children need to see the environment 506654Snate@binkert.orgExport('env') 513395Shsul@eecs.umich.edu 526654Snate@binkert.orgbuild_env = [(opt, env[opt]) for opt in export_vars] 536654Snate@binkert.org 546654Snate@binkert.orgfrom m5.util import code_formatter, compareVersions 553395Shsul@eecs.umich.edu 569139Snilay@cs.wisc.edu######################################################################## 579520SAndreas.Sandberg@ARM.com# Code for adding source files of various types 589520SAndreas.Sandberg@ARM.com# 599520SAndreas.Sandberg@ARM.com# When specifying a source file of some type, a set of guards can be 609139Snilay@cs.wisc.edu# specified for that file. When get() is used to find the files, if 613481Shsul@eecs.umich.edu# get specifies a set of filters, only files that match those filters 629139Snilay@cs.wisc.edu# will be accepted (unspecified filters on files are assumed to be 633481Shsul@eecs.umich.edu# false). Current filters are: 649139Snilay@cs.wisc.edu# main -- specifies the gem5 main() function 659139Snilay@cs.wisc.edu# skip_lib -- do not put this file into the gem5 library 669139Snilay@cs.wisc.edu# skip_no_python -- do not put this file into a no_python library 679139Snilay@cs.wisc.edu# as it embeds compiled Python 689139Snilay@cs.wisc.edu# <unittest> -- unit tests use filters based on the unit test name 699139Snilay@cs.wisc.edu# 709139Snilay@cs.wisc.edu# A parent can now be specified for a source file and default filter 719139Snilay@cs.wisc.edu# values will be retrieved recursively from parents (children override 723481Shsul@eecs.umich.edu# parents). 739518SAndreas.Sandberg@ARM.com# 749518SAndreas.Sandberg@ARM.comclass SourceMeta(type): 759518SAndreas.Sandberg@ARM.com '''Meta class for source files that keeps track of all files of a 763481Shsul@eecs.umich.edu particular type and has a get function for finding all functions 779139Snilay@cs.wisc.edu of a certain type that match a set of guards''' 789139Snilay@cs.wisc.edu def __init__(cls, name, bases, dict): 793481Shsul@eecs.umich.edu super(SourceMeta, cls).__init__(name, bases, dict) 809139Snilay@cs.wisc.edu cls.all = [] 819139Snilay@cs.wisc.edu 829139Snilay@cs.wisc.edu def get(cls, **guards): 839139Snilay@cs.wisc.edu '''Find all files that match the specified guards. If a source 849139Snilay@cs.wisc.edu file does not specify a flag, the default is False''' 853481Shsul@eecs.umich.edu for src in cls.all: 863481Shsul@eecs.umich.edu for flag,value in guards.iteritems(): 873481Shsul@eecs.umich.edu # if the flag is found and has a different value, skip 889665Sandreas.hansson@arm.com # this file 899665Sandreas.hansson@arm.com if src.all_guards.get(flag, False) != value: 909665Sandreas.hansson@arm.com break 919665Sandreas.hansson@arm.com else: 929665Sandreas.hansson@arm.com yield src 938919Snilay@cs.wisc.edu 948919Snilay@cs.wisc.educlass SourceFile(object): 958919Snilay@cs.wisc.edu '''Base object that encapsulates the notion of a source file. 9610159Sgedare@rtems.org This includes, the source node, target node, various manipulations 9710159Sgedare@rtems.org of those. A source file also specifies a set of guards which 988919Snilay@cs.wisc.edu describing which builds the source file applies to. A parent can 998919Snilay@cs.wisc.edu also be specified to get default guards from''' 1008919Snilay@cs.wisc.edu __metaclass__ = SourceMeta 1018919Snilay@cs.wisc.edu def __init__(self, source, parent=None, **guards): 1028919Snilay@cs.wisc.edu self.guards = guards 1038919Snilay@cs.wisc.edu self.parent = parent 1048919Snilay@cs.wisc.edu 1058919Snilay@cs.wisc.edu tnode = source 1068919Snilay@cs.wisc.edu if not isinstance(source, SCons.Node.FS.File): 1078919Snilay@cs.wisc.edu tnode = File(source) 1088919Snilay@cs.wisc.edu 1098919Snilay@cs.wisc.edu self.tnode = tnode 1103481Shsul@eecs.umich.edu self.snode = tnode.srcnode() 1119816Sjthestness@gmail.com 1129140Snilay@cs.wisc.edu for base in type(self).__mro__: 1139140Snilay@cs.wisc.edu if issubclass(base, SourceFile): 1149140Snilay@cs.wisc.edu base.all.append(self) 1159140Snilay@cs.wisc.edu 1169140Snilay@cs.wisc.edu @property 1179140Snilay@cs.wisc.edu def filename(self): 1189140Snilay@cs.wisc.edu return str(self.tnode) 1199140Snilay@cs.wisc.edu 1209140Snilay@cs.wisc.edu @property 1219140Snilay@cs.wisc.edu def dirname(self): 1229140Snilay@cs.wisc.edu return dirname(self.filename) 1239140Snilay@cs.wisc.edu 1249140Snilay@cs.wisc.edu @property 1259140Snilay@cs.wisc.edu def basename(self): 1269140Snilay@cs.wisc.edu return basename(self.filename) 1279140Snilay@cs.wisc.edu 1289140Snilay@cs.wisc.edu @property 1299140Snilay@cs.wisc.edu def extname(self): 1309140Snilay@cs.wisc.edu index = self.basename.rfind('.') 1319867Sjthestness@gmail.com if index <= 0: 1329140Snilay@cs.wisc.edu # dot files aren't extensions 1339140Snilay@cs.wisc.edu return self.basename, None 1349140Snilay@cs.wisc.edu 1359140Snilay@cs.wisc.edu return self.basename[:index], self.basename[index+1:] 1369140Snilay@cs.wisc.edu 1379140Snilay@cs.wisc.edu @property 1389140Snilay@cs.wisc.edu def all_guards(self): 1399140Snilay@cs.wisc.edu '''find all guards for this object getting default values 1409140Snilay@cs.wisc.edu recursively from its parents''' 1419140Snilay@cs.wisc.edu guards = {} 1429140Snilay@cs.wisc.edu if self.parent: 14310608Sdam.sunwoo@arm.com guards.update(self.parent.guards) 14410608Sdam.sunwoo@arm.com guards.update(self.guards) 14510608Sdam.sunwoo@arm.com return guards 14610608Sdam.sunwoo@arm.com 14710608Sdam.sunwoo@arm.com def __lt__(self, other): return self.filename < other.filename 14810608Sdam.sunwoo@arm.com def __le__(self, other): return self.filename <= other.filename 14910608Sdam.sunwoo@arm.com def __gt__(self, other): return self.filename > other.filename 15010608Sdam.sunwoo@arm.com def __ge__(self, other): return self.filename >= other.filename 15110608Sdam.sunwoo@arm.com def __eq__(self, other): return self.filename == other.filename 15210608Sdam.sunwoo@arm.com def __ne__(self, other): return self.filename != other.filename 15310608Sdam.sunwoo@arm.com 15410608Sdam.sunwoo@arm.com @staticmethod 15510608Sdam.sunwoo@arm.com def done(): 15610608Sdam.sunwoo@arm.com def disabled(cls, name, *ignored): 15710608Sdam.sunwoo@arm.com raise RuntimeError("Additional SourceFile '%s'" % name,\ 15810608Sdam.sunwoo@arm.com "declared, but targets deps are already fixed.") 15910608Sdam.sunwoo@arm.com SourceFile.__init__ = disabled 16010608Sdam.sunwoo@arm.com 16110608Sdam.sunwoo@arm.com 16210608Sdam.sunwoo@arm.comclass Source(SourceFile): 16310608Sdam.sunwoo@arm.com '''Add a c/c++ source file to the build''' 16410608Sdam.sunwoo@arm.com def __init__(self, source, Werror=True, swig=False, **guards): 16510608Sdam.sunwoo@arm.com '''specify the source file, and any guards''' 16610608Sdam.sunwoo@arm.com super(Source, self).__init__(source, **guards) 16710608Sdam.sunwoo@arm.com 16810608Sdam.sunwoo@arm.com self.Werror = Werror 16910608Sdam.sunwoo@arm.com self.swig = swig 17010608Sdam.sunwoo@arm.com 17110608Sdam.sunwoo@arm.comclass PySource(SourceFile): 17210608Sdam.sunwoo@arm.com '''Add a python source file to the named package''' 17310608Sdam.sunwoo@arm.com invalid_sym_char = re.compile('[^A-z0-9_]') 17410608Sdam.sunwoo@arm.com modules = {} 17510608Sdam.sunwoo@arm.com tnodes = {} 17610608Sdam.sunwoo@arm.com symnames = {} 17710608Sdam.sunwoo@arm.com 17810608Sdam.sunwoo@arm.com def __init__(self, package, source, **guards): 17910608Sdam.sunwoo@arm.com '''specify the python package, the source file, and any guards''' 1809140Snilay@cs.wisc.edu super(PySource, self).__init__(source, **guards) 1819140Snilay@cs.wisc.edu 18210608Sdam.sunwoo@arm.com modname,ext = self.extname 1839140Snilay@cs.wisc.edu assert ext == 'py' 1849140Snilay@cs.wisc.edu 1859140Snilay@cs.wisc.edu if package: 1869140Snilay@cs.wisc.edu path = package.split('.') 1879140Snilay@cs.wisc.edu else: 1889140Snilay@cs.wisc.edu path = [] 1899140Snilay@cs.wisc.edu 1909140Snilay@cs.wisc.edu modpath = path[:] 1919140Snilay@cs.wisc.edu if modname != '__init__': 1929140Snilay@cs.wisc.edu modpath += [ modname ] 1939140Snilay@cs.wisc.edu modpath = '.'.join(modpath) 1949140Snilay@cs.wisc.edu 1959816Sjthestness@gmail.com arcpath = path + [ self.basename ] 1969140Snilay@cs.wisc.edu abspath = self.snode.abspath 1979140Snilay@cs.wisc.edu if not exists(abspath): 1989816Sjthestness@gmail.com abspath = self.tnode.abspath 1999140Snilay@cs.wisc.edu 2009215Sandreas.hansson@arm.com self.package = package 2019140Snilay@cs.wisc.edu self.modname = modname 2029140Snilay@cs.wisc.edu self.modpath = modpath 2039140Snilay@cs.wisc.edu self.arcname = joinpath(*arcpath) 2049140Snilay@cs.wisc.edu self.abspath = abspath 2059140Snilay@cs.wisc.edu self.compiled = File(self.filename + 'c') 2069140Snilay@cs.wisc.edu self.cpp = File(self.filename + '.cc') 2079140Snilay@cs.wisc.edu self.symname = PySource.invalid_sym_char.sub('_', modpath) 2089140Snilay@cs.wisc.edu 2099140Snilay@cs.wisc.edu PySource.modules[modpath] = self 2109140Snilay@cs.wisc.edu PySource.tnodes[self.tnode] = self 2119140Snilay@cs.wisc.edu PySource.symnames[self.symname] = self 2129140Snilay@cs.wisc.edu 2139140Snilay@cs.wisc.educlass SimObject(PySource): 2149140Snilay@cs.wisc.edu '''Add a SimObject python file as a python source object and add 2159140Snilay@cs.wisc.edu it to a list of sim object modules''' 2169140Snilay@cs.wisc.edu 2179140Snilay@cs.wisc.edu fixed = False 2189140Snilay@cs.wisc.edu modnames = [] 2199140Snilay@cs.wisc.edu 2209140Snilay@cs.wisc.edu def __init__(self, source, **guards): 2219140Snilay@cs.wisc.edu '''Specify the source file and any guards (automatically in 2229140Snilay@cs.wisc.edu the m5.objects package)''' 2239140Snilay@cs.wisc.edu super(SimObject, self).__init__('m5.objects', source, **guards) 2249140Snilay@cs.wisc.edu if self.fixed: 2259140Snilay@cs.wisc.edu raise AttributeError, "Too late to call SimObject now." 2269140Snilay@cs.wisc.edu 2279156Sandreas.hansson@arm.com bisect.insort_right(SimObject.modnames, self.modname) 2289140Snilay@cs.wisc.edu 2299634Sjthestness@gmail.comclass SwigSource(SourceFile): 2309140Snilay@cs.wisc.edu '''Add a swig file to build''' 2319140Snilay@cs.wisc.edu 2329140Snilay@cs.wisc.edu def __init__(self, package, source, **guards): 2339140Snilay@cs.wisc.edu '''Specify the python package, the source file, and any guards''' 2349140Snilay@cs.wisc.edu super(SwigSource, self).__init__(source, skip_no_python=True, **guards) 2359140Snilay@cs.wisc.edu 2369140Snilay@cs.wisc.edu modname,ext = self.extname 2379140Snilay@cs.wisc.edu assert ext == 'i' 2389140Snilay@cs.wisc.edu 2399140Snilay@cs.wisc.edu self.module = modname 2409140Snilay@cs.wisc.edu cc_file = joinpath(self.dirname, modname + '_wrap.cc') 2419140Snilay@cs.wisc.edu py_file = joinpath(self.dirname, modname + '.py') 2429140Snilay@cs.wisc.edu 2439140Snilay@cs.wisc.edu self.cc_source = Source(cc_file, swig=True, parent=self, **guards) 2449140Snilay@cs.wisc.edu self.py_source = PySource(package, py_file, parent=self, **guards) 2459140Snilay@cs.wisc.edu 2469140Snilay@cs.wisc.educlass ProtoBuf(SourceFile): 2479140Snilay@cs.wisc.edu '''Add a Protocol Buffer to build''' 2489140Snilay@cs.wisc.edu 2499140Snilay@cs.wisc.edu def __init__(self, source, **guards): 2509140Snilay@cs.wisc.edu '''Specify the source file, and any guards''' 2519140Snilay@cs.wisc.edu super(ProtoBuf, self).__init__(source, **guards) 2529140Snilay@cs.wisc.edu 2539140Snilay@cs.wisc.edu # Get the file name and the extension 2549140Snilay@cs.wisc.edu modname,ext = self.extname 2559140Snilay@cs.wisc.edu assert ext == 'proto' 2569140Snilay@cs.wisc.edu 2579140Snilay@cs.wisc.edu # Currently, we stick to generating the C++ headers, so we 2589606Snilay@cs.wisc.edu # only need to track the source and header. 2599140Snilay@cs.wisc.edu self.cc_file = File(modname + '.pb.cc') 2609140Snilay@cs.wisc.edu self.hh_file = File(modname + '.pb.h') 2619634Sjthestness@gmail.com 2629140Snilay@cs.wisc.educlass UnitTest(object): 2639140Snilay@cs.wisc.edu '''Create a UnitTest''' 2649140Snilay@cs.wisc.edu 2659140Snilay@cs.wisc.edu all = [] 2669140Snilay@cs.wisc.edu def __init__(self, target, *sources, **kwargs): 2679140Snilay@cs.wisc.edu '''Specify the target name and any sources. Sources that are 2689140Snilay@cs.wisc.edu not SourceFiles are evalued with Source(). All files are 2699140Snilay@cs.wisc.edu guarded with a guard of the same name as the UnitTest 2709140Snilay@cs.wisc.edu target.''' 2719140Snilay@cs.wisc.edu 2729140Snilay@cs.wisc.edu srcs = [] 2739140Snilay@cs.wisc.edu for src in sources: 2749140Snilay@cs.wisc.edu if not isinstance(src, SourceFile): 2759140Snilay@cs.wisc.edu src = Source(src, skip_lib=True) 2769140Snilay@cs.wisc.edu src.guards[target] = True 2779460Ssaidi@eecs.umich.edu srcs.append(src) 2789140Snilay@cs.wisc.edu 27910608Sdam.sunwoo@arm.com self.sources = srcs 28010608Sdam.sunwoo@arm.com self.target = target 28110608Sdam.sunwoo@arm.com self.main = kwargs.get('main', False) 28210608Sdam.sunwoo@arm.com UnitTest.all.append(self) 28310608Sdam.sunwoo@arm.com 28410608Sdam.sunwoo@arm.com# Children should have access 28510608Sdam.sunwoo@arm.comExport('Source') 28610608Sdam.sunwoo@arm.comExport('PySource') 28710608Sdam.sunwoo@arm.comExport('SimObject') 28810608Sdam.sunwoo@arm.comExport('SwigSource') 28910608Sdam.sunwoo@arm.comExport('ProtoBuf') 29010608Sdam.sunwoo@arm.comExport('UnitTest') 29110608Sdam.sunwoo@arm.com 29210608Sdam.sunwoo@arm.com######################################################################## 29310608Sdam.sunwoo@arm.com# 29410608Sdam.sunwoo@arm.com# Debug Flags 29510608Sdam.sunwoo@arm.com# 29610608Sdam.sunwoo@arm.comdebug_flags = {} 29710608Sdam.sunwoo@arm.comdef DebugFlag(name, desc=None): 29810608Sdam.sunwoo@arm.com if name in debug_flags: 29910608Sdam.sunwoo@arm.com raise AttributeError, "Flag %s already specified" % name 30010608Sdam.sunwoo@arm.com debug_flags[name] = (name, (), desc) 30110608Sdam.sunwoo@arm.com 30210608Sdam.sunwoo@arm.comdef CompoundFlag(name, flags, desc=None): 30310608Sdam.sunwoo@arm.com if name in debug_flags: 30410608Sdam.sunwoo@arm.com raise AttributeError, "Flag %s already specified" % name 30510608Sdam.sunwoo@arm.com 30610608Sdam.sunwoo@arm.com compound = tuple(flags) 30710608Sdam.sunwoo@arm.com debug_flags[name] = (name, compound, desc) 30810608Sdam.sunwoo@arm.com 30910608Sdam.sunwoo@arm.comExport('DebugFlag') 31010608Sdam.sunwoo@arm.comExport('CompoundFlag') 31110608Sdam.sunwoo@arm.com 31210608Sdam.sunwoo@arm.com######################################################################## 31310608Sdam.sunwoo@arm.com# 31410608Sdam.sunwoo@arm.com# Set some compiler variables 31510608Sdam.sunwoo@arm.com# 31610608Sdam.sunwoo@arm.com 31710608Sdam.sunwoo@arm.com# Include file paths are rooted in this directory. SCons will 31810608Sdam.sunwoo@arm.com# automatically expand '.' to refer to both the source directory and 31910608Sdam.sunwoo@arm.com# the corresponding build directory to pick up generated include 32010608Sdam.sunwoo@arm.com# files. 32110608Sdam.sunwoo@arm.comenv.Append(CPPPATH=Dir('.')) 32210608Sdam.sunwoo@arm.com 32310608Sdam.sunwoo@arm.comfor extra_dir in extras_dir_list: 32410608Sdam.sunwoo@arm.com env.Append(CPPPATH=Dir(extra_dir)) 32510608Sdam.sunwoo@arm.com 32610608Sdam.sunwoo@arm.com# Workaround for bug in SCons version > 0.97d20071212 32710608Sdam.sunwoo@arm.com# Scons bug id: 2006 gem5 Bug id: 308 32810608Sdam.sunwoo@arm.comfor root, dirs, files in os.walk(base_dir, topdown=True): 32910608Sdam.sunwoo@arm.com Dir(root[len(base_dir) + 1:]) 33010608Sdam.sunwoo@arm.com 33110608Sdam.sunwoo@arm.com######################################################################## 33210608Sdam.sunwoo@arm.com# 33310608Sdam.sunwoo@arm.com# Walk the tree and execute all SConscripts in subdirectories 33410608Sdam.sunwoo@arm.com# 33510608Sdam.sunwoo@arm.com 33610608Sdam.sunwoo@arm.comhere = Dir('.').srcnode().abspath 33710608Sdam.sunwoo@arm.comfor root, dirs, files in os.walk(base_dir, topdown=True): 33810608Sdam.sunwoo@arm.com if root == here: 33910608Sdam.sunwoo@arm.com # we don't want to recurse back into this SConscript 34010608Sdam.sunwoo@arm.com continue 34110608Sdam.sunwoo@arm.com 34210608Sdam.sunwoo@arm.com if 'SConscript' in files: 34310608Sdam.sunwoo@arm.com build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) 34410608Sdam.sunwoo@arm.com SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 34510608Sdam.sunwoo@arm.com 34610608Sdam.sunwoo@arm.comfor extra_dir in extras_dir_list: 34710608Sdam.sunwoo@arm.com prefix_len = len(dirname(extra_dir)) + 1 34810608Sdam.sunwoo@arm.com 34910608Sdam.sunwoo@arm.com # Also add the corresponding build directory to pick up generated 35010608Sdam.sunwoo@arm.com # include files. 35110608Sdam.sunwoo@arm.com env.Append(CPPPATH=Dir(joinpath(env['BUILDDIR'], extra_dir[prefix_len:]))) 35210608Sdam.sunwoo@arm.com 35310608Sdam.sunwoo@arm.com for root, dirs, files in os.walk(extra_dir, topdown=True): 35410608Sdam.sunwoo@arm.com # if build lives in the extras directory, don't walk down it 35510608Sdam.sunwoo@arm.com if 'build' in dirs: 35610608Sdam.sunwoo@arm.com dirs.remove('build') 35710608Sdam.sunwoo@arm.com 35810608Sdam.sunwoo@arm.com if 'SConscript' in files: 35910608Sdam.sunwoo@arm.com build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) 36010608Sdam.sunwoo@arm.com SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 36110608Sdam.sunwoo@arm.com 36210608Sdam.sunwoo@arm.comfor opt in export_vars: 36310608Sdam.sunwoo@arm.com env.ConfigFile(opt) 36410608Sdam.sunwoo@arm.com 36510608Sdam.sunwoo@arm.comdef makeTheISA(source, target, env): 36610608Sdam.sunwoo@arm.com isas = [ src.get_contents() for src in source ] 36710608Sdam.sunwoo@arm.com target_isa = env['TARGET_ISA'] 36810608Sdam.sunwoo@arm.com def define(isa): 36910608Sdam.sunwoo@arm.com return isa.upper() + '_ISA' 37010608Sdam.sunwoo@arm.com 37110608Sdam.sunwoo@arm.com def namespace(isa): 37210608Sdam.sunwoo@arm.com return isa[0].upper() + isa[1:].lower() + 'ISA' 37310608Sdam.sunwoo@arm.com 37410608Sdam.sunwoo@arm.com 37510608Sdam.sunwoo@arm.com code = code_formatter() 37610608Sdam.sunwoo@arm.com code('''\ 37710608Sdam.sunwoo@arm.com#ifndef __CONFIG_THE_ISA_HH__ 37810608Sdam.sunwoo@arm.com#define __CONFIG_THE_ISA_HH__ 37910608Sdam.sunwoo@arm.com 38010608Sdam.sunwoo@arm.com''') 38110608Sdam.sunwoo@arm.com 38210608Sdam.sunwoo@arm.com # create defines for the preprocessing and compile-time determination 38310608Sdam.sunwoo@arm.com for i,isa in enumerate(isas): 38410608Sdam.sunwoo@arm.com code('#define $0 $1', define(isa), i + 1) 38510608Sdam.sunwoo@arm.com code() 38610608Sdam.sunwoo@arm.com 38710608Sdam.sunwoo@arm.com # create an enum for any run-time determination of the ISA, we 38810608Sdam.sunwoo@arm.com # reuse the same name as the namespaces 38910608Sdam.sunwoo@arm.com code('enum class Arch {') 39010608Sdam.sunwoo@arm.com for i,isa in enumerate(isas): 39110608Sdam.sunwoo@arm.com if i + 1 == len(isas): 39210608Sdam.sunwoo@arm.com code(' $0 = $1', namespace(isa), define(isa)) 39310608Sdam.sunwoo@arm.com else: 39410608Sdam.sunwoo@arm.com code(' $0 = $1,', namespace(isa), define(isa)) 39510608Sdam.sunwoo@arm.com code('};') 39610608Sdam.sunwoo@arm.com 39710608Sdam.sunwoo@arm.com code(''' 39810608Sdam.sunwoo@arm.com 39910608Sdam.sunwoo@arm.com#define THE_ISA ${{define(target_isa)}} 40010608Sdam.sunwoo@arm.com#define TheISA ${{namespace(target_isa)}} 40110608Sdam.sunwoo@arm.com#define THE_ISA_STR "${{target_isa}}" 40210608Sdam.sunwoo@arm.com 40310608Sdam.sunwoo@arm.com#endif // __CONFIG_THE_ISA_HH__''') 4049151Satgutier@umich.edu 4059151Satgutier@umich.edu code.write(str(target[0])) 4069151Satgutier@umich.edu 4079151Satgutier@umich.eduenv.Command('config/the_isa.hh', map(Value, all_isa_list), 4089151Satgutier@umich.edu MakeAction(makeTheISA, Transform("CFG ISA", 0))) 4099151Satgutier@umich.edu 4109151Satgutier@umich.edudef makeTheGPUISA(source, target, env): 4119460Ssaidi@eecs.umich.edu isas = [ src.get_contents() for src in source ] 4129151Satgutier@umich.edu target_gpu_isa = env['TARGET_GPU_ISA'] 4139521SAndreas.Sandberg@ARM.com def define(isa): 4149151Satgutier@umich.edu return isa.upper() + '_ISA' 4159151Satgutier@umich.edu 4169151Satgutier@umich.edu def namespace(isa): 4179151Satgutier@umich.edu return isa[0].upper() + isa[1:].lower() + 'ISA' 4189151Satgutier@umich.edu 4199151Satgutier@umich.edu 4209151Satgutier@umich.edu code = code_formatter() 4219151Satgutier@umich.edu code('''\ 4229460Ssaidi@eecs.umich.edu#ifndef __CONFIG_THE_GPU_ISA_HH__ 4239151Satgutier@umich.edu#define __CONFIG_THE_GPU_ISA_HH__ 4243481Shsul@eecs.umich.edu 4253395Shsul@eecs.umich.edu''') 4263395Shsul@eecs.umich.edu 4275211Ssaidi@eecs.umich.edu # create defines for the preprocessing and compile-time determination 4285211Ssaidi@eecs.umich.edu for i,isa in enumerate(isas): 4293395Shsul@eecs.umich.edu code('#define $0 $1', define(isa), i + 1) 4303395Shsul@eecs.umich.edu code() 4313395Shsul@eecs.umich.edu 4325370Ssaidi@eecs.umich.edu # create an enum for any run-time determination of the ISA, we 4336654Snate@binkert.org # reuse the same name as the namespaces 4345370Ssaidi@eecs.umich.edu code('enum class GPUArch {') 4355371Shsul@eecs.umich.edu for i,isa in enumerate(isas): 4366654Snate@binkert.org if i + 1 == len(isas): 4375370Ssaidi@eecs.umich.edu code(' $0 = $1', namespace(isa), define(isa)) 4389151Satgutier@umich.edu else: 4399151Satgutier@umich.edu code(' $0 = $1,', namespace(isa), define(isa)) 4409151Satgutier@umich.edu code('};') 4419151Satgutier@umich.edu 4429151Satgutier@umich.edu code(''' 4439151Satgutier@umich.edu 4443395Shsul@eecs.umich.edu#define THE_GPU_ISA ${{define(target_gpu_isa)}} 4453481Shsul@eecs.umich.edu#define TheGpuISA ${{namespace(target_gpu_isa)}} 4463481Shsul@eecs.umich.edu#define THE_GPU_ISA_STR "${{target_gpu_isa}}" 4478318Sksewell@umich.edu 4486144Sksewell@umich.edu#endif // __CONFIG_THE_GPU_ISA_HH__''') 4498311Sksewell@umich.edu 4506144Sksewell@umich.edu code.write(str(target[0])) 4516641Sksewell@umich.edu 4526641Sksewell@umich.eduenv.Command('config/the_gpu_isa.hh', map(Value, all_gpu_isa_list), 4536641Sksewell@umich.edu MakeAction(makeTheGPUISA, Transform("CFG ISA", 0))) 4546641Sksewell@umich.edu 4553481Shsul@eecs.umich.edu######################################################################## 4569433SAndreas.Sandberg@ARM.com# 4573481Shsul@eecs.umich.edu# Prevent any SimObjects from being added after this point, they 4583481Shsul@eecs.umich.edu# should all have been added in the SConscripts above 4593481Shsul@eecs.umich.edu# 4605361Srstrong@cs.ucsd.eduSimObject.fixed = True 4615369Ssaidi@eecs.umich.edu 46211251Sradhika.jagtap@ARM.comclass DictImporter(object): 4638803Sgblack@eecs.umich.edu '''This importer takes a dictionary of arbitrary module names that 4649793Sakash.bagdia@arm.com map to arbitrary filenames.''' 46511251Sradhika.jagtap@ARM.com def __init__(self, modules): 46611251Sradhika.jagtap@ARM.com self.modules = modules 4675369Ssaidi@eecs.umich.edu self.installed = set() 4688311Sksewell@umich.edu 4698311Sksewell@umich.edu def __del__(self): 4708887Sgeoffrey.blake@arm.com self.unload() 4718887Sgeoffrey.blake@arm.com 4728887Sgeoffrey.blake@arm.com def unload(self): 4733481Shsul@eecs.umich.edu import sys 47411251Sradhika.jagtap@ARM.com for module in self.installed: 47511251Sradhika.jagtap@ARM.com del sys.modules[module] 47611251Sradhika.jagtap@ARM.com self.installed = set() 47711251Sradhika.jagtap@ARM.com 47811251Sradhika.jagtap@ARM.com def find_module(self, fullname, path): 4795311Ssaidi@eecs.umich.edu if fullname == 'm5.defines': 4803481Shsul@eecs.umich.edu return self 4813395Shsul@eecs.umich.edu 4829151Satgutier@umich.edu if fullname == 'm5.objects': 4839518SAndreas.Sandberg@ARM.com return self 4849518SAndreas.Sandberg@ARM.com 4859518SAndreas.Sandberg@ARM.com if fullname.startswith('m5.internal'): 4869518SAndreas.Sandberg@ARM.com return None 4879518SAndreas.Sandberg@ARM.com 4889518SAndreas.Sandberg@ARM.com source = self.modules.get(fullname, None) 4899518SAndreas.Sandberg@ARM.com if source is not None and fullname.startswith('m5.objects'): 4909518SAndreas.Sandberg@ARM.com return self 4919151Satgutier@umich.edu 4929518SAndreas.Sandberg@ARM.com return None 4939518SAndreas.Sandberg@ARM.com 4949151Satgutier@umich.edu def load_module(self, fullname): 4959151Satgutier@umich.edu mod = imp.new_module(fullname) 4969151Satgutier@umich.edu sys.modules[fullname] = mod 4979151Satgutier@umich.edu self.installed.add(fullname) 4989793Sakash.bagdia@arm.com 4999151Satgutier@umich.edu mod.__loader__ = self 5009151Satgutier@umich.edu if fullname == 'm5.objects': 5019151Satgutier@umich.edu mod.__path__ = fullname.split('.') 5029151Satgutier@umich.edu return mod 5039151Satgutier@umich.edu 5049151Satgutier@umich.edu if fullname == 'm5.defines': 5059151Satgutier@umich.edu mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) 5069151Satgutier@umich.edu return mod 5079151Satgutier@umich.edu 5089151Satgutier@umich.edu source = self.modules[fullname] 5099151Satgutier@umich.edu if source.modname == '__init__': 5109151Satgutier@umich.edu mod.__path__ = source.modpath 5119151Satgutier@umich.edu mod.__file__ = source.abspath 5129151Satgutier@umich.edu 5139151Satgutier@umich.edu exec file(source.abspath, 'r') in mod.__dict__ 5149151Satgutier@umich.edu 5153395Shsul@eecs.umich.edu return mod 5169433SAndreas.Sandberg@ARM.com 5173395Shsul@eecs.umich.eduimport m5.SimObject 5189433SAndreas.Sandberg@ARM.comimport m5.params 5193395Shsul@eecs.umich.edufrom m5.util import code_formatter 5203478Shsul@eecs.umich.edu 5213395Shsul@eecs.umich.edum5.SimObject.clear() 5223395Shsul@eecs.umich.edum5.params.clear() 5233478Shsul@eecs.umich.edu 5248803Sgblack@eecs.umich.edu# install the python importer so we can grab stuff from the source 5258803Sgblack@eecs.umich.edu# tree itself. We can't have SimObjects added after this point or 5269793Sakash.bagdia@arm.com# else we won't know about them for the rest of the stuff. 5279793Sakash.bagdia@arm.comimporter = DictImporter(PySource.modules) 5283480Shsul@eecs.umich.edusys.meta_path[0:0] = [ importer ] 5295361Srstrong@cs.ucsd.edu 5305369Ssaidi@eecs.umich.edu# import all sim objects so we can populate the all_objects list 5315361Srstrong@cs.ucsd.edu# make sure that we're working with a list, then let's sort it 5325361Srstrong@cs.ucsd.edufor modname in SimObject.modnames: 5335361Srstrong@cs.ucsd.edu exec('from m5.objects import %s' % modname) 5345369Ssaidi@eecs.umich.edu 5355361Srstrong@cs.ucsd.edu# we need to unload all of the currently imported modules so that they 5365361Srstrong@cs.ucsd.edu# will be re-imported the next time the sconscript is run 5375378Ssaidi@eecs.umich.eduimporter.unload() 5386654Snate@binkert.orgsys.meta_path.remove(importer) 5395361Srstrong@cs.ucsd.edu 5405361Srstrong@cs.ucsd.edusim_objects = m5.SimObject.allClasses 5415361Srstrong@cs.ucsd.eduall_enums = m5.params.allEnums 5425361Srstrong@cs.ucsd.edu 5435361Srstrong@cs.ucsd.eduif m5.SimObject.noCxxHeader: 5445361Srstrong@cs.ucsd.edu print >> sys.stderr, \ 5455361Srstrong@cs.ucsd.edu "warning: At least one SimObject lacks a header specification. " \ 5465361Srstrong@cs.ucsd.edu "This can cause unexpected results in the generated SWIG " \ 5475361Srstrong@cs.ucsd.edu "wrappers." 5485361Srstrong@cs.ucsd.edu 5495361Srstrong@cs.ucsd.edu# Find param types that need to be explicitly wrapped with swig. 5508311Sksewell@umich.edu# These will be recognized because the ParamDesc will have a 5518311Sksewell@umich.edu# swig_decl() method. Most param types are based on types that don't 5525353Svilas.sridharan@gmail.com# need this, either because they're based on native types (like Int) 5538887Sgeoffrey.blake@arm.com# or because they're SimObjects (which get swigged independently). 5548887Sgeoffrey.blake@arm.com# For now the only things handled here are VectorParam types. 5558887Sgeoffrey.blake@arm.comparams_to_swig = {} 5568887Sgeoffrey.blake@arm.comfor name,obj in sorted(sim_objects.iteritems()): 5578887Sgeoffrey.blake@arm.com for param in obj._params.local.values(): 5588211Satgutier@umich.edu # load the ptype attribute now because it depends on the 5598211Satgutier@umich.edu # current version of SimObject.allClasses, but when scons 5608211Satgutier@umich.edu # actually uses the value, all versions of 5618211Satgutier@umich.edu # SimObject.allClasses will have been loaded 5623395Shsul@eecs.umich.edu param.ptype 5635361Srstrong@cs.ucsd.edu 5645369Ssaidi@eecs.umich.edu if not hasattr(param, 'swig_decl'): 5655361Srstrong@cs.ucsd.edu continue 5665361Srstrong@cs.ucsd.edu pname = param.ptype_str 5675361Srstrong@cs.ucsd.edu if pname not in params_to_swig: 5685361Srstrong@cs.ucsd.edu params_to_swig[pname] = param 5695361Srstrong@cs.ucsd.edu 5705378Ssaidi@eecs.umich.edu######################################################################## 5716654Snate@binkert.org# 5725369Ssaidi@eecs.umich.edu# calculate extra dependencies 5735361Srstrong@cs.ucsd.edu# 5745361Srstrong@cs.ucsd.edumodule_depends = ["m5", "m5.SimObject", "m5.params"] 5755361Srstrong@cs.ucsd.edudepends = [ PySource.modules[dep].snode for dep in module_depends ] 5765361Srstrong@cs.ucsd.edudepends.sort(key = lambda x: x.name) 5775361Srstrong@cs.ucsd.edu 5785361Srstrong@cs.ucsd.edu######################################################################## 5795361Srstrong@cs.ucsd.edu# 5805361Srstrong@cs.ucsd.edu# Commands for the basic automatically generated python files 5815361Srstrong@cs.ucsd.edu# 5825361Srstrong@cs.ucsd.edu 58310608Sdam.sunwoo@arm.com# Generate Python file containing a dict specifying the current 58410608Sdam.sunwoo@arm.com# buildEnv flags. 58510608Sdam.sunwoo@arm.comdef makeDefinesPyFile(target, source, env): 5867531Ssteve.reinhardt@amd.com build_env = source[0].get_contents() 5879816Sjthestness@gmail.com 5889816Sjthestness@gmail.com code = code_formatter() 5897531Ssteve.reinhardt@amd.com code(""" 5903395Shsul@eecs.umich.eduimport m5.internal 59110757SCurtis.Dunham@arm.comimport m5.util 59210757SCurtis.Dunham@arm.com 59310757SCurtis.Dunham@arm.combuildEnv = m5.util.SmartDict($build_env) 59410757SCurtis.Dunham@arm.com 59510757SCurtis.Dunham@arm.comcompileDate = m5.internal.core.compileDate 59610757SCurtis.Dunham@arm.com_globals = globals() 59710757SCurtis.Dunham@arm.comfor key,val in m5.internal.core.__dict__.iteritems(): 5989816Sjthestness@gmail.com if key.startswith('flag_'): 5999816Sjthestness@gmail.com flag = key[5:] 6009816Sjthestness@gmail.com _globals[flag] = val 6019816Sjthestness@gmail.comdel _globals 6029816Sjthestness@gmail.com""") 6039816Sjthestness@gmail.com code.write(target[0].abspath) 6049816Sjthestness@gmail.com 6059816Sjthestness@gmail.comdefines_info = Value(build_env) 6069816Sjthestness@gmail.com# Generate a file with all of the compile options in it 6079816Sjthestness@gmail.comenv.Command('python/m5/defines.py', defines_info, 6089816Sjthestness@gmail.com MakeAction(makeDefinesPyFile, Transform("DEFINES", 0))) 6099816Sjthestness@gmail.comPySource('m5', 'python/m5/defines.py') 6109816Sjthestness@gmail.com 6119816Sjthestness@gmail.com# Generate python file containing info about the M5 source code 6129816Sjthestness@gmail.comdef makeInfoPyFile(target, source, env): 6139816Sjthestness@gmail.com code = code_formatter() 6149816Sjthestness@gmail.com for src in source: 6159867Sjthestness@gmail.com data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) 6169867Sjthestness@gmail.com code('$src = ${{repr(data)}}') 6179867Sjthestness@gmail.com code.write(str(target[0])) 6189867Sjthestness@gmail.com 6199867Sjthestness@gmail.com# Generate a file that wraps the basic top level files 6209816Sjthestness@gmail.comenv.Command('python/m5/info.py', 6219816Sjthestness@gmail.com [ '#/COPYING', '#/LICENSE', '#/README', ], 6229816Sjthestness@gmail.com MakeAction(makeInfoPyFile, Transform("INFO"))) 6239816Sjthestness@gmail.comPySource('m5', 'python/m5/info.py') 6249816Sjthestness@gmail.com 6259816Sjthestness@gmail.com######################################################################## 6269816Sjthestness@gmail.com# 6279816Sjthestness@gmail.com# Create all of the SimObject param headers and enum headers 6289816Sjthestness@gmail.com# 6299816Sjthestness@gmail.com 6309816Sjthestness@gmail.comdef createSimObjectParamStruct(target, source, env): 6319816Sjthestness@gmail.com assert len(target) == 1 and len(source) == 1 6329816Sjthestness@gmail.com 6333481Shsul@eecs.umich.edu name = str(source[0].get_contents()) 6345361Srstrong@cs.ucsd.edu obj = sim_objects[name] 6355361Srstrong@cs.ucsd.edu 6365361Srstrong@cs.ucsd.edu code = code_formatter() 6375361Srstrong@cs.ucsd.edu obj.cxx_param_decl(code) 6385361Srstrong@cs.ucsd.edu code.write(target[0].abspath) 6395361Srstrong@cs.ucsd.edu 6405361Srstrong@cs.ucsd.edudef createSimObjectCxxConfig(is_header): 6415361Srstrong@cs.ucsd.edu def body(target, source, env): 6425361Srstrong@cs.ucsd.edu assert len(target) == 1 and len(source) == 1 6435361Srstrong@cs.ucsd.edu 6445361Srstrong@cs.ucsd.edu name = str(source[0].get_contents()) 6457766Sgblack@eecs.umich.edu obj = sim_objects[name] 6463395Shsul@eecs.umich.edu 6479521SAndreas.Sandberg@ARM.com code = code_formatter() 6483395Shsul@eecs.umich.edu obj.cxx_config_param_file(code, is_header) 6493481Shsul@eecs.umich.edu code.write(target[0].abspath) 6505361Srstrong@cs.ucsd.edu return body 6515361Srstrong@cs.ucsd.edu 6525361Srstrong@cs.ucsd.edudef createParamSwigWrapper(target, source, env): 6535361Srstrong@cs.ucsd.edu assert len(target) == 1 and len(source) == 1 6545361Srstrong@cs.ucsd.edu 6555361Srstrong@cs.ucsd.edu name = str(source[0].get_contents()) 6565361Srstrong@cs.ucsd.edu param = params_to_swig[name] 6579151Satgutier@umich.edu 6587766Sgblack@eecs.umich.edu code = code_formatter() 6595361Srstrong@cs.ucsd.edu param.swig_decl(code) 6605361Srstrong@cs.ucsd.edu code.write(target[0].abspath) 6619521SAndreas.Sandberg@ARM.com 6623395Shsul@eecs.umich.edudef createEnumStrings(target, source, env): 6637489Ssteve.reinhardt@amd.com assert len(target) == 1 and len(source) == 1 6647489Ssteve.reinhardt@amd.com 6657489Ssteve.reinhardt@amd.com name = str(source[0].get_contents()) 6667489Ssteve.reinhardt@amd.com obj = all_enums[name] 66710608Sdam.sunwoo@arm.com 66810608Sdam.sunwoo@arm.com code = code_formatter() 66910608Sdam.sunwoo@arm.com obj.cxx_def(code) 6707489Ssteve.reinhardt@amd.com code.write(target[0].abspath) 6717489Ssteve.reinhardt@amd.com 6727489Ssteve.reinhardt@amd.comdef createEnumDecls(target, source, env): 6737489Ssteve.reinhardt@amd.com assert len(target) == 1 and len(source) == 1 6747489Ssteve.reinhardt@amd.com 6755369Ssaidi@eecs.umich.edu name = str(source[0].get_contents()) 6769140Snilay@cs.wisc.edu obj = all_enums[name] 6779140Snilay@cs.wisc.edu 6789140Snilay@cs.wisc.edu code = code_formatter() 6799140Snilay@cs.wisc.edu obj.cxx_decl(code) 6809606Snilay@cs.wisc.edu code.write(target[0].abspath) 68110608Sdam.sunwoo@arm.com 68210608Sdam.sunwoo@arm.comdef createEnumSwigWrapper(target, source, env): 68310608Sdam.sunwoo@arm.com assert len(target) == 1 and len(source) == 1 68410608Sdam.sunwoo@arm.com 68510608Sdam.sunwoo@arm.com name = str(source[0].get_contents()) 68610608Sdam.sunwoo@arm.com obj = all_enums[name] 68710608Sdam.sunwoo@arm.com 68810608Sdam.sunwoo@arm.com code = code_formatter() 68910608Sdam.sunwoo@arm.com obj.swig_decl(code) 6909140Snilay@cs.wisc.edu code.write(target[0].abspath) 6919151Satgutier@umich.edu 6929151Satgutier@umich.edudef createSimObjectSwigWrapper(target, source, env): 6939151Satgutier@umich.edu name = source[0].get_contents() 6949151Satgutier@umich.edu obj = sim_objects[name] 6959140Snilay@cs.wisc.edu 6969140Snilay@cs.wisc.edu code = code_formatter() 6979151Satgutier@umich.edu obj.swig_decl(code) 6989460Ssaidi@eecs.umich.edu code.write(target[0].abspath) 6999151Satgutier@umich.edu 7009151Satgutier@umich.edu# dummy target for generated code 7019460Ssaidi@eecs.umich.edu# we start out with all the Source files so they get copied to build/*/ also. 7023395Shsul@eecs.umich.eduSWIG = env.Dummy('swig', [s.tnode for s in Source.get()]) 7039460Ssaidi@eecs.umich.edu 7046776SBrad.Beckmann@amd.com# Generate all of the SimObject param C++ struct header files 7057525Ssteve.reinhardt@amd.comparams_hh_files = [] 7069457Svilanova@ac.upc.edufor name,simobj in sorted(sim_objects.iteritems()): 7079494Sandreas@sandberg.pp.se py_source = PySource.modules[simobj.__module__] 7089494Sandreas@sandberg.pp.se extra_deps = [ py_source.tnode ] 709 710 hh_file = File('params/%s.hh' % name) 711 params_hh_files.append(hh_file) 712 env.Command(hh_file, Value(name), 713 MakeAction(createSimObjectParamStruct, Transform("SO PARAM"))) 714 env.Depends(hh_file, depends + extra_deps) 715 env.Depends(SWIG, hh_file) 716 717# C++ parameter description files 718if GetOption('with_cxx_config'): 719 for name,simobj in sorted(sim_objects.iteritems()): 720 py_source = PySource.modules[simobj.__module__] 721 extra_deps = [ py_source.tnode ] 722 723 cxx_config_hh_file = File('cxx_config/%s.hh' % name) 724 cxx_config_cc_file = File('cxx_config/%s.cc' % name) 725 env.Command(cxx_config_hh_file, Value(name), 726 MakeAction(createSimObjectCxxConfig(True), 727 Transform("CXXCPRHH"))) 728 env.Command(cxx_config_cc_file, Value(name), 729 MakeAction(createSimObjectCxxConfig(False), 730 Transform("CXXCPRCC"))) 731 env.Depends(cxx_config_hh_file, depends + extra_deps + 732 [File('params/%s.hh' % name), File('sim/cxx_config.hh')]) 733 env.Depends(cxx_config_cc_file, depends + extra_deps + 734 [cxx_config_hh_file]) 735 Source(cxx_config_cc_file) 736 737 cxx_config_init_cc_file = File('cxx_config/init.cc') 738 739 def createCxxConfigInitCC(target, source, env): 740 assert len(target) == 1 and len(source) == 1 741 742 code = code_formatter() 743 744 for name,simobj in sorted(sim_objects.iteritems()): 745 if not hasattr(simobj, 'abstract') or not simobj.abstract: 746 code('#include "cxx_config/${name}.hh"') 747 code() 748 code('void cxxConfigInit()') 749 code('{') 750 code.indent() 751 for name,simobj in sorted(sim_objects.iteritems()): 752 not_abstract = not hasattr(simobj, 'abstract') or \ 753 not simobj.abstract 754 if not_abstract and 'type' in simobj.__dict__: 755 code('cxx_config_directory["${name}"] = ' 756 '${name}CxxConfigParams::makeDirectoryEntry();') 757 code.dedent() 758 code('}') 759 code.write(target[0].abspath) 760 761 py_source = PySource.modules[simobj.__module__] 762 extra_deps = [ py_source.tnode ] 763 env.Command(cxx_config_init_cc_file, Value(name), 764 MakeAction(createCxxConfigInitCC, Transform("CXXCINIT"))) 765 cxx_param_hh_files = ["cxx_config/%s.hh" % simobj 766 for name,simobj in sorted(sim_objects.iteritems()) 767 if not hasattr(simobj, 'abstract') or not simobj.abstract] 768 Depends(cxx_config_init_cc_file, cxx_param_hh_files + 769 [File('sim/cxx_config.hh')]) 770 Source(cxx_config_init_cc_file) 771 772# Generate any needed param SWIG wrapper files 773params_i_files = [] 774for name,param in sorted(params_to_swig.iteritems()): 775 i_file = File('python/m5/internal/%s.i' % (param.swig_module_name())) 776 params_i_files.append(i_file) 777 env.Command(i_file, Value(name), 778 MakeAction(createParamSwigWrapper, Transform("SW PARAM"))) 779 env.Depends(i_file, depends) 780 env.Depends(SWIG, i_file) 781 SwigSource('m5.internal', i_file) 782 783# Generate all enum header files 784for name,enum in sorted(all_enums.iteritems()): 785 py_source = PySource.modules[enum.__module__] 786 extra_deps = [ py_source.tnode ] 787 788 cc_file = File('enums/%s.cc' % name) 789 env.Command(cc_file, Value(name), 790 MakeAction(createEnumStrings, Transform("ENUM STR"))) 791 env.Depends(cc_file, depends + extra_deps) 792 env.Depends(SWIG, cc_file) 793 Source(cc_file) 794 795 hh_file = File('enums/%s.hh' % name) 796 env.Command(hh_file, Value(name), 797 MakeAction(createEnumDecls, Transform("ENUMDECL"))) 798 env.Depends(hh_file, depends + extra_deps) 799 env.Depends(SWIG, hh_file) 800 801 i_file = File('python/m5/internal/enum_%s.i' % name) 802 env.Command(i_file, Value(name), 803 MakeAction(createEnumSwigWrapper, Transform("ENUMSWIG"))) 804 env.Depends(i_file, depends + extra_deps) 805 env.Depends(SWIG, i_file) 806 SwigSource('m5.internal', i_file) 807 808# Generate SimObject SWIG wrapper files 809for name,simobj in sorted(sim_objects.iteritems()): 810 py_source = PySource.modules[simobj.__module__] 811 extra_deps = [ py_source.tnode ] 812 i_file = File('python/m5/internal/param_%s.i' % name) 813 env.Command(i_file, Value(name), 814 MakeAction(createSimObjectSwigWrapper, Transform("SO SWIG"))) 815 env.Depends(i_file, depends + extra_deps) 816 SwigSource('m5.internal', i_file) 817 818# Generate the main swig init file 819def makeEmbeddedSwigInit(target, source, env): 820 code = code_formatter() 821 module = source[0].get_contents() 822 code('''\ 823#include "sim/init.hh" 824 825extern "C" { 826 void init_${module}(); 827} 828 829EmbeddedSwig embed_swig_${module}(init_${module}); 830''') 831 code.write(str(target[0])) 832 833# Build all swig modules 834for swig in SwigSource.all: 835 env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode, 836 MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' 837 '-o ${TARGETS[0]} $SOURCES', Transform("SWIG"))) 838 cc_file = str(swig.tnode) 839 init_file = '%s/%s_init.cc' % (dirname(cc_file), basename(cc_file)) 840 env.Command(init_file, Value(swig.module), 841 MakeAction(makeEmbeddedSwigInit, Transform("EMBED SW"))) 842 env.Depends(SWIG, init_file) 843 Source(init_file, **swig.guards) 844 845# Build all protocol buffers if we have got protoc and protobuf available 846if env['HAVE_PROTOBUF']: 847 for proto in ProtoBuf.all: 848 # Use both the source and header as the target, and the .proto 849 # file as the source. When executing the protoc compiler, also 850 # specify the proto_path to avoid having the generated files 851 # include the path. 852 env.Command([proto.cc_file, proto.hh_file], proto.tnode, 853 MakeAction('$PROTOC --cpp_out ${TARGET.dir} ' 854 '--proto_path ${SOURCE.dir} $SOURCE', 855 Transform("PROTOC"))) 856 857 env.Depends(SWIG, [proto.cc_file, proto.hh_file]) 858 # Add the C++ source file 859 Source(proto.cc_file, **proto.guards) 860elif ProtoBuf.all: 861 print 'Got protobuf to build, but lacks support!' 862 Exit(1) 863 864# 865# Handle debug flags 866# 867def makeDebugFlagCC(target, source, env): 868 assert(len(target) == 1 and len(source) == 1) 869 870 code = code_formatter() 871 872 # delay definition of CompoundFlags until after all the definition 873 # of all constituent SimpleFlags 874 comp_code = code_formatter() 875 876 # file header 877 code(''' 878/* 879 * DO NOT EDIT THIS FILE! Automatically generated by SCons. 880 */ 881 882#include "base/debug.hh" 883 884namespace Debug { 885 886''') 887 888 for name, flag in sorted(source[0].read().iteritems()): 889 n, compound, desc = flag 890 assert n == name 891 892 if not compound: 893 code('SimpleFlag $name("$name", "$desc");') 894 else: 895 comp_code('CompoundFlag $name("$name", "$desc",') 896 comp_code.indent() 897 last = len(compound) - 1 898 for i,flag in enumerate(compound): 899 if i != last: 900 comp_code('&$flag,') 901 else: 902 comp_code('&$flag);') 903 comp_code.dedent() 904 905 code.append(comp_code) 906 code() 907 code('} // namespace Debug') 908 909 code.write(str(target[0])) 910 911def makeDebugFlagHH(target, source, env): 912 assert(len(target) == 1 and len(source) == 1) 913 914 val = eval(source[0].get_contents()) 915 name, compound, desc = val 916 917 code = code_formatter() 918 919 # file header boilerplate 920 code('''\ 921/* 922 * DO NOT EDIT THIS FILE! Automatically generated by SCons. 923 */ 924 925#ifndef __DEBUG_${name}_HH__ 926#define __DEBUG_${name}_HH__ 927 928namespace Debug { 929''') 930 931 if compound: 932 code('class CompoundFlag;') 933 code('class SimpleFlag;') 934 935 if compound: 936 code('extern CompoundFlag $name;') 937 for flag in compound: 938 code('extern SimpleFlag $flag;') 939 else: 940 code('extern SimpleFlag $name;') 941 942 code(''' 943} 944 945#endif // __DEBUG_${name}_HH__ 946''') 947 948 code.write(str(target[0])) 949 950for name,flag in sorted(debug_flags.iteritems()): 951 n, compound, desc = flag 952 assert n == name 953 954 hh_file = 'debug/%s.hh' % name 955 env.Command(hh_file, Value(flag), 956 MakeAction(makeDebugFlagHH, Transform("TRACING", 0))) 957 env.Depends(SWIG, hh_file) 958 959env.Command('debug/flags.cc', Value(debug_flags), 960 MakeAction(makeDebugFlagCC, Transform("TRACING", 0))) 961env.Depends(SWIG, 'debug/flags.cc') 962Source('debug/flags.cc') 963 964# version tags 965tags = \ 966env.Command('sim/tags.cc', None, 967 MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET', 968 Transform("VER TAGS"))) 969env.AlwaysBuild(tags) 970 971# Embed python files. All .py files that have been indicated by a 972# PySource() call in a SConscript need to be embedded into the M5 973# library. To do that, we compile the file to byte code, marshal the 974# byte code, compress it, and then generate a c++ file that 975# inserts the result into an array. 976def embedPyFile(target, source, env): 977 def c_str(string): 978 if string is None: 979 return "0" 980 return '"%s"' % string 981 982 '''Action function to compile a .py into a code object, marshal 983 it, compress it, and stick it into an asm file so the code appears 984 as just bytes with a label in the data section''' 985 986 src = file(str(source[0]), 'r').read() 987 988 pysource = PySource.tnodes[source[0]] 989 compiled = compile(src, pysource.abspath, 'exec') 990 marshalled = marshal.dumps(compiled) 991 compressed = zlib.compress(marshalled) 992 data = compressed 993 sym = pysource.symname 994 995 code = code_formatter() 996 code('''\ 997#include "sim/init.hh" 998 999namespace { 1000 1001const uint8_t data_${sym}[] = { 1002''') 1003 code.indent() 1004 step = 16 1005 for i in xrange(0, len(data), step): 1006 x = array.array('B', data[i:i+step]) 1007 code(''.join('%d,' % d for d in x)) 1008 code.dedent() 1009 1010 code('''}; 1011 1012EmbeddedPython embedded_${sym}( 1013 ${{c_str(pysource.arcname)}}, 1014 ${{c_str(pysource.abspath)}}, 1015 ${{c_str(pysource.modpath)}}, 1016 data_${sym}, 1017 ${{len(data)}}, 1018 ${{len(marshalled)}}); 1019 1020} // anonymous namespace 1021''') 1022 code.write(str(target[0])) 1023 1024for source in PySource.all: 1025 env.Command(source.cpp, source.tnode, 1026 MakeAction(embedPyFile, Transform("EMBED PY"))) 1027 env.Depends(SWIG, source.cpp) 1028 Source(source.cpp, skip_no_python=True) 1029 1030######################################################################## 1031# 1032# Define binaries. Each different build type (debug, opt, etc.) gets 1033# a slightly different build environment. 1034# 1035 1036# List of constructed environments to pass back to SConstruct 1037date_source = Source('base/date.cc', skip_lib=True) 1038 1039# Capture this directory for the closure makeEnv, otherwise when it is 1040# called, it won't know what directory it should use. 1041variant_dir = Dir('.').path 1042def variant(*path): 1043 return os.path.join(variant_dir, *path) 1044def variantd(*path): 1045 return variant(*path)+'/' 1046 1047# Function to create a new build environment as clone of current 1048# environment 'env' with modified object suffix and optional stripped 1049# binary. Additional keyword arguments are appended to corresponding 1050# build environment vars. 1051def makeEnv(env, label, objsfx, strip = False, **kwargs): 1052 # SCons doesn't know to append a library suffix when there is a '.' in the 1053 # name. Use '_' instead. 1054 libname = variant('gem5_' + label) 1055 exename = variant('gem5.' + label) 1056 secondary_exename = variant('m5.' + label) 1057 1058 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') 1059 new_env.Label = label 1060 new_env.Append(**kwargs) 1061 1062 swig_env = new_env.Clone() 1063 1064 # Both gcc and clang have issues with unused labels and values in 1065 # the SWIG generated code 1066 swig_env.Append(CCFLAGS=['-Wno-unused-label', '-Wno-unused-value']) 1067 1068 if env['GCC']: 1069 # Depending on the SWIG version, we also need to supress 1070 # warnings about uninitialized variables and missing field 1071 # initializers. 1072 swig_env.Append(CCFLAGS=['-Wno-uninitialized', 1073 '-Wno-missing-field-initializers', 1074 '-Wno-unused-but-set-variable', 1075 '-Wno-maybe-uninitialized', 1076 '-Wno-type-limits']) 1077 1078 # Only gcc >= 4.9 supports UBSan, so check both the version 1079 # and the command-line option before adding the compiler and 1080 # linker flags. 1081 if GetOption('with_ubsan') and \ 1082 compareVersions(env['GCC_VERSION'], '4.9') >= 0: 1083 new_env.Append(CCFLAGS='-fsanitize=undefined') 1084 new_env.Append(LINKFLAGS='-fsanitize=undefined') 1085 1086 # The address sanitizer is available for gcc >= 4.8 1087 if GetOption('with_asan') and \ 1088 compareVersions(env['GCC_VERSION'], '4.8') >= 0: 1089 new_env.Append(CCFLAGS='-fsanitize=address') 1090 new_env.Append(LINKFLAGS='-fsanitize=address') 1091 1092 if env['CLANG']: 1093 swig_env.Append(CCFLAGS=['-Wno-sometimes-uninitialized', 1094 '-Wno-deprecated-register', 1095 '-Wno-tautological-compare']) 1096 1097 # We require clang >= 3.1, so there is no need to check any 1098 # versions here. 1099 if GetOption('with_ubsan'): 1100 new_env.Append(CCFLAGS='-fsanitize=undefined') 1101 new_env.Append(LINKFLAGS='-fsanitize=undefined') 1102 1103 if GetOption('with_asan'): 1104 new_env.Append(CCFLAGS='-fsanitize=address') 1105 new_env.Append(LINKFLAGS='-fsanitize=address') 1106 1107 werror_env = new_env.Clone() 1108 # Treat warnings as errors but white list some warnings that we 1109 # want to allow (e.g., deprecation warnings). 1110 werror_env.Append(CCFLAGS=['-Werror', 1111 '-Wno-error=deprecated-declarations', 1112 '-Wno-error=deprecated', 1113 ]) 1114 1115 def make_obj(source, static, extra_deps = None): 1116 '''This function adds the specified source to the correct 1117 build environment, and returns the corresponding SCons Object 1118 nodes''' 1119 1120 if source.swig: 1121 env = swig_env 1122 elif source.Werror: 1123 env = werror_env 1124 else: 1125 env = new_env 1126 1127 if static: 1128 obj = env.StaticObject(source.tnode) 1129 else: 1130 obj = env.SharedObject(source.tnode) 1131 1132 if extra_deps: 1133 env.Depends(obj, extra_deps) 1134 1135 return obj 1136 1137 lib_guards = {'main': False, 'skip_lib': False} 1138 1139 # Without Python, leave out all SWIG and Python content from the 1140 # library builds. The option doesn't affect gem5 built as a program 1141 if GetOption('without_python'): 1142 lib_guards['skip_no_python'] = False 1143 1144 static_objs = [ make_obj(s, True) for s in Source.get(**lib_guards) ] 1145 shared_objs = [ make_obj(s, False) for s in Source.get(**lib_guards) ] 1146 1147 static_date = make_obj(date_source, static=True, extra_deps=static_objs) 1148 static_objs.append(static_date) 1149 1150 shared_date = make_obj(date_source, static=False, extra_deps=shared_objs) 1151 shared_objs.append(shared_date) 1152 1153 # First make a library of everything but main() so other programs can 1154 # link against m5. 1155 static_lib = new_env.StaticLibrary(libname, static_objs) 1156 shared_lib = new_env.SharedLibrary(libname, shared_objs) 1157 1158 # Now link a stub with main() and the static library. 1159 main_objs = [ make_obj(s, True) for s in Source.get(main=True) ] 1160 1161 for test in UnitTest.all: 1162 flags = { test.target : True } 1163 test_sources = Source.get(**flags) 1164 test_objs = [ make_obj(s, static=True) for s in test_sources ] 1165 if test.main: 1166 test_objs += main_objs 1167 path = variant('unittest/%s.%s' % (test.target, label)) 1168 new_env.Program(path, test_objs + static_objs) 1169 1170 progname = exename 1171 if strip: 1172 progname += '.unstripped' 1173 1174 targets = new_env.Program(progname, main_objs + static_objs) 1175 1176 if strip: 1177 if sys.platform == 'sunos5': 1178 cmd = 'cp $SOURCE $TARGET; strip $TARGET' 1179 else: 1180 cmd = 'strip $SOURCE -o $TARGET' 1181 targets = new_env.Command(exename, progname, 1182 MakeAction(cmd, Transform("STRIP"))) 1183 1184 new_env.Command(secondary_exename, exename, 1185 MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK"))) 1186 1187 new_env.M5Binary = targets[0] 1188 return new_env 1189 1190# Start out with the compiler flags common to all compilers, 1191# i.e. they all use -g for opt and -g -pg for prof 1192ccflags = {'debug' : [], 'opt' : ['-g'], 'fast' : [], 'prof' : ['-g', '-pg'], 1193 'perf' : ['-g']} 1194 1195# Start out with the linker flags common to all linkers, i.e. -pg for 1196# prof, and -lprofiler for perf. The -lprofile flag is surrounded by 1197# no-as-needed and as-needed as the binutils linker is too clever and 1198# simply doesn't link to the library otherwise. 1199ldflags = {'debug' : [], 'opt' : [], 'fast' : [], 'prof' : ['-pg'], 1200 'perf' : ['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']} 1201 1202# For Link Time Optimization, the optimisation flags used to compile 1203# individual files are decoupled from those used at link time 1204# (i.e. you can compile with -O3 and perform LTO with -O0), so we need 1205# to also update the linker flags based on the target. 1206if env['GCC']: 1207 if sys.platform == 'sunos5': 1208 ccflags['debug'] += ['-gstabs+'] 1209 else: 1210 ccflags['debug'] += ['-ggdb3'] 1211 ldflags['debug'] += ['-O0'] 1212 # opt, fast, prof and perf all share the same cc flags, also add 1213 # the optimization to the ldflags as LTO defers the optimization 1214 # to link time 1215 for target in ['opt', 'fast', 'prof', 'perf']: 1216 ccflags[target] += ['-O3'] 1217 ldflags[target] += ['-O3'] 1218 1219 ccflags['fast'] += env['LTO_CCFLAGS'] 1220 ldflags['fast'] += env['LTO_LDFLAGS'] 1221elif env['CLANG']: 1222 ccflags['debug'] += ['-g', '-O0'] 1223 # opt, fast, prof and perf all share the same cc flags 1224 for target in ['opt', 'fast', 'prof', 'perf']: 1225 ccflags[target] += ['-O3'] 1226else: 1227 print 'Unknown compiler, please fix compiler options' 1228 Exit(1) 1229 1230 1231# To speed things up, we only instantiate the build environments we 1232# need. We try to identify the needed environment for each target; if 1233# we can't, we fall back on instantiating all the environments just to 1234# be safe. 1235target_types = ['debug', 'opt', 'fast', 'prof', 'perf'] 1236obj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof', 1237 'gpo' : 'perf'} 1238 1239def identifyTarget(t): 1240 ext = t.split('.')[-1] 1241 if ext in target_types: 1242 return ext 1243 if obj2target.has_key(ext): 1244 return obj2target[ext] 1245 match = re.search(r'/tests/([^/]+)/', t) 1246 if match and match.group(1) in target_types: 1247 return match.group(1) 1248 return 'all' 1249 1250needed_envs = [identifyTarget(target) for target in BUILD_TARGETS] 1251if 'all' in needed_envs: 1252 needed_envs += target_types 1253 1254def makeEnvirons(target, source, env): 1255 # cause any later Source() calls to be fatal, as a diagnostic. 1256 Source.done() 1257 1258 envList = [] 1259 1260 # Debug binary 1261 if 'debug' in needed_envs: 1262 envList.append( 1263 makeEnv(env, 'debug', '.do', 1264 CCFLAGS = Split(ccflags['debug']), 1265 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'], 1266 LINKFLAGS = Split(ldflags['debug']))) 1267 1268 # Optimized binary 1269 if 'opt' in needed_envs: 1270 envList.append( 1271 makeEnv(env, 'opt', '.o', 1272 CCFLAGS = Split(ccflags['opt']), 1273 CPPDEFINES = ['TRACING_ON=1'], 1274 LINKFLAGS = Split(ldflags['opt']))) 1275 1276 # "Fast" binary 1277 if 'fast' in needed_envs: 1278 envList.append( 1279 makeEnv(env, 'fast', '.fo', strip = True, 1280 CCFLAGS = Split(ccflags['fast']), 1281 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1282 LINKFLAGS = Split(ldflags['fast']))) 1283 1284 # Profiled binary using gprof 1285 if 'prof' in needed_envs: 1286 envList.append( 1287 makeEnv(env, 'prof', '.po', 1288 CCFLAGS = Split(ccflags['prof']), 1289 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1290 LINKFLAGS = Split(ldflags['prof']))) 1291 1292 # Profiled binary using google-pprof 1293 if 'perf' in needed_envs: 1294 envList.append( 1295 makeEnv(env, 'perf', '.gpo', 1296 CCFLAGS = Split(ccflags['perf']), 1297 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1298 LINKFLAGS = Split(ldflags['perf']))) 1299 1300 # Set up the regression tests for each build. 1301 for e in envList: 1302 SConscript(os.path.join(env.root.abspath, 'tests', 'SConscript'), 1303 variant_dir = variantd('tests', e.Label), 1304 exports = { 'env' : e }, duplicate = False) 1305 1306# The MakeEnvirons Builder defers the full dependency collection until 1307# after processing the ISA definition (due to dynamically generated 1308# source files). Add this dependency to all targets so they will wait 1309# until the environments are completely set up. Otherwise, a second 1310# process (e.g. -j2 or higher) will try to compile the requested target, 1311# not know how, and fail. 1312env.Append(BUILDERS = {'MakeEnvirons' : 1313 Builder(action=MakeAction(makeEnvirons, 1314 Transform("ENVIRONS", 1)))}) 1315 1316isa_target = env['PHONY_BASE'] + '-deps' 1317environs = env['PHONY_BASE'] + '-environs' 1318env.Depends('#all-deps', isa_target) 1319env.Depends('#all-environs', environs) 1320env.ScanISA(isa_target, File('arch/%s/generated/inc.d' % env['TARGET_ISA'])) 1321envSetup = env.MakeEnvirons(environs, isa_target) 1322 1323# make sure no -deps targets occur before all ISAs are complete 1324env.Depends(isa_target, '#all-isas') 1325# likewise for -environs targets and all the -deps targets 1326env.Depends(environs, '#all-deps') 1327