SConscript revision 13730
1955SN/A# -*- mode:python -*- 2955SN/A 311408Sandreas.sandberg@arm.com# Copyright (c) 2018 ARM Limited 49812Sandreas.hansson@arm.com# 59812Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall 69812Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual 79812Sandreas.hansson@arm.com# property including but not limited to intellectual property relating 89812Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software 99812Sandreas.hansson@arm.com# licensed hereunder. You may use the software subject to the license 109812Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated 119812Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software, 129812Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form. 139812Sandreas.hansson@arm.com# 149812Sandreas.hansson@arm.com# Copyright (c) 2004-2005 The Regents of The University of Michigan 157816Ssteve.reinhardt@amd.com# All rights reserved. 165871Snate@binkert.org# 171762SN/A# Redistribution and use in source and binary forms, with or without 18955SN/A# modification, are permitted provided that the following conditions are 19955SN/A# met: redistributions of source code must retain the above copyright 20955SN/A# notice, this list of conditions and the following disclaimer; 21955SN/A# redistributions in binary form must reproduce the above copyright 22955SN/A# notice, this list of conditions and the following disclaimer in the 23955SN/A# documentation and/or other materials provided with the distribution; 24955SN/A# neither the name of the copyright holders nor the names of its 25955SN/A# contributors may be used to endorse or promote products derived from 26955SN/A# this software without specific prior written permission. 27955SN/A# 28955SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29955SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30955SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31955SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32955SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33955SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34955SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35955SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36955SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37955SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38955SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39955SN/A# 40955SN/A# Authors: Nathan Binkert 41955SN/A 422665Ssaidi@eecs.umich.edufrom __future__ import print_function 432665Ssaidi@eecs.umich.edu 445863Snate@binkert.orgimport array 45955SN/Aimport bisect 46955SN/Aimport functools 47955SN/Aimport imp 48955SN/Aimport os 49955SN/Aimport re 508878Ssteve.reinhardt@amd.comimport sys 512632Sstever@eecs.umich.eduimport zlib 528878Ssteve.reinhardt@amd.com 532632Sstever@eecs.umich.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath 54955SN/A 558878Ssteve.reinhardt@amd.comimport SCons 562632Sstever@eecs.umich.edu 572761Sstever@eecs.umich.edufrom gem5_scons import Transform 582632Sstever@eecs.umich.edu 592632Sstever@eecs.umich.edu# This file defines how to build a particular configuration of gem5 602632Sstever@eecs.umich.edu# based on variable settings in the 'env' build environment. 612761Sstever@eecs.umich.edu 622761Sstever@eecs.umich.eduImport('*') 632761Sstever@eecs.umich.edu 648878Ssteve.reinhardt@amd.com# Children need to see the environment 658878Ssteve.reinhardt@amd.comExport('env') 662761Sstever@eecs.umich.edu 672761Sstever@eecs.umich.edubuild_env = [(opt, env[opt]) for opt in export_vars] 682761Sstever@eecs.umich.edu 692761Sstever@eecs.umich.edufrom m5.util import code_formatter, compareVersions 702761Sstever@eecs.umich.edu 718878Ssteve.reinhardt@amd.com######################################################################## 728878Ssteve.reinhardt@amd.com# Code for adding source files of various types 732632Sstever@eecs.umich.edu# 742632Sstever@eecs.umich.edu# When specifying a source file of some type, a set of tags can be 758878Ssteve.reinhardt@amd.com# specified for that file. 768878Ssteve.reinhardt@amd.com 772632Sstever@eecs.umich.educlass SourceFilter(object): 78955SN/A def __init__(self, predicate): 79955SN/A self.predicate = predicate 80955SN/A 815863Snate@binkert.org def __or__(self, other): 825863Snate@binkert.org return SourceFilter(lambda tags: self.predicate(tags) or 835863Snate@binkert.org other.predicate(tags)) 845863Snate@binkert.org 855863Snate@binkert.org def __and__(self, other): 865863Snate@binkert.org return SourceFilter(lambda tags: self.predicate(tags) and 875863Snate@binkert.org other.predicate(tags)) 885863Snate@binkert.org 895863Snate@binkert.orgdef with_tags_that(predicate): 905863Snate@binkert.org '''Return a list of sources with tags that satisfy a predicate.''' 915863Snate@binkert.org return SourceFilter(predicate) 928878Ssteve.reinhardt@amd.com 935863Snate@binkert.orgdef with_any_tags(*tags): 945863Snate@binkert.org '''Return a list of sources with any of the supplied tags.''' 955863Snate@binkert.org return SourceFilter(lambda stags: len(set(tags) & stags) > 0) 969812Sandreas.hansson@arm.com 979812Sandreas.hansson@arm.comdef with_all_tags(*tags): 985863Snate@binkert.org '''Return a list of sources with all of the supplied tags.''' 999812Sandreas.hansson@arm.com return SourceFilter(lambda stags: set(tags) <= stags) 1005863Snate@binkert.org 1015863Snate@binkert.orgdef with_tag(tag): 1025863Snate@binkert.org '''Return a list of sources with the supplied tag.''' 1039812Sandreas.hansson@arm.com return SourceFilter(lambda stags: tag in stags) 1049812Sandreas.hansson@arm.com 1055863Snate@binkert.orgdef without_tags(*tags): 1065863Snate@binkert.org '''Return a list of sources without any of the supplied tags.''' 1078878Ssteve.reinhardt@amd.com return SourceFilter(lambda stags: len(set(tags) & stags) == 0) 1085863Snate@binkert.org 1095863Snate@binkert.orgdef without_tag(tag): 1105863Snate@binkert.org '''Return a list of sources with the supplied tag.''' 1116654Snate@binkert.org return SourceFilter(lambda stags: tag not in stags) 11210196SCurtis.Dunham@arm.com 113955SN/Asource_filter_factories = { 1145396Ssaidi@eecs.umich.edu 'with_tags_that': with_tags_that, 11511401Sandreas.sandberg@arm.com 'with_any_tags': with_any_tags, 1165863Snate@binkert.org 'with_all_tags': with_all_tags, 1175863Snate@binkert.org 'with_tag': with_tag, 1184202Sbinkertn@umich.edu 'without_tags': without_tags, 1195863Snate@binkert.org 'without_tag': without_tag, 1205863Snate@binkert.org} 1215863Snate@binkert.org 1225863Snate@binkert.orgExport(source_filter_factories) 123955SN/A 1246654Snate@binkert.orgclass SourceList(list): 1255273Sstever@gmail.com def apply_filter(self, f): 1265871Snate@binkert.org def match(source): 1275273Sstever@gmail.com return f.predicate(source.tags) 1286655Snate@binkert.org return SourceList(filter(match, self)) 1298878Ssteve.reinhardt@amd.com 1306655Snate@binkert.org def __getattr__(self, name): 1316655Snate@binkert.org func = source_filter_factories.get(name, None) 1329219Spower.jg@gmail.com if not func: 1336655Snate@binkert.org raise AttributeError 1345871Snate@binkert.org 1356654Snate@binkert.org @functools.wraps(func) 1368947Sandreas.hansson@arm.com def wrapper(*args, **kwargs): 1375396Ssaidi@eecs.umich.edu return self.apply_filter(func(*args, **kwargs)) 1388120Sgblack@eecs.umich.edu return wrapper 1398120Sgblack@eecs.umich.edu 1408120Sgblack@eecs.umich.educlass SourceMeta(type): 1418120Sgblack@eecs.umich.edu '''Meta class for source files that keeps track of all files of a 1428120Sgblack@eecs.umich.edu particular type.''' 1438120Sgblack@eecs.umich.edu def __init__(cls, name, bases, dict): 1448120Sgblack@eecs.umich.edu super(SourceMeta, cls).__init__(name, bases, dict) 1458120Sgblack@eecs.umich.edu cls.all = SourceList() 1468879Ssteve.reinhardt@amd.com 1478879Ssteve.reinhardt@amd.comclass SourceFile(object): 1488879Ssteve.reinhardt@amd.com '''Base object that encapsulates the notion of a source file. 1498879Ssteve.reinhardt@amd.com This includes, the source node, target node, various manipulations 1508879Ssteve.reinhardt@amd.com of those. A source file also specifies a set of tags which 1518879Ssteve.reinhardt@amd.com describing arbitrary properties of the source file.''' 1528879Ssteve.reinhardt@amd.com __metaclass__ = SourceMeta 1538879Ssteve.reinhardt@amd.com 1548879Ssteve.reinhardt@amd.com static_objs = {} 1558879Ssteve.reinhardt@amd.com shared_objs = {} 1568879Ssteve.reinhardt@amd.com 1578879Ssteve.reinhardt@amd.com def __init__(self, source, tags=None, add_tags=None): 1588879Ssteve.reinhardt@amd.com if tags is None: 1598120Sgblack@eecs.umich.edu tags='gem5 lib' 1608120Sgblack@eecs.umich.edu if isinstance(tags, basestring): 1618120Sgblack@eecs.umich.edu tags = set([tags]) 1628120Sgblack@eecs.umich.edu if not isinstance(tags, set): 1638120Sgblack@eecs.umich.edu tags = set(tags) 1648120Sgblack@eecs.umich.edu self.tags = tags 1658120Sgblack@eecs.umich.edu 1668120Sgblack@eecs.umich.edu if add_tags: 1678120Sgblack@eecs.umich.edu if isinstance(add_tags, basestring): 1688120Sgblack@eecs.umich.edu add_tags = set([add_tags]) 1698120Sgblack@eecs.umich.edu if not isinstance(add_tags, set): 1708120Sgblack@eecs.umich.edu add_tags = set(add_tags) 1718120Sgblack@eecs.umich.edu self.tags |= add_tags 1728120Sgblack@eecs.umich.edu 1738879Ssteve.reinhardt@amd.com tnode = source 1748879Ssteve.reinhardt@amd.com if not isinstance(source, SCons.Node.FS.File): 1758879Ssteve.reinhardt@amd.com tnode = File(source) 1768879Ssteve.reinhardt@amd.com 17710458Sandreas.hansson@arm.com self.tnode = tnode 17810458Sandreas.hansson@arm.com self.snode = tnode.srcnode() 17910458Sandreas.hansson@arm.com 1808879Ssteve.reinhardt@amd.com for base in type(self).__mro__: 1818879Ssteve.reinhardt@amd.com if issubclass(base, SourceFile): 1828879Ssteve.reinhardt@amd.com base.all.append(self) 1838879Ssteve.reinhardt@amd.com 1849227Sandreas.hansson@arm.com def static(self, env): 1859227Sandreas.hansson@arm.com key = (self.tnode, env['OBJSUFFIX']) 18612063Sgabeblack@google.com if not key in self.static_objs: 18712063Sgabeblack@google.com self.static_objs[key] = env.StaticObject(self.tnode) 18812063Sgabeblack@google.com return self.static_objs[key] 1898879Ssteve.reinhardt@amd.com 1908879Ssteve.reinhardt@amd.com def shared(self, env): 1918879Ssteve.reinhardt@amd.com key = (self.tnode, env['OBJSUFFIX']) 1928879Ssteve.reinhardt@amd.com if not key in self.shared_objs: 19310453SAndrew.Bardsley@arm.com self.shared_objs[key] = env.SharedObject(self.tnode) 19410453SAndrew.Bardsley@arm.com return self.shared_objs[key] 19510453SAndrew.Bardsley@arm.com 19610456SCurtis.Dunham@arm.com @property 19710456SCurtis.Dunham@arm.com def filename(self): 19810456SCurtis.Dunham@arm.com return str(self.tnode) 19910457Sandreas.hansson@arm.com 20010457Sandreas.hansson@arm.com @property 20111342Sandreas.hansson@arm.com def dirname(self): 20211342Sandreas.hansson@arm.com return dirname(self.filename) 2038120Sgblack@eecs.umich.edu 20412063Sgabeblack@google.com @property 20512063Sgabeblack@google.com def basename(self): 20612063Sgabeblack@google.com return basename(self.filename) 20712063Sgabeblack@google.com 2088947Sandreas.hansson@arm.com @property 2097816Ssteve.reinhardt@amd.com def extname(self): 2105871Snate@binkert.org index = self.basename.rfind('.') 2115871Snate@binkert.org if index <= 0: 2126121Snate@binkert.org # dot files aren't extensions 2135871Snate@binkert.org return self.basename, None 2145871Snate@binkert.org 2159926Sstan.czerniawski@arm.com return self.basename[:index], self.basename[index+1:] 2169926Sstan.czerniawski@arm.com 2179119Sandreas.hansson@arm.com def __lt__(self, other): return self.filename < other.filename 21810068Sandreas.hansson@arm.com def __le__(self, other): return self.filename <= other.filename 21911989Sandreas.sandberg@arm.com def __gt__(self, other): return self.filename > other.filename 220955SN/A def __ge__(self, other): return self.filename >= other.filename 2219416SAndreas.Sandberg@ARM.com def __eq__(self, other): return self.filename == other.filename 22211342Sandreas.hansson@arm.com def __ne__(self, other): return self.filename != other.filename 22311212Sjoseph.gross@amd.com 22411212Sjoseph.gross@amd.comdef blobToCpp(data, symbol, cpp_code, hpp_code=None, namespace=None): 22511212Sjoseph.gross@amd.com ''' 22611212Sjoseph.gross@amd.com Convert bytes data into C++ .cpp and .hh uint8_t byte array 22711212Sjoseph.gross@amd.com code containing that binary data. 2289416SAndreas.Sandberg@ARM.com 2299416SAndreas.Sandberg@ARM.com :param data: binary data to be converted to C++ 2305871Snate@binkert.org :param symbol: name of the symbol 23110584Sandreas.hansson@arm.com :param cpp_code: append the generated cpp_code to this object 2329416SAndreas.Sandberg@ARM.com :param hpp_code: append the generated hpp_code to this object 2339416SAndreas.Sandberg@ARM.com If None, ignore it. Otherwise, also include it 2345871Snate@binkert.org in the .cpp file. 235955SN/A :param namespace: namespace to put the symbol into. If None, 23610671Sandreas.hansson@arm.com don't put the symbols into any namespace. 23710671Sandreas.hansson@arm.com ''' 23810671Sandreas.hansson@arm.com symbol_len_declaration = 'const std::size_t {}_len'.format(symbol) 23910671Sandreas.hansson@arm.com symbol_declaration = 'const std::uint8_t {}[]'.format(symbol) 2408881Smarc.orr@gmail.com if hpp_code is not None: 2416121Snate@binkert.org cpp_code('''\ 2426121Snate@binkert.org#include "blobs/{}.hh" 2431533SN/A'''.format(symbol)) 2449239Sandreas.hansson@arm.com hpp_code('''\ 2459239Sandreas.hansson@arm.com#include <cstddef> 2469239Sandreas.hansson@arm.com#include <cstdint> 2479239Sandreas.hansson@arm.com''') 2489239Sandreas.hansson@arm.com if namespace is not None: 2499239Sandreas.hansson@arm.com hpp_code('namespace {} {{'.format(namespace)) 2509239Sandreas.hansson@arm.com hpp_code('extern ' + symbol_len_declaration + ';') 2516655Snate@binkert.org hpp_code('extern ' + symbol_declaration + ';') 2526655Snate@binkert.org if namespace is not None: 2536655Snate@binkert.org hpp_code('}') 2546655Snate@binkert.org if namespace is not None: 2555871Snate@binkert.org cpp_code('namespace {} {{'.format(namespace)) 2565871Snate@binkert.org if hpp_code is not None: 2575863Snate@binkert.org cpp_code(symbol_len_declaration + ' = {};'.format(len(data))) 2585871Snate@binkert.org cpp_code(symbol_declaration + ' = {') 2598878Ssteve.reinhardt@amd.com cpp_code.indent() 2605871Snate@binkert.org step = 16 2615871Snate@binkert.org for i in xrange(0, len(data), step): 2625871Snate@binkert.org x = array.array('B', data[i:i+step]) 2635863Snate@binkert.org cpp_code(''.join('%d,' % d for d in x)) 2646121Snate@binkert.org cpp_code.dedent() 2655863Snate@binkert.org cpp_code('};') 26611408Sandreas.sandberg@arm.com if namespace is not None: 26711408Sandreas.sandberg@arm.com cpp_code('}') 2688336Ssteve.reinhardt@amd.com 26911469SCurtis.Dunham@arm.comdef Blob(blob_path, symbol): 27011469SCurtis.Dunham@arm.com ''' 2718336Ssteve.reinhardt@amd.com Embed an arbitrary blob into the gem5 executable, 2724678Snate@binkert.org and make it accessible to C++ as a byte array. 27311887Sandreas.sandberg@arm.com ''' 27411887Sandreas.sandberg@arm.com blob_path = os.path.abspath(blob_path) 27511887Sandreas.sandberg@arm.com blob_out_dir = os.path.join(env['BUILDDIR'], 'blobs') 27611887Sandreas.sandberg@arm.com path_noext = joinpath(blob_out_dir, symbol) 27711887Sandreas.sandberg@arm.com cpp_path = path_noext + '.cc' 27811887Sandreas.sandberg@arm.com hpp_path = path_noext + '.hh' 27911887Sandreas.sandberg@arm.com def embedBlob(target, source, env): 28011887Sandreas.sandberg@arm.com data = file(str(source[0]), 'r').read() 28111887Sandreas.sandberg@arm.com cpp_code = code_formatter() 28211887Sandreas.sandberg@arm.com hpp_code = code_formatter() 28311887Sandreas.sandberg@arm.com blobToCpp(data, symbol, cpp_code, hpp_code, namespace='Blobs') 28411408Sandreas.sandberg@arm.com cpp_path = str(target[0]) 28511401Sandreas.sandberg@arm.com hpp_path = str(target[1]) 28611401Sandreas.sandberg@arm.com cpp_dir = os.path.split(cpp_path)[0] 28711401Sandreas.sandberg@arm.com if not os.path.exists(cpp_dir): 28811401Sandreas.sandberg@arm.com os.makedirs(cpp_dir) 28911401Sandreas.sandberg@arm.com cpp_code.write(cpp_path) 29011401Sandreas.sandberg@arm.com hpp_code.write(hpp_path) 2918336Ssteve.reinhardt@amd.com env.Command([cpp_path, hpp_path], blob_path, 2928336Ssteve.reinhardt@amd.com MakeAction(embedBlob, Transform("EMBED BLOB"))) 2938336Ssteve.reinhardt@amd.com Source(cpp_path) 2944678Snate@binkert.org 29511401Sandreas.sandberg@arm.comdef GdbXml(xml_id, symbol): 2964678Snate@binkert.org Blob(joinpath(gdb_xml_dir, xml_id), symbol) 2974678Snate@binkert.org 29811401Sandreas.sandberg@arm.comclass Source(SourceFile): 29911401Sandreas.sandberg@arm.com ungrouped_tag = 'No link group' 3008336Ssteve.reinhardt@amd.com source_groups = set() 3014678Snate@binkert.org 3028336Ssteve.reinhardt@amd.com _current_group_tag = ungrouped_tag 3038336Ssteve.reinhardt@amd.com 3048336Ssteve.reinhardt@amd.com @staticmethod 3058336Ssteve.reinhardt@amd.com def link_group_tag(group): 3068336Ssteve.reinhardt@amd.com return 'link group: %s' % group 3078336Ssteve.reinhardt@amd.com 3085871Snate@binkert.org @classmethod 3095871Snate@binkert.org def set_group(cls, group): 3108336Ssteve.reinhardt@amd.com new_tag = Source.link_group_tag(group) 31111408Sandreas.sandberg@arm.com Source._current_group_tag = new_tag 31211408Sandreas.sandberg@arm.com Source.source_groups.add(group) 31311408Sandreas.sandberg@arm.com 31411408Sandreas.sandberg@arm.com def _add_link_group_tag(self): 31511408Sandreas.sandberg@arm.com self.tags.add(Source._current_group_tag) 31611408Sandreas.sandberg@arm.com 31711408Sandreas.sandberg@arm.com '''Add a c/c++ source file to the build''' 3188336Ssteve.reinhardt@amd.com def __init__(self, source, tags=None, add_tags=None): 31911401Sandreas.sandberg@arm.com '''specify the source file, and any tags''' 32011401Sandreas.sandberg@arm.com super(Source, self).__init__(source, tags, add_tags) 32111401Sandreas.sandberg@arm.com self._add_link_group_tag() 3225871Snate@binkert.org 3238336Ssteve.reinhardt@amd.comclass PySource(SourceFile): 3248336Ssteve.reinhardt@amd.com '''Add a python source file to the named package''' 32511401Sandreas.sandberg@arm.com invalid_sym_char = re.compile('[^A-z0-9_]') 32611401Sandreas.sandberg@arm.com modules = {} 32711401Sandreas.sandberg@arm.com tnodes = {} 32811401Sandreas.sandberg@arm.com symnames = {} 32911401Sandreas.sandberg@arm.com 3304678Snate@binkert.org def __init__(self, package, source, tags=None, add_tags=None): 3315871Snate@binkert.org '''specify the python package, the source file, and any tags''' 3324678Snate@binkert.org super(PySource, self).__init__(source, tags, add_tags) 33311401Sandreas.sandberg@arm.com 33411401Sandreas.sandberg@arm.com modname,ext = self.extname 33511401Sandreas.sandberg@arm.com assert ext == 'py' 33611401Sandreas.sandberg@arm.com 33711401Sandreas.sandberg@arm.com if package: 33811401Sandreas.sandberg@arm.com path = package.split('.') 33911401Sandreas.sandberg@arm.com else: 34011401Sandreas.sandberg@arm.com path = [] 34111401Sandreas.sandberg@arm.com 34211401Sandreas.sandberg@arm.com modpath = path[:] 34311401Sandreas.sandberg@arm.com if modname != '__init__': 34411401Sandreas.sandberg@arm.com modpath += [ modname ] 34511450Sandreas.sandberg@arm.com modpath = '.'.join(modpath) 34611450Sandreas.sandberg@arm.com 34711450Sandreas.sandberg@arm.com arcpath = path + [ self.basename ] 34811450Sandreas.sandberg@arm.com abspath = self.snode.abspath 34911450Sandreas.sandberg@arm.com if not exists(abspath): 35011450Sandreas.sandberg@arm.com abspath = self.tnode.abspath 35111450Sandreas.sandberg@arm.com 35211450Sandreas.sandberg@arm.com self.package = package 35311450Sandreas.sandberg@arm.com self.modname = modname 35411450Sandreas.sandberg@arm.com self.modpath = modpath 35511450Sandreas.sandberg@arm.com self.arcname = joinpath(*arcpath) 35611401Sandreas.sandberg@arm.com self.abspath = abspath 35711450Sandreas.sandberg@arm.com self.compiled = File(self.filename + 'c') 35811450Sandreas.sandberg@arm.com self.cpp = File(self.filename + '.cc') 35911450Sandreas.sandberg@arm.com self.symname = PySource.invalid_sym_char.sub('_', modpath) 36011401Sandreas.sandberg@arm.com 36111450Sandreas.sandberg@arm.com PySource.modules[modpath] = self 36211401Sandreas.sandberg@arm.com PySource.tnodes[self.tnode] = self 3638336Ssteve.reinhardt@amd.com PySource.symnames[self.symname] = self 3648336Ssteve.reinhardt@amd.com 3658336Ssteve.reinhardt@amd.comclass SimObject(PySource): 3668336Ssteve.reinhardt@amd.com '''Add a SimObject python file as a python source object and add 3678336Ssteve.reinhardt@amd.com it to a list of sim object modules''' 3688336Ssteve.reinhardt@amd.com 3698336Ssteve.reinhardt@amd.com fixed = False 3708336Ssteve.reinhardt@amd.com modnames = [] 3718336Ssteve.reinhardt@amd.com 3728336Ssteve.reinhardt@amd.com def __init__(self, source, tags=None, add_tags=None): 37311401Sandreas.sandberg@arm.com '''Specify the source file and any tags (automatically in 37411401Sandreas.sandberg@arm.com the m5.objects package)''' 3758336Ssteve.reinhardt@amd.com super(SimObject, self).__init__('m5.objects', source, tags, add_tags) 3768336Ssteve.reinhardt@amd.com if self.fixed: 3778336Ssteve.reinhardt@amd.com raise AttributeError, "Too late to call SimObject now." 3785871Snate@binkert.org 37911476Sandreas.sandberg@arm.com bisect.insort_right(SimObject.modnames, self.modname) 38011476Sandreas.sandberg@arm.com 38111476Sandreas.sandberg@arm.comclass ProtoBuf(SourceFile): 38211476Sandreas.sandberg@arm.com '''Add a Protocol Buffer to build''' 38311476Sandreas.sandberg@arm.com 38411476Sandreas.sandberg@arm.com def __init__(self, source, tags=None, add_tags=None): 38511476Sandreas.sandberg@arm.com '''Specify the source file, and any tags''' 38611476Sandreas.sandberg@arm.com super(ProtoBuf, self).__init__(source, tags, add_tags) 38711476Sandreas.sandberg@arm.com 38811887Sandreas.sandberg@arm.com # Get the file name and the extension 38911887Sandreas.sandberg@arm.com modname,ext = self.extname 39011887Sandreas.sandberg@arm.com assert ext == 'proto' 39111408Sandreas.sandberg@arm.com 39211887Sandreas.sandberg@arm.com # Currently, we stick to generating the C++ headers, so we 39311887Sandreas.sandberg@arm.com # only need to track the source and header. 39411887Sandreas.sandberg@arm.com self.cc_file = File(modname + '.pb.cc') 39511887Sandreas.sandberg@arm.com self.hh_file = File(modname + '.pb.h') 39611887Sandreas.sandberg@arm.com 39711887Sandreas.sandberg@arm.com 39811926Sgabeblack@google.comexectuable_classes = [] 39911926Sgabeblack@google.comclass ExecutableMeta(type): 40011926Sgabeblack@google.com '''Meta class for Executables.''' 40111926Sgabeblack@google.com all = [] 40211887Sandreas.sandberg@arm.com 40311887Sandreas.sandberg@arm.com def __init__(cls, name, bases, d): 40411944Sandreas.sandberg@arm.com if not d.pop('abstract', False): 40511887Sandreas.sandberg@arm.com ExecutableMeta.all.append(cls) 40611927Sgabeblack@google.com super(ExecutableMeta, cls).__init__(name, bases, d) 40711927Sgabeblack@google.com 40811927Sgabeblack@google.com cls.all = [] 40911927Sgabeblack@google.com 41011927Sgabeblack@google.comclass Executable(object): 41111927Sgabeblack@google.com '''Base class for creating an executable from sources.''' 41211887Sandreas.sandberg@arm.com __metaclass__ = ExecutableMeta 41311928Sgabeblack@google.com 41411928Sgabeblack@google.com abstract = True 41511887Sandreas.sandberg@arm.com 41611887Sandreas.sandberg@arm.com def __init__(self, target, *srcs_and_filts): 41711887Sandreas.sandberg@arm.com '''Specify the target name and any sources. Sources that are 41811887Sandreas.sandberg@arm.com not SourceFiles are evalued with Source().''' 41911887Sandreas.sandberg@arm.com super(Executable, self).__init__() 42011887Sandreas.sandberg@arm.com self.all.append(self) 42111887Sandreas.sandberg@arm.com self.target = target 42211887Sandreas.sandberg@arm.com 42311887Sandreas.sandberg@arm.com isFilter = lambda arg: isinstance(arg, SourceFilter) 42411887Sandreas.sandberg@arm.com self.filters = filter(isFilter, srcs_and_filts) 42511476Sandreas.sandberg@arm.com sources = filter(lambda a: not isFilter(a), srcs_and_filts) 42611476Sandreas.sandberg@arm.com 42711408Sandreas.sandberg@arm.com srcs = SourceList() 42811408Sandreas.sandberg@arm.com for src in sources: 42911408Sandreas.sandberg@arm.com if not isinstance(src, SourceFile): 43011408Sandreas.sandberg@arm.com src = Source(src, tags=[]) 43111408Sandreas.sandberg@arm.com srcs.append(src) 43211408Sandreas.sandberg@arm.com 43311408Sandreas.sandberg@arm.com self.sources = srcs 43411887Sandreas.sandberg@arm.com self.dir = Dir('.') 43511887Sandreas.sandberg@arm.com 43611476Sandreas.sandberg@arm.com def path(self, env): 43711887Sandreas.sandberg@arm.com return self.dir.File(self.target + '.' + env['EXE_SUFFIX']) 43811887Sandreas.sandberg@arm.com 43911476Sandreas.sandberg@arm.com def srcs_to_objs(self, env, sources): 44011476Sandreas.sandberg@arm.com return list([ s.static(env) for s in sources ]) 44111476Sandreas.sandberg@arm.com 44211476Sandreas.sandberg@arm.com @classmethod 4436121Snate@binkert.org def declare_all(cls, env): 444955SN/A return list([ instance.declare(env) for instance in cls.all ]) 445955SN/A 4462632Sstever@eecs.umich.edu def declare(self, env, objs=None): 4472632Sstever@eecs.umich.edu if objs is None: 448955SN/A objs = self.srcs_to_objs(env, self.sources) 449955SN/A 450955SN/A env = env.Clone() 451955SN/A env['BIN_RPATH_PREFIX'] = os.path.relpath( 4528878Ssteve.reinhardt@amd.com env['BUILDDIR'], self.path(env).dir.abspath) 453955SN/A 4542632Sstever@eecs.umich.edu if env['STRIP_EXES']: 4552632Sstever@eecs.umich.edu stripped = self.path(env) 4562632Sstever@eecs.umich.edu unstripped = env.File(str(stripped) + '.unstripped') 4572632Sstever@eecs.umich.edu if sys.platform == 'sunos5': 4582632Sstever@eecs.umich.edu cmd = 'cp $SOURCE $TARGET; strip $TARGET' 4592632Sstever@eecs.umich.edu else: 4602632Sstever@eecs.umich.edu cmd = 'strip $SOURCE -o $TARGET' 4618268Ssteve.reinhardt@amd.com env.Program(unstripped, objs) 4628268Ssteve.reinhardt@amd.com return env.Command(stripped, unstripped, 4638268Ssteve.reinhardt@amd.com MakeAction(cmd, Transform("STRIP"))) 4648268Ssteve.reinhardt@amd.com else: 4658268Ssteve.reinhardt@amd.com return env.Program(self.path(env), objs) 4668268Ssteve.reinhardt@amd.com 4678268Ssteve.reinhardt@amd.comclass UnitTest(Executable): 4682632Sstever@eecs.umich.edu '''Create a UnitTest''' 4692632Sstever@eecs.umich.edu def __init__(self, target, *srcs_and_filts, **kwargs): 4702632Sstever@eecs.umich.edu super(UnitTest, self).__init__(target, *srcs_and_filts) 4712632Sstever@eecs.umich.edu 4728268Ssteve.reinhardt@amd.com self.main = kwargs.get('main', False) 4732632Sstever@eecs.umich.edu 4748268Ssteve.reinhardt@amd.com def declare(self, env): 4758268Ssteve.reinhardt@amd.com sources = list(self.sources) 4768268Ssteve.reinhardt@amd.com for f in self.filters: 4778268Ssteve.reinhardt@amd.com sources += Source.all.apply_filter(f) 4783718Sstever@eecs.umich.edu objs = self.srcs_to_objs(env, sources) + env['STATIC_OBJS'] 4792634Sstever@eecs.umich.edu if self.main: 4802634Sstever@eecs.umich.edu objs += env['MAIN_OBJS'] 4815863Snate@binkert.org return super(UnitTest, self).declare(env, objs) 4822638Sstever@eecs.umich.edu 4838268Ssteve.reinhardt@amd.comclass GTest(Executable): 4842632Sstever@eecs.umich.edu '''Create a unit test based on the google test framework.''' 4852632Sstever@eecs.umich.edu all = [] 4862632Sstever@eecs.umich.edu def __init__(self, *srcs_and_filts, **kwargs): 4872632Sstever@eecs.umich.edu super(GTest, self).__init__(*srcs_and_filts) 4882632Sstever@eecs.umich.edu 4891858SN/A self.skip_lib = kwargs.pop('skip_lib', False) 4903716Sstever@eecs.umich.edu 4912638Sstever@eecs.umich.edu @classmethod 4922638Sstever@eecs.umich.edu def declare_all(cls, env): 4932638Sstever@eecs.umich.edu env = env.Clone() 4942638Sstever@eecs.umich.edu env.Append(LIBS=env['GTEST_LIBS']) 4952638Sstever@eecs.umich.edu env.Append(CPPFLAGS=env['GTEST_CPPFLAGS']) 4962638Sstever@eecs.umich.edu env['GTEST_LIB_SOURCES'] = Source.all.with_tag('gtest lib') 4972638Sstever@eecs.umich.edu env['GTEST_OUT_DIR'] = \ 4985863Snate@binkert.org Dir(env['BUILDDIR']).Dir('unittests.' + env['EXE_SUFFIX']) 4995863Snate@binkert.org return super(GTest, cls).declare_all(env) 5005863Snate@binkert.org 501955SN/A def declare(self, env): 5025341Sstever@gmail.com sources = list(self.sources) 5035341Sstever@gmail.com if not self.skip_lib: 5045863Snate@binkert.org sources += env['GTEST_LIB_SOURCES'] 5057756SAli.Saidi@ARM.com for f in self.filters: 5065341Sstever@gmail.com sources += Source.all.apply_filter(f) 5076121Snate@binkert.org objs = self.srcs_to_objs(env, sources) 5084494Ssaidi@eecs.umich.edu 5096121Snate@binkert.org binary = super(GTest, self).declare(env, objs) 5101105SN/A 5112667Sstever@eecs.umich.edu out_dir = env['GTEST_OUT_DIR'] 5122667Sstever@eecs.umich.edu xml_file = out_dir.Dir(str(self.dir)).File(self.target + '.xml') 5132667Sstever@eecs.umich.edu AlwaysBuild(env.Command(xml_file, binary, 5142667Sstever@eecs.umich.edu "${SOURCES[0]} --gtest_output=xml:${TARGETS[0]}")) 5156121Snate@binkert.org 5162667Sstever@eecs.umich.edu return binary 5175341Sstever@gmail.com 5185863Snate@binkert.orgclass Gem5(Executable): 5195341Sstever@gmail.com '''Create a gem5 executable.''' 5205341Sstever@gmail.com 5215341Sstever@gmail.com def __init__(self, target): 5228120Sgblack@eecs.umich.edu super(Gem5, self).__init__(target) 5235341Sstever@gmail.com 5248120Sgblack@eecs.umich.edu def declare(self, env): 5255341Sstever@gmail.com objs = env['MAIN_OBJS'] + env['STATIC_OBJS'] 5268120Sgblack@eecs.umich.edu return super(Gem5, self).declare(env, objs) 5276121Snate@binkert.org 5286121Snate@binkert.org 5299396Sandreas.hansson@arm.com# Children should have access 5305397Ssaidi@eecs.umich.eduExport('Blob') 5315397Ssaidi@eecs.umich.eduExport('GdbXml') 5327727SAli.Saidi@ARM.comExport('Source') 5338268Ssteve.reinhardt@amd.comExport('PySource') 5346168Snate@binkert.orgExport('SimObject') 5355341Sstever@gmail.comExport('ProtoBuf') 5368120Sgblack@eecs.umich.eduExport('Executable') 5378120Sgblack@eecs.umich.eduExport('UnitTest') 5388120Sgblack@eecs.umich.eduExport('GTest') 5396814Sgblack@eecs.umich.edu 5405863Snate@binkert.org######################################################################## 5418120Sgblack@eecs.umich.edu# 5425341Sstever@gmail.com# Debug Flags 5435863Snate@binkert.org# 5448268Ssteve.reinhardt@amd.comdebug_flags = {} 5456121Snate@binkert.orgdef DebugFlag(name, desc=None): 5466121Snate@binkert.org if name in debug_flags: 5478268Ssteve.reinhardt@amd.com raise AttributeError, "Flag %s already specified" % name 5485742Snate@binkert.org debug_flags[name] = (name, (), desc) 5495742Snate@binkert.org 5505341Sstever@gmail.comdef CompoundFlag(name, flags, desc=None): 5515742Snate@binkert.org if name in debug_flags: 5525742Snate@binkert.org raise AttributeError, "Flag %s already specified" % name 5535341Sstever@gmail.com 5546017Snate@binkert.org compound = tuple(flags) 5556121Snate@binkert.org debug_flags[name] = (name, compound, desc) 5566017Snate@binkert.org 5577816Ssteve.reinhardt@amd.comExport('DebugFlag') 5587756SAli.Saidi@ARM.comExport('CompoundFlag') 5597756SAli.Saidi@ARM.com 5607756SAli.Saidi@ARM.com######################################################################## 5617756SAli.Saidi@ARM.com# 5627756SAli.Saidi@ARM.com# Set some compiler variables 5637756SAli.Saidi@ARM.com# 5647756SAli.Saidi@ARM.com 5657756SAli.Saidi@ARM.com# Include file paths are rooted in this directory. SCons will 5667816Ssteve.reinhardt@amd.com# automatically expand '.' to refer to both the source directory and 5677816Ssteve.reinhardt@amd.com# the corresponding build directory to pick up generated include 5687816Ssteve.reinhardt@amd.com# files. 5697816Ssteve.reinhardt@amd.comenv.Append(CPPPATH=Dir('.')) 5707816Ssteve.reinhardt@amd.com 5717816Ssteve.reinhardt@amd.comfor extra_dir in extras_dir_list: 5727816Ssteve.reinhardt@amd.com env.Append(CPPPATH=Dir(extra_dir)) 5737816Ssteve.reinhardt@amd.com 5747816Ssteve.reinhardt@amd.com# Workaround for bug in SCons version > 0.97d20071212 5757816Ssteve.reinhardt@amd.com# Scons bug id: 2006 gem5 Bug id: 308 5767756SAli.Saidi@ARM.comfor root, dirs, files in os.walk(base_dir, topdown=True): 5777816Ssteve.reinhardt@amd.com Dir(root[len(base_dir) + 1:]) 5787816Ssteve.reinhardt@amd.com 5797816Ssteve.reinhardt@amd.com######################################################################## 5807816Ssteve.reinhardt@amd.com# 5817816Ssteve.reinhardt@amd.com# Walk the tree and execute all SConscripts in subdirectories 5827816Ssteve.reinhardt@amd.com# 5837816Ssteve.reinhardt@amd.com 5847816Ssteve.reinhardt@amd.comhere = Dir('.').srcnode().abspath 5857816Ssteve.reinhardt@amd.comfor root, dirs, files in os.walk(base_dir, topdown=True): 5867816Ssteve.reinhardt@amd.com if root == here: 5877816Ssteve.reinhardt@amd.com # we don't want to recurse back into this SConscript 5887816Ssteve.reinhardt@amd.com continue 5897816Ssteve.reinhardt@amd.com 5907816Ssteve.reinhardt@amd.com if 'SConscript' in files: 5917816Ssteve.reinhardt@amd.com build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) 5927816Ssteve.reinhardt@amd.com Source.set_group(build_dir) 5937816Ssteve.reinhardt@amd.com SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 5947816Ssteve.reinhardt@amd.com 5957816Ssteve.reinhardt@amd.comfor extra_dir in extras_dir_list: 5967816Ssteve.reinhardt@amd.com prefix_len = len(dirname(extra_dir)) + 1 5977816Ssteve.reinhardt@amd.com 5987816Ssteve.reinhardt@amd.com # Also add the corresponding build directory to pick up generated 5997816Ssteve.reinhardt@amd.com # include files. 6007816Ssteve.reinhardt@amd.com env.Append(CPPPATH=Dir(joinpath(env['BUILDDIR'], extra_dir[prefix_len:]))) 6017816Ssteve.reinhardt@amd.com 6027816Ssteve.reinhardt@amd.com for root, dirs, files in os.walk(extra_dir, topdown=True): 6037816Ssteve.reinhardt@amd.com # if build lives in the extras directory, don't walk down it 6047816Ssteve.reinhardt@amd.com if 'build' in dirs: 6057816Ssteve.reinhardt@amd.com dirs.remove('build') 6067816Ssteve.reinhardt@amd.com 6077816Ssteve.reinhardt@amd.com if 'SConscript' in files: 6087816Ssteve.reinhardt@amd.com build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) 6097816Ssteve.reinhardt@amd.com SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 6107816Ssteve.reinhardt@amd.com 6117816Ssteve.reinhardt@amd.comfor opt in export_vars: 6127816Ssteve.reinhardt@amd.com env.ConfigFile(opt) 6137816Ssteve.reinhardt@amd.com 6147816Ssteve.reinhardt@amd.comdef makeTheISA(source, target, env): 6157816Ssteve.reinhardt@amd.com isas = [ src.get_contents() for src in source ] 6167816Ssteve.reinhardt@amd.com target_isa = env['TARGET_ISA'] 6177816Ssteve.reinhardt@amd.com def define(isa): 6187816Ssteve.reinhardt@amd.com return isa.upper() + '_ISA' 6197816Ssteve.reinhardt@amd.com 6207816Ssteve.reinhardt@amd.com def namespace(isa): 6217816Ssteve.reinhardt@amd.com return isa[0].upper() + isa[1:].lower() + 'ISA' 6227816Ssteve.reinhardt@amd.com 6237816Ssteve.reinhardt@amd.com 6247816Ssteve.reinhardt@amd.com code = code_formatter() 6257816Ssteve.reinhardt@amd.com code('''\ 6267816Ssteve.reinhardt@amd.com#ifndef __CONFIG_THE_ISA_HH__ 6277816Ssteve.reinhardt@amd.com#define __CONFIG_THE_ISA_HH__ 6287816Ssteve.reinhardt@amd.com 6297816Ssteve.reinhardt@amd.com''') 6307816Ssteve.reinhardt@amd.com 6317816Ssteve.reinhardt@amd.com # create defines for the preprocessing and compile-time determination 6327816Ssteve.reinhardt@amd.com for i,isa in enumerate(isas): 6337816Ssteve.reinhardt@amd.com code('#define $0 $1', define(isa), i + 1) 6347816Ssteve.reinhardt@amd.com code() 6357816Ssteve.reinhardt@amd.com 6367816Ssteve.reinhardt@amd.com # create an enum for any run-time determination of the ISA, we 6377816Ssteve.reinhardt@amd.com # reuse the same name as the namespaces 6388947Sandreas.hansson@arm.com code('enum class Arch {') 6398947Sandreas.hansson@arm.com for i,isa in enumerate(isas): 6407756SAli.Saidi@ARM.com if i + 1 == len(isas): 6418120Sgblack@eecs.umich.edu code(' $0 = $1', namespace(isa), define(isa)) 6427756SAli.Saidi@ARM.com else: 6437756SAli.Saidi@ARM.com code(' $0 = $1,', namespace(isa), define(isa)) 6447756SAli.Saidi@ARM.com code('};') 6457756SAli.Saidi@ARM.com 6467816Ssteve.reinhardt@amd.com code(''' 6477816Ssteve.reinhardt@amd.com 6487816Ssteve.reinhardt@amd.com#define THE_ISA ${{define(target_isa)}} 6497816Ssteve.reinhardt@amd.com#define TheISA ${{namespace(target_isa)}} 6507816Ssteve.reinhardt@amd.com#define THE_ISA_STR "${{target_isa}}" 65111979Sgabeblack@google.com 6527816Ssteve.reinhardt@amd.com#endif // __CONFIG_THE_ISA_HH__''') 6537816Ssteve.reinhardt@amd.com 6547816Ssteve.reinhardt@amd.com code.write(str(target[0])) 6557816Ssteve.reinhardt@amd.com 6567756SAli.Saidi@ARM.comenv.Command('config/the_isa.hh', map(Value, all_isa_list), 6577756SAli.Saidi@ARM.com MakeAction(makeTheISA, Transform("CFG ISA", 0))) 6589227Sandreas.hansson@arm.com 6599227Sandreas.hansson@arm.comdef makeTheGPUISA(source, target, env): 6609227Sandreas.hansson@arm.com isas = [ src.get_contents() for src in source ] 6619227Sandreas.hansson@arm.com target_gpu_isa = env['TARGET_GPU_ISA'] 6629590Sandreas@sandberg.pp.se def define(isa): 6639590Sandreas@sandberg.pp.se return isa.upper() + '_ISA' 6649590Sandreas@sandberg.pp.se 6659590Sandreas@sandberg.pp.se def namespace(isa): 6669590Sandreas@sandberg.pp.se return isa[0].upper() + isa[1:].lower() + 'ISA' 6679590Sandreas@sandberg.pp.se 6686654Snate@binkert.org 6696654Snate@binkert.org code = code_formatter() 6705871Snate@binkert.org code('''\ 6716121Snate@binkert.org#ifndef __CONFIG_THE_GPU_ISA_HH__ 6728946Sandreas.hansson@arm.com#define __CONFIG_THE_GPU_ISA_HH__ 6739419Sandreas.hansson@arm.com 6743940Ssaidi@eecs.umich.edu''') 6753918Ssaidi@eecs.umich.edu 6763918Ssaidi@eecs.umich.edu # create defines for the preprocessing and compile-time determination 6771858SN/A for i,isa in enumerate(isas): 6789556Sandreas.hansson@arm.com code('#define $0 $1', define(isa), i + 1) 6799556Sandreas.hansson@arm.com code() 6809556Sandreas.hansson@arm.com 6819556Sandreas.hansson@arm.com # create an enum for any run-time determination of the ISA, we 68211294Sandreas.hansson@arm.com # reuse the same name as the namespaces 68311294Sandreas.hansson@arm.com code('enum class GPUArch {') 68411294Sandreas.hansson@arm.com for i,isa in enumerate(isas): 68511294Sandreas.hansson@arm.com if i + 1 == len(isas): 68610878Sandreas.hansson@arm.com code(' $0 = $1', namespace(isa), define(isa)) 68710878Sandreas.hansson@arm.com else: 68811811Sbaz21@cam.ac.uk code(' $0 = $1,', namespace(isa), define(isa)) 68911811Sbaz21@cam.ac.uk code('};') 69011811Sbaz21@cam.ac.uk 69111982Sgabeblack@google.com code(''' 69211982Sgabeblack@google.com 69311982Sgabeblack@google.com#define THE_GPU_ISA ${{define(target_gpu_isa)}} 69411982Sgabeblack@google.com#define TheGpuISA ${{namespace(target_gpu_isa)}} 69511992Sgabeblack@google.com#define THE_GPU_ISA_STR "${{target_gpu_isa}}" 69611982Sgabeblack@google.com 69711982Sgabeblack@google.com#endif // __CONFIG_THE_GPU_ISA_HH__''') 6989556Sandreas.hansson@arm.com 6999556Sandreas.hansson@arm.com code.write(str(target[0])) 7009556Sandreas.hansson@arm.com 7019556Sandreas.hansson@arm.comenv.Command('config/the_gpu_isa.hh', map(Value, all_gpu_isa_list), 7029556Sandreas.hansson@arm.com MakeAction(makeTheGPUISA, Transform("CFG ISA", 0))) 7039556Sandreas.hansson@arm.com 7049556Sandreas.hansson@arm.com######################################################################## 7059556Sandreas.hansson@arm.com# 7069556Sandreas.hansson@arm.com# Prevent any SimObjects from being added after this point, they 7079556Sandreas.hansson@arm.com# should all have been added in the SConscripts above 7089556Sandreas.hansson@arm.com# 7099556Sandreas.hansson@arm.comSimObject.fixed = True 7109556Sandreas.hansson@arm.com 7119556Sandreas.hansson@arm.comclass DictImporter(object): 7129556Sandreas.hansson@arm.com '''This importer takes a dictionary of arbitrary module names that 7139556Sandreas.hansson@arm.com map to arbitrary filenames.''' 7149556Sandreas.hansson@arm.com def __init__(self, modules): 7159556Sandreas.hansson@arm.com self.modules = modules 7169556Sandreas.hansson@arm.com self.installed = set() 7176121Snate@binkert.org 71811500Sandreas.hansson@arm.com def __del__(self): 71910238Sandreas.hansson@arm.com self.unload() 72010878Sandreas.hansson@arm.com 7219420Sandreas.hansson@arm.com def unload(self): 72211500Sandreas.hansson@arm.com import sys 72311500Sandreas.hansson@arm.com for module in self.installed: 7249420Sandreas.hansson@arm.com del sys.modules[module] 7259420Sandreas.hansson@arm.com self.installed = set() 7269420Sandreas.hansson@arm.com 7279420Sandreas.hansson@arm.com def find_module(self, fullname, path): 7289420Sandreas.hansson@arm.com if fullname == 'm5.defines': 72912063Sgabeblack@google.com return self 73012063Sgabeblack@google.com 73112063Sgabeblack@google.com if fullname == 'm5.objects': 73212063Sgabeblack@google.com return self 73312063Sgabeblack@google.com 73412063Sgabeblack@google.com if fullname.startswith('_m5'): 73512063Sgabeblack@google.com return None 73612063Sgabeblack@google.com 73712063Sgabeblack@google.com source = self.modules.get(fullname, None) 73812063Sgabeblack@google.com if source is not None and fullname.startswith('m5.objects'): 73912063Sgabeblack@google.com return self 74012063Sgabeblack@google.com 74112063Sgabeblack@google.com return None 74212063Sgabeblack@google.com 74312063Sgabeblack@google.com def load_module(self, fullname): 74412063Sgabeblack@google.com mod = imp.new_module(fullname) 74512063Sgabeblack@google.com sys.modules[fullname] = mod 74612063Sgabeblack@google.com self.installed.add(fullname) 74712063Sgabeblack@google.com 74812063Sgabeblack@google.com mod.__loader__ = self 74912063Sgabeblack@google.com if fullname == 'm5.objects': 75012063Sgabeblack@google.com mod.__path__ = fullname.split('.') 75110264Sandreas.hansson@arm.com return mod 75210264Sandreas.hansson@arm.com 75310264Sandreas.hansson@arm.com if fullname == 'm5.defines': 75410264Sandreas.hansson@arm.com mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) 75511925Sgabeblack@google.com return mod 75611925Sgabeblack@google.com 75711500Sandreas.hansson@arm.com source = self.modules[fullname] 75810264Sandreas.hansson@arm.com if source.modname == '__init__': 75911500Sandreas.hansson@arm.com mod.__path__ = source.modpath 76011500Sandreas.hansson@arm.com mod.__file__ = source.abspath 76111500Sandreas.hansson@arm.com 76211500Sandreas.hansson@arm.com exec file(source.abspath, 'r') in mod.__dict__ 76310866Sandreas.hansson@arm.com 76411500Sandreas.hansson@arm.com return mod 76511500Sandreas.hansson@arm.com 76611500Sandreas.hansson@arm.comimport m5.SimObject 76711500Sandreas.hansson@arm.comimport m5.params 76811500Sandreas.hansson@arm.comfrom m5.util import code_formatter 76911500Sandreas.hansson@arm.com 77011500Sandreas.hansson@arm.comm5.SimObject.clear() 77110264Sandreas.hansson@arm.comm5.params.clear() 77210457Sandreas.hansson@arm.com 77310457Sandreas.hansson@arm.com# install the python importer so we can grab stuff from the source 77410457Sandreas.hansson@arm.com# tree itself. We can't have SimObjects added after this point or 77510457Sandreas.hansson@arm.com# else we won't know about them for the rest of the stuff. 77610457Sandreas.hansson@arm.comimporter = DictImporter(PySource.modules) 77710457Sandreas.hansson@arm.comsys.meta_path[0:0] = [ importer ] 77810457Sandreas.hansson@arm.com 77910457Sandreas.hansson@arm.com# import all sim objects so we can populate the all_objects list 78010457Sandreas.hansson@arm.com# make sure that we're working with a list, then let's sort it 78112063Sgabeblack@google.comfor modname in SimObject.modnames: 78212063Sgabeblack@google.com exec('from m5.objects import %s' % modname) 78312063Sgabeblack@google.com 78412063Sgabeblack@google.com# we need to unload all of the currently imported modules so that they 78512063Sgabeblack@google.com# will be re-imported the next time the sconscript is run 78612063Sgabeblack@google.comimporter.unload() 78712063Sgabeblack@google.comsys.meta_path.remove(importer) 78812063Sgabeblack@google.com 78912063Sgabeblack@google.comsim_objects = m5.SimObject.allClasses 79012063Sgabeblack@google.comall_enums = m5.params.allEnums 79112063Sgabeblack@google.com 79210238Sandreas.hansson@arm.comfor name,obj in sorted(sim_objects.iteritems()): 79310238Sandreas.hansson@arm.com for param in obj._params.local.values(): 79410238Sandreas.hansson@arm.com # load the ptype attribute now because it depends on the 79512063Sgabeblack@google.com # current version of SimObject.allClasses, but when scons 79610238Sandreas.hansson@arm.com # actually uses the value, all versions of 79710238Sandreas.hansson@arm.com # SimObject.allClasses will have been loaded 79810416Sandreas.hansson@arm.com param.ptype 79910238Sandreas.hansson@arm.com 8009227Sandreas.hansson@arm.com######################################################################## 80110238Sandreas.hansson@arm.com# 80210416Sandreas.hansson@arm.com# calculate extra dependencies 80310416Sandreas.hansson@arm.com# 8049227Sandreas.hansson@arm.commodule_depends = ["m5", "m5.SimObject", "m5.params"] 8059590Sandreas@sandberg.pp.sedepends = [ PySource.modules[dep].snode for dep in module_depends ] 8069590Sandreas@sandberg.pp.sedepends.sort(key = lambda x: x.name) 8079590Sandreas@sandberg.pp.se 80811497SMatteo.Andreozzi@arm.com######################################################################## 80911497SMatteo.Andreozzi@arm.com# 81011497SMatteo.Andreozzi@arm.com# Commands for the basic automatically generated python files 81111497SMatteo.Andreozzi@arm.com# 8128737Skoansin.tan@gmail.com 81310878Sandreas.hansson@arm.com# Generate Python file containing a dict specifying the current 81411500Sandreas.hansson@arm.com# buildEnv flags. 8159420Sandreas.hansson@arm.comdef makeDefinesPyFile(target, source, env): 8168737Skoansin.tan@gmail.com build_env = source[0].get_contents() 81710106SMitch.Hayenga@arm.com 8188737Skoansin.tan@gmail.com code = code_formatter() 8198737Skoansin.tan@gmail.com code(""" 82010878Sandreas.hansson@arm.comimport _m5.core 82110878Sandreas.hansson@arm.comimport m5.util 8228737Skoansin.tan@gmail.com 8238737Skoansin.tan@gmail.combuildEnv = m5.util.SmartDict($build_env) 8248737Skoansin.tan@gmail.com 8258737Skoansin.tan@gmail.comcompileDate = _m5.core.compileDate 8268737Skoansin.tan@gmail.com_globals = globals() 8278737Skoansin.tan@gmail.comfor key,val in _m5.core.__dict__.items(): 82811294Sandreas.hansson@arm.com if key.startswith('flag_'): 8299556Sandreas.hansson@arm.com flag = key[5:] 8309556Sandreas.hansson@arm.com _globals[flag] = val 8319556Sandreas.hansson@arm.comdel _globals 83211294Sandreas.hansson@arm.com""") 83310278SAndreas.Sandberg@ARM.com code.write(target[0].abspath) 83410278SAndreas.Sandberg@ARM.com 83510278SAndreas.Sandberg@ARM.comdefines_info = Value(build_env) 83610278SAndreas.Sandberg@ARM.com# Generate a file with all of the compile options in it 83710278SAndreas.Sandberg@ARM.comenv.Command('python/m5/defines.py', defines_info, 83810278SAndreas.Sandberg@ARM.com MakeAction(makeDefinesPyFile, Transform("DEFINES", 0))) 8399556Sandreas.hansson@arm.comPySource('m5', 'python/m5/defines.py') 8409590Sandreas@sandberg.pp.se 8419590Sandreas@sandberg.pp.se# Generate python file containing info about the M5 source code 8429420Sandreas.hansson@arm.comdef makeInfoPyFile(target, source, env): 8439846Sandreas.hansson@arm.com code = code_formatter() 8449846Sandreas.hansson@arm.com for src in source: 8459846Sandreas.hansson@arm.com data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) 8469846Sandreas.hansson@arm.com code('$src = ${{repr(data)}}') 8478946Sandreas.hansson@arm.com code.write(str(target[0])) 84811811Sbaz21@cam.ac.uk 84911811Sbaz21@cam.ac.uk# Generate a file that wraps the basic top level files 85011811Sbaz21@cam.ac.ukenv.Command('python/m5/info.py', 85111811Sbaz21@cam.ac.uk [ '#/COPYING', '#/LICENSE', '#/README', ], 8523918Ssaidi@eecs.umich.edu MakeAction(makeInfoPyFile, Transform("INFO"))) 8539068SAli.Saidi@ARM.comPySource('m5', 'python/m5/info.py') 8549068SAli.Saidi@ARM.com 8559068SAli.Saidi@ARM.com######################################################################## 8569068SAli.Saidi@ARM.com# 8579068SAli.Saidi@ARM.com# Create all of the SimObject param headers and enum headers 8589068SAli.Saidi@ARM.com# 8599068SAli.Saidi@ARM.com 8609068SAli.Saidi@ARM.comdef createSimObjectParamStruct(target, source, env): 8619068SAli.Saidi@ARM.com assert len(target) == 1 and len(source) == 1 8629419Sandreas.hansson@arm.com 8639068SAli.Saidi@ARM.com name = source[0].get_text_contents() 8649068SAli.Saidi@ARM.com obj = sim_objects[name] 8659068SAli.Saidi@ARM.com 8669068SAli.Saidi@ARM.com code = code_formatter() 8679068SAli.Saidi@ARM.com obj.cxx_param_decl(code) 8689068SAli.Saidi@ARM.com code.write(target[0].abspath) 8693918Ssaidi@eecs.umich.edu 8703918Ssaidi@eecs.umich.edudef createSimObjectCxxConfig(is_header): 8716157Snate@binkert.org def body(target, source, env): 8726157Snate@binkert.org assert len(target) == 1 and len(source) == 1 8736157Snate@binkert.org 8746157Snate@binkert.org name = str(source[0].get_contents()) 8755397Ssaidi@eecs.umich.edu obj = sim_objects[name] 8765397Ssaidi@eecs.umich.edu 8776121Snate@binkert.org code = code_formatter() 8786121Snate@binkert.org obj.cxx_config_param_file(code, is_header) 8796121Snate@binkert.org code.write(target[0].abspath) 8806121Snate@binkert.org return body 8816121Snate@binkert.org 8826121Snate@binkert.orgdef createEnumStrings(target, source, env): 8835397Ssaidi@eecs.umich.edu assert len(target) == 1 and len(source) == 2 8841851SN/A 8851851SN/A name = source[0].get_text_contents() 8867739Sgblack@eecs.umich.edu use_python = source[1].read() 887955SN/A obj = all_enums[name] 8889396Sandreas.hansson@arm.com 8899396Sandreas.hansson@arm.com code = code_formatter() 8909396Sandreas.hansson@arm.com obj.cxx_def(code) 8919396Sandreas.hansson@arm.com if use_python: 8929396Sandreas.hansson@arm.com obj.pybind_def(code) 8939396Sandreas.hansson@arm.com code.write(target[0].abspath) 8949396Sandreas.hansson@arm.com 8959396Sandreas.hansson@arm.comdef createEnumDecls(target, source, env): 8969396Sandreas.hansson@arm.com assert len(target) == 1 and len(source) == 1 8979396Sandreas.hansson@arm.com 8989396Sandreas.hansson@arm.com name = source[0].get_text_contents() 8999396Sandreas.hansson@arm.com obj = all_enums[name] 9009396Sandreas.hansson@arm.com 9019396Sandreas.hansson@arm.com code = code_formatter() 9029396Sandreas.hansson@arm.com obj.cxx_decl(code) 9039396Sandreas.hansson@arm.com code.write(target[0].abspath) 9049477Sandreas.hansson@arm.com 9059477Sandreas.hansson@arm.comdef createSimObjectPyBindWrapper(target, source, env): 9069477Sandreas.hansson@arm.com name = source[0].get_text_contents() 9079477Sandreas.hansson@arm.com obj = sim_objects[name] 9089477Sandreas.hansson@arm.com 9099477Sandreas.hansson@arm.com code = code_formatter() 9109477Sandreas.hansson@arm.com obj.pybind_decl(code) 9119477Sandreas.hansson@arm.com code.write(target[0].abspath) 9129477Sandreas.hansson@arm.com 9139477Sandreas.hansson@arm.com# Generate all of the SimObject param C++ struct header files 9149477Sandreas.hansson@arm.comparams_hh_files = [] 9159477Sandreas.hansson@arm.comfor name,simobj in sorted(sim_objects.iteritems()): 9169477Sandreas.hansson@arm.com py_source = PySource.modules[simobj.__module__] 9179477Sandreas.hansson@arm.com extra_deps = [ py_source.tnode ] 9189477Sandreas.hansson@arm.com 9199477Sandreas.hansson@arm.com hh_file = File('params/%s.hh' % name) 9209477Sandreas.hansson@arm.com params_hh_files.append(hh_file) 9219477Sandreas.hansson@arm.com env.Command(hh_file, Value(name), 9229477Sandreas.hansson@arm.com MakeAction(createSimObjectParamStruct, Transform("SO PARAM"))) 9239477Sandreas.hansson@arm.com env.Depends(hh_file, depends + extra_deps) 9249477Sandreas.hansson@arm.com 9259477Sandreas.hansson@arm.com# C++ parameter description files 9269396Sandreas.hansson@arm.comif GetOption('with_cxx_config'): 9272667Sstever@eecs.umich.edu for name,simobj in sorted(sim_objects.iteritems()): 92810710Sandreas.hansson@arm.com py_source = PySource.modules[simobj.__module__] 92910710Sandreas.hansson@arm.com extra_deps = [ py_source.tnode ] 93010710Sandreas.hansson@arm.com 93111811Sbaz21@cam.ac.uk cxx_config_hh_file = File('cxx_config/%s.hh' % name) 93211811Sbaz21@cam.ac.uk cxx_config_cc_file = File('cxx_config/%s.cc' % name) 93311811Sbaz21@cam.ac.uk env.Command(cxx_config_hh_file, Value(name), 93411811Sbaz21@cam.ac.uk MakeAction(createSimObjectCxxConfig(True), 93511811Sbaz21@cam.ac.uk Transform("CXXCPRHH"))) 93611811Sbaz21@cam.ac.uk env.Command(cxx_config_cc_file, Value(name), 93710710Sandreas.hansson@arm.com MakeAction(createSimObjectCxxConfig(False), 93810710Sandreas.hansson@arm.com Transform("CXXCPRCC"))) 93910710Sandreas.hansson@arm.com env.Depends(cxx_config_hh_file, depends + extra_deps + 94010710Sandreas.hansson@arm.com [File('params/%s.hh' % name), File('sim/cxx_config.hh')]) 94110384SCurtis.Dunham@arm.com env.Depends(cxx_config_cc_file, depends + extra_deps + 9429986Sandreas@sandberg.pp.se [cxx_config_hh_file]) 9439986Sandreas@sandberg.pp.se Source(cxx_config_cc_file) 9449986Sandreas@sandberg.pp.se 9459986Sandreas@sandberg.pp.se cxx_config_init_cc_file = File('cxx_config/init.cc') 9469986Sandreas@sandberg.pp.se 9479986Sandreas@sandberg.pp.se def createCxxConfigInitCC(target, source, env): 9489986Sandreas@sandberg.pp.se assert len(target) == 1 and len(source) == 1 9499986Sandreas@sandberg.pp.se 9509986Sandreas@sandberg.pp.se code = code_formatter() 9519986Sandreas@sandberg.pp.se 9529986Sandreas@sandberg.pp.se for name,simobj in sorted(sim_objects.iteritems()): 9539986Sandreas@sandberg.pp.se if not hasattr(simobj, 'abstract') or not simobj.abstract: 9549986Sandreas@sandberg.pp.se code('#include "cxx_config/${name}.hh"') 9559986Sandreas@sandberg.pp.se code() 9569986Sandreas@sandberg.pp.se code('void cxxConfigInit()') 9579986Sandreas@sandberg.pp.se code('{') 9589986Sandreas@sandberg.pp.se code.indent() 9599986Sandreas@sandberg.pp.se for name,simobj in sorted(sim_objects.iteritems()): 9609986Sandreas@sandberg.pp.se not_abstract = not hasattr(simobj, 'abstract') or \ 9619986Sandreas@sandberg.pp.se not simobj.abstract 9622638Sstever@eecs.umich.edu if not_abstract and 'type' in simobj.__dict__: 9632638Sstever@eecs.umich.edu code('cxx_config_directory["${name}"] = ' 9646121Snate@binkert.org '${name}CxxConfigParams::makeDirectoryEntry();') 9653716Sstever@eecs.umich.edu code.dedent() 9665522Snate@binkert.org code('}') 9679986Sandreas@sandberg.pp.se code.write(target[0].abspath) 9689986Sandreas@sandberg.pp.se 9699986Sandreas@sandberg.pp.se py_source = PySource.modules[simobj.__module__] 9705522Snate@binkert.org extra_deps = [ py_source.tnode ] 9715227Ssaidi@eecs.umich.edu env.Command(cxx_config_init_cc_file, Value(name), 9725227Ssaidi@eecs.umich.edu MakeAction(createCxxConfigInitCC, Transform("CXXCINIT"))) 9735227Ssaidi@eecs.umich.edu cxx_param_hh_files = ["cxx_config/%s.hh" % simobj 9745227Ssaidi@eecs.umich.edu for name,simobj in sorted(sim_objects.iteritems()) 9756654Snate@binkert.org if not hasattr(simobj, 'abstract') or not simobj.abstract] 9766654Snate@binkert.org Depends(cxx_config_init_cc_file, cxx_param_hh_files + 9777769SAli.Saidi@ARM.com [File('sim/cxx_config.hh')]) 9787769SAli.Saidi@ARM.com Source(cxx_config_init_cc_file) 9797769SAli.Saidi@ARM.com 9807769SAli.Saidi@ARM.com# Generate all enum header files 9815227Ssaidi@eecs.umich.edufor name,enum in sorted(all_enums.iteritems()): 9825227Ssaidi@eecs.umich.edu py_source = PySource.modules[enum.__module__] 9835227Ssaidi@eecs.umich.edu extra_deps = [ py_source.tnode ] 9845204Sstever@gmail.com 9855204Sstever@gmail.com cc_file = File('enums/%s.cc' % name) 9865204Sstever@gmail.com env.Command(cc_file, [Value(name), Value(env['USE_PYTHON'])], 9875204Sstever@gmail.com MakeAction(createEnumStrings, Transform("ENUM STR"))) 9885204Sstever@gmail.com env.Depends(cc_file, depends + extra_deps) 9895204Sstever@gmail.com Source(cc_file) 9905204Sstever@gmail.com 9915204Sstever@gmail.com hh_file = File('enums/%s.hh' % name) 9925204Sstever@gmail.com env.Command(hh_file, Value(name), 9935204Sstever@gmail.com MakeAction(createEnumDecls, Transform("ENUMDECL"))) 9945204Sstever@gmail.com env.Depends(hh_file, depends + extra_deps) 9955204Sstever@gmail.com 9965204Sstever@gmail.com# Generate SimObject Python bindings wrapper files 9975204Sstever@gmail.comif env['USE_PYTHON']: 9985204Sstever@gmail.com for name,simobj in sorted(sim_objects.iteritems()): 9995204Sstever@gmail.com py_source = PySource.modules[simobj.__module__] 10005204Sstever@gmail.com extra_deps = [ py_source.tnode ] 10016121Snate@binkert.org cc_file = File('python/_m5/param_%s.cc' % name) 10025204Sstever@gmail.com env.Command(cc_file, Value(name), 10037727SAli.Saidi@ARM.com MakeAction(createSimObjectPyBindWrapper, 10047727SAli.Saidi@ARM.com Transform("SO PyBind"))) 10057727SAli.Saidi@ARM.com env.Depends(cc_file, depends + extra_deps) 10067727SAli.Saidi@ARM.com Source(cc_file) 10077727SAli.Saidi@ARM.com 100811988Sandreas.sandberg@arm.com# Build all protocol buffers if we have got protoc and protobuf available 100911988Sandreas.sandberg@arm.comif env['HAVE_PROTOBUF']: 101010453SAndrew.Bardsley@arm.com for proto in ProtoBuf.all: 101110453SAndrew.Bardsley@arm.com # Use both the source and header as the target, and the .proto 101210453SAndrew.Bardsley@arm.com # file as the source. When executing the protoc compiler, also 101310453SAndrew.Bardsley@arm.com # specify the proto_path to avoid having the generated files 101410453SAndrew.Bardsley@arm.com # include the path. 101510453SAndrew.Bardsley@arm.com env.Command([proto.cc_file, proto.hh_file], proto.tnode, 101610453SAndrew.Bardsley@arm.com MakeAction('$PROTOC --cpp_out ${TARGET.dir} ' 101710453SAndrew.Bardsley@arm.com '--proto_path ${SOURCE.dir} $SOURCE', 101810453SAndrew.Bardsley@arm.com Transform("PROTOC"))) 101910453SAndrew.Bardsley@arm.com 102010160Sandreas.hansson@arm.com # Add the C++ source file 102110453SAndrew.Bardsley@arm.com Source(proto.cc_file, tags=proto.tags) 102210453SAndrew.Bardsley@arm.comelif ProtoBuf.all: 102310453SAndrew.Bardsley@arm.com print('Got protobuf to build, but lacks support!') 102410453SAndrew.Bardsley@arm.com Exit(1) 102510453SAndrew.Bardsley@arm.com 102610453SAndrew.Bardsley@arm.com# 102710453SAndrew.Bardsley@arm.com# Handle debug flags 102810453SAndrew.Bardsley@arm.com# 10299812Sandreas.hansson@arm.comdef makeDebugFlagCC(target, source, env): 103010453SAndrew.Bardsley@arm.com assert(len(target) == 1 and len(source) == 1) 103110453SAndrew.Bardsley@arm.com 103210453SAndrew.Bardsley@arm.com code = code_formatter() 103310453SAndrew.Bardsley@arm.com 103410453SAndrew.Bardsley@arm.com # delay definition of CompoundFlags until after all the definition 103510453SAndrew.Bardsley@arm.com # of all constituent SimpleFlags 103610453SAndrew.Bardsley@arm.com comp_code = code_formatter() 103710453SAndrew.Bardsley@arm.com 103810453SAndrew.Bardsley@arm.com # file header 103910453SAndrew.Bardsley@arm.com code(''' 104010453SAndrew.Bardsley@arm.com/* 104110453SAndrew.Bardsley@arm.com * DO NOT EDIT THIS FILE! Automatically generated by SCons. 10427727SAli.Saidi@ARM.com */ 104310453SAndrew.Bardsley@arm.com 104410453SAndrew.Bardsley@arm.com#include "base/debug.hh" 104510453SAndrew.Bardsley@arm.com 104610453SAndrew.Bardsley@arm.comnamespace Debug { 104710453SAndrew.Bardsley@arm.com 10483118Sstever@eecs.umich.edu''') 104910453SAndrew.Bardsley@arm.com 105010453SAndrew.Bardsley@arm.com for name, flag in sorted(source[0].read().iteritems()): 105110453SAndrew.Bardsley@arm.com n, compound, desc = flag 105210453SAndrew.Bardsley@arm.com assert n == name 10533118Sstever@eecs.umich.edu 10543483Ssaidi@eecs.umich.edu if not compound: 10553494Ssaidi@eecs.umich.edu code('SimpleFlag $name("$name", "$desc");') 10563494Ssaidi@eecs.umich.edu else: 10573483Ssaidi@eecs.umich.edu comp_code('CompoundFlag $name("$name", "$desc",') 10583483Ssaidi@eecs.umich.edu comp_code.indent() 10593483Ssaidi@eecs.umich.edu last = len(compound) - 1 10603053Sstever@eecs.umich.edu for i,flag in enumerate(compound): 10613053Sstever@eecs.umich.edu if i != last: 10623918Ssaidi@eecs.umich.edu comp_code('&$flag,') 10633053Sstever@eecs.umich.edu else: 10643053Sstever@eecs.umich.edu comp_code('&$flag);') 10653053Sstever@eecs.umich.edu comp_code.dedent() 10663053Sstever@eecs.umich.edu 10673053Sstever@eecs.umich.edu code.append(comp_code) 10689396Sandreas.hansson@arm.com code() 10699396Sandreas.hansson@arm.com code('} // namespace Debug') 10709396Sandreas.hansson@arm.com 10719396Sandreas.hansson@arm.com code.write(str(target[0])) 10729396Sandreas.hansson@arm.com 10739396Sandreas.hansson@arm.comdef makeDebugFlagHH(target, source, env): 10749396Sandreas.hansson@arm.com assert(len(target) == 1 and len(source) == 1) 10759396Sandreas.hansson@arm.com 10769396Sandreas.hansson@arm.com val = eval(source[0].get_contents()) 10779477Sandreas.hansson@arm.com name, compound, desc = val 10789396Sandreas.hansson@arm.com 10799477Sandreas.hansson@arm.com code = code_formatter() 10809477Sandreas.hansson@arm.com 10819477Sandreas.hansson@arm.com # file header boilerplate 10829477Sandreas.hansson@arm.com code('''\ 10839396Sandreas.hansson@arm.com/* 10847840Snate@binkert.org * DO NOT EDIT THIS FILE! Automatically generated by SCons. 10857865Sgblack@eecs.umich.edu */ 10867865Sgblack@eecs.umich.edu 10877865Sgblack@eecs.umich.edu#ifndef __DEBUG_${name}_HH__ 10887865Sgblack@eecs.umich.edu#define __DEBUG_${name}_HH__ 10897865Sgblack@eecs.umich.edu 10907840Snate@binkert.orgnamespace Debug { 10919900Sandreas@sandberg.pp.se''') 10929900Sandreas@sandberg.pp.se 10939900Sandreas@sandberg.pp.se if compound: 10949900Sandreas@sandberg.pp.se code('class CompoundFlag;') 109510456SCurtis.Dunham@arm.com code('class SimpleFlag;') 109610456SCurtis.Dunham@arm.com 109710456SCurtis.Dunham@arm.com if compound: 109810456SCurtis.Dunham@arm.com code('extern CompoundFlag $name;') 109910456SCurtis.Dunham@arm.com for flag in compound: 110010456SCurtis.Dunham@arm.com code('extern SimpleFlag $flag;') 110110456SCurtis.Dunham@arm.com else: 110210456SCurtis.Dunham@arm.com code('extern SimpleFlag $name;') 110310456SCurtis.Dunham@arm.com 110410456SCurtis.Dunham@arm.com code(''' 11059045SAli.Saidi@ARM.com} 110611235Sandreas.sandberg@arm.com 110711235Sandreas.sandberg@arm.com#endif // __DEBUG_${name}_HH__ 110811235Sandreas.sandberg@arm.com''') 110911235Sandreas.sandberg@arm.com 111011235Sandreas.sandberg@arm.com code.write(str(target[0])) 111111235Sandreas.sandberg@arm.com 111211235Sandreas.sandberg@arm.comfor name,flag in sorted(debug_flags.iteritems()): 111311235Sandreas.sandberg@arm.com n, compound, desc = flag 111411811Sbaz21@cam.ac.uk assert n == name 111511811Sbaz21@cam.ac.uk 111611811Sbaz21@cam.ac.uk hh_file = 'debug/%s.hh' % name 111711811Sbaz21@cam.ac.uk env.Command(hh_file, Value(flag), 111811811Sbaz21@cam.ac.uk MakeAction(makeDebugFlagHH, Transform("TRACING", 0))) 111911235Sandreas.sandberg@arm.com 112011235Sandreas.sandberg@arm.comenv.Command('debug/flags.cc', Value(debug_flags), 112111235Sandreas.sandberg@arm.com MakeAction(makeDebugFlagCC, Transform("TRACING", 0))) 112211235Sandreas.sandberg@arm.comSource('debug/flags.cc') 112311235Sandreas.sandberg@arm.com 112411235Sandreas.sandberg@arm.com# version tags 112511235Sandreas.sandberg@arm.comtags = \ 11267840Snate@binkert.orgenv.Command('sim/tags.cc', None, 11277840Snate@binkert.org MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET', 11287840Snate@binkert.org Transform("VER TAGS"))) 11291858SN/Aenv.AlwaysBuild(tags) 11301858SN/A 11311858SN/A# Build a small helper that marshals the Python code using the same 11321858SN/A# version of Python as gem5. This is in an unorthodox location to 11331858SN/A# avoid building it for every variant. 11341858SN/Apy_marshal = env.Program('python/marshal.cc')[0] 11359903Sandreas.hansson@arm.com 11369903Sandreas.hansson@arm.com# Embed python files. All .py files that have been indicated by a 11379903Sandreas.hansson@arm.com# PySource() call in a SConscript need to be embedded into the M5 11389903Sandreas.hansson@arm.com# library. To do that, we compile the file to byte code, marshal the 113910841Sandreas.sandberg@arm.com# byte code, compress it, and then generate a c++ file that 11409651SAndreas.Sandberg@ARM.com# inserts the result into an array. 11419903Sandreas.hansson@arm.comdef embedPyFile(target, source, env): 11429651SAndreas.Sandberg@ARM.com def c_str(string): 11439651SAndreas.Sandberg@ARM.com if string is None: 114412056Sgabeblack@google.com return "0" 114512056Sgabeblack@google.com return '"%s"' % string 114612056Sgabeblack@google.com 114712056Sgabeblack@google.com '''Action function to compile a .py into a code object, marshal it, 114812056Sgabeblack@google.com compress it, and stick it into an asm file so the code appears as 114910841Sandreas.sandberg@arm.com just bytes with a label in the data section. The action takes two 115010841Sandreas.sandberg@arm.com sources: 115110841Sandreas.sandberg@arm.com 115210841Sandreas.sandberg@arm.com source[0]: Binary used to marshal Python sources 115310841Sandreas.sandberg@arm.com source[1]: Python script to marshal 115410841Sandreas.sandberg@arm.com ''' 11559651SAndreas.Sandberg@ARM.com 11569651SAndreas.Sandberg@ARM.com import subprocess 11579651SAndreas.Sandberg@ARM.com 11589651SAndreas.Sandberg@ARM.com marshalled = subprocess.check_output([source[0].abspath, str(source[1])]) 11599651SAndreas.Sandberg@ARM.com 11609651SAndreas.Sandberg@ARM.com compressed = zlib.compress(marshalled) 11619651SAndreas.Sandberg@ARM.com data = compressed 11629651SAndreas.Sandberg@ARM.com pysource = PySource.tnodes[source[1]] 11639651SAndreas.Sandberg@ARM.com sym = pysource.symname 116410841Sandreas.sandberg@arm.com 116510841Sandreas.sandberg@arm.com code = code_formatter() 116610841Sandreas.sandberg@arm.com code('''\ 116710841Sandreas.sandberg@arm.com#include "sim/init.hh" 116810841Sandreas.sandberg@arm.com 116910841Sandreas.sandberg@arm.comnamespace { 117010860Sandreas.sandberg@arm.com 117110841Sandreas.sandberg@arm.com''') 117210841Sandreas.sandberg@arm.com blobToCpp(data, 'data_' + sym, code) 117310841Sandreas.sandberg@arm.com code('''\ 117410841Sandreas.sandberg@arm.com 117510841Sandreas.sandberg@arm.com 117610841Sandreas.sandberg@arm.comEmbeddedPython embedded_${sym}( 117710841Sandreas.sandberg@arm.com ${{c_str(pysource.arcname)}}, 117810841Sandreas.sandberg@arm.com ${{c_str(pysource.abspath)}}, 117910841Sandreas.sandberg@arm.com ${{c_str(pysource.modpath)}}, 118010841Sandreas.sandberg@arm.com data_${sym}, 118110841Sandreas.sandberg@arm.com ${{len(data)}}, 11829651SAndreas.Sandberg@ARM.com ${{len(marshalled)}}); 11839651SAndreas.Sandberg@ARM.com 11849986Sandreas@sandberg.pp.se} // anonymous namespace 11859986Sandreas@sandberg.pp.se''') 11869986Sandreas@sandberg.pp.se code.write(str(target[0])) 11879986Sandreas@sandberg.pp.se 11889986Sandreas@sandberg.pp.sefor source in PySource.all: 11899986Sandreas@sandberg.pp.se env.Command(source.cpp, [ py_marshal, source.tnode ], 11905863Snate@binkert.org MakeAction(embedPyFile, Transform("EMBED PY"))) 11915863Snate@binkert.org Source(source.cpp, tags=source.tags, add_tags='python') 11925863Snate@binkert.org 11935863Snate@binkert.org######################################################################## 11946121Snate@binkert.org# 11951858SN/A# Define binaries. Each different build type (debug, opt, etc.) gets 11965863Snate@binkert.org# a slightly different build environment. 11975863Snate@binkert.org# 11985863Snate@binkert.org 11995863Snate@binkert.org# List of constructed environments to pass back to SConstruct 12005863Snate@binkert.orgdate_source = Source('base/date.cc', tags=[]) 12012139SN/A 12024202Sbinkertn@umich.edugem5_binary = Gem5('gem5') 120311308Santhony.gutierrez@amd.com 12044202Sbinkertn@umich.edu# Function to create a new build environment as clone of current 120511308Santhony.gutierrez@amd.com# environment 'env' with modified object suffix and optional stripped 12062139SN/A# binary. Additional keyword arguments are appended to corresponding 12076994Snate@binkert.org# build environment vars. 12086994Snate@binkert.orgdef makeEnv(env, label, objsfx, strip=False, disable_partial=False, **kwargs): 12096994Snate@binkert.org # SCons doesn't know to append a library suffix when there is a '.' in the 12106994Snate@binkert.org # name. Use '_' instead. 12116994Snate@binkert.org libname = 'gem5_' + label 12126994Snate@binkert.org secondary_exename = 'm5.' + label 12136994Snate@binkert.org 12146994Snate@binkert.org new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') 121510319SAndreas.Sandberg@ARM.com new_env.Label = label 12166994Snate@binkert.org new_env.Append(**kwargs) 12176994Snate@binkert.org 12186994Snate@binkert.org lib_sources = Source.all.with_tag('gem5 lib') 12196994Snate@binkert.org 12206994Snate@binkert.org # Without Python, leave out all Python content from the library 12216994Snate@binkert.org # builds. The option doesn't affect gem5 built as a program 12226994Snate@binkert.org if GetOption('without_python'): 12236994Snate@binkert.org lib_sources = lib_sources.without_tag('python') 12246994Snate@binkert.org 12256994Snate@binkert.org static_objs = [] 12266994Snate@binkert.org shared_objs = [] 12272155SN/A 12285863Snate@binkert.org for s in lib_sources.with_tag(Source.ungrouped_tag): 12291869SN/A static_objs.append(s.static(new_env)) 12301869SN/A shared_objs.append(s.shared(new_env)) 12315863Snate@binkert.org 12325863Snate@binkert.org for group in Source.source_groups: 12334202Sbinkertn@umich.edu srcs = lib_sources.with_tag(Source.link_group_tag(group)) 12346108Snate@binkert.org if not srcs: 12356108Snate@binkert.org continue 12366108Snate@binkert.org 12376108Snate@binkert.org group_static = [ s.static(new_env) for s in srcs ] 12389219Spower.jg@gmail.com group_shared = [ s.shared(new_env) for s in srcs ] 12399219Spower.jg@gmail.com 12409219Spower.jg@gmail.com # If partial linking is disabled, add these sources to the build 12419219Spower.jg@gmail.com # directly, and short circuit this loop. 12429219Spower.jg@gmail.com if disable_partial: 12439219Spower.jg@gmail.com static_objs.extend(group_static) 12449219Spower.jg@gmail.com shared_objs.extend(group_shared) 12459219Spower.jg@gmail.com continue 12464202Sbinkertn@umich.edu 12475863Snate@binkert.org # Set up the static partially linked objects. 124810135SCurtis.Dunham@arm.com file_name = new_env.subst("${OBJPREFIX}lib${OBJSUFFIX}.partial") 12498474Sgblack@eecs.umich.edu target = File(joinpath(group, file_name)) 12505742Snate@binkert.org partial = env.PartialStatic(target=target, source=group_static) 12518268Ssteve.reinhardt@amd.com static_objs.extend(partial) 12528268Ssteve.reinhardt@amd.com 12538268Ssteve.reinhardt@amd.com # Set up the shared partially linked objects. 12545742Snate@binkert.org file_name = new_env.subst("${SHOBJPREFIX}lib${SHOBJSUFFIX}.partial") 12555341Sstever@gmail.com target = File(joinpath(group, file_name)) 12568474Sgblack@eecs.umich.edu partial = env.PartialShared(target=target, source=group_shared) 12578474Sgblack@eecs.umich.edu shared_objs.extend(partial) 12585342Sstever@gmail.com 12594202Sbinkertn@umich.edu static_date = date_source.static(new_env) 12604202Sbinkertn@umich.edu new_env.Depends(static_date, static_objs) 126111308Santhony.gutierrez@amd.com static_objs.extend(static_date) 12624202Sbinkertn@umich.edu 12635863Snate@binkert.org shared_date = date_source.shared(new_env) 12645863Snate@binkert.org new_env.Depends(shared_date, shared_objs) 126511308Santhony.gutierrez@amd.com shared_objs.extend(shared_date) 12666994Snate@binkert.org 12676994Snate@binkert.org main_objs = [ s.static(new_env) for s in Source.all.with_tag('main') ] 126810319SAndreas.Sandberg@ARM.com 12695863Snate@binkert.org # First make a library of everything but main() so other programs can 12705863Snate@binkert.org # link against m5. 12715863Snate@binkert.org static_lib = new_env.StaticLibrary(libname, static_objs) 12725863Snate@binkert.org shared_lib = new_env.SharedLibrary(libname, shared_objs) 12735863Snate@binkert.org 12745863Snate@binkert.org # Keep track of the object files generated so far so Executables can 12755863Snate@binkert.org # include them. 12765863Snate@binkert.org new_env['STATIC_OBJS'] = static_objs 12777840Snate@binkert.org new_env['SHARED_OBJS'] = shared_objs 12785863Snate@binkert.org new_env['MAIN_OBJS'] = main_objs 12795952Ssaidi@eecs.umich.edu 12809651SAndreas.Sandberg@ARM.com new_env['STATIC_LIB'] = static_lib 128112056Sgabeblack@google.com new_env['SHARED_LIB'] = shared_lib 128212056Sgabeblack@google.com 128312056Sgabeblack@google.com # Record some settings for building Executables. 128411308Santhony.gutierrez@amd.com new_env['EXE_SUFFIX'] = label 12859219Spower.jg@gmail.com new_env['STRIP_EXES'] = strip 12869219Spower.jg@gmail.com 128711235Sandreas.sandberg@arm.com for cls in ExecutableMeta.all: 128811235Sandreas.sandberg@arm.com cls.declare_all(new_env) 12891869SN/A 12901858SN/A new_env.M5Binary = File(gem5_binary.path(new_env)) 12915863Snate@binkert.org 129211308Santhony.gutierrez@amd.com new_env.Command(secondary_exename, new_env.M5Binary, 129312061Sjason@lowepower.com MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK"))) 129412061Sjason@lowepower.com 12951858SN/A # Set up regression tests. 1296955SN/A SConscript(os.path.join(env.root.abspath, 'tests', 'SConscript'), 1297955SN/A variant_dir=Dir('tests').Dir(new_env.Label), 12981869SN/A exports={ 'env' : new_env }, duplicate=False) 12991869SN/A 13001869SN/A# Start out with the compiler flags common to all compilers, 13011869SN/A# i.e. they all use -g for opt and -g -pg for prof 13021869SN/Accflags = {'debug' : [], 'opt' : ['-g'], 'fast' : [], 'prof' : ['-g', '-pg'], 13035863Snate@binkert.org 'perf' : ['-g']} 13045863Snate@binkert.org 13055863Snate@binkert.org# Start out with the linker flags common to all linkers, i.e. -pg for 13061869SN/A# prof, and -lprofiler for perf. The -lprofile flag is surrounded by 13075863Snate@binkert.org# no-as-needed and as-needed as the binutils linker is too clever and 13081869SN/A# simply doesn't link to the library otherwise. 13095863Snate@binkert.orgldflags = {'debug' : [], 'opt' : [], 'fast' : [], 'prof' : ['-pg'], 13101869SN/A 'perf' : ['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']} 13111869SN/A 13121869SN/A# For Link Time Optimization, the optimisation flags used to compile 13131869SN/A# individual files are decoupled from those used at link time 13148483Sgblack@eecs.umich.edu# (i.e. you can compile with -O3 and perform LTO with -O0), so we need 13151869SN/A# to also update the linker flags based on the target. 13161869SN/Aif env['GCC']: 13171869SN/A if sys.platform == 'sunos5': 13181869SN/A ccflags['debug'] += ['-gstabs+'] 13195863Snate@binkert.org else: 13205863Snate@binkert.org ccflags['debug'] += ['-ggdb3'] 13211869SN/A ldflags['debug'] += ['-O0'] 13225863Snate@binkert.org # opt, fast, prof and perf all share the same cc flags, also add 13235863Snate@binkert.org # the optimization to the ldflags as LTO defers the optimization 13243356Sbinkertn@umich.edu # to link time 13253356Sbinkertn@umich.edu for target in ['opt', 'fast', 'prof', 'perf']: 13263356Sbinkertn@umich.edu ccflags[target] += ['-O3'] 13273356Sbinkertn@umich.edu ldflags[target] += ['-O3'] 13283356Sbinkertn@umich.edu 13294781Snate@binkert.org ccflags['fast'] += env['LTO_CCFLAGS'] 13305863Snate@binkert.org ldflags['fast'] += env['LTO_LDFLAGS'] 13315863Snate@binkert.orgelif env['CLANG']: 13321869SN/A ccflags['debug'] += ['-g', '-O0'] 13331869SN/A # opt, fast, prof and perf all share the same cc flags 13341869SN/A for target in ['opt', 'fast', 'prof', 'perf']: 13356121Snate@binkert.org ccflags[target] += ['-O3'] 13361869SN/Aelse: 133711982Sgabeblack@google.com print('Unknown compiler, please fix compiler options') 133811982Sgabeblack@google.com Exit(1) 133911982Sgabeblack@google.com 134011982Sgabeblack@google.com 134111982Sgabeblack@google.com# To speed things up, we only instantiate the build environments we 134211982Sgabeblack@google.com# need. We try to identify the needed environment for each target; if 134311982Sgabeblack@google.com# we can't, we fall back on instantiating all the environments just to 134411982Sgabeblack@google.com# be safe. 134511982Sgabeblack@google.comtarget_types = ['debug', 'opt', 'fast', 'prof', 'perf'] 134611982Sgabeblack@google.comobj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof', 134711982Sgabeblack@google.com 'gpo' : 'perf'} 134811982Sgabeblack@google.com 134911982Sgabeblack@google.comdef identifyTarget(t): 135011982Sgabeblack@google.com ext = t.split('.')[-1] 135111982Sgabeblack@google.com if ext in target_types: 135211982Sgabeblack@google.com return ext 135311982Sgabeblack@google.com if ext in obj2target: 135411982Sgabeblack@google.com return obj2target[ext] 135511982Sgabeblack@google.com match = re.search(r'/tests/([^/]+)/', t) 135611982Sgabeblack@google.com if match and match.group(1) in target_types: 135711982Sgabeblack@google.com return match.group(1) 135811982Sgabeblack@google.com return 'all' 135911982Sgabeblack@google.com 136011982Sgabeblack@google.comneeded_envs = [identifyTarget(target) for target in BUILD_TARGETS] 136111982Sgabeblack@google.comif 'all' in needed_envs: 136211982Sgabeblack@google.com needed_envs += target_types 136311978Sgabeblack@google.com 136411978Sgabeblack@google.comdisable_partial = False 136512034Sgabeblack@google.comif env['PLATFORM'] == 'darwin': 136611978Sgabeblack@google.com # Up until Apple LLVM version 10.0.0 (clang-1000.11.45.5), partial 136711978Sgabeblack@google.com # linked objects do not expose symbols that are marked with the 136811978Sgabeblack@google.com # hidden visibility and consequently building gem5 on Mac OS 136912034Sgabeblack@google.com # fails. As a workaround, we disable partial linking, however, we 137011978Sgabeblack@google.com # may want to revisit in the future. 137111978Sgabeblack@google.com disable_partial = True 137210915Sandreas.sandberg@arm.com 137311986Sandreas.sandberg@arm.com# Debug binary 137411986Sandreas.sandberg@arm.comif 'debug' in needed_envs: 13751869SN/A makeEnv(env, 'debug', '.do', 13761869SN/A CCFLAGS = Split(ccflags['debug']), 137712015Sgabeblack@google.com CPPDEFINES = ['DEBUG', 'TRACING_ON=1'], 137812015Sgabeblack@google.com LINKFLAGS = Split(ldflags['debug']), 137912015Sgabeblack@google.com disable_partial=disable_partial) 138012015Sgabeblack@google.com 13813546Sgblack@eecs.umich.edu# Optimized binary 13823546Sgblack@eecs.umich.eduif 'opt' in needed_envs: 13833546Sgblack@eecs.umich.edu makeEnv(env, 'opt', '.o', 138412015Sgabeblack@google.com CCFLAGS = Split(ccflags['opt']), 138512015Sgabeblack@google.com CPPDEFINES = ['TRACING_ON=1'], 138612015Sgabeblack@google.com LINKFLAGS = Split(ldflags['opt']), 138712015Sgabeblack@google.com disable_partial=disable_partial) 138812015Sgabeblack@google.com 138912015Sgabeblack@google.com# "Fast" binary 139012015Sgabeblack@google.comif 'fast' in needed_envs: 139112015Sgabeblack@google.com disable_partial = disable_partial and \ 13923546Sgblack@eecs.umich.edu env.get('BROKEN_INCREMENTAL_LTO', False) and \ 139312015Sgabeblack@google.com GetOption('force_lto') 139412015Sgabeblack@google.com makeEnv(env, 'fast', '.fo', strip = True, 139510196SCurtis.Dunham@arm.com CCFLAGS = Split(ccflags['fast']), 139612015Sgabeblack@google.com CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 139712015Sgabeblack@google.com LINKFLAGS = Split(ldflags['fast']), 139812015Sgabeblack@google.com disable_partial=disable_partial) 139912015Sgabeblack@google.com 140012015Sgabeblack@google.com# Profiled binary using gprof 140112015Sgabeblack@google.comif 'prof' in needed_envs: 140212015Sgabeblack@google.com makeEnv(env, 'prof', '.po', 140312015Sgabeblack@google.com CCFLAGS = Split(ccflags['prof']), 140412015Sgabeblack@google.com CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 140512015Sgabeblack@google.com LINKFLAGS = Split(ldflags['prof']), 140612015Sgabeblack@google.com disable_partial=disable_partial) 14073546Sgblack@eecs.umich.edu 140810196SCurtis.Dunham@arm.com# Profiled binary using google-pprof 140910196SCurtis.Dunham@arm.comif 'perf' in needed_envs: 141010196SCurtis.Dunham@arm.com makeEnv(env, 'perf', '.gpo', 141110196SCurtis.Dunham@arm.com CCFLAGS = Split(ccflags['perf']), 141210196SCurtis.Dunham@arm.com CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 141310196SCurtis.Dunham@arm.com LINKFLAGS = Split(ldflags['perf']), 141410196SCurtis.Dunham@arm.com disable_partial=disable_partial) 141510196SCurtis.Dunham@arm.com