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