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