SConscript revision 5801
12124SN/A# -*- mode:python -*- 22124SN/A 32706Sksewell@umich.edu# Copyright (c) 2004-2005 The Regents of The University of Michigan 42706Sksewell@umich.edu# All rights reserved. 52706Sksewell@umich.edu# 62706Sksewell@umich.edu# Redistribution and use in source and binary forms, with or without 72706Sksewell@umich.edu# modification, are permitted provided that the following conditions are 82706Sksewell@umich.edu# met: redistributions of source code must retain the above copyright 92706Sksewell@umich.edu# notice, this list of conditions and the following disclaimer; 102706Sksewell@umich.edu# redistributions in binary form must reproduce the above copyright 112706Sksewell@umich.edu# notice, this list of conditions and the following disclaimer in the 122706Sksewell@umich.edu# documentation and/or other materials provided with the distribution; 132706Sksewell@umich.edu# neither the name of the copyright holders nor the names of its 142706Sksewell@umich.edu# contributors may be used to endorse or promote products derived from 152706Sksewell@umich.edu# this software without specific prior written permission. 162706Sksewell@umich.edu# 172706Sksewell@umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182706Sksewell@umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192706Sksewell@umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202706Sksewell@umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212706Sksewell@umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222706Sksewell@umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232706Sksewell@umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242706Sksewell@umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252706Sksewell@umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262706Sksewell@umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272706Sksewell@umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282706Sksewell@umich.edu# 292706Sksewell@umich.edu# Authors: Nathan Binkert 302706Sksewell@umich.edu 312022SN/Aimport array 322022SN/Aimport imp 332022SN/Aimport marshal 342022SN/Aimport os 352022SN/Aimport re 362135SN/Aimport sys 372025SN/Aimport zlib 382025SN/A 392022SN/Afrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath 402135SN/A 412135SN/Aimport SCons 422135SN/A 432135SN/A# This file defines how to build a particular configuration of M5 442135SN/A# based on variable settings in the 'env' build environment. 452026SN/A 462026SN/AImport('*') 472025SN/A 482026SN/A# Children need to see the environment 492061SN/AExport('env') 502026SN/A 512026SN/Abuild_env = dict([(opt, env[opt]) for opt in env.ExportOptions]) 522686Sksewell@umich.edu 532686Sksewell@umich.edudef sort_list(_list): 542686Sksewell@umich.edu """return a sorted copy of '_list'""" 552686Sksewell@umich.edu if isinstance(_list, list): 562686Sksewell@umich.edu _list = _list[:] 572686Sksewell@umich.edu else: 582029SN/A _list = list(_list) 592026SN/A _list.sort() 602686Sksewell@umich.edu return _list 612041SN/A 622029SN/Aclass PySourceFile(object): 632041SN/A invalid_sym_char = re.compile('[^A-z0-9_]') 642239SN/A def __init__(self, package, tnode): 652029SN/A snode = tnode.srcnode() 662029SN/A filename = str(tnode) 672029SN/A pyname = basename(filename) 682029SN/A assert pyname.endswith('.py') 692135SN/A name = pyname[:-3] 702135SN/A if package: 712029SN/A path = package.split('.') 722029SN/A else: 732029SN/A path = [] 742029SN/A 752029SN/A modpath = path[:] 762029SN/A if name != '__init__': 772601SN/A modpath += [name] 782601SN/A modpath = '.'.join(modpath) 792601SN/A 802601SN/A arcpath = path + [ pyname ] 812239SN/A arcname = joinpath(*arcpath) 822239SN/A 832239SN/A debugname = snode.abspath 842029SN/A if not exists(debugname): 852029SN/A debugname = tnode.abspath 862025SN/A 872029SN/A self.tnode = tnode 882029SN/A self.snode = snode 892025SN/A self.pyname = pyname 902124SN/A self.package = package 912043SN/A self.modpath = modpath 922135SN/A self.arcname = arcname 932025SN/A self.debugname = debugname 942043SN/A self.compiled = File(filename + 'c') 952043SN/A self.assembly = File(filename + '.s') 962025SN/A self.symname = "PyEMB_" + self.invalid_sym_char.sub('_', modpath) 972686Sksewell@umich.edu 982686Sksewell@umich.edu 992686Sksewell@umich.edu######################################################################## 1002686Sksewell@umich.edu# Code for adding source files of various types 1012025SN/A# 1022025SN/Acc_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