Deleted Added
sdiff udiff text old ( 8126:5138d1e453f1 ) new ( 8232:b28d06a175be )
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 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
202#
203trace_flags = {}
204def TraceFlag(name, desc=None):
205 if name in trace_flags:
206 raise AttributeError, "Flag %s already specified" % name
207 trace_flags[name] = (name, (), desc)
208
209def CompoundFlag(name, flags, desc=None):
210 if name in trace_flags:
211 raise AttributeError, "Flag %s already specified" % name
212
213 compound = tuple(flags)
214 trace_flags[name] = (name, compound, desc)
215
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
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"
641
642 flagsList.sort()
643 return flagsList
644
645
646# Generate traceflags.py
647def traceFlagsPy(target, source, env):
648 assert(len(target) == 1)
649 code = code_formatter()
650
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
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
733''')
734
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('};')
745 code()
746
747 for flag, compound, desc in allFlags:
748 if not compound:
749 continue
750 code('static const Flags ${flag}Map[] = {')
751 code.indent()
752 for flag in compound:
753 code('$flag,')
754 code('(Flags)-1')
755 code.dedent()
756 code('};')
757 code()
758
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('};')
770
771 code.write(str(target[0]))
772
773def traceFlagsHH(target, source, env):
774 assert(len(target) == 1)
775
776 allFlags = getFlags(source)
777 code = code_formatter()
778
779 # file header boilerplate
780 code('''\
781/*
782 * DO NOT EDIT THIS FILE!
783 *
784 * Automatically generated from traceflags.py
785 */
786
787#ifndef __BASE_TRACE_FLAGS_HH__
788#define __BASE_TRACE_FLAGS_HH__
789
790namespace Trace {
791
792enum Flags {''')
793
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
801
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('''
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.''')
812
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__
840''')
841
842 code.write(str(target[0]))
843
844flags = map(Value, trace_flags.values())
845env.Command('base/traceflags.py', flags,
846 MakeAction(traceFlagsPy, Transform("TRACING", 0)))
847PySource('m5', 'base/traceflags.py')
848
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')
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')