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