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