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