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