SConscript revision 13675:afeab32b3655
113531Sjairo.balart@metempsy.com# -*- mode:python -*- 214167Sgiacomo.travaglini@arm.com 314167Sgiacomo.travaglini@arm.com# Copyright (c) 2018 ARM Limited 414167Sgiacomo.travaglini@arm.com# 514167Sgiacomo.travaglini@arm.com# The license below extends only to copyright in the software and shall 614167Sgiacomo.travaglini@arm.com# not be construed as granting a license to any other intellectual 714167Sgiacomo.travaglini@arm.com# property including but not limited to intellectual property relating 814167Sgiacomo.travaglini@arm.com# to a hardware implementation of the functionality of the software 914167Sgiacomo.travaglini@arm.com# licensed hereunder. You may use the software subject to the license 1014167Sgiacomo.travaglini@arm.com# terms below provided that you ensure that this notice is replicated 1114167Sgiacomo.travaglini@arm.com# unmodified and in its entirety in all distributions of the software, 1214167Sgiacomo.travaglini@arm.com# modified or unmodified, in source code or in binary form. 1314167Sgiacomo.travaglini@arm.com# 1413531Sjairo.balart@metempsy.com# Copyright (c) 2004-2005 The Regents of The University of Michigan 1513531Sjairo.balart@metempsy.com# All rights reserved. 1613531Sjairo.balart@metempsy.com# 1713531Sjairo.balart@metempsy.com# Redistribution and use in source and binary forms, with or without 1813531Sjairo.balart@metempsy.com# modification, are permitted provided that the following conditions are 1913531Sjairo.balart@metempsy.com# met: redistributions of source code must retain the above copyright 2013531Sjairo.balart@metempsy.com# notice, this list of conditions and the following disclaimer; 2113531Sjairo.balart@metempsy.com# redistributions in binary form must reproduce the above copyright 2213531Sjairo.balart@metempsy.com# notice, this list of conditions and the following disclaimer in the 2313531Sjairo.balart@metempsy.com# documentation and/or other materials provided with the distribution; 2413531Sjairo.balart@metempsy.com# neither the name of the copyright holders nor the names of its 2513531Sjairo.balart@metempsy.com# contributors may be used to endorse or promote products derived from 2613531Sjairo.balart@metempsy.com# this software without specific prior written permission. 2713531Sjairo.balart@metempsy.com# 2813531Sjairo.balart@metempsy.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2913531Sjairo.balart@metempsy.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3013531Sjairo.balart@metempsy.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3113531Sjairo.balart@metempsy.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3213531Sjairo.balart@metempsy.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3313531Sjairo.balart@metempsy.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3413531Sjairo.balart@metempsy.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3513531Sjairo.balart@metempsy.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3613531Sjairo.balart@metempsy.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3713531Sjairo.balart@metempsy.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3813531Sjairo.balart@metempsy.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3913531Sjairo.balart@metempsy.com# 4013531Sjairo.balart@metempsy.com# Authors: Nathan Binkert 4113531Sjairo.balart@metempsy.com 4213756Sjairo.balart@metempsy.comfrom __future__ import print_function 4313531Sjairo.balart@metempsy.com 4413531Sjairo.balart@metempsy.comimport array 4513531Sjairo.balart@metempsy.comimport bisect 4613531Sjairo.balart@metempsy.comimport functools 4714257Sgiacomo.travaglini@arm.comimport imp 4813531Sjairo.balart@metempsy.comimport marshal 4913531Sjairo.balart@metempsy.comimport os 5013531Sjairo.balart@metempsy.comimport re 5113531Sjairo.balart@metempsy.comimport subprocess 5213531Sjairo.balart@metempsy.comimport sys 5313756Sjairo.balart@metempsy.comimport zlib 5413756Sjairo.balart@metempsy.com 5513756Sjairo.balart@metempsy.comfrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath 5613756Sjairo.balart@metempsy.com 5713756Sjairo.balart@metempsy.comimport SCons 5813756Sjairo.balart@metempsy.com 5913756Sjairo.balart@metempsy.comfrom gem5_scons import Transform 6013531Sjairo.balart@metempsy.com 6113756Sjairo.balart@metempsy.com# This file defines how to build a particular configuration of gem5 6213756Sjairo.balart@metempsy.com# based on variable settings in the 'env' build environment. 6313756Sjairo.balart@metempsy.com 6413756Sjairo.balart@metempsy.comImport('*') 6513756Sjairo.balart@metempsy.com 6613756Sjairo.balart@metempsy.com# Children need to see the environment 6713756Sjairo.balart@metempsy.comExport('env') 6813531Sjairo.balart@metempsy.com 6913531Sjairo.balart@metempsy.combuild_env = [(opt, env[opt]) for opt in export_vars] 7013531Sjairo.balart@metempsy.com 7113531Sjairo.balart@metempsy.comfrom m5.util import code_formatter, compareVersions 7214258Sgiacomo.travaglini@arm.com 7314258Sgiacomo.travaglini@arm.com######################################################################## 7414258Sgiacomo.travaglini@arm.com# Code for adding source files of various types 7514258Sgiacomo.travaglini@arm.com# 7614258Sgiacomo.travaglini@arm.com# When specifying a source file of some type, a set of tags can be 7714258Sgiacomo.travaglini@arm.com# specified for that file. 7814258Sgiacomo.travaglini@arm.com 7914258Sgiacomo.travaglini@arm.comclass SourceFilter(object): 8014258Sgiacomo.travaglini@arm.com def __init__(self, predicate): 8114258Sgiacomo.travaglini@arm.com self.predicate = predicate 8214258Sgiacomo.travaglini@arm.com 8314258Sgiacomo.travaglini@arm.com def __or__(self, other): 8414258Sgiacomo.travaglini@arm.com return SourceFilter(lambda tags: self.predicate(tags) or 8514257Sgiacomo.travaglini@arm.com other.predicate(tags)) 8614167Sgiacomo.travaglini@arm.com 8714167Sgiacomo.travaglini@arm.com def __and__(self, other): 8814167Sgiacomo.travaglini@arm.com return SourceFilter(lambda tags: self.predicate(tags) and 8914167Sgiacomo.travaglini@arm.com other.predicate(tags)) 9014167Sgiacomo.travaglini@arm.com 9113531Sjairo.balart@metempsy.comdef with_tags_that(predicate): 9213531Sjairo.balart@metempsy.com '''Return a list of sources with tags that satisfy a predicate.''' 9314257Sgiacomo.travaglini@arm.com return SourceFilter(predicate) 9414257Sgiacomo.travaglini@arm.com 9514257Sgiacomo.travaglini@arm.comdef with_any_tags(*tags): 9614257Sgiacomo.travaglini@arm.com '''Return a list of sources with any of the supplied tags.''' 9714257Sgiacomo.travaglini@arm.com return SourceFilter(lambda stags: len(set(tags) & stags) > 0) 9814257Sgiacomo.travaglini@arm.com 9914257Sgiacomo.travaglini@arm.comdef with_all_tags(*tags): 10014257Sgiacomo.travaglini@arm.com '''Return a list of sources with all of the supplied tags.''' 10114257Sgiacomo.travaglini@arm.com return SourceFilter(lambda stags: set(tags) <= stags) 10214257Sgiacomo.travaglini@arm.com 10314257Sgiacomo.travaglini@arm.comdef with_tag(tag): 10414257Sgiacomo.travaglini@arm.com '''Return a list of sources with the supplied tag.''' 10514257Sgiacomo.travaglini@arm.com return SourceFilter(lambda stags: tag in stags) 10614257Sgiacomo.travaglini@arm.com 10714257Sgiacomo.travaglini@arm.comdef without_tags(*tags): 10814257Sgiacomo.travaglini@arm.com '''Return a list of sources without any of the supplied tags.''' 10914257Sgiacomo.travaglini@arm.com return SourceFilter(lambda stags: len(set(tags) & stags) == 0) 11014257Sgiacomo.travaglini@arm.com 11114257Sgiacomo.travaglini@arm.comdef without_tag(tag): 11214257Sgiacomo.travaglini@arm.com '''Return a list of sources with the supplied tag.''' 11314257Sgiacomo.travaglini@arm.com return SourceFilter(lambda stags: tag not in stags) 11414257Sgiacomo.travaglini@arm.com 11514257Sgiacomo.travaglini@arm.comsource_filter_factories = { 11614257Sgiacomo.travaglini@arm.com 'with_tags_that': with_tags_that, 11714257Sgiacomo.travaglini@arm.com 'with_any_tags': with_any_tags, 11814257Sgiacomo.travaglini@arm.com 'with_all_tags': with_all_tags, 11914257Sgiacomo.travaglini@arm.com 'with_tag': with_tag, 12014257Sgiacomo.travaglini@arm.com 'without_tags': without_tags, 12114257Sgiacomo.travaglini@arm.com 'without_tag': without_tag, 12214257Sgiacomo.travaglini@arm.com} 12314257Sgiacomo.travaglini@arm.com 12413531Sjairo.balart@metempsy.comExport(source_filter_factories) 12513531Sjairo.balart@metempsy.com 12613531Sjairo.balart@metempsy.comclass SourceList(list): 12713531Sjairo.balart@metempsy.com def apply_filter(self, f): 12813531Sjairo.balart@metempsy.com def match(source): 12913531Sjairo.balart@metempsy.com return f.predicate(source.tags) 13014258Sgiacomo.travaglini@arm.com return SourceList(filter(match, self)) 13113531Sjairo.balart@metempsy.com 13214258Sgiacomo.travaglini@arm.com def __getattr__(self, name): 13314258Sgiacomo.travaglini@arm.com func = source_filter_factories.get(name, None) 13414258Sgiacomo.travaglini@arm.com if not func: 13513531Sjairo.balart@metempsy.com raise AttributeError 13613531Sjairo.balart@metempsy.com 13713531Sjairo.balart@metempsy.com @functools.wraps(func) 13813531Sjairo.balart@metempsy.com def wrapper(*args, **kwargs): 13913531Sjairo.balart@metempsy.com return self.apply_filter(func(*args, **kwargs)) 14013531Sjairo.balart@metempsy.com return wrapper 14113531Sjairo.balart@metempsy.com 14213531Sjairo.balart@metempsy.comclass SourceMeta(type): 14313531Sjairo.balart@metempsy.com '''Meta class for source files that keeps track of all files of a 14413531Sjairo.balart@metempsy.com particular type.''' 14513531Sjairo.balart@metempsy.com def __init__(cls, name, bases, dict): 14613531Sjairo.balart@metempsy.com super(SourceMeta, cls).__init__(name, bases, dict) 14713531Sjairo.balart@metempsy.com cls.all = SourceList() 14813531Sjairo.balart@metempsy.com 14913531Sjairo.balart@metempsy.comclass SourceFile(object): 15013531Sjairo.balart@metempsy.com '''Base object that encapsulates the notion of a source file. 15113531Sjairo.balart@metempsy.com This includes, the source node, target node, various manipulations 15213531Sjairo.balart@metempsy.com of those. A source file also specifies a set of tags which 15313531Sjairo.balart@metempsy.com describing arbitrary properties of the source file.''' 15413531Sjairo.balart@metempsy.com __metaclass__ = SourceMeta 15513756Sjairo.balart@metempsy.com 15613531Sjairo.balart@metempsy.com static_objs = {} 15713531Sjairo.balart@metempsy.com shared_objs = {} 15813531Sjairo.balart@metempsy.com 15913531Sjairo.balart@metempsy.com def __init__(self, source, tags=None, add_tags=None): 16013756Sjairo.balart@metempsy.com if tags is None: 16113531Sjairo.balart@metempsy.com tags='gem5 lib' 16213531Sjairo.balart@metempsy.com if isinstance(tags, basestring): 16313531Sjairo.balart@metempsy.com tags = set([tags]) 16413531Sjairo.balart@metempsy.com if not isinstance(tags, set): 16513531Sjairo.balart@metempsy.com tags = set(tags) 16613531Sjairo.balart@metempsy.com self.tags = tags 16713531Sjairo.balart@metempsy.com 16813531Sjairo.balart@metempsy.com if add_tags: 16913531Sjairo.balart@metempsy.com if isinstance(add_tags, basestring): 17013756Sjairo.balart@metempsy.com add_tags = set([add_tags]) 17113756Sjairo.balart@metempsy.com if not isinstance(add_tags, set): 17213531Sjairo.balart@metempsy.com add_tags = set(add_tags) 17313531Sjairo.balart@metempsy.com self.tags |= add_tags 17413531Sjairo.balart@metempsy.com 17513531Sjairo.balart@metempsy.com tnode = source 17613531Sjairo.balart@metempsy.com if not isinstance(source, SCons.Node.FS.File): 17713531Sjairo.balart@metempsy.com tnode = File(source) 17813531Sjairo.balart@metempsy.com 17913531Sjairo.balart@metempsy.com self.tnode = tnode 18013531Sjairo.balart@metempsy.com self.snode = tnode.srcnode() 18113531Sjairo.balart@metempsy.com 18213531Sjairo.balart@metempsy.com for base in type(self).__mro__: 18313531Sjairo.balart@metempsy.com if issubclass(base, SourceFile): 18413531Sjairo.balart@metempsy.com base.all.append(self) 18513531Sjairo.balart@metempsy.com 18613531Sjairo.balart@metempsy.com def static(self, env): 18713531Sjairo.balart@metempsy.com key = (self.tnode, env['OBJSUFFIX']) 18813531Sjairo.balart@metempsy.com if not key in self.static_objs: 18913531Sjairo.balart@metempsy.com self.static_objs[key] = env.StaticObject(self.tnode) 19013531Sjairo.balart@metempsy.com return self.static_objs[key] 19113756Sjairo.balart@metempsy.com 19213756Sjairo.balart@metempsy.com def shared(self, env): 19313531Sjairo.balart@metempsy.com key = (self.tnode, env['OBJSUFFIX']) 19413531Sjairo.balart@metempsy.com if not key in self.shared_objs: 19513531Sjairo.balart@metempsy.com self.shared_objs[key] = env.SharedObject(self.tnode) 19613531Sjairo.balart@metempsy.com return self.shared_objs[key] 19713531Sjairo.balart@metempsy.com 19813531Sjairo.balart@metempsy.com @property 19913531Sjairo.balart@metempsy.com def filename(self): 20013531Sjairo.balart@metempsy.com return str(self.tnode) 20113531Sjairo.balart@metempsy.com 20213531Sjairo.balart@metempsy.com @property 20313756Sjairo.balart@metempsy.com def dirname(self): 20413531Sjairo.balart@metempsy.com return dirname(self.filename) 20513531Sjairo.balart@metempsy.com 20613531Sjairo.balart@metempsy.com @property 20713531Sjairo.balart@metempsy.com def basename(self): 20813531Sjairo.balart@metempsy.com return basename(self.filename) 20913531Sjairo.balart@metempsy.com 21013531Sjairo.balart@metempsy.com @property 21113531Sjairo.balart@metempsy.com def extname(self): 21213756Sjairo.balart@metempsy.com index = self.basename.rfind('.') 21313756Sjairo.balart@metempsy.com if index <= 0: 21413531Sjairo.balart@metempsy.com # dot files aren't extensions 21513531Sjairo.balart@metempsy.com return self.basename, None 21613531Sjairo.balart@metempsy.com 21713531Sjairo.balart@metempsy.com return self.basename[:index], self.basename[index+1:] 21813531Sjairo.balart@metempsy.com 21913531Sjairo.balart@metempsy.com def __lt__(self, other): return self.filename < other.filename 22013531Sjairo.balart@metempsy.com def __le__(self, other): return self.filename <= other.filename 22113531Sjairo.balart@metempsy.com def __gt__(self, other): return self.filename > other.filename 22213531Sjairo.balart@metempsy.com def __ge__(self, other): return self.filename >= other.filename 22313531Sjairo.balart@metempsy.com def __eq__(self, other): return self.filename == other.filename 22413531Sjairo.balart@metempsy.com def __ne__(self, other): return self.filename != other.filename 22513531Sjairo.balart@metempsy.com 22613531Sjairo.balart@metempsy.comdef blobToCpp(data, symbol, cpp_code, hpp_code=None, namespace=None): 22713756Sjairo.balart@metempsy.com ''' 22813531Sjairo.balart@metempsy.com Convert bytes data into C++ .cpp and .hh uint8_t byte array 22913531Sjairo.balart@metempsy.com code containing that binary data. 23013531Sjairo.balart@metempsy.com 23113531Sjairo.balart@metempsy.com :param data: binary data to be converted to C++ 23213531Sjairo.balart@metempsy.com :param symbol: name of the symbol 23313531Sjairo.balart@metempsy.com :param cpp_code: append the generated cpp_code to this object 23413531Sjairo.balart@metempsy.com :param hpp_code: append the generated hpp_code to this object 23513531Sjairo.balart@metempsy.com If None, ignore it. Otherwise, also include it 23613756Sjairo.balart@metempsy.com in the .cpp file. 23713756Sjairo.balart@metempsy.com :param namespace: namespace to put the symbol into. If None, 23813531Sjairo.balart@metempsy.com don't put the symbols into any namespace. 23913531Sjairo.balart@metempsy.com ''' 24013531Sjairo.balart@metempsy.com symbol_len_declaration = 'const std::size_t {}_len'.format(symbol) 24113531Sjairo.balart@metempsy.com symbol_declaration = 'const std::uint8_t {}[]'.format(symbol) 24213531Sjairo.balart@metempsy.com if hpp_code is not None: 24313531Sjairo.balart@metempsy.com cpp_code('''\ 24413531Sjairo.balart@metempsy.com#include "blobs/{}.hh" 24513531Sjairo.balart@metempsy.com'''.format(symbol)) 24613531Sjairo.balart@metempsy.com hpp_code('''\ 24713531Sjairo.balart@metempsy.com#include <cstddef> 24813531Sjairo.balart@metempsy.com#include <cstdint> 24913531Sjairo.balart@metempsy.com''') 25013756Sjairo.balart@metempsy.com if namespace is not None: 25113531Sjairo.balart@metempsy.com hpp_code('namespace {} {{'.format(namespace)) 25213531Sjairo.balart@metempsy.com hpp_code('extern ' + symbol_len_declaration + ';') 25313531Sjairo.balart@metempsy.com hpp_code('extern ' + symbol_declaration + ';') 25413531Sjairo.balart@metempsy.com if namespace is not None: 25513531Sjairo.balart@metempsy.com hpp_code('}') 25613531Sjairo.balart@metempsy.com if namespace is not None: 25713531Sjairo.balart@metempsy.com cpp_code('namespace {} {{'.format(namespace)) 25813531Sjairo.balart@metempsy.com if hpp_code is not None: 25913531Sjairo.balart@metempsy.com cpp_code(symbol_len_declaration + ' = {};'.format(len(data))) 26013531Sjairo.balart@metempsy.com cpp_code(symbol_declaration + ' = {') 26113756Sjairo.balart@metempsy.com cpp_code.indent() 26213756Sjairo.balart@metempsy.com step = 16 26313531Sjairo.balart@metempsy.com for i in xrange(0, len(data), step): 26413531Sjairo.balart@metempsy.com x = array.array('B', data[i:i+step]) 26513531Sjairo.balart@metempsy.com cpp_code(''.join('%d,' % d for d in x)) 26613531Sjairo.balart@metempsy.com cpp_code.dedent() 26713531Sjairo.balart@metempsy.com cpp_code('};') 26813531Sjairo.balart@metempsy.com if namespace is not None: 26913531Sjairo.balart@metempsy.com cpp_code('}') 27013531Sjairo.balart@metempsy.com 27113531Sjairo.balart@metempsy.comdef Blob(blob_path, symbol): 27213531Sjairo.balart@metempsy.com ''' 27313531Sjairo.balart@metempsy.com Embed an arbitrary blob into the gem5 executable, 27413531Sjairo.balart@metempsy.com and make it accessible to C++ as a byte array. 27513756Sjairo.balart@metempsy.com ''' 27613531Sjairo.balart@metempsy.com blob_path = os.path.abspath(blob_path) 27713531Sjairo.balart@metempsy.com blob_out_dir = os.path.join(env['BUILDDIR'], 'blobs') 27813531Sjairo.balart@metempsy.com path_noext = joinpath(blob_out_dir, symbol) 27913531Sjairo.balart@metempsy.com cpp_path = path_noext + '.cc' 28013531Sjairo.balart@metempsy.com hpp_path = path_noext + '.hh' 28113531Sjairo.balart@metempsy.com def embedBlob(target, source, env): 28213531Sjairo.balart@metempsy.com data = file(str(source[0]), 'r').read() 28313531Sjairo.balart@metempsy.com cpp_code = code_formatter() 28413531Sjairo.balart@metempsy.com hpp_code = code_formatter() 28513531Sjairo.balart@metempsy.com blobToCpp(data, symbol, cpp_code, hpp_code, namespace='Blobs') 28613756Sjairo.balart@metempsy.com cpp_path = str(target[0]) 28713756Sjairo.balart@metempsy.com hpp_path = str(target[1]) 28813531Sjairo.balart@metempsy.com cpp_dir = os.path.split(cpp_path)[0] 28913531Sjairo.balart@metempsy.com if not os.path.exists(cpp_dir): 29013531Sjairo.balart@metempsy.com os.makedirs(cpp_dir) 29113531Sjairo.balart@metempsy.com cpp_code.write(cpp_path) 29213531Sjairo.balart@metempsy.com hpp_code.write(hpp_path) 29313531Sjairo.balart@metempsy.com env.Command([cpp_path, hpp_path], blob_path, 29413531Sjairo.balart@metempsy.com MakeAction(embedBlob, Transform("EMBED BLOB"))) 29513531Sjairo.balart@metempsy.com Source(cpp_path) 29613531Sjairo.balart@metempsy.com 29713531Sjairo.balart@metempsy.comdef GdbXml(xml_id, symbol): 29813531Sjairo.balart@metempsy.com Blob(joinpath(gdb_xml_dir, xml_id), symbol) 29913756Sjairo.balart@metempsy.com 30013531Sjairo.balart@metempsy.comclass Source(SourceFile): 30113531Sjairo.balart@metempsy.com ungrouped_tag = 'No link group' 30213531Sjairo.balart@metempsy.com source_groups = set() 30313531Sjairo.balart@metempsy.com 30413531Sjairo.balart@metempsy.com _current_group_tag = ungrouped_tag 30513531Sjairo.balart@metempsy.com 30613531Sjairo.balart@metempsy.com @staticmethod 30713531Sjairo.balart@metempsy.com def link_group_tag(group): 30813531Sjairo.balart@metempsy.com return 'link group: %s' % group 30913756Sjairo.balart@metempsy.com 31013756Sjairo.balart@metempsy.com @classmethod 31113531Sjairo.balart@metempsy.com def set_group(cls, group): 31213531Sjairo.balart@metempsy.com new_tag = Source.link_group_tag(group) 31313531Sjairo.balart@metempsy.com Source._current_group_tag = new_tag 31413531Sjairo.balart@metempsy.com Source.source_groups.add(group) 31513531Sjairo.balart@metempsy.com 31613531Sjairo.balart@metempsy.com def _add_link_group_tag(self): 31713531Sjairo.balart@metempsy.com self.tags.add(Source._current_group_tag) 31813531Sjairo.balart@metempsy.com 31913531Sjairo.balart@metempsy.com '''Add a c/c++ source file to the build''' 32013531Sjairo.balart@metempsy.com def __init__(self, source, tags=None, add_tags=None): 32113531Sjairo.balart@metempsy.com '''specify the source file, and any tags''' 32213531Sjairo.balart@metempsy.com super(Source, self).__init__(source, tags, add_tags) 32313531Sjairo.balart@metempsy.com self._add_link_group_tag() 32413531Sjairo.balart@metempsy.com 32513531Sjairo.balart@metempsy.comclass PySource(SourceFile): 32613531Sjairo.balart@metempsy.com '''Add a python source file to the named package''' 32713531Sjairo.balart@metempsy.com invalid_sym_char = re.compile('[^A-z0-9_]') 32813531Sjairo.balart@metempsy.com modules = {} 32913531Sjairo.balart@metempsy.com tnodes = {} 33013531Sjairo.balart@metempsy.com symnames = {} 33113531Sjairo.balart@metempsy.com 33213531Sjairo.balart@metempsy.com def __init__(self, package, source, tags=None, add_tags=None): 33313756Sjairo.balart@metempsy.com '''specify the python package, the source file, and any tags''' 33413531Sjairo.balart@metempsy.com super(PySource, self).__init__(source, tags, add_tags) 33513531Sjairo.balart@metempsy.com 33613531Sjairo.balart@metempsy.com modname,ext = self.extname 33713531Sjairo.balart@metempsy.com assert ext == 'py' 33813531Sjairo.balart@metempsy.com 33913531Sjairo.balart@metempsy.com if package: 34013531Sjairo.balart@metempsy.com path = package.split('.') 34113531Sjairo.balart@metempsy.com else: 34213531Sjairo.balart@metempsy.com path = [] 34313531Sjairo.balart@metempsy.com 34413756Sjairo.balart@metempsy.com modpath = path[:] 34513756Sjairo.balart@metempsy.com if modname != '__init__': 34613531Sjairo.balart@metempsy.com modpath += [ modname ] 34713531Sjairo.balart@metempsy.com modpath = '.'.join(modpath) 34813531Sjairo.balart@metempsy.com 34913531Sjairo.balart@metempsy.com arcpath = path + [ self.basename ] 35013531Sjairo.balart@metempsy.com abspath = self.snode.abspath 35113531Sjairo.balart@metempsy.com if not exists(abspath): 35213531Sjairo.balart@metempsy.com abspath = self.tnode.abspath 35313531Sjairo.balart@metempsy.com 35413531Sjairo.balart@metempsy.com self.package = package 35513531Sjairo.balart@metempsy.com self.modname = modname 35613531Sjairo.balart@metempsy.com self.modpath = modpath 35713531Sjairo.balart@metempsy.com self.arcname = joinpath(*arcpath) 35813531Sjairo.balart@metempsy.com self.abspath = abspath 35913531Sjairo.balart@metempsy.com self.compiled = File(self.filename + 'c') 36013531Sjairo.balart@metempsy.com self.cpp = File(self.filename + '.cc') 36113531Sjairo.balart@metempsy.com self.symname = PySource.invalid_sym_char.sub('_', modpath) 36213531Sjairo.balart@metempsy.com 36313531Sjairo.balart@metempsy.com PySource.modules[modpath] = self 36413531Sjairo.balart@metempsy.com PySource.tnodes[self.tnode] = self 36513531Sjairo.balart@metempsy.com PySource.symnames[self.symname] = self 36613531Sjairo.balart@metempsy.com 36713531Sjairo.balart@metempsy.comclass SimObject(PySource): 36813531Sjairo.balart@metempsy.com '''Add a SimObject python file as a python source object and add 36913531Sjairo.balart@metempsy.com it to a list of sim object modules''' 37013531Sjairo.balart@metempsy.com 37113531Sjairo.balart@metempsy.com fixed = False 37213531Sjairo.balart@metempsy.com modnames = [] 37313531Sjairo.balart@metempsy.com 37413531Sjairo.balart@metempsy.com def __init__(self, source, tags=None, add_tags=None): 37513531Sjairo.balart@metempsy.com '''Specify the source file and any tags (automatically in 37613756Sjairo.balart@metempsy.com the m5.objects package)''' 37713531Sjairo.balart@metempsy.com super(SimObject, self).__init__('m5.objects', source, tags, add_tags) 37813531Sjairo.balart@metempsy.com if self.fixed: 37913531Sjairo.balart@metempsy.com raise AttributeError, "Too late to call SimObject now." 38013531Sjairo.balart@metempsy.com 38113531Sjairo.balart@metempsy.com bisect.insort_right(SimObject.modnames, self.modname) 38213531Sjairo.balart@metempsy.com 38313756Sjairo.balart@metempsy.comclass ProtoBuf(SourceFile): 38413531Sjairo.balart@metempsy.com '''Add a Protocol Buffer to build''' 38513531Sjairo.balart@metempsy.com 38613531Sjairo.balart@metempsy.com def __init__(self, source, tags=None, add_tags=None): 38713531Sjairo.balart@metempsy.com '''Specify the source file, and any tags''' 38813531Sjairo.balart@metempsy.com super(ProtoBuf, self).__init__(source, tags, add_tags) 38913531Sjairo.balart@metempsy.com 39013531Sjairo.balart@metempsy.com # Get the file name and the extension 39113531Sjairo.balart@metempsy.com modname,ext = self.extname 39213531Sjairo.balart@metempsy.com assert ext == 'proto' 39313531Sjairo.balart@metempsy.com 39413531Sjairo.balart@metempsy.com # Currently, we stick to generating the C++ headers, so we 39513531Sjairo.balart@metempsy.com # only need to track the source and header. 39613531Sjairo.balart@metempsy.com self.cc_file = File(modname + '.pb.cc') 39713531Sjairo.balart@metempsy.com self.hh_file = File(modname + '.pb.h') 39813531Sjairo.balart@metempsy.com 39913756Sjairo.balart@metempsy.com 40013531Sjairo.balart@metempsy.comexectuable_classes = [] 40113531Sjairo.balart@metempsy.comclass ExecutableMeta(type): 40213531Sjairo.balart@metempsy.com '''Meta class for Executables.''' 40313531Sjairo.balart@metempsy.com all = [] 40413531Sjairo.balart@metempsy.com 40513531Sjairo.balart@metempsy.com def __init__(cls, name, bases, d): 40613531Sjairo.balart@metempsy.com if not d.pop('abstract', False): 40713531Sjairo.balart@metempsy.com ExecutableMeta.all.append(cls) 40813531Sjairo.balart@metempsy.com super(ExecutableMeta, cls).__init__(name, bases, d) 40913531Sjairo.balart@metempsy.com 41013531Sjairo.balart@metempsy.com cls.all = [] 41113531Sjairo.balart@metempsy.com 41213531Sjairo.balart@metempsy.comclass Executable(object): 41313531Sjairo.balart@metempsy.com '''Base class for creating an executable from sources.''' 41413531Sjairo.balart@metempsy.com __metaclass__ = ExecutableMeta 41513531Sjairo.balart@metempsy.com 41613531Sjairo.balart@metempsy.com abstract = True 41713531Sjairo.balart@metempsy.com 41813531Sjairo.balart@metempsy.com def __init__(self, target, *srcs_and_filts): 41913531Sjairo.balart@metempsy.com '''Specify the target name and any sources. Sources that are 42013531Sjairo.balart@metempsy.com not SourceFiles are evalued with Source().''' 42113531Sjairo.balart@metempsy.com super(Executable, self).__init__() 42213531Sjairo.balart@metempsy.com self.all.append(self) 42313531Sjairo.balart@metempsy.com self.target = target 42413531Sjairo.balart@metempsy.com 42513531Sjairo.balart@metempsy.com isFilter = lambda arg: isinstance(arg, SourceFilter) 42613531Sjairo.balart@metempsy.com self.filters = filter(isFilter, srcs_and_filts) 42713531Sjairo.balart@metempsy.com sources = filter(lambda a: not isFilter(a), srcs_and_filts) 42813531Sjairo.balart@metempsy.com 42913531Sjairo.balart@metempsy.com srcs = SourceList() 43013531Sjairo.balart@metempsy.com for src in sources: 43113531Sjairo.balart@metempsy.com if not isinstance(src, SourceFile): 43213531Sjairo.balart@metempsy.com src = Source(src, tags=[]) 43313531Sjairo.balart@metempsy.com srcs.append(src) 43413531Sjairo.balart@metempsy.com 43513531Sjairo.balart@metempsy.com self.sources = srcs 43613531Sjairo.balart@metempsy.com self.dir = Dir('.') 43713531Sjairo.balart@metempsy.com 43813531Sjairo.balart@metempsy.com def path(self, env): 43913531Sjairo.balart@metempsy.com return self.dir.File(self.target + '.' + env['EXE_SUFFIX']) 44013531Sjairo.balart@metempsy.com 44113531Sjairo.balart@metempsy.com def srcs_to_objs(self, env, sources): 44213531Sjairo.balart@metempsy.com return list([ s.static(env) for s in sources ]) 44313531Sjairo.balart@metempsy.com 44413531Sjairo.balart@metempsy.com @classmethod 44513531Sjairo.balart@metempsy.com def declare_all(cls, env): 44613531Sjairo.balart@metempsy.com return list([ instance.declare(env) for instance in cls.all ]) 44713531Sjairo.balart@metempsy.com 44813531Sjairo.balart@metempsy.com def declare(self, env, objs=None): 44913531Sjairo.balart@metempsy.com if objs is None: 45013531Sjairo.balart@metempsy.com objs = self.srcs_to_objs(env, self.sources) 45113531Sjairo.balart@metempsy.com 45213531Sjairo.balart@metempsy.com if env['STRIP_EXES']: 45313531Sjairo.balart@metempsy.com stripped = self.path(env) 45413531Sjairo.balart@metempsy.com unstripped = env.File(str(stripped) + '.unstripped') 45513531Sjairo.balart@metempsy.com if sys.platform == 'sunos5': 45613531Sjairo.balart@metempsy.com cmd = 'cp $SOURCE $TARGET; strip $TARGET' 45713531Sjairo.balart@metempsy.com else: 45813531Sjairo.balart@metempsy.com cmd = 'strip $SOURCE -o $TARGET' 45913531Sjairo.balart@metempsy.com env.Program(unstripped, objs) 46013531Sjairo.balart@metempsy.com return env.Command(stripped, unstripped, 46113531Sjairo.balart@metempsy.com MakeAction(cmd, Transform("STRIP"))) 46213531Sjairo.balart@metempsy.com else: 46313531Sjairo.balart@metempsy.com return env.Program(self.path(env), objs) 46413531Sjairo.balart@metempsy.com 46513531Sjairo.balart@metempsy.comclass UnitTest(Executable): 46613531Sjairo.balart@metempsy.com '''Create a UnitTest''' 46713531Sjairo.balart@metempsy.com def __init__(self, target, *srcs_and_filts, **kwargs): 46813531Sjairo.balart@metempsy.com super(UnitTest, self).__init__(target, *srcs_and_filts) 46913531Sjairo.balart@metempsy.com 47014257Sgiacomo.travaglini@arm.com self.main = kwargs.get('main', False) 47113531Sjairo.balart@metempsy.com 47213531Sjairo.balart@metempsy.com def declare(self, env): 47313531Sjairo.balart@metempsy.com sources = list(self.sources) 47413531Sjairo.balart@metempsy.com for f in self.filters: 47513531Sjairo.balart@metempsy.com sources += Source.all.apply_filter(f) 47613531Sjairo.balart@metempsy.com objs = self.srcs_to_objs(env, sources) + env['STATIC_OBJS'] 47713531Sjairo.balart@metempsy.com if self.main: 47813531Sjairo.balart@metempsy.com objs += env['MAIN_OBJS'] 47913531Sjairo.balart@metempsy.com return super(UnitTest, self).declare(env, objs) 48013756Sjairo.balart@metempsy.com 48114167Sgiacomo.travaglini@arm.comclass GTest(Executable): 48213531Sjairo.balart@metempsy.com '''Create a unit test based on the google test framework.''' 48314167Sgiacomo.travaglini@arm.com all = [] 48414167Sgiacomo.travaglini@arm.com def __init__(self, *srcs_and_filts, **kwargs): 48513531Sjairo.balart@metempsy.com super(GTest, self).__init__(*srcs_and_filts) 48614167Sgiacomo.travaglini@arm.com 48714167Sgiacomo.travaglini@arm.com self.skip_lib = kwargs.pop('skip_lib', False) 48813531Sjairo.balart@metempsy.com 48913531Sjairo.balart@metempsy.com @classmethod 49014167Sgiacomo.travaglini@arm.com def declare_all(cls, env): 49113531Sjairo.balart@metempsy.com env = env.Clone() 49214167Sgiacomo.travaglini@arm.com env.Append(LIBS=env['GTEST_LIBS']) 49314167Sgiacomo.travaglini@arm.com env.Append(CPPFLAGS=env['GTEST_CPPFLAGS']) 49413531Sjairo.balart@metempsy.com env['GTEST_LIB_SOURCES'] = Source.all.with_tag('gtest lib') 49513531Sjairo.balart@metempsy.com env['GTEST_OUT_DIR'] = \ 49613531Sjairo.balart@metempsy.com Dir(env['BUILDDIR']).Dir('unittests.' + env['EXE_SUFFIX']) 49713531Sjairo.balart@metempsy.com return super(GTest, cls).declare_all(env) 49813531Sjairo.balart@metempsy.com 49913531Sjairo.balart@metempsy.com def declare(self, env): 50013531Sjairo.balart@metempsy.com sources = list(self.sources) 50113531Sjairo.balart@metempsy.com if not self.skip_lib: 50213531Sjairo.balart@metempsy.com sources += env['GTEST_LIB_SOURCES'] 50313531Sjairo.balart@metempsy.com for f in self.filters: 50413531Sjairo.balart@metempsy.com sources += Source.all.apply_filter(f) 50513531Sjairo.balart@metempsy.com objs = self.srcs_to_objs(env, sources) 50613531Sjairo.balart@metempsy.com 50713531Sjairo.balart@metempsy.com binary = super(GTest, self).declare(env, objs) 50813531Sjairo.balart@metempsy.com 50913531Sjairo.balart@metempsy.com out_dir = env['GTEST_OUT_DIR'] 51013531Sjairo.balart@metempsy.com xml_file = out_dir.Dir(str(self.dir)).File(self.target + '.xml') 51113531Sjairo.balart@metempsy.com AlwaysBuild(env.Command(xml_file, binary, 51213531Sjairo.balart@metempsy.com "${SOURCES[0]} --gtest_output=xml:${TARGETS[0]}")) 51313531Sjairo.balart@metempsy.com 51413531Sjairo.balart@metempsy.com return binary 51513531Sjairo.balart@metempsy.com 51613531Sjairo.balart@metempsy.comclass Gem5(Executable): 51713531Sjairo.balart@metempsy.com '''Create a gem5 executable.''' 51813531Sjairo.balart@metempsy.com 51913531Sjairo.balart@metempsy.com def __init__(self, target): 52013531Sjairo.balart@metempsy.com super(Gem5, self).__init__(target) 52113531Sjairo.balart@metempsy.com 52213531Sjairo.balart@metempsy.com def declare(self, env): 52313756Sjairo.balart@metempsy.com objs = env['MAIN_OBJS'] + env['STATIC_OBJS'] 52413531Sjairo.balart@metempsy.com return super(Gem5, self).declare(env, objs) 52513531Sjairo.balart@metempsy.com 52613531Sjairo.balart@metempsy.com 52713531Sjairo.balart@metempsy.com# Children should have access 52813531Sjairo.balart@metempsy.comExport('Blob') 52913531Sjairo.balart@metempsy.comExport('GdbXml') 53013756Sjairo.balart@metempsy.comExport('Source') 53113531Sjairo.balart@metempsy.comExport('PySource') 53213531Sjairo.balart@metempsy.comExport('SimObject') 53313531Sjairo.balart@metempsy.comExport('ProtoBuf') 53413531Sjairo.balart@metempsy.comExport('Executable') 53513531Sjairo.balart@metempsy.comExport('UnitTest') 53613531Sjairo.balart@metempsy.comExport('GTest') 53713531Sjairo.balart@metempsy.com 53813531Sjairo.balart@metempsy.com######################################################################## 53913756Sjairo.balart@metempsy.com# 54013756Sjairo.balart@metempsy.com# Debug Flags 54113531Sjairo.balart@metempsy.com# 54213531Sjairo.balart@metempsy.comdebug_flags = {} 54313531Sjairo.balart@metempsy.comdef DebugFlag(name, desc=None): 54413531Sjairo.balart@metempsy.com if name in debug_flags: 54513531Sjairo.balart@metempsy.com raise AttributeError, "Flag %s already specified" % name 54613531Sjairo.balart@metempsy.com debug_flags[name] = (name, (), desc) 54713531Sjairo.balart@metempsy.com 54813531Sjairo.balart@metempsy.comdef CompoundFlag(name, flags, desc=None): 54913531Sjairo.balart@metempsy.com if name in debug_flags: 55013531Sjairo.balart@metempsy.com raise AttributeError, "Flag %s already specified" % name 55113531Sjairo.balart@metempsy.com 55213531Sjairo.balart@metempsy.com compound = tuple(flags) 55313531Sjairo.balart@metempsy.com debug_flags[name] = (name, compound, desc) 55413531Sjairo.balart@metempsy.com 55513531Sjairo.balart@metempsy.comExport('DebugFlag') 55613531Sjairo.balart@metempsy.comExport('CompoundFlag') 55713531Sjairo.balart@metempsy.com 55813531Sjairo.balart@metempsy.com######################################################################## 55913531Sjairo.balart@metempsy.com# 56013531Sjairo.balart@metempsy.com# Set some compiler variables 56113531Sjairo.balart@metempsy.com# 56213531Sjairo.balart@metempsy.com 56313812Sgiacomo.travaglini@arm.com# Include file paths are rooted in this directory. SCons will 56413812Sgiacomo.travaglini@arm.com# automatically expand '.' to refer to both the source directory and 56513812Sgiacomo.travaglini@arm.com# the corresponding build directory to pick up generated include 56613812Sgiacomo.travaglini@arm.com# files. 56713531Sjairo.balart@metempsy.comenv.Append(CPPPATH=Dir('.')) 56813756Sjairo.balart@metempsy.com 56913756Sjairo.balart@metempsy.comfor extra_dir in extras_dir_list: 57013531Sjairo.balart@metempsy.com env.Append(CPPPATH=Dir(extra_dir)) 57113531Sjairo.balart@metempsy.com 57213531Sjairo.balart@metempsy.com# Workaround for bug in SCons version > 0.97d20071212 57313531Sjairo.balart@metempsy.com# Scons bug id: 2006 gem5 Bug id: 308 57413531Sjairo.balart@metempsy.comfor root, dirs, files in os.walk(base_dir, topdown=True): 57513531Sjairo.balart@metempsy.com Dir(root[len(base_dir) + 1:]) 57613531Sjairo.balart@metempsy.com 57713531Sjairo.balart@metempsy.com######################################################################## 57813531Sjairo.balart@metempsy.com# 57913531Sjairo.balart@metempsy.com# Walk the tree and execute all SConscripts in subdirectories 58013531Sjairo.balart@metempsy.com# 58113531Sjairo.balart@metempsy.com 58213531Sjairo.balart@metempsy.comhere = Dir('.').srcnode().abspath 58313531Sjairo.balart@metempsy.comfor root, dirs, files in os.walk(base_dir, topdown=True): 58413531Sjairo.balart@metempsy.com if root == here: 58513531Sjairo.balart@metempsy.com # we don't want to recurse back into this SConscript 58613531Sjairo.balart@metempsy.com continue 58713531Sjairo.balart@metempsy.com 58813531Sjairo.balart@metempsy.com if 'SConscript' in files: 58913756Sjairo.balart@metempsy.com build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) 59013531Sjairo.balart@metempsy.com Source.set_group(build_dir) 59113531Sjairo.balart@metempsy.com SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 59213531Sjairo.balart@metempsy.com 59313531Sjairo.balart@metempsy.comfor extra_dir in extras_dir_list: 59413531Sjairo.balart@metempsy.com prefix_len = len(dirname(extra_dir)) + 1 59513531Sjairo.balart@metempsy.com 59613531Sjairo.balart@metempsy.com # Also add the corresponding build directory to pick up generated 59713756Sjairo.balart@metempsy.com # include files. 59813756Sjairo.balart@metempsy.com env.Append(CPPPATH=Dir(joinpath(env['BUILDDIR'], extra_dir[prefix_len:]))) 59913531Sjairo.balart@metempsy.com 60013531Sjairo.balart@metempsy.com for root, dirs, files in os.walk(extra_dir, topdown=True): 60113531Sjairo.balart@metempsy.com # if build lives in the extras directory, don't walk down it 60213531Sjairo.balart@metempsy.com if 'build' in dirs: 60313531Sjairo.balart@metempsy.com dirs.remove('build') 60413531Sjairo.balart@metempsy.com 60513531Sjairo.balart@metempsy.com if 'SConscript' in files: 60613531Sjairo.balart@metempsy.com build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) 60713531Sjairo.balart@metempsy.com SConscript(joinpath(root, 'SConscript'), variant_dir=build_dir) 60813531Sjairo.balart@metempsy.com 60913531Sjairo.balart@metempsy.comfor opt in export_vars: 61013531Sjairo.balart@metempsy.com env.ConfigFile(opt) 61113531Sjairo.balart@metempsy.com 61213531Sjairo.balart@metempsy.comdef makeTheISA(source, target, env): 61313531Sjairo.balart@metempsy.com isas = [ src.get_contents() for src in source ] 61413531Sjairo.balart@metempsy.com target_isa = env['TARGET_ISA'] 61513531Sjairo.balart@metempsy.com def define(isa): 61614231Sgiacomo.travaglini@arm.com return isa.upper() + '_ISA' 61713531Sjairo.balart@metempsy.com 61813531Sjairo.balart@metempsy.com def namespace(isa): 61913756Sjairo.balart@metempsy.com return isa[0].upper() + isa[1:].lower() + 'ISA' 62013531Sjairo.balart@metempsy.com 62113531Sjairo.balart@metempsy.com 62213531Sjairo.balart@metempsy.com code = code_formatter() 62313531Sjairo.balart@metempsy.com code('''\ 62413531Sjairo.balart@metempsy.com#ifndef __CONFIG_THE_ISA_HH__ 62513531Sjairo.balart@metempsy.com#define __CONFIG_THE_ISA_HH__ 62613531Sjairo.balart@metempsy.com 62713756Sjairo.balart@metempsy.com''') 62813756Sjairo.balart@metempsy.com 62913531Sjairo.balart@metempsy.com # create defines for the preprocessing and compile-time determination 63013531Sjairo.balart@metempsy.com for i,isa in enumerate(isas): 63113531Sjairo.balart@metempsy.com code('#define $0 $1', define(isa), i + 1) 63213531Sjairo.balart@metempsy.com code() 63313531Sjairo.balart@metempsy.com 63413531Sjairo.balart@metempsy.com # create an enum for any run-time determination of the ISA, we 63513531Sjairo.balart@metempsy.com # reuse the same name as the namespaces 63613531Sjairo.balart@metempsy.com code('enum class Arch {') 63713531Sjairo.balart@metempsy.com for i,isa in enumerate(isas): 63813531Sjairo.balart@metempsy.com if i + 1 == len(isas): 63913531Sjairo.balart@metempsy.com code(' $0 = $1', namespace(isa), define(isa)) 64013531Sjairo.balart@metempsy.com else: 64114231Sgiacomo.travaglini@arm.com code(' $0 = $1,', namespace(isa), define(isa)) 64213531Sjairo.balart@metempsy.com code('};') 64313531Sjairo.balart@metempsy.com 64413531Sjairo.balart@metempsy.com code(''' 64514231Sgiacomo.travaglini@arm.com 64613531Sjairo.balart@metempsy.com#define THE_ISA ${{define(target_isa)}} 64713756Sjairo.balart@metempsy.com#define TheISA ${{namespace(target_isa)}} 64813531Sjairo.balart@metempsy.com#define THE_ISA_STR "${{target_isa}}" 64913531Sjairo.balart@metempsy.com 65013531Sjairo.balart@metempsy.com#endif // __CONFIG_THE_ISA_HH__''') 65113531Sjairo.balart@metempsy.com 65213531Sjairo.balart@metempsy.com code.write(str(target[0])) 65313531Sjairo.balart@metempsy.com 65413531Sjairo.balart@metempsy.comenv.Command('config/the_isa.hh', map(Value, all_isa_list), 65513531Sjairo.balart@metempsy.com MakeAction(makeTheISA, Transform("CFG ISA", 0))) 65613756Sjairo.balart@metempsy.com 65713756Sjairo.balart@metempsy.comdef makeTheGPUISA(source, target, env): 65813531Sjairo.balart@metempsy.com isas = [ src.get_contents() for src in source ] 65913531Sjairo.balart@metempsy.com target_gpu_isa = env['TARGET_GPU_ISA'] 66013531Sjairo.balart@metempsy.com def define(isa): 66113531Sjairo.balart@metempsy.com return isa.upper() + '_ISA' 66213531Sjairo.balart@metempsy.com 66313531Sjairo.balart@metempsy.com def namespace(isa): 66413531Sjairo.balart@metempsy.com return isa[0].upper() + isa[1:].lower() + 'ISA' 66513531Sjairo.balart@metempsy.com 66613531Sjairo.balart@metempsy.com 66713531Sjairo.balart@metempsy.com code = code_formatter() 66813531Sjairo.balart@metempsy.com code('''\ 66913531Sjairo.balart@metempsy.com#ifndef __CONFIG_THE_GPU_ISA_HH__ 67013531Sjairo.balart@metempsy.com#define __CONFIG_THE_GPU_ISA_HH__ 67113531Sjairo.balart@metempsy.com 67213531Sjairo.balart@metempsy.com''') 67313531Sjairo.balart@metempsy.com 67413531Sjairo.balart@metempsy.com # create defines for the preprocessing and compile-time determination 67513531Sjairo.balart@metempsy.com for i,isa in enumerate(isas): 67613531Sjairo.balart@metempsy.com code('#define $0 $1', define(isa), i + 1) 67713531Sjairo.balart@metempsy.com code() 67813531Sjairo.balart@metempsy.com 67913531Sjairo.balart@metempsy.com # create an enum for any run-time determination of the ISA, we 68013756Sjairo.balart@metempsy.com # reuse the same name as the namespaces 68113756Sjairo.balart@metempsy.com code('enum class GPUArch {') 68213531Sjairo.balart@metempsy.com for i,isa in enumerate(isas): 68313531Sjairo.balart@metempsy.com if i + 1 == len(isas): 68413531Sjairo.balart@metempsy.com code(' $0 = $1', namespace(isa), define(isa)) 68513531Sjairo.balart@metempsy.com else: 68613531Sjairo.balart@metempsy.com code(' $0 = $1,', namespace(isa), define(isa)) 68713531Sjairo.balart@metempsy.com code('};') 68813531Sjairo.balart@metempsy.com 68913531Sjairo.balart@metempsy.com code(''' 69013531Sjairo.balart@metempsy.com 69113531Sjairo.balart@metempsy.com#define THE_GPU_ISA ${{define(target_gpu_isa)}} 69213531Sjairo.balart@metempsy.com#define TheGpuISA ${{namespace(target_gpu_isa)}} 69313531Sjairo.balart@metempsy.com#define THE_GPU_ISA_STR "${{target_gpu_isa}}" 69413531Sjairo.balart@metempsy.com 69513531Sjairo.balart@metempsy.com#endif // __CONFIG_THE_GPU_ISA_HH__''') 69613531Sjairo.balart@metempsy.com 69713531Sjairo.balart@metempsy.com code.write(str(target[0])) 69813531Sjairo.balart@metempsy.com 69913531Sjairo.balart@metempsy.comenv.Command('config/the_gpu_isa.hh', map(Value, all_gpu_isa_list), 70013756Sjairo.balart@metempsy.com MakeAction(makeTheGPUISA, Transform("CFG ISA", 0))) 70113531Sjairo.balart@metempsy.com 70213531Sjairo.balart@metempsy.com######################################################################## 70313531Sjairo.balart@metempsy.com# 70413531Sjairo.balart@metempsy.com# Prevent any SimObjects from being added after this point, they 70513531Sjairo.balart@metempsy.com# should all have been added in the SConscripts above 70613531Sjairo.balart@metempsy.com# 70713531Sjairo.balart@metempsy.comSimObject.fixed = True 70813531Sjairo.balart@metempsy.com 70913531Sjairo.balart@metempsy.comclass DictImporter(object): 71013531Sjairo.balart@metempsy.com '''This importer takes a dictionary of arbitrary module names that 71113531Sjairo.balart@metempsy.com map to arbitrary filenames.''' 71213531Sjairo.balart@metempsy.com def __init__(self, modules): 71313531Sjairo.balart@metempsy.com self.modules = modules 71413531Sjairo.balart@metempsy.com self.installed = set() 71513531Sjairo.balart@metempsy.com 71613531Sjairo.balart@metempsy.com def __del__(self): 71713531Sjairo.balart@metempsy.com self.unload() 71813531Sjairo.balart@metempsy.com 71913531Sjairo.balart@metempsy.com def unload(self): 72013531Sjairo.balart@metempsy.com import sys 72113531Sjairo.balart@metempsy.com for module in self.installed: 72213531Sjairo.balart@metempsy.com del sys.modules[module] 72313531Sjairo.balart@metempsy.com self.installed = set() 72413531Sjairo.balart@metempsy.com 72513531Sjairo.balart@metempsy.com def find_module(self, fullname, path): 72613531Sjairo.balart@metempsy.com if fullname == 'm5.defines': 72713531Sjairo.balart@metempsy.com return self 72813531Sjairo.balart@metempsy.com 72913531Sjairo.balart@metempsy.com if fullname == 'm5.objects': 73013531Sjairo.balart@metempsy.com return self 73113531Sjairo.balart@metempsy.com 73213531Sjairo.balart@metempsy.com if fullname.startswith('_m5'): 73313756Sjairo.balart@metempsy.com return None 73413531Sjairo.balart@metempsy.com 73513756Sjairo.balart@metempsy.com source = self.modules.get(fullname, None) 73613756Sjairo.balart@metempsy.com if source is not None and fullname.startswith('m5.objects'): 73713756Sjairo.balart@metempsy.com return self 73813756Sjairo.balart@metempsy.com 73913756Sjairo.balart@metempsy.com return None 74013531Sjairo.balart@metempsy.com 74113531Sjairo.balart@metempsy.com def load_module(self, fullname): 74213531Sjairo.balart@metempsy.com mod = imp.new_module(fullname) 74313531Sjairo.balart@metempsy.com sys.modules[fullname] = mod 74413531Sjairo.balart@metempsy.com self.installed.add(fullname) 74513531Sjairo.balart@metempsy.com 74613531Sjairo.balart@metempsy.com mod.__loader__ = self 74713756Sjairo.balart@metempsy.com if fullname == 'm5.objects': 74813531Sjairo.balart@metempsy.com mod.__path__ = fullname.split('.') 74913531Sjairo.balart@metempsy.com return mod 75013531Sjairo.balart@metempsy.com 75113531Sjairo.balart@metempsy.com if fullname == 'm5.defines': 75213531Sjairo.balart@metempsy.com mod.__dict__['buildEnv'] = m5.util.SmartDict(build_env) 75313531Sjairo.balart@metempsy.com return mod 75413531Sjairo.balart@metempsy.com 75513531Sjairo.balart@metempsy.com source = self.modules[fullname] 75613531Sjairo.balart@metempsy.com if source.modname == '__init__': 75713531Sjairo.balart@metempsy.com mod.__path__ = source.modpath 75813531Sjairo.balart@metempsy.com mod.__file__ = source.abspath 75913531Sjairo.balart@metempsy.com 76013531Sjairo.balart@metempsy.com exec file(source.abspath, 'r') in mod.__dict__ 76113531Sjairo.balart@metempsy.com 76213531Sjairo.balart@metempsy.com return mod 76313531Sjairo.balart@metempsy.com 76413531Sjairo.balart@metempsy.comimport m5.SimObject 76513531Sjairo.balart@metempsy.comimport m5.params 76613531Sjairo.balart@metempsy.comfrom m5.util import code_formatter 76713531Sjairo.balart@metempsy.com 76813531Sjairo.balart@metempsy.comm5.SimObject.clear() 76913531Sjairo.balart@metempsy.comm5.params.clear() 77013531Sjairo.balart@metempsy.com 77113531Sjairo.balart@metempsy.com# install the python importer so we can grab stuff from the source 77213756Sjairo.balart@metempsy.com# tree itself. We can't have SimObjects added after this point or 77314230Sgiacomo.travaglini@arm.com# else we won't know about them for the rest of the stuff. 77413531Sjairo.balart@metempsy.comimporter = DictImporter(PySource.modules) 77513531Sjairo.balart@metempsy.comsys.meta_path[0:0] = [ importer ] 77613531Sjairo.balart@metempsy.com 77713531Sjairo.balart@metempsy.com# import all sim objects so we can populate the all_objects list 77813531Sjairo.balart@metempsy.com# make sure that we're working with a list, then let's sort it 77913531Sjairo.balart@metempsy.comfor modname in SimObject.modnames: 78013756Sjairo.balart@metempsy.com exec('from m5.objects import %s' % modname) 78113531Sjairo.balart@metempsy.com 78213531Sjairo.balart@metempsy.com# we need to unload all of the currently imported modules so that they 78313531Sjairo.balart@metempsy.com# will be re-imported the next time the sconscript is run 78413531Sjairo.balart@metempsy.comimporter.unload() 78513531Sjairo.balart@metempsy.comsys.meta_path.remove(importer) 78613531Sjairo.balart@metempsy.com 78713531Sjairo.balart@metempsy.comsim_objects = m5.SimObject.allClasses 78813531Sjairo.balart@metempsy.comall_enums = m5.params.allEnums 78913531Sjairo.balart@metempsy.com 79013531Sjairo.balart@metempsy.comfor name,obj in sorted(sim_objects.iteritems()): 79113531Sjairo.balart@metempsy.com for param in obj._params.local.values(): 79213531Sjairo.balart@metempsy.com # load the ptype attribute now because it depends on the 79313531Sjairo.balart@metempsy.com # current version of SimObject.allClasses, but when scons 79413756Sjairo.balart@metempsy.com # actually uses the value, all versions of 79513531Sjairo.balart@metempsy.com # SimObject.allClasses will have been loaded 79613531Sjairo.balart@metempsy.com param.ptype 79713531Sjairo.balart@metempsy.com 79813531Sjairo.balart@metempsy.com######################################################################## 79913531Sjairo.balart@metempsy.com# 80013531Sjairo.balart@metempsy.com# calculate extra dependencies 80113531Sjairo.balart@metempsy.com# 80213531Sjairo.balart@metempsy.commodule_depends = ["m5", "m5.SimObject", "m5.params"] 80313531Sjairo.balart@metempsy.comdepends = [ PySource.modules[dep].snode for dep in module_depends ] 80413531Sjairo.balart@metempsy.comdepends.sort(key = lambda x: x.name) 80513531Sjairo.balart@metempsy.com 80613531Sjairo.balart@metempsy.com######################################################################## 80713531Sjairo.balart@metempsy.com# 80813531Sjairo.balart@metempsy.com# Commands for the basic automatically generated python files 80913531Sjairo.balart@metempsy.com# 81013531Sjairo.balart@metempsy.com 81113531Sjairo.balart@metempsy.com# Generate Python file containing a dict specifying the current 81213531Sjairo.balart@metempsy.com# buildEnv flags. 81313531Sjairo.balart@metempsy.comdef makeDefinesPyFile(target, source, env): 81413531Sjairo.balart@metempsy.com build_env = source[0].get_contents() 81513531Sjairo.balart@metempsy.com 81613531Sjairo.balart@metempsy.com code = code_formatter() 81713531Sjairo.balart@metempsy.com code(""" 81813531Sjairo.balart@metempsy.comimport _m5.core 81913531Sjairo.balart@metempsy.comimport m5.util 82013531Sjairo.balart@metempsy.com 82113531Sjairo.balart@metempsy.combuildEnv = m5.util.SmartDict($build_env) 82213531Sjairo.balart@metempsy.com 82313531Sjairo.balart@metempsy.comcompileDate = _m5.core.compileDate 82413531Sjairo.balart@metempsy.com_globals = globals() 82513531Sjairo.balart@metempsy.comfor key,val in _m5.core.__dict__.iteritems(): 82613531Sjairo.balart@metempsy.com if key.startswith('flag_'): 82713531Sjairo.balart@metempsy.com flag = key[5:] 82813531Sjairo.balart@metempsy.com _globals[flag] = val 82913531Sjairo.balart@metempsy.comdel _globals 83013531Sjairo.balart@metempsy.com""") 83113531Sjairo.balart@metempsy.com code.write(target[0].abspath) 83213531Sjairo.balart@metempsy.com 83313531Sjairo.balart@metempsy.comdefines_info = Value(build_env) 83413531Sjairo.balart@metempsy.com# Generate a file with all of the compile options in it 83513531Sjairo.balart@metempsy.comenv.Command('python/m5/defines.py', defines_info, 83613531Sjairo.balart@metempsy.com MakeAction(makeDefinesPyFile, Transform("DEFINES", 0))) 83713531Sjairo.balart@metempsy.comPySource('m5', 'python/m5/defines.py') 83813531Sjairo.balart@metempsy.com 83913531Sjairo.balart@metempsy.com# Generate python file containing info about the M5 source code 84013531Sjairo.balart@metempsy.comdef makeInfoPyFile(target, source, env): 84113531Sjairo.balart@metempsy.com code = code_formatter() 84213531Sjairo.balart@metempsy.com for src in source: 84313531Sjairo.balart@metempsy.com data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) 84413531Sjairo.balart@metempsy.com code('$src = ${{repr(data)}}') 84513531Sjairo.balart@metempsy.com code.write(str(target[0])) 84613531Sjairo.balart@metempsy.com 84713531Sjairo.balart@metempsy.com# Generate a file that wraps the basic top level files 84813531Sjairo.balart@metempsy.comenv.Command('python/m5/info.py', 84913531Sjairo.balart@metempsy.com [ '#/COPYING', '#/LICENSE', '#/README', ], 85013531Sjairo.balart@metempsy.com MakeAction(makeInfoPyFile, Transform("INFO"))) 85113531Sjairo.balart@metempsy.comPySource('m5', 'python/m5/info.py') 85213531Sjairo.balart@metempsy.com 85313531Sjairo.balart@metempsy.com######################################################################## 85413531Sjairo.balart@metempsy.com# 85513531Sjairo.balart@metempsy.com# Create all of the SimObject param headers and enum headers 85613531Sjairo.balart@metempsy.com# 85713531Sjairo.balart@metempsy.com 85813531Sjairo.balart@metempsy.comdef createSimObjectParamStruct(target, source, env): 85913531Sjairo.balart@metempsy.com assert len(target) == 1 and len(source) == 1 86013531Sjairo.balart@metempsy.com 86113531Sjairo.balart@metempsy.com name = source[0].get_text_contents() 86213531Sjairo.balart@metempsy.com obj = sim_objects[name] 86313531Sjairo.balart@metempsy.com 86413531Sjairo.balart@metempsy.com code = code_formatter() 86513531Sjairo.balart@metempsy.com obj.cxx_param_decl(code) 86613531Sjairo.balart@metempsy.com code.write(target[0].abspath) 86713531Sjairo.balart@metempsy.com 86813531Sjairo.balart@metempsy.comdef createSimObjectCxxConfig(is_header): 86913531Sjairo.balart@metempsy.com def body(target, source, env): 87013531Sjairo.balart@metempsy.com assert len(target) == 1 and len(source) == 1 87113531Sjairo.balart@metempsy.com 87213531Sjairo.balart@metempsy.com name = str(source[0].get_contents()) 87313531Sjairo.balart@metempsy.com obj = sim_objects[name] 87413531Sjairo.balart@metempsy.com 87513531Sjairo.balart@metempsy.com code = code_formatter() 87613531Sjairo.balart@metempsy.com obj.cxx_config_param_file(code, is_header) 87713531Sjairo.balart@metempsy.com code.write(target[0].abspath) 87813531Sjairo.balart@metempsy.com return body 87913531Sjairo.balart@metempsy.com 88013531Sjairo.balart@metempsy.comdef createEnumStrings(target, source, env): 88113531Sjairo.balart@metempsy.com assert len(target) == 1 and len(source) == 2 88213531Sjairo.balart@metempsy.com 88313531Sjairo.balart@metempsy.com name = source[0].get_text_contents() 88413531Sjairo.balart@metempsy.com use_python = source[1].read() 88513531Sjairo.balart@metempsy.com obj = all_enums[name] 88613531Sjairo.balart@metempsy.com 88713531Sjairo.balart@metempsy.com code = code_formatter() 88813531Sjairo.balart@metempsy.com obj.cxx_def(code) 88913531Sjairo.balart@metempsy.com if use_python: 89013531Sjairo.balart@metempsy.com obj.pybind_def(code) 89113531Sjairo.balart@metempsy.com code.write(target[0].abspath) 89213531Sjairo.balart@metempsy.com 89313531Sjairo.balart@metempsy.comdef createEnumDecls(target, source, env): 89413531Sjairo.balart@metempsy.com assert len(target) == 1 and len(source) == 1 89513531Sjairo.balart@metempsy.com 89613531Sjairo.balart@metempsy.com name = source[0].get_text_contents() 89713531Sjairo.balart@metempsy.com obj = all_enums[name] 89813531Sjairo.balart@metempsy.com 89913531Sjairo.balart@metempsy.com code = code_formatter() 90013531Sjairo.balart@metempsy.com obj.cxx_decl(code) 90113531Sjairo.balart@metempsy.com code.write(target[0].abspath) 90213531Sjairo.balart@metempsy.com 90313531Sjairo.balart@metempsy.comdef createSimObjectPyBindWrapper(target, source, env): 90413531Sjairo.balart@metempsy.com name = source[0].get_text_contents() 90513531Sjairo.balart@metempsy.com obj = sim_objects[name] 90613531Sjairo.balart@metempsy.com 90713531Sjairo.balart@metempsy.com code = code_formatter() 90813531Sjairo.balart@metempsy.com obj.pybind_decl(code) 90913531Sjairo.balart@metempsy.com code.write(target[0].abspath) 91014232Sgiacomo.travaglini@arm.com 91114232Sgiacomo.travaglini@arm.com# Generate all of the SimObject param C++ struct header files 91213531Sjairo.balart@metempsy.comparams_hh_files = [] 91313531Sjairo.balart@metempsy.comfor name,simobj in sorted(sim_objects.iteritems()): 91414251Sgiacomo.travaglini@arm.com py_source = PySource.modules[simobj.__module__] 91514251Sgiacomo.travaglini@arm.com extra_deps = [ py_source.tnode ] 91614251Sgiacomo.travaglini@arm.com 91714251Sgiacomo.travaglini@arm.com hh_file = File('params/%s.hh' % name) 91814253Sgiacomo.travaglini@arm.com params_hh_files.append(hh_file) 91914253Sgiacomo.travaglini@arm.com env.Command(hh_file, Value(name), 92014253Sgiacomo.travaglini@arm.com MakeAction(createSimObjectParamStruct, Transform("SO PARAM"))) 92114253Sgiacomo.travaglini@arm.com env.Depends(hh_file, depends + extra_deps) 92214253Sgiacomo.travaglini@arm.com 92314253Sgiacomo.travaglini@arm.com# C++ parameter description files 92414253Sgiacomo.travaglini@arm.comif GetOption('with_cxx_config'): 92514253Sgiacomo.travaglini@arm.com for name,simobj in sorted(sim_objects.iteritems()): 92614253Sgiacomo.travaglini@arm.com py_source = PySource.modules[simobj.__module__] 92714253Sgiacomo.travaglini@arm.com extra_deps = [ py_source.tnode ] 92814253Sgiacomo.travaglini@arm.com 92914253Sgiacomo.travaglini@arm.com cxx_config_hh_file = File('cxx_config/%s.hh' % name) 93014253Sgiacomo.travaglini@arm.com cxx_config_cc_file = File('cxx_config/%s.cc' % name) 93114253Sgiacomo.travaglini@arm.com env.Command(cxx_config_hh_file, Value(name), 93214253Sgiacomo.travaglini@arm.com MakeAction(createSimObjectCxxConfig(True), 93314253Sgiacomo.travaglini@arm.com Transform("CXXCPRHH"))) 93414253Sgiacomo.travaglini@arm.com env.Command(cxx_config_cc_file, Value(name), 93514253Sgiacomo.travaglini@arm.com MakeAction(createSimObjectCxxConfig(False), 93614253Sgiacomo.travaglini@arm.com Transform("CXXCPRCC"))) 93714253Sgiacomo.travaglini@arm.com env.Depends(cxx_config_hh_file, depends + extra_deps + 93814253Sgiacomo.travaglini@arm.com [File('params/%s.hh' % name), File('sim/cxx_config.hh')]) 93914253Sgiacomo.travaglini@arm.com env.Depends(cxx_config_cc_file, depends + extra_deps + 94014253Sgiacomo.travaglini@arm.com [cxx_config_hh_file]) 94114253Sgiacomo.travaglini@arm.com Source(cxx_config_cc_file) 94214253Sgiacomo.travaglini@arm.com 94314253Sgiacomo.travaglini@arm.com cxx_config_init_cc_file = File('cxx_config/init.cc') 94414253Sgiacomo.travaglini@arm.com 94514253Sgiacomo.travaglini@arm.com def createCxxConfigInitCC(target, source, env): 94614253Sgiacomo.travaglini@arm.com assert len(target) == 1 and len(source) == 1 94714253Sgiacomo.travaglini@arm.com 94814253Sgiacomo.travaglini@arm.com code = code_formatter() 94914253Sgiacomo.travaglini@arm.com 95014253Sgiacomo.travaglini@arm.com for name,simobj in sorted(sim_objects.iteritems()): 95114253Sgiacomo.travaglini@arm.com if not hasattr(simobj, 'abstract') or not simobj.abstract: 95214253Sgiacomo.travaglini@arm.com code('#include "cxx_config/${name}.hh"') 95314253Sgiacomo.travaglini@arm.com code() 95414253Sgiacomo.travaglini@arm.com code('void cxxConfigInit()') 95514253Sgiacomo.travaglini@arm.com code('{') 95614253Sgiacomo.travaglini@arm.com code.indent() 95714253Sgiacomo.travaglini@arm.com for name,simobj in sorted(sim_objects.iteritems()): 95814253Sgiacomo.travaglini@arm.com not_abstract = not hasattr(simobj, 'abstract') or \ 95914253Sgiacomo.travaglini@arm.com not simobj.abstract 96014253Sgiacomo.travaglini@arm.com if not_abstract and 'type' in simobj.__dict__: 96114253Sgiacomo.travaglini@arm.com code('cxx_config_directory["${name}"] = ' 96214253Sgiacomo.travaglini@arm.com '${name}CxxConfigParams::makeDirectoryEntry();') 96314253Sgiacomo.travaglini@arm.com code.dedent() 96414253Sgiacomo.travaglini@arm.com code('}') 96514253Sgiacomo.travaglini@arm.com code.write(target[0].abspath) 96614253Sgiacomo.travaglini@arm.com 96714253Sgiacomo.travaglini@arm.com py_source = PySource.modules[simobj.__module__] 96814253Sgiacomo.travaglini@arm.com extra_deps = [ py_source.tnode ] 96914253Sgiacomo.travaglini@arm.com env.Command(cxx_config_init_cc_file, Value(name), 97014253Sgiacomo.travaglini@arm.com MakeAction(createCxxConfigInitCC, Transform("CXXCINIT"))) 97114253Sgiacomo.travaglini@arm.com cxx_param_hh_files = ["cxx_config/%s.hh" % simobj 97214253Sgiacomo.travaglini@arm.com for name,simobj in sorted(sim_objects.iteritems()) 97314253Sgiacomo.travaglini@arm.com if not hasattr(simobj, 'abstract') or not simobj.abstract] 97414253Sgiacomo.travaglini@arm.com Depends(cxx_config_init_cc_file, cxx_param_hh_files + 97514253Sgiacomo.travaglini@arm.com [File('sim/cxx_config.hh')]) 97614253Sgiacomo.travaglini@arm.com Source(cxx_config_init_cc_file) 97714253Sgiacomo.travaglini@arm.com 97814253Sgiacomo.travaglini@arm.com# Generate all enum header files 97914253Sgiacomo.travaglini@arm.comfor name,enum in sorted(all_enums.iteritems()): 98014253Sgiacomo.travaglini@arm.com py_source = PySource.modules[enum.__module__] 98114253Sgiacomo.travaglini@arm.com extra_deps = [ py_source.tnode ] 98214253Sgiacomo.travaglini@arm.com 98314253Sgiacomo.travaglini@arm.com cc_file = File('enums/%s.cc' % name) 98414253Sgiacomo.travaglini@arm.com env.Command(cc_file, [Value(name), Value(env['USE_PYTHON'])], 98514253Sgiacomo.travaglini@arm.com MakeAction(createEnumStrings, Transform("ENUM STR"))) 98614253Sgiacomo.travaglini@arm.com env.Depends(cc_file, depends + extra_deps) 98714253Sgiacomo.travaglini@arm.com Source(cc_file) 98813531Sjairo.balart@metempsy.com 98913531Sjairo.balart@metempsy.com hh_file = File('enums/%s.hh' % name) 99013531Sjairo.balart@metempsy.com env.Command(hh_file, Value(name), 99113531Sjairo.balart@metempsy.com MakeAction(createEnumDecls, Transform("ENUMDECL"))) 99213531Sjairo.balart@metempsy.com env.Depends(hh_file, depends + extra_deps) 99313531Sjairo.balart@metempsy.com 99413531Sjairo.balart@metempsy.com# Generate SimObject Python bindings wrapper files 99513531Sjairo.balart@metempsy.comif env['USE_PYTHON']: 99613531Sjairo.balart@metempsy.com for name,simobj in sorted(sim_objects.iteritems()): 99713531Sjairo.balart@metempsy.com py_source = PySource.modules[simobj.__module__] 99813531Sjairo.balart@metempsy.com extra_deps = [ py_source.tnode ] 99913531Sjairo.balart@metempsy.com cc_file = File('python/_m5/param_%s.cc' % name) 100013531Sjairo.balart@metempsy.com env.Command(cc_file, Value(name), 100113531Sjairo.balart@metempsy.com MakeAction(createSimObjectPyBindWrapper, 100214231Sgiacomo.travaglini@arm.com Transform("SO PyBind"))) 100313531Sjairo.balart@metempsy.com env.Depends(cc_file, depends + extra_deps) 100413531Sjairo.balart@metempsy.com Source(cc_file) 100513531Sjairo.balart@metempsy.com 100613756Sjairo.balart@metempsy.com# Build all protocol buffers if we have got protoc and protobuf available 100713531Sjairo.balart@metempsy.comif env['HAVE_PROTOBUF']: 100813531Sjairo.balart@metempsy.com for proto in ProtoBuf.all: 100913531Sjairo.balart@metempsy.com # Use both the source and header as the target, and the .proto 101013531Sjairo.balart@metempsy.com # file as the source. When executing the protoc compiler, also 101114231Sgiacomo.travaglini@arm.com # specify the proto_path to avoid having the generated files 101214231Sgiacomo.travaglini@arm.com # include the path. 101314231Sgiacomo.travaglini@arm.com env.Command([proto.cc_file, proto.hh_file], proto.tnode, 101413531Sjairo.balart@metempsy.com MakeAction('$PROTOC --cpp_out ${TARGET.dir} ' 101513531Sjairo.balart@metempsy.com '--proto_path ${SOURCE.dir} $SOURCE', 101614231Sgiacomo.travaglini@arm.com Transform("PROTOC"))) 101714231Sgiacomo.travaglini@arm.com 101813531Sjairo.balart@metempsy.com # Add the C++ source file 101914231Sgiacomo.travaglini@arm.com Source(proto.cc_file, tags=proto.tags) 102014231Sgiacomo.travaglini@arm.comelif ProtoBuf.all: 102113531Sjairo.balart@metempsy.com print('Got protobuf to build, but lacks support!') 102214231Sgiacomo.travaglini@arm.com Exit(1) 102314231Sgiacomo.travaglini@arm.com 102414231Sgiacomo.travaglini@arm.com# 102514231Sgiacomo.travaglini@arm.com# Handle debug flags 102614231Sgiacomo.travaglini@arm.com# 102714231Sgiacomo.travaglini@arm.comdef makeDebugFlagCC(target, source, env): 102814231Sgiacomo.travaglini@arm.com assert(len(target) == 1 and len(source) == 1) 102914231Sgiacomo.travaglini@arm.com 103014231Sgiacomo.travaglini@arm.com code = code_formatter() 103114231Sgiacomo.travaglini@arm.com 103214231Sgiacomo.travaglini@arm.com # delay definition of CompoundFlags until after all the definition 103314231Sgiacomo.travaglini@arm.com # of all constituent SimpleFlags 103414231Sgiacomo.travaglini@arm.com comp_code = code_formatter() 103514231Sgiacomo.travaglini@arm.com 103614231Sgiacomo.travaglini@arm.com # file header 103714231Sgiacomo.travaglini@arm.com code(''' 103814231Sgiacomo.travaglini@arm.com/* 103914231Sgiacomo.travaglini@arm.com * DO NOT EDIT THIS FILE! Automatically generated by SCons. 104014231Sgiacomo.travaglini@arm.com */ 104114231Sgiacomo.travaglini@arm.com 104214231Sgiacomo.travaglini@arm.com#include "base/debug.hh" 104314231Sgiacomo.travaglini@arm.com 104414231Sgiacomo.travaglini@arm.comnamespace Debug { 104514231Sgiacomo.travaglini@arm.com 104614231Sgiacomo.travaglini@arm.com''') 104714231Sgiacomo.travaglini@arm.com 104814231Sgiacomo.travaglini@arm.com for name, flag in sorted(source[0].read().iteritems()): 104914231Sgiacomo.travaglini@arm.com n, compound, desc = flag 105013531Sjairo.balart@metempsy.com assert n == name 105113531Sjairo.balart@metempsy.com 105213531Sjairo.balart@metempsy.com if not compound: 105313531Sjairo.balart@metempsy.com code('SimpleFlag $name("$name", "$desc");') 105414231Sgiacomo.travaglini@arm.com else: 105513531Sjairo.balart@metempsy.com comp_code('CompoundFlag $name("$name", "$desc",') 105614231Sgiacomo.travaglini@arm.com comp_code.indent() 105714231Sgiacomo.travaglini@arm.com last = len(compound) - 1 105814259Sgiacomo.travaglini@arm.com for i,flag in enumerate(compound): 105913531Sjairo.balart@metempsy.com if i != last: 106013531Sjairo.balart@metempsy.com comp_code('&$flag,') 106113531Sjairo.balart@metempsy.com else: 106213531Sjairo.balart@metempsy.com comp_code('&$flag);') 106313531Sjairo.balart@metempsy.com comp_code.dedent() 106413531Sjairo.balart@metempsy.com 106513531Sjairo.balart@metempsy.com code.append(comp_code) 106613756Sjairo.balart@metempsy.com code() 106713531Sjairo.balart@metempsy.com code('} // namespace Debug') 106813531Sjairo.balart@metempsy.com 106913531Sjairo.balart@metempsy.com code.write(str(target[0])) 107013531Sjairo.balart@metempsy.com 107113756Sjairo.balart@metempsy.comdef makeDebugFlagHH(target, source, env): 107213531Sjairo.balart@metempsy.com assert(len(target) == 1 and len(source) == 1) 107314231Sgiacomo.travaglini@arm.com 107414231Sgiacomo.travaglini@arm.com val = eval(source[0].get_contents()) 107513531Sjairo.balart@metempsy.com name, compound, desc = val 107614231Sgiacomo.travaglini@arm.com 107714231Sgiacomo.travaglini@arm.com code = code_formatter() 107813531Sjairo.balart@metempsy.com 107913531Sjairo.balart@metempsy.com # file header boilerplate 108013756Sjairo.balart@metempsy.com code('''\ 108113756Sjairo.balart@metempsy.com/* 108214231Sgiacomo.travaglini@arm.com * DO NOT EDIT THIS FILE! Automatically generated by SCons. 108313531Sjairo.balart@metempsy.com */ 108413531Sjairo.balart@metempsy.com 108513531Sjairo.balart@metempsy.com#ifndef __DEBUG_${name}_HH__ 108613531Sjairo.balart@metempsy.com#define __DEBUG_${name}_HH__ 108713531Sjairo.balart@metempsy.com 108813531Sjairo.balart@metempsy.comnamespace Debug { 108913531Sjairo.balart@metempsy.com''') 109014231Sgiacomo.travaglini@arm.com 109113531Sjairo.balart@metempsy.com if compound: 109214231Sgiacomo.travaglini@arm.com code('class CompoundFlag;') 109313531Sjairo.balart@metempsy.com code('class SimpleFlag;') 109413531Sjairo.balart@metempsy.com 109513531Sjairo.balart@metempsy.com if compound: 109613531Sjairo.balart@metempsy.com code('extern CompoundFlag $name;') 109713756Sjairo.balart@metempsy.com for flag in compound: 109813531Sjairo.balart@metempsy.com code('extern SimpleFlag $flag;') 109913531Sjairo.balart@metempsy.com else: 110013531Sjairo.balart@metempsy.com code('extern SimpleFlag $name;') 110113531Sjairo.balart@metempsy.com 110213531Sjairo.balart@metempsy.com code(''' 110313531Sjairo.balart@metempsy.com} 110413531Sjairo.balart@metempsy.com 110513531Sjairo.balart@metempsy.com#endif // __DEBUG_${name}_HH__ 110613531Sjairo.balart@metempsy.com''') 110713531Sjairo.balart@metempsy.com 110813531Sjairo.balart@metempsy.com code.write(str(target[0])) 110913531Sjairo.balart@metempsy.com 111013531Sjairo.balart@metempsy.comfor name,flag in sorted(debug_flags.iteritems()): 111113531Sjairo.balart@metempsy.com n, compound, desc = flag 111213531Sjairo.balart@metempsy.com assert n == name 111313531Sjairo.balart@metempsy.com 111413531Sjairo.balart@metempsy.com hh_file = 'debug/%s.hh' % name 111513531Sjairo.balart@metempsy.com env.Command(hh_file, Value(flag), 111613756Sjairo.balart@metempsy.com MakeAction(makeDebugFlagHH, Transform("TRACING", 0))) 111713531Sjairo.balart@metempsy.com 111813531Sjairo.balart@metempsy.comenv.Command('debug/flags.cc', Value(debug_flags), 111913531Sjairo.balart@metempsy.com MakeAction(makeDebugFlagCC, Transform("TRACING", 0))) 112013531Sjairo.balart@metempsy.comSource('debug/flags.cc') 112113531Sjairo.balart@metempsy.com 112213531Sjairo.balart@metempsy.com# version tags 112313531Sjairo.balart@metempsy.comtags = \ 112413531Sjairo.balart@metempsy.comenv.Command('sim/tags.cc', None, 112513531Sjairo.balart@metempsy.com MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET', 112613531Sjairo.balart@metempsy.com Transform("VER TAGS"))) 112713531Sjairo.balart@metempsy.comenv.AlwaysBuild(tags) 112813531Sjairo.balart@metempsy.com 112913531Sjairo.balart@metempsy.com# Embed python files. All .py files that have been indicated by a 113013531Sjairo.balart@metempsy.com# PySource() call in a SConscript need to be embedded into the M5 113113531Sjairo.balart@metempsy.com# library. To do that, we compile the file to byte code, marshal the 113213531Sjairo.balart@metempsy.com# byte code, compress it, and then generate a c++ file that 113313531Sjairo.balart@metempsy.com# inserts the result into an array. 113413531Sjairo.balart@metempsy.comdef embedPyFile(target, source, env): 113513531Sjairo.balart@metempsy.com def c_str(string): 113613531Sjairo.balart@metempsy.com if string is None: 113713531Sjairo.balart@metempsy.com return "0" 113813531Sjairo.balart@metempsy.com return '"%s"' % string 113913531Sjairo.balart@metempsy.com 114013531Sjairo.balart@metempsy.com '''Action function to compile a .py into a code object, marshal 114113531Sjairo.balart@metempsy.com it, compress it, and stick it into an asm file so the code appears 114213531Sjairo.balart@metempsy.com as just bytes with a label in the data section''' 114313531Sjairo.balart@metempsy.com 114413531Sjairo.balart@metempsy.com src = file(str(source[0]), 'r').read() 114513531Sjairo.balart@metempsy.com 114613531Sjairo.balart@metempsy.com pysource = PySource.tnodes[source[0]] 114713531Sjairo.balart@metempsy.com compiled = compile(src, pysource.abspath, 'exec') 114813531Sjairo.balart@metempsy.com marshalled = marshal.dumps(compiled) 114913531Sjairo.balart@metempsy.com compressed = zlib.compress(marshalled) 115013531Sjairo.balart@metempsy.com data = compressed 115113531Sjairo.balart@metempsy.com sym = pysource.symname 115213531Sjairo.balart@metempsy.com 115313531Sjairo.balart@metempsy.com code = code_formatter() 115413531Sjairo.balart@metempsy.com code('''\ 115513531Sjairo.balart@metempsy.com#include "sim/init.hh" 115613531Sjairo.balart@metempsy.com 115713531Sjairo.balart@metempsy.comnamespace { 115813531Sjairo.balart@metempsy.com 115913531Sjairo.balart@metempsy.com''') 116013531Sjairo.balart@metempsy.com blobToCpp(data, 'data_' + sym, code) 116113531Sjairo.balart@metempsy.com code('''\ 116213531Sjairo.balart@metempsy.com 116313531Sjairo.balart@metempsy.com 116413531Sjairo.balart@metempsy.comEmbeddedPython embedded_${sym}( 116513531Sjairo.balart@metempsy.com ${{c_str(pysource.arcname)}}, 116613531Sjairo.balart@metempsy.com ${{c_str(pysource.abspath)}}, 116713531Sjairo.balart@metempsy.com ${{c_str(pysource.modpath)}}, 116813531Sjairo.balart@metempsy.com data_${sym}, 116913531Sjairo.balart@metempsy.com ${{len(data)}}, 117013531Sjairo.balart@metempsy.com ${{len(marshalled)}}); 117113531Sjairo.balart@metempsy.com 117213531Sjairo.balart@metempsy.com} // anonymous namespace 117313531Sjairo.balart@metempsy.com''') 117413531Sjairo.balart@metempsy.com code.write(str(target[0])) 117513531Sjairo.balart@metempsy.com 117613531Sjairo.balart@metempsy.comfor source in PySource.all: 117713531Sjairo.balart@metempsy.com env.Command(source.cpp, source.tnode, 117813531Sjairo.balart@metempsy.com MakeAction(embedPyFile, Transform("EMBED PY"))) 117913531Sjairo.balart@metempsy.com Source(source.cpp, tags=source.tags, add_tags='python') 118013531Sjairo.balart@metempsy.com 118113531Sjairo.balart@metempsy.com######################################################################## 118213531Sjairo.balart@metempsy.com# 118313531Sjairo.balart@metempsy.com# Define binaries. Each different build type (debug, opt, etc.) gets 118413531Sjairo.balart@metempsy.com# a slightly different build environment. 118513531Sjairo.balart@metempsy.com# 118613531Sjairo.balart@metempsy.com 118713531Sjairo.balart@metempsy.com# List of constructed environments to pass back to SConstruct 118813531Sjairo.balart@metempsy.comdate_source = Source('base/date.cc', tags=[]) 118913531Sjairo.balart@metempsy.com 119013531Sjairo.balart@metempsy.comgem5_binary = Gem5('gem5') 119113531Sjairo.balart@metempsy.com 1192# Function to create a new build environment as clone of current 1193# environment 'env' with modified object suffix and optional stripped 1194# binary. Additional keyword arguments are appended to corresponding 1195# build environment vars. 1196def makeEnv(env, label, objsfx, strip=False, disable_partial=False, **kwargs): 1197 # SCons doesn't know to append a library suffix when there is a '.' in the 1198 # name. Use '_' instead. 1199 libname = 'gem5_' + label 1200 secondary_exename = 'm5.' + label 1201 1202 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') 1203 new_env.Label = label 1204 new_env.Append(**kwargs) 1205 1206 lib_sources = Source.all.with_tag('gem5 lib') 1207 1208 # Without Python, leave out all Python content from the library 1209 # builds. The option doesn't affect gem5 built as a program 1210 if GetOption('without_python'): 1211 lib_sources = lib_sources.without_tag('python') 1212 1213 static_objs = [] 1214 shared_objs = [] 1215 1216 for s in lib_sources.with_tag(Source.ungrouped_tag): 1217 static_objs.append(s.static(new_env)) 1218 shared_objs.append(s.shared(new_env)) 1219 1220 for group in Source.source_groups: 1221 srcs = lib_sources.with_tag(Source.link_group_tag(group)) 1222 if not srcs: 1223 continue 1224 1225 group_static = [ s.static(new_env) for s in srcs ] 1226 group_shared = [ s.shared(new_env) for s in srcs ] 1227 1228 # If partial linking is disabled, add these sources to the build 1229 # directly, and short circuit this loop. 1230 if disable_partial: 1231 static_objs.extend(group_static) 1232 shared_objs.extend(group_shared) 1233 continue 1234 1235 # Set up the static partially linked objects. 1236 file_name = new_env.subst("${OBJPREFIX}lib${OBJSUFFIX}.partial") 1237 target = File(joinpath(group, file_name)) 1238 partial = env.PartialStatic(target=target, source=group_static) 1239 static_objs.extend(partial) 1240 1241 # Set up the shared partially linked objects. 1242 file_name = new_env.subst("${SHOBJPREFIX}lib${SHOBJSUFFIX}.partial") 1243 target = File(joinpath(group, file_name)) 1244 partial = env.PartialShared(target=target, source=group_shared) 1245 shared_objs.extend(partial) 1246 1247 static_date = date_source.static(new_env) 1248 new_env.Depends(static_date, static_objs) 1249 static_objs.extend(static_date) 1250 1251 shared_date = date_source.shared(new_env) 1252 new_env.Depends(shared_date, shared_objs) 1253 shared_objs.extend(shared_date) 1254 1255 main_objs = [ s.static(new_env) for s in Source.all.with_tag('main') ] 1256 1257 # First make a library of everything but main() so other programs can 1258 # link against m5. 1259 static_lib = new_env.StaticLibrary(libname, static_objs) 1260 shared_lib = new_env.SharedLibrary(libname, shared_objs) 1261 1262 # Keep track of the object files generated so far so Executables can 1263 # include them. 1264 new_env['STATIC_OBJS'] = static_objs 1265 new_env['SHARED_OBJS'] = shared_objs 1266 new_env['MAIN_OBJS'] = main_objs 1267 1268 new_env['STATIC_LIB'] = static_lib 1269 new_env['SHARED_LIB'] = shared_lib 1270 1271 # Record some settings for building Executables. 1272 new_env['EXE_SUFFIX'] = label 1273 new_env['STRIP_EXES'] = strip 1274 1275 for cls in ExecutableMeta.all: 1276 cls.declare_all(new_env) 1277 1278 new_env.M5Binary = File(gem5_binary.path(new_env)) 1279 1280 new_env.Command(secondary_exename, new_env.M5Binary, 1281 MakeAction('ln $SOURCE $TARGET', Transform("HARDLINK"))) 1282 1283 # Set up regression tests. 1284 SConscript(os.path.join(env.root.abspath, 'tests', 'SConscript'), 1285 variant_dir=Dir('tests').Dir(new_env.Label), 1286 exports={ 'env' : new_env }, duplicate=False) 1287 1288# Start out with the compiler flags common to all compilers, 1289# i.e. they all use -g for opt and -g -pg for prof 1290ccflags = {'debug' : [], 'opt' : ['-g'], 'fast' : [], 'prof' : ['-g', '-pg'], 1291 'perf' : ['-g']} 1292 1293# Start out with the linker flags common to all linkers, i.e. -pg for 1294# prof, and -lprofiler for perf. The -lprofile flag is surrounded by 1295# no-as-needed and as-needed as the binutils linker is too clever and 1296# simply doesn't link to the library otherwise. 1297ldflags = {'debug' : [], 'opt' : [], 'fast' : [], 'prof' : ['-pg'], 1298 'perf' : ['-Wl,--no-as-needed', '-lprofiler', '-Wl,--as-needed']} 1299 1300# For Link Time Optimization, the optimisation flags used to compile 1301# individual files are decoupled from those used at link time 1302# (i.e. you can compile with -O3 and perform LTO with -O0), so we need 1303# to also update the linker flags based on the target. 1304if env['GCC']: 1305 if sys.platform == 'sunos5': 1306 ccflags['debug'] += ['-gstabs+'] 1307 else: 1308 ccflags['debug'] += ['-ggdb3'] 1309 ldflags['debug'] += ['-O0'] 1310 # opt, fast, prof and perf all share the same cc flags, also add 1311 # the optimization to the ldflags as LTO defers the optimization 1312 # to link time 1313 for target in ['opt', 'fast', 'prof', 'perf']: 1314 ccflags[target] += ['-O3'] 1315 ldflags[target] += ['-O3'] 1316 1317 ccflags['fast'] += env['LTO_CCFLAGS'] 1318 ldflags['fast'] += env['LTO_LDFLAGS'] 1319elif env['CLANG']: 1320 ccflags['debug'] += ['-g', '-O0'] 1321 # opt, fast, prof and perf all share the same cc flags 1322 for target in ['opt', 'fast', 'prof', 'perf']: 1323 ccflags[target] += ['-O3'] 1324else: 1325 print('Unknown compiler, please fix compiler options') 1326 Exit(1) 1327 1328 1329# To speed things up, we only instantiate the build environments we 1330# need. We try to identify the needed environment for each target; if 1331# we can't, we fall back on instantiating all the environments just to 1332# be safe. 1333target_types = ['debug', 'opt', 'fast', 'prof', 'perf'] 1334obj2target = {'do': 'debug', 'o': 'opt', 'fo': 'fast', 'po': 'prof', 1335 'gpo' : 'perf'} 1336 1337def identifyTarget(t): 1338 ext = t.split('.')[-1] 1339 if ext in target_types: 1340 return ext 1341 if ext in obj2target: 1342 return obj2target[ext] 1343 match = re.search(r'/tests/([^/]+)/', t) 1344 if match and match.group(1) in target_types: 1345 return match.group(1) 1346 return 'all' 1347 1348needed_envs = [identifyTarget(target) for target in BUILD_TARGETS] 1349if 'all' in needed_envs: 1350 needed_envs += target_types 1351 1352disable_partial = False 1353if env['PLATFORM'] == 'darwin': 1354 # Up until Apple LLVM version 10.0.0 (clang-1000.11.45.5), partial 1355 # linked objects do not expose symbols that are marked with the 1356 # hidden visibility and consequently building gem5 on Mac OS 1357 # fails. As a workaround, we disable partial linking, however, we 1358 # may want to revisit in the future. 1359 disable_partial = True 1360 1361# Debug binary 1362if 'debug' in needed_envs: 1363 makeEnv(env, 'debug', '.do', 1364 CCFLAGS = Split(ccflags['debug']), 1365 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'], 1366 LINKFLAGS = Split(ldflags['debug']), 1367 disable_partial=disable_partial) 1368 1369# Optimized binary 1370if 'opt' in needed_envs: 1371 makeEnv(env, 'opt', '.o', 1372 CCFLAGS = Split(ccflags['opt']), 1373 CPPDEFINES = ['TRACING_ON=1'], 1374 LINKFLAGS = Split(ldflags['opt']), 1375 disable_partial=disable_partial) 1376 1377# "Fast" binary 1378if 'fast' in needed_envs: 1379 disable_partial = disable_partial and \ 1380 env.get('BROKEN_INCREMENTAL_LTO', False) and \ 1381 GetOption('force_lto') 1382 makeEnv(env, 'fast', '.fo', strip = True, 1383 CCFLAGS = Split(ccflags['fast']), 1384 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1385 LINKFLAGS = Split(ldflags['fast']), 1386 disable_partial=disable_partial) 1387 1388# Profiled binary using gprof 1389if 'prof' in needed_envs: 1390 makeEnv(env, 'prof', '.po', 1391 CCFLAGS = Split(ccflags['prof']), 1392 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1393 LINKFLAGS = Split(ldflags['prof']), 1394 disable_partial=disable_partial) 1395 1396# Profiled binary using google-pprof 1397if 'perf' in needed_envs: 1398 makeEnv(env, 'perf', '.gpo', 1399 CCFLAGS = Split(ccflags['perf']), 1400 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1401 LINKFLAGS = Split(ldflags['perf']), 1402 disable_partial=disable_partial) 1403