SConscript revision 6240:ceb4c8a5e7a2
1# -*- mode:python -*- 2 3# Copyright (c) 2004-2005 The Regents of The University of Michigan 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are 8# met: redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer; 10# redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution; 13# neither the name of the copyright holders nor the names of its 14# contributors may be used to endorse or promote products derived from 15# this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28# 29# Authors: Nathan Binkert 30 31import array 32import bisect 33import imp 34import marshal 35import os 36import re 37import sys 38import zlib 39 40from os.path import basename, dirname, exists, isdir, isfile, join as joinpath 41 42import SCons 43 44# This file defines how to build a particular configuration of M5 45# based on variable settings in the 'env' build environment. 46 47Import('*') 48 49# Children need to see the environment 50Export('env') 51 52build_env = dict([(opt, env[opt]) for opt in export_vars]) 53 54######################################################################## 55# Code for adding source files of various types 56# 57class SourceMeta(type): 58 def __init__(cls, name, bases, dict): 59 super(SourceMeta, cls).__init__(name, bases, dict) 60 cls.all = [] 61 62 def get(cls, **kwargs): 63 for src in cls.all: 64 for attr,value in kwargs.iteritems(): 65 if getattr(src, attr) != value: 66 break 67 else: 68 yield src 69 70class SourceFile(object): 71 __metaclass__ = SourceMeta 72 def __init__(self, source): 73 tnode = source 74 if not isinstance(source, SCons.Node.FS.File): 75 tnode = File(source) 76 77 self.tnode = tnode 78 self.snode = tnode.srcnode() 79 self.filename = str(tnode) 80 self.dirname = dirname(self.filename) 81 self.basename = basename(self.filename) 82 index = self.basename.rfind('.') 83 if index <= 0: 84 # dot files aren't extensions 85 self.extname = self.basename, None 86 else: 87 self.extname = self.basename[:index], self.basename[index+1:] 88 89 for base in type(self).__mro__: 90 if issubclass(base, SourceFile): 91 bisect.insort_right(base.all, self) 92 93 def __lt__(self, other): return self.filename < other.filename 94 def __le__(self, other): return self.filename <= other.filename 95 def __gt__(self, other): return self.filename > other.filename 96 def __ge__(self, other): return self.filename >= other.filename 97 def __eq__(self, other): return self.filename == other.filename 98 def __ne__(self, other): return self.filename != other.filename 99 100class Source(SourceFile): 101 '''Add a c/c++ source file to the build''' 102 def __init__(self, source, Werror=True, swig=False, bin_only=False, 103 skip_lib=False): 104 super(Source, self).__init__(source) 105 106 self.Werror = Werror 107 self.swig = swig 108 self.bin_only = bin_only 109 self.skip_lib = bin_only or skip_lib 110 111class PySource(SourceFile): 112 '''Add a python source file to the named package''' 113 invalid_sym_char = re.compile('[^A-z0-9_]') 114 modules = {} 115 tnodes = {} 116 symnames = {} 117 118 def __init__(self, package, source): 119 super(PySource, self).__init__(source) 120 121 modname,ext = self.extname 122 assert ext == 'py' 123 124 if package: 125 path = package.split('.') 126 else: 127 path = [] 128 129 modpath = path[:] 130 if modname != '__init__': 131 modpath += [ modname ] 132 modpath = '.'.join(modpath) 133 134 arcpath = path + [ self.basename ] 135 debugname = self.snode.abspath 136 if not exists(debugname): 137 debugname = self.tnode.abspath 138 139 self.package = package 140 self.modname = modname 141 self.modpath = modpath 142 self.arcname = joinpath(*arcpath) 143 self.debugname = debugname 144 self.compiled = File(self.filename + 'c') 145 self.assembly = File(self.filename + '.s') 146 self.symname = "PyEMB_" + PySource.invalid_sym_char.sub('_', modpath) 147 148 PySource.modules[modpath] = self 149 PySource.tnodes[self.tnode] = self 150 PySource.symnames[self.symname] = self 151 152class SimObject(PySource): 153 '''Add a SimObject python file as a python source object and add 154 it to a list of sim object modules''' 155 156 fixed = False 157 modnames = [] 158 159 def __init__(self, source): 160 super(SimObject, self).__init__('m5.objects', source) 161 if self.fixed: 162 raise AttributeError, "Too late to call SimObject now." 163 164 bisect.insort_right(SimObject.modnames, self.modname) 165 166class SwigSource(SourceFile): 167 '''Add a swig file to build''' 168 169 def __init__(self, package, source): 170 super(SwigSource, self).__init__(source) 171 172 modname,ext = self.extname 173 assert ext == 'i' 174 175 self.module = modname 176 cc_file = joinpath(self.dirname, modname + '_wrap.cc') 177 py_file = joinpath(self.dirname, modname + '.py') 178 179 self.cc_source = Source(cc_file, swig=True) 180 self.py_source = PySource(package, py_file) 181 182unit_tests = [] 183def UnitTest(target, sources): 184 if not isinstance(sources, (list, tuple)): 185 sources = [ sources ] 186 187 sources = [ Source(src, skip_lib=True) for src in sources ] 188 unit_tests.append((target, sources)) 189 190# Children should have access 191Export('Source') 192Export('PySource') 193Export('SimObject') 194Export('SwigSource') 195Export('UnitTest') 196 197######################################################################## 198# 199# Trace Flags 200# 201trace_flags = {} 202def TraceFlag(name, desc=None): 203 if name in trace_flags: 204 raise AttributeError, "Flag %s already specified" % name 205 trace_flags[name] = (name, (), desc) 206 207def CompoundFlag(name, flags, desc=None): 208 if name in trace_flags: 209 raise AttributeError, "Flag %s already specified" % name 210 211 compound = tuple(flags) 212 trace_flags[name] = (name, compound, desc) 213 214Export('TraceFlag') 215Export('CompoundFlag') 216 217######################################################################## 218# 219# Set some compiler variables 220# 221 222# Include file paths are rooted in this directory. SCons will 223# automatically expand '.' to refer to both the source directory and 224# the corresponding build directory to pick up generated include 225# files. 226env.Append(CPPPATH=Dir('.')) 227 228for extra_dir in extras_dir_list: 229 env.Append(CPPPATH=Dir(extra_dir)) 230 231# Add a flag defining what THE_ISA should be for all compilation 232env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())]) 233 234# Workaround for bug in SCons version > 0.97d20071212 235# Scons bug id: 2006 M5 Bug id: 308 236for root, dirs, files in os.walk(base_dir, topdown=True): 237 Dir(root[len(base_dir) + 1:]) 238 239######################################################################## 240# 241# Walk the tree and execute all SConscripts in subdirectories 242# 243 244here = Dir('.').srcnode().abspath 245for root, dirs, files in os.walk(base_dir, topdown=True): 246 if root == here: 247 # we don't want to recurse back into this SConscript 248 continue 249 250 if 'SConscript' in files: 251 build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:]) 252 SConscript(joinpath(root, 'SConscript'), build_dir=build_dir) 253 254for extra_dir in extras_dir_list: 255 prefix_len = len(dirname(extra_dir)) + 1 256 for root, dirs, files in os.walk(extra_dir, topdown=True): 257 if 'SConscript' in files: 258 build_dir = joinpath(env['BUILDDIR'], root[prefix_len:]) 259 SConscript(joinpath(root, 'SConscript'), build_dir=build_dir) 260 261for opt in export_vars: 262 env.ConfigFile(opt) 263 264######################################################################## 265# 266# Prevent any SimObjects from being added after this point, they 267# should all have been added in the SConscripts above 268# 269class DictImporter(object): 270 '''This importer takes a dictionary of arbitrary module names that 271 map to arbitrary filenames.''' 272 def __init__(self, modules): 273 self.modules = modules 274 self.installed = set() 275 276 def __del__(self): 277 self.unload() 278 279 def unload(self): 280 import sys 281 for module in self.installed: 282 del sys.modules[module] 283 self.installed = set() 284 285 def find_module(self, fullname, path): 286 if fullname == 'defines': 287 return self 288 289 if fullname == 'm5.objects': 290 return self 291 292 if fullname.startswith('m5.internal'): 293 return None 294 295 source = self.modules.get(fullname, None) 296 if source is not None and exists(source.snode.abspath): 297 return self 298 299 return None 300 301 def load_module(self, fullname): 302 mod = imp.new_module(fullname) 303 sys.modules[fullname] = mod 304 self.installed.add(fullname) 305 306 mod.__loader__ = self 307 if fullname == 'm5.objects': 308 mod.__path__ = fullname.split('.') 309 return mod 310 311 if fullname == 'defines': 312 mod.__dict__['buildEnv'] = build_env 313 return mod 314 315 source = self.modules[fullname] 316 if source.modname == '__init__': 317 mod.__path__ = source.modpath 318 mod.__file__ = source.snode.abspath 319 320 exec file(source.snode.abspath, 'r') in mod.__dict__ 321 322 return mod 323 324# install the python importer so we can grab stuff from the source 325# tree itself. We can't have SimObjects added after this point or 326# else we won't know about them for the rest of the stuff. 327SimObject.fixed = True 328importer = DictImporter(PySource.modules) 329sys.meta_path[0:0] = [ importer ] 330 331import m5 332 333# import all sim objects so we can populate the all_objects list 334# make sure that we're working with a list, then let's sort it 335for modname in SimObject.modnames: 336 exec('from m5.objects import %s' % modname) 337 338# we need to unload all of the currently imported modules so that they 339# will be re-imported the next time the sconscript is run 340importer.unload() 341sys.meta_path.remove(importer) 342 343sim_objects = m5.SimObject.allClasses 344all_enums = m5.params.allEnums 345 346all_params = {} 347for name,obj in sorted(sim_objects.iteritems()): 348 for param in obj._params.local.values(): 349 if not hasattr(param, 'swig_decl'): 350 continue 351 pname = param.ptype_str 352 if pname not in all_params: 353 all_params[pname] = param 354 355######################################################################## 356# 357# calculate extra dependencies 358# 359module_depends = ["m5", "m5.SimObject", "m5.params"] 360depends = [ PySource.modules[dep].tnode for dep in module_depends ] 361 362######################################################################## 363# 364# Commands for the basic automatically generated python files 365# 366 367# Generate Python file containing a dict specifying the current 368# build_env flags. 369def makeDefinesPyFile(target, source, env): 370 f = file(str(target[0]), 'w') 371 build_env, hg_info = [ x.get_contents() for x in source ] 372 print >>f, "buildEnv = %s" % build_env 373 print >>f, "hgRev = '%s'" % hg_info 374 f.close() 375 376defines_info = [ Value(build_env), Value(env['HG_INFO']) ] 377# Generate a file with all of the compile options in it 378env.Command('python/m5/defines.py', defines_info, makeDefinesPyFile) 379PySource('m5', 'python/m5/defines.py') 380 381# Generate python file containing info about the M5 source code 382def makeInfoPyFile(target, source, env): 383 f = file(str(target[0]), 'w') 384 for src in source: 385 data = ''.join(file(src.srcnode().abspath, 'r').xreadlines()) 386 print >>f, "%s = %s" % (src, repr(data)) 387 f.close() 388 389# Generate a file that wraps the basic top level files 390env.Command('python/m5/info.py', 391 [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ], 392 makeInfoPyFile) 393PySource('m5', 'python/m5/info.py') 394 395# Generate the __init__.py file for m5.objects 396def makeObjectsInitFile(target, source, env): 397 f = file(str(target[0]), 'w') 398 print >>f, 'from params import *' 399 print >>f, 'from m5.SimObject import *' 400 for module in source: 401 print >>f, 'from %s import *' % module.get_contents() 402 f.close() 403 404# Generate an __init__.py file for the objects package 405env.Command('python/m5/objects/__init__.py', 406 map(Value, SimObject.modnames), 407 makeObjectsInitFile) 408PySource('m5.objects', 'python/m5/objects/__init__.py') 409 410######################################################################## 411# 412# Create all of the SimObject param headers and enum headers 413# 414 415def createSimObjectParam(target, source, env): 416 assert len(target) == 1 and len(source) == 1 417 418 hh_file = file(target[0].abspath, 'w') 419 name = str(source[0].get_contents()) 420 obj = sim_objects[name] 421 422 print >>hh_file, obj.cxx_decl() 423 hh_file.close() 424 425def createSwigParam(target, source, env): 426 assert len(target) == 1 and len(source) == 1 427 428 i_file = file(target[0].abspath, 'w') 429 name = str(source[0].get_contents()) 430 param = all_params[name] 431 432 for line in param.swig_decl(): 433 print >>i_file, line 434 i_file.close() 435 436def createEnumStrings(target, source, env): 437 assert len(target) == 1 and len(source) == 1 438 439 cc_file = file(target[0].abspath, 'w') 440 name = str(source[0].get_contents()) 441 obj = all_enums[name] 442 443 print >>cc_file, obj.cxx_def() 444 cc_file.close() 445 446def createEnumParam(target, source, env): 447 assert len(target) == 1 and len(source) == 1 448 449 hh_file = file(target[0].abspath, 'w') 450 name = str(source[0].get_contents()) 451 obj = all_enums[name] 452 453 print >>hh_file, obj.cxx_decl() 454 hh_file.close() 455 456# Generate all of the SimObject param struct header files 457params_hh_files = [] 458for name,simobj in sorted(sim_objects.iteritems()): 459 py_source = PySource.modules[simobj.__module__] 460 extra_deps = [ py_source.tnode ] 461 462 hh_file = File('params/%s.hh' % name) 463 params_hh_files.append(hh_file) 464 env.Command(hh_file, Value(name), createSimObjectParam) 465 env.Depends(hh_file, depends + extra_deps) 466 467# Generate any parameter header files needed 468params_i_files = [] 469for name,param in all_params.iteritems(): 470 if isinstance(param, m5.params.VectorParamDesc): 471 ext = 'vptype' 472 else: 473 ext = 'ptype' 474 475 i_file = File('params/%s_%s.i' % (name, ext)) 476 params_i_files.append(i_file) 477 env.Command(i_file, Value(name), createSwigParam) 478 env.Depends(i_file, depends) 479 480# Generate all enum header files 481for name,enum in sorted(all_enums.iteritems()): 482 py_source = PySource.modules[enum.__module__] 483 extra_deps = [ py_source.tnode ] 484 485 cc_file = File('enums/%s.cc' % name) 486 env.Command(cc_file, Value(name), createEnumStrings) 487 env.Depends(cc_file, depends + extra_deps) 488 Source(cc_file) 489 490 hh_file = File('enums/%s.hh' % name) 491 env.Command(hh_file, Value(name), createEnumParam) 492 env.Depends(hh_file, depends + extra_deps) 493 494# Build the big monolithic swigged params module (wraps all SimObject 495# param structs and enum structs) 496def buildParams(target, source, env): 497 names = [ s.get_contents() for s in source ] 498 objs = [ sim_objects[name] for name in names ] 499 out = file(target[0].abspath, 'w') 500 501 ordered_objs = [] 502 obj_seen = set() 503 def order_obj(obj): 504 name = str(obj) 505 if name in obj_seen: 506 return 507 508 obj_seen.add(name) 509 if str(obj) != 'SimObject': 510 order_obj(obj.__bases__[0]) 511 512 ordered_objs.append(obj) 513 514 for obj in objs: 515 order_obj(obj) 516 517 enums = set() 518 predecls = [] 519 pd_seen = set() 520 521 def add_pds(*pds): 522 for pd in pds: 523 if pd not in pd_seen: 524 predecls.append(pd) 525 pd_seen.add(pd) 526 527 for obj in ordered_objs: 528 params = obj._params.local.values() 529 for param in params: 530 ptype = param.ptype 531 if issubclass(ptype, m5.params.Enum): 532 if ptype not in enums: 533 enums.add(ptype) 534 pds = param.swig_predecls() 535 if isinstance(pds, (list, tuple)): 536 add_pds(*pds) 537 else: 538 add_pds(pds) 539 540 print >>out, '%module params' 541 542 print >>out, '%{' 543 for obj in ordered_objs: 544 print >>out, '#include "params/%s.hh"' % obj 545 print >>out, '%}' 546 547 for pd in predecls: 548 print >>out, pd 549 550 enums = list(enums) 551 enums.sort() 552 for enum in enums: 553 print >>out, '%%include "enums/%s.hh"' % enum.__name__ 554 print >>out 555 556 for obj in ordered_objs: 557 if obj.swig_objdecls: 558 for decl in obj.swig_objdecls: 559 print >>out, decl 560 continue 561 562 class_path = obj.cxx_class.split('::') 563 classname = class_path[-1] 564 namespaces = class_path[:-1] 565 namespaces.reverse() 566 567 code = '' 568 569 if namespaces: 570 code += '// avoid name conflicts\n' 571 sep_string = '_COLONS_' 572 flat_name = sep_string.join(class_path) 573 code += '%%rename(%s) %s;\n' % (flat_name, classname) 574 575 code += '// stop swig from creating/wrapping default ctor/dtor\n' 576 code += '%%nodefault %s;\n' % classname 577 code += 'class %s ' % classname 578 if obj._base: 579 code += ': public %s' % obj._base.cxx_class 580 code += ' {};\n' 581 582 for ns in namespaces: 583 new_code = 'namespace %s {\n' % ns 584 new_code += code 585 new_code += '}\n' 586 code = new_code 587 588 print >>out, code 589 590 print >>out, '%%include "src/sim/sim_object_params.hh"' % obj 591 for obj in ordered_objs: 592 print >>out, '%%include "params/%s.hh"' % obj 593 594params_file = File('params/params.i') 595names = sorted(sim_objects.keys()) 596env.Command(params_file, map(Value, names), buildParams) 597env.Depends(params_file, params_hh_files + params_i_files + depends) 598SwigSource('m5.objects', params_file) 599 600# Build all swig modules 601for swig in SwigSource.all: 602 env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode, 603 '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' 604 '-o ${TARGETS[0]} $SOURCES') 605 env.Depends(swig.py_source.tnode, swig.tnode) 606 env.Depends(swig.cc_source.tnode, swig.tnode) 607 608# Generate the main swig init file 609def makeSwigInit(target, source, env): 610 f = file(str(target[0]), 'w') 611 print >>f, 'extern "C" {' 612 for module in source: 613 print >>f, ' void init_%s();' % module.get_contents() 614 print >>f, '}' 615 print >>f, 'void initSwig() {' 616 for module in source: 617 print >>f, ' init_%s();' % module.get_contents() 618 print >>f, '}' 619 f.close() 620 621env.Command('python/swig/init.cc', 622 map(Value, sorted(s.module for s in SwigSource.all)), 623 makeSwigInit) 624Source('python/swig/init.cc') 625 626def getFlags(source_flags): 627 flagsMap = {} 628 flagsList = [] 629 for s in source_flags: 630 val = eval(s.get_contents()) 631 name, compound, desc = val 632 flagsList.append(val) 633 flagsMap[name] = bool(compound) 634 635 for name, compound, desc in flagsList: 636 for flag in compound: 637 if flag not in flagsMap: 638 raise AttributeError, "Trace flag %s not found" % flag 639 if flagsMap[flag]: 640 raise AttributeError, \ 641 "Compound flag can't point to another compound flag" 642 643 flagsList.sort() 644 return flagsList 645 646 647# Generate traceflags.py 648def traceFlagsPy(target, source, env): 649 assert(len(target) == 1) 650 651 f = file(str(target[0]), 'w') 652 653 allFlags = getFlags(source) 654 655 print >>f, 'basic = [' 656 for flag, compound, desc in allFlags: 657 if not compound: 658 print >>f, " '%s'," % flag 659 print >>f, " ]" 660 print >>f 661 662 print >>f, 'compound = [' 663 print >>f, " 'All'," 664 for flag, compound, desc in allFlags: 665 if compound: 666 print >>f, " '%s'," % flag 667 print >>f, " ]" 668 print >>f 669 670 print >>f, "all = frozenset(basic + compound)" 671 print >>f 672 673 print >>f, 'compoundMap = {' 674 all = tuple([flag for flag,compound,desc in allFlags if not compound]) 675 print >>f, " 'All' : %s," % (all, ) 676 for flag, compound, desc in allFlags: 677 if compound: 678 print >>f, " '%s' : %s," % (flag, compound) 679 print >>f, " }" 680 print >>f 681 682 print >>f, 'descriptions = {' 683 print >>f, " 'All' : 'All flags'," 684 for flag, compound, desc in allFlags: 685 print >>f, " '%s' : '%s'," % (flag, desc) 686 print >>f, " }" 687 688 f.close() 689 690def traceFlagsCC(target, source, env): 691 assert(len(target) == 1) 692 693 f = file(str(target[0]), 'w') 694 695 allFlags = getFlags(source) 696 697 # file header 698 print >>f, ''' 699/* 700 * DO NOT EDIT THIS FILE! Automatically generated 701 */ 702 703#include "base/traceflags.hh" 704 705using namespace Trace; 706 707const char *Trace::flagStrings[] = 708{''' 709 710 # The string array is used by SimpleEnumParam to map the strings 711 # provided by the user to enum values. 712 for flag, compound, desc in allFlags: 713 if not compound: 714 print >>f, ' "%s",' % flag 715 716 print >>f, ' "All",' 717 for flag, compound, desc in allFlags: 718 if compound: 719 print >>f, ' "%s",' % flag 720 721 print >>f, '};' 722 print >>f 723 print >>f, 'const int Trace::numFlagStrings = %d;' % (len(allFlags) + 1) 724 print >>f 725 726 # 727 # Now define the individual compound flag arrays. There is an array 728 # for each compound flag listing the component base flags. 729 # 730 all = tuple([flag for flag,compound,desc in allFlags if not compound]) 731 print >>f, 'static const Flags AllMap[] = {' 732 for flag, compound, desc in allFlags: 733 if not compound: 734 print >>f, " %s," % flag 735 print >>f, '};' 736 print >>f 737 738 for flag, compound, desc in allFlags: 739 if not compound: 740 continue 741 print >>f, 'static const Flags %sMap[] = {' % flag 742 for flag in compound: 743 print >>f, " %s," % flag 744 print >>f, " (Flags)-1" 745 print >>f, '};' 746 print >>f 747 748 # 749 # Finally the compoundFlags[] array maps the compound flags 750 # to their individual arrays/ 751 # 752 print >>f, 'const Flags *Trace::compoundFlags[] =' 753 print >>f, '{' 754 print >>f, ' AllMap,' 755 for flag, compound, desc in allFlags: 756 if compound: 757 print >>f, ' %sMap,' % flag 758 # file trailer 759 print >>f, '};' 760 761 f.close() 762 763def traceFlagsHH(target, source, env): 764 assert(len(target) == 1) 765 766 f = file(str(target[0]), 'w') 767 768 allFlags = getFlags(source) 769 770 # file header boilerplate 771 print >>f, ''' 772/* 773 * DO NOT EDIT THIS FILE! 774 * 775 * Automatically generated from traceflags.py 776 */ 777 778#ifndef __BASE_TRACE_FLAGS_HH__ 779#define __BASE_TRACE_FLAGS_HH__ 780 781namespace Trace { 782 783enum Flags {''' 784 785 # Generate the enum. Base flags come first, then compound flags. 786 idx = 0 787 for flag, compound, desc in allFlags: 788 if not compound: 789 print >>f, ' %s = %d,' % (flag, idx) 790 idx += 1 791 792 numBaseFlags = idx 793 print >>f, ' NumFlags = %d,' % idx 794 795 # put a comment in here to separate base from compound flags 796 print >>f, ''' 797// The remaining enum values are *not* valid indices for Trace::flags. 798// They are "compound" flags, which correspond to sets of base 799// flags, and are used by changeFlag.''' 800 801 print >>f, ' All = %d,' % idx 802 idx += 1 803 for flag, compound, desc in allFlags: 804 if compound: 805 print >>f, ' %s = %d,' % (flag, idx) 806 idx += 1 807 808 numCompoundFlags = idx - numBaseFlags 809 print >>f, ' NumCompoundFlags = %d' % numCompoundFlags 810 811 # trailer boilerplate 812 print >>f, '''\ 813}; // enum Flags 814 815// Array of strings for SimpleEnumParam 816extern const char *flagStrings[]; 817extern const int numFlagStrings; 818 819// Array of arraay pointers: for each compound flag, gives the list of 820// base flags to set. Inidividual flag arrays are terminated by -1. 821extern const Flags *compoundFlags[]; 822 823/* namespace Trace */ } 824 825#endif // __BASE_TRACE_FLAGS_HH__ 826''' 827 828 f.close() 829 830flags = map(Value, trace_flags.values()) 831env.Command('base/traceflags.py', flags, traceFlagsPy) 832PySource('m5', 'base/traceflags.py') 833 834env.Command('base/traceflags.hh', flags, traceFlagsHH) 835env.Command('base/traceflags.cc', flags, traceFlagsCC) 836Source('base/traceflags.cc') 837 838# embed python files. All .py files that have been indicated by a 839# PySource() call in a SConscript need to be embedded into the M5 840# library. To do that, we compile the file to byte code, marshal the 841# byte code, compress it, and then generate an assembly file that 842# inserts the result into the data section with symbols indicating the 843# beginning, and end (and with the size at the end) 844def objectifyPyFile(target, source, env): 845 '''Action function to compile a .py into a code object, marshal 846 it, compress it, and stick it into an asm file so the code appears 847 as just bytes with a label in the data section''' 848 849 src = file(str(source[0]), 'r').read() 850 dst = file(str(target[0]), 'w') 851 852 pysource = PySource.tnodes[source[0]] 853 compiled = compile(src, pysource.debugname, 'exec') 854 marshalled = marshal.dumps(compiled) 855 compressed = zlib.compress(marshalled) 856 data = compressed 857 858 # Some C/C++ compilers prepend an underscore to global symbol 859 # names, so if they're going to do that, we need to prepend that 860 # leading underscore to globals in the assembly file. 861 if env['LEADING_UNDERSCORE']: 862 sym = '_' + pysource.symname 863 else: 864 sym = pysource.symname 865 866 step = 16 867 print >>dst, ".data" 868 print >>dst, ".globl %s_beg" % sym 869 print >>dst, ".globl %s_end" % sym 870 print >>dst, "%s_beg:" % sym 871 for i in xrange(0, len(data), step): 872 x = array.array('B', data[i:i+step]) 873 print >>dst, ".byte", ','.join([str(d) for d in x]) 874 print >>dst, "%s_end:" % sym 875 print >>dst, ".long %d" % len(marshalled) 876 877for source in PySource.all: 878 env.Command(source.assembly, source.tnode, objectifyPyFile) 879 Source(source.assembly) 880 881# Generate init_python.cc which creates a bunch of EmbeddedPyModule 882# structs that describe the embedded python code. One such struct 883# contains information about the importer that python uses to get at 884# the embedded files, and then there's a list of all of the rest that 885# the importer uses to load the rest on demand. 886def pythonInit(target, source, env): 887 dst = file(str(target[0]), 'w') 888 889 def dump_mod(sym, endchar=','): 890 pysource = PySource.symnames[sym] 891 print >>dst, ' { "%s",' % pysource.arcname 892 print >>dst, ' "%s",' % pysource.modpath 893 print >>dst, ' %s_beg, %s_end,' % (sym, sym) 894 print >>dst, ' %s_end - %s_beg,' % (sym, sym) 895 print >>dst, ' *(int *)%s_end }%s' % (sym, endchar) 896 897 print >>dst, '#include "sim/init.hh"' 898 899 for sym in source: 900 sym = sym.get_contents() 901 print >>dst, "extern const char %s_beg[], %s_end[];" % (sym, sym) 902 903 print >>dst, "const EmbeddedPyModule embeddedPyImporter = " 904 dump_mod("PyEMB_importer", endchar=';'); 905 print >>dst 906 907 print >>dst, "const EmbeddedPyModule embeddedPyModules[] = {" 908 for i,sym in enumerate(source): 909 sym = sym.get_contents() 910 if sym == "PyEMB_importer": 911 # Skip the importer since we've already exported it 912 continue 913 dump_mod(sym) 914 print >>dst, " { 0, 0, 0, 0, 0, 0 }" 915 print >>dst, "};" 916 917 918env.Command('sim/init_python.cc', 919 map(Value, (s.symname for s in PySource.all)), 920 pythonInit) 921Source('sim/init_python.cc') 922 923######################################################################## 924# 925# Define binaries. Each different build type (debug, opt, etc.) gets 926# a slightly different build environment. 927# 928 929# List of constructed environments to pass back to SConstruct 930envList = [] 931 932date_source = Source('base/date.cc', skip_lib=True) 933 934# Function to create a new build environment as clone of current 935# environment 'env' with modified object suffix and optional stripped 936# binary. Additional keyword arguments are appended to corresponding 937# build environment vars. 938def makeEnv(label, objsfx, strip = False, **kwargs): 939 # SCons doesn't know to append a library suffix when there is a '.' in the 940 # name. Use '_' instead. 941 libname = 'm5_' + label 942 exename = 'm5.' + label 943 944 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's') 945 new_env.Label = label 946 new_env.Append(**kwargs) 947 948 swig_env = new_env.Clone() 949 swig_env.Append(CCFLAGS='-Werror') 950 if env['GCC']: 951 swig_env.Append(CCFLAGS='-Wno-uninitialized') 952 swig_env.Append(CCFLAGS='-Wno-sign-compare') 953 swig_env.Append(CCFLAGS='-Wno-parentheses') 954 955 werror_env = new_env.Clone() 956 werror_env.Append(CCFLAGS='-Werror') 957 958 def make_obj(source, static, extra_deps = None): 959 '''This function adds the specified source to the correct 960 build environment, and returns the corresponding SCons Object 961 nodes''' 962 963 if source.swig: 964 env = swig_env 965 elif source.Werror: 966 env = werror_env 967 else: 968 env = new_env 969 970 if static: 971 obj = env.StaticObject(source.tnode) 972 else: 973 obj = env.SharedObject(source.tnode) 974 975 if extra_deps: 976 env.Depends(obj, extra_deps) 977 978 return obj 979 980 static_objs = [ make_obj(s, True) for s in Source.get(skip_lib=False)] 981 shared_objs = [ make_obj(s, False) for s in Source.get(skip_lib=False)] 982 983 static_date = make_obj(date_source, static=True, extra_deps=static_objs) 984 static_objs.append(static_date) 985 986 shared_date = make_obj(date_source, static=False, extra_deps=shared_objs) 987 shared_objs.append(shared_date) 988 989 # First make a library of everything but main() so other programs can 990 # link against m5. 991 static_lib = new_env.StaticLibrary(libname, static_objs) 992 shared_lib = new_env.SharedLibrary(libname, shared_objs) 993 994 for target, sources in unit_tests: 995 objs = [ make_obj(s, static=True) for s in sources ] 996 new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs) 997 998 # Now link a stub with main() and the static library. 999 bin_objs = [make_obj(s, True) for s in Source.get(bin_only=True) ] 1000 progname = exename 1001 if strip: 1002 progname += '.unstripped' 1003 1004 targets = new_env.Program(progname, bin_objs + static_objs) 1005 1006 if strip: 1007 if sys.platform == 'sunos5': 1008 cmd = 'cp $SOURCE $TARGET; strip $TARGET' 1009 else: 1010 cmd = 'strip $SOURCE -o $TARGET' 1011 targets = new_env.Command(exename, progname, cmd) 1012 1013 new_env.M5Binary = targets[0] 1014 envList.append(new_env) 1015 1016# Debug binary 1017ccflags = {} 1018if env['GCC']: 1019 if sys.platform == 'sunos5': 1020 ccflags['debug'] = '-gstabs+' 1021 else: 1022 ccflags['debug'] = '-ggdb3' 1023 ccflags['opt'] = '-g -O3' 1024 ccflags['fast'] = '-O3' 1025 ccflags['prof'] = '-O3 -g -pg' 1026elif env['SUNCC']: 1027 ccflags['debug'] = '-g0' 1028 ccflags['opt'] = '-g -O' 1029 ccflags['fast'] = '-fast' 1030 ccflags['prof'] = '-fast -g -pg' 1031elif env['ICC']: 1032 ccflags['debug'] = '-g -O0' 1033 ccflags['opt'] = '-g -O' 1034 ccflags['fast'] = '-fast' 1035 ccflags['prof'] = '-fast -g -pg' 1036else: 1037 print 'Unknown compiler, please fix compiler options' 1038 Exit(1) 1039 1040makeEnv('debug', '.do', 1041 CCFLAGS = Split(ccflags['debug']), 1042 CPPDEFINES = ['DEBUG', 'TRACING_ON=1']) 1043 1044# Optimized binary 1045makeEnv('opt', '.o', 1046 CCFLAGS = Split(ccflags['opt']), 1047 CPPDEFINES = ['TRACING_ON=1']) 1048 1049# "Fast" binary 1050makeEnv('fast', '.fo', strip = True, 1051 CCFLAGS = Split(ccflags['fast']), 1052 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0']) 1053 1054# Profiled binary 1055makeEnv('prof', '.po', 1056 CCFLAGS = Split(ccflags['prof']), 1057 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'], 1058 LINKFLAGS = '-pg') 1059 1060Return('envList') 1061