SConscript revision 6365
12155SN/A# -*- mode:python -*- 22155SN/A 32155SN/A# Copyright (c) 2004-2005 The Regents of The University of Michigan 42155SN/A# All rights reserved. 52155SN/A# 62155SN/A# Redistribution and use in source and binary forms, with or without 72155SN/A# modification, are permitted provided that the following conditions are 82155SN/A# met: redistributions of source code must retain the above copyright 92155SN/A# notice, this list of conditions and the following disclaimer; 102155SN/A# redistributions in binary form must reproduce the above copyright 112155SN/A# notice, this list of conditions and the following disclaimer in the 122155SN/A# documentation and/or other materials provided with the distribution; 132155SN/A# neither the name of the copyright holders nor the names of its 142155SN/A# contributors may be used to endorse or promote products derived from 152155SN/A# this software without specific prior written permission. 162155SN/A# 172155SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 182155SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 192155SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 202155SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 212155SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 222155SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 232155SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 242155SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 252155SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 262155SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 272155SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 282665Ssaidi@eecs.umich.edu# 292665Ssaidi@eecs.umich.edu# Authors: Nathan Binkert 302155SN/A 314202Sbinkertn@umich.eduimport array 322155SN/Aimport bisect 339850Sandreas.hansson@arm.comimport imp 349850Sandreas.hansson@arm.comimport marshal 359850Sandreas.hansson@arm.comimport os 367768SAli.Saidi@ARM.comimport re 377768SAli.Saidi@ARM.comimport sys 388887Sgeoffrey.blake@arm.comimport zlib 392766Sktlim@umich.edu 404486Sbinkertn@umich.edufrom os.path import basename, dirname, exists, isdir, isfile, join as joinpath 414486Sbinkertn@umich.edu 424776Sgblack@eecs.umich.eduimport SCons 434776Sgblack@eecs.umich.edu 448739Sgblack@eecs.umich.edu# This file defines how to build a particular configuration of M5 456365Sgblack@eecs.umich.edu# based on variable settings in the 'env' build environment. 4610259SAndrew.Bardsley@arm.com 474486Sbinkertn@umich.eduImport('*') 484202Sbinkertn@umich.edu 494202Sbinkertn@umich.edu# Children need to see the environment 504202Sbinkertn@umich.eduExport('env') 514202Sbinkertn@umich.edu 5210319SAndreas.Sandberg@ARM.combuild_env = dict([(opt, env[opt]) for opt in export_vars]) 534202Sbinkertn@umich.edu 544776Sgblack@eecs.umich.edu######################################################################## 558739Sgblack@eecs.umich.edu# Code for adding source files of various types 566365Sgblack@eecs.umich.edu# 574202Sbinkertn@umich.educlass SourceMeta(type): 588777Sgblack@eecs.umich.edu def __init__(cls, name, bases, dict): 594202Sbinkertn@umich.edu super(SourceMeta, cls).__init__(name, bases, dict) 609913Ssteve.reinhardt@amd.com cls.all = [] 614202Sbinkertn@umich.edu 624202Sbinkertn@umich.edu def get(cls, **kwargs): 635217Ssaidi@eecs.umich.edu for src in cls.all: 644202Sbinkertn@umich.edu for attr,value in kwargs.iteritems(): 6510259SAndrew.Bardsley@arm.com if getattr(src, attr) != value: 662155SN/A break 678793Sgblack@eecs.umich.edu else: 688793Sgblack@eecs.umich.edu yield src 698793Sgblack@eecs.umich.edu 704776Sgblack@eecs.umich.educlass SourceFile(object): 718887Sgeoffrey.blake@arm.com __metaclass__ = SourceMeta 7210201SAndrew.Bardsley@arm.com def __init__(self, source): 738887Sgeoffrey.blake@arm.com tnode = source 749340SAndreas.Sandberg@arm.com if not isinstance(source, SCons.Node.FS.File): 758887Sgeoffrey.blake@arm.com tnode = File(source) 765192Ssaidi@eecs.umich.edu 778335Snate@binkert.org self.tnode = tnode 788335Snate@binkert.org self.snode = tnode.srcnode() 798335Snate@binkert.org self.filename = str(tnode) 808335Snate@binkert.org self.dirname = dirname(self.filename) 818335Snate@binkert.org self.basename = basename(self.filename) 829534SAndreas.Sandberg@ARM.com index = self.basename.rfind('.') 839534SAndreas.Sandberg@ARM.com if index <= 0: 849534SAndreas.Sandberg@ARM.com # dot files aren't extensions 858335Snate@binkert.org self.extname = self.basename, None 869534SAndreas.Sandberg@ARM.com else: 879534SAndreas.Sandberg@ARM.com self.extname = self.basename[:index], self.basename[index+1:] 888335Snate@binkert.org 899534SAndreas.Sandberg@ARM.com for base in type(self).__mro__: 909534SAndreas.Sandberg@ARM.com if issubclass(base, SourceFile): 919534SAndreas.Sandberg@ARM.com bisect.insort_right(base.all, self) 929534SAndreas.Sandberg@ARM.com 939534SAndreas.Sandberg@ARM.com def __lt__(self, other): return self.filename < other.filename 949534SAndreas.Sandberg@ARM.com def __le__(self, other): return self.filename <= other.filename 959534SAndreas.Sandberg@ARM.com def __gt__(self, other): return self.filename > other.filename 969534SAndreas.Sandberg@ARM.com def __ge__(self, other): return self.filename >= other.filename 979534SAndreas.Sandberg@ARM.com def __eq__(self, other): return self.filename == other.filename 989534SAndreas.Sandberg@ARM.com def __ne__(self, other): return self.filename != other.filename 9910383Smitch.hayenga@arm.com 1008335Snate@binkert.orgclass Source(SourceFile): 1018335Snate@binkert.org '''Add a c/c++ source file to the build''' 1028471SGiacomo.Gabrielli@arm.com def __init__(self, source, Werror=True, swig=False, bin_only=False, 1038335Snate@binkert.org skip_lib=False): 1048335Snate@binkert.org super(Source, self).__init__(source) 1055192Ssaidi@eecs.umich.edu 1068232Snate@binkert.org self.Werror = Werror 1078232Snate@binkert.org self.swig = swig 1088232Snate@binkert.org self.bin_only = bin_only 1098300Schander.sudanthi@arm.com self.skip_lib = bin_only or skip_lib 11010383Smitch.hayenga@arm.com 1115192Ssaidi@eecs.umich.educlass PySource(SourceFile): 1128300Schander.sudanthi@arm.com '''Add a python source file to the named package''' 1138300Schander.sudanthi@arm.com invalid_sym_char = re.compile('[^A-z0-9_]') 1146036Sksewell@umich.edu modules = {} 1158300Schander.sudanthi@arm.com tnodes = {} 1168300Schander.sudanthi@arm.com 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