Deleted Added
sdiff udiff text old ( 7722:c10bc8ad3f97 ) new ( 7756:846fb3ffe0dc )
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, " [ CFG ISA] $STRIP_TARGET"))
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, hg_info = [ x.get_contents() for x in source ]
414
415 code = code_formatter()
416 code("""
417import m5.internal
418import m5.util
419
420buildEnv = m5.util.SmartDict($build_env)
421hgRev = '$hg_info'
422
423compileDate = m5.internal.core.compileDate
424_globals = globals()
425for key,val in m5.internal.core.__dict__.iteritems():
426 if key.startswith('flag_'):
427 flag = key[5:]
428 _globals[flag] = val
429del _globals
430""")
431 code.write(target[0].abspath)
432
433defines_info = [ Value(build_env), Value(env['HG_INFO']) ]
434# Generate a file with all of the compile options in it
435env.Command('python/m5/defines.py', defines_info,
436 MakeAction(makeDefinesPyFile, " [ DEFINES] $STRIP_TARGET"))
437PySource('m5', 'python/m5/defines.py')
438
439# Generate python file containing info about the M5 source code
440def makeInfoPyFile(target, source, env):
441 code = code_formatter()
442 for src in source:
443 data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
444 code('$src = ${{repr(data)}}')
445 code.write(str(target[0]))
446
447# Generate a file that wraps the basic top level files
448env.Command('python/m5/info.py',
449 [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
450 MakeAction(makeInfoPyFile, " [ INFO] $STRIP_TARGET"))
451PySource('m5', 'python/m5/info.py')
452
453########################################################################
454#
455# Create all of the SimObject param headers and enum headers
456#
457
458def createSimObjectParam(target, source, env):
459 assert len(target) == 1 and len(source) == 1
460
461 name = str(source[0].get_contents())
462 obj = sim_objects[name]
463
464 code = code_formatter()
465 obj.cxx_decl(code)
466 code.write(target[0].abspath)
467
468def createSwigParam(target, source, env):
469 assert len(target) == 1 and len(source) == 1
470
471 name = str(source[0].get_contents())
472 param = all_params[name]
473
474 code = code_formatter()
475 code('%module(package="m5.internal") $0_${name}', param.file_ext)
476 param.swig_decl(code)
477 code.write(target[0].abspath)
478
479def createEnumStrings(target, source, env):
480 assert len(target) == 1 and len(source) == 1
481
482 name = str(source[0].get_contents())
483 obj = all_enums[name]
484
485 code = code_formatter()
486 obj.cxx_def(code)
487 code.write(target[0].abspath)
488
489def createEnumParam(target, source, env):
490 assert len(target) == 1 and len(source) == 1
491
492 name = str(source[0].get_contents())
493 obj = all_enums[name]
494
495 code = code_formatter()
496 obj.cxx_decl(code)
497 code.write(target[0].abspath)
498
499def createEnumSwig(target, source, env):
500 assert len(target) == 1 and len(source) == 1
501
502 name = str(source[0].get_contents())
503 obj = all_enums[name]
504
505 code = code_formatter()
506 code('''\
507%module(package="m5.internal") enum_$name
508
509%{
510#include "enums/$name.hh"
511%}
512
513%include "enums/$name.hh"
514''')
515 code.write(target[0].abspath)
516
517# Generate all of the SimObject param struct header files
518params_hh_files = []
519for name,simobj in sorted(sim_objects.iteritems()):
520 py_source = PySource.modules[simobj.__module__]
521 extra_deps = [ py_source.tnode ]
522
523 hh_file = File('params/%s.hh' % name)
524 params_hh_files.append(hh_file)
525 env.Command(hh_file, Value(name),
526 MakeAction(createSimObjectParam, " [SO PARAM] $STRIP_TARGET"))
527 env.Depends(hh_file, depends + extra_deps)
528
529# Generate any parameter header files needed
530params_i_files = []
531for name,param in all_params.iteritems():
532 i_file = File('python/m5/internal/%s_%s.i' % (param.file_ext, name))
533 params_i_files.append(i_file)
534 env.Command(i_file, Value(name),
535 MakeAction(createSwigParam, " [SW PARAM] $STRIP_TARGET"))
536 env.Depends(i_file, depends)
537 SwigSource('m5.internal', i_file)
538
539# Generate all enum header files
540for name,enum in sorted(all_enums.iteritems()):
541 py_source = PySource.modules[enum.__module__]
542 extra_deps = [ py_source.tnode ]
543
544 cc_file = File('enums/%s.cc' % name)
545 env.Command(cc_file, Value(name),
546 MakeAction(createEnumStrings, " [ENUM STR] $STRIP_TARGET"))
547 env.Depends(cc_file, depends + extra_deps)
548 Source(cc_file)
549
550 hh_file = File('enums/%s.hh' % name)
551 env.Command(hh_file, Value(name),
552 MakeAction(createEnumParam, " [EN PARAM] $STRIP_TARGET"))
553 env.Depends(hh_file, depends + extra_deps)
554
555 i_file = File('python/m5/internal/enum_%s.i' % name)
556 env.Command(i_file, Value(name),
557 MakeAction(createEnumSwig, " [ENUMSWIG] $STRIP_TARGET"))
558 env.Depends(i_file, depends + extra_deps)
559 SwigSource('m5.internal', i_file)
560
561def buildParam(target, source, env):
562 name = source[0].get_contents()
563 obj = sim_objects[name]
564 class_path = obj.cxx_class.split('::')
565 classname = class_path[-1]
566 namespaces = class_path[:-1]
567 params = obj._params.local.values()
568
569 code = code_formatter()
570
571 code('%module(package="m5.internal") param_$name')
572 code()
573 code('%{')
574 code('#include "params/$obj.hh"')
575 for param in params:
576 param.cxx_predecls(code)
577 code('%}')
578 code()
579
580 for param in params:
581 param.swig_predecls(code)
582
583 code()
584 if obj._base:
585 code('%import "python/m5/internal/param_${{obj._base}}.i"')
586 code()
587 obj.swig_objdecls(code)
588 code()
589
590 code('%include "params/$obj.hh"')
591
592 code.write(target[0].abspath)
593
594for name in sim_objects.iterkeys():
595 params_file = File('python/m5/internal/param_%s.i' % name)
596 env.Command(params_file, Value(name),
597 MakeAction(buildParam, " [BLDPARAM] $STRIP_TARGET"))
598 env.Depends(params_file, depends)
599 SwigSource('m5.internal', params_file)
600
601# Generate the main swig init file
602def makeEmbeddedSwigInit(target, source, env):
603 code = code_formatter()
604 module = source[0].get_contents()
605 code('''\
606#include "sim/init.hh"
607
608extern "C" {
609 void init_${module}();
610}
611
612EmbeddedSwig embed_swig_${module}(init_${module});
613''')
614 code.write(str(target[0]))
615
616# Build all swig modules
617for swig in SwigSource.all:
618 env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode,
619 MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
620 '-o ${TARGETS[0]} $SOURCES', " [ SWIG] $STRIP_TARGET"))
621 init_file = 'python/swig/init_%s.cc' % swig.module
622 env.Command(init_file, Value(swig.module),
623 MakeAction(makeEmbeddedSwigInit, " [EMBED SW] $STRIP_TARGET"))
624 Source(init_file)
625 env.Depends(swig.py_source.tnode, swig.tnode)
626 env.Depends(swig.cc_source.tnode, swig.tnode)
627
628def getFlags(source_flags):
629 flagsMap = {}
630 flagsList = []
631 for s in source_flags:
632 val = eval(s.get_contents())
633 name, compound, desc = val
634 flagsList.append(val)
635 flagsMap[name] = bool(compound)
636
637 for name, compound, desc in flagsList:
638 for flag in compound:
639 if flag not in flagsMap:
640 raise AttributeError, "Trace flag %s not found" % flag
641 if flagsMap[flag]:
642 raise AttributeError, \
643 "Compound flag can't point to another compound flag"
644
645 flagsList.sort()
646 return flagsList
647
648
649# Generate traceflags.py
650def traceFlagsPy(target, source, env):
651 assert(len(target) == 1)
652 code = code_formatter()
653
654 allFlags = getFlags(source)
655
656 code('basic = [')
657 code.indent()
658 for flag, compound, desc in allFlags:
659 if not compound:
660 code("'$flag',")
661 code(']')
662 code.dedent()
663 code()
664
665 code('compound = [')
666 code.indent()
667 code("'All',")
668 for flag, compound, desc in allFlags:
669 if compound:
670 code("'$flag',")
671 code("]")
672 code.dedent()
673 code()
674
675 code("all = frozenset(basic + compound)")
676 code()
677
678 code('compoundMap = {')
679 code.indent()
680 all = tuple([flag for flag,compound,desc in allFlags if not compound])
681 code("'All' : $all,")
682 for flag, compound, desc in allFlags:
683 if compound:
684 code("'$flag' : $compound,")
685 code('}')
686 code.dedent()
687 code()
688
689 code('descriptions = {')
690 code.indent()
691 code("'All' : 'All flags',")
692 for flag, compound, desc in allFlags:
693 code("'$flag' : '$desc',")
694 code("}")
695 code.dedent()
696
697 code.write(str(target[0]))
698
699def traceFlagsCC(target, source, env):
700 assert(len(target) == 1)
701
702 allFlags = getFlags(source)
703 code = code_formatter()
704
705 # file header
706 code('''
707/*
708 * DO NOT EDIT THIS FILE! Automatically generated
709 */
710
711#include "base/traceflags.hh"
712
713using namespace Trace;
714
715const char *Trace::flagStrings[] =
716{''')
717
718 code.indent()
719 # The string array is used by SimpleEnumParam to map the strings
720 # provided by the user to enum values.
721 for flag, compound, desc in allFlags:
722 if not compound:
723 code('"$flag",')
724
725 code('"All",')
726 for flag, compound, desc in allFlags:
727 if compound:
728 code('"$flag",')
729 code.dedent()
730
731 code('''\
732};
733
734const int Trace::numFlagStrings = ${{len(allFlags) + 1}};
735
736''')
737
738 # Now define the individual compound flag arrays. There is an array
739 # for each compound flag listing the component base flags.
740 all = tuple([flag for flag,compound,desc in allFlags if not compound])
741 code('static const Flags AllMap[] = {')
742 code.indent()
743 for flag, compound, desc in allFlags:
744 if not compound:
745 code('$flag,')
746 code.dedent()
747 code('};')
748 code()
749
750 for flag, compound, desc in allFlags:
751 if not compound:
752 continue
753 code('static const Flags ${flag}Map[] = {')
754 code.indent()
755 for flag in compound:
756 code('$flag,')
757 code('(Flags)-1')
758 code.dedent()
759 code('};')
760 code()
761
762 # Finally the compoundFlags[] array maps the compound flags
763 # to their individual arrays/
764 code('const Flags *Trace::compoundFlags[] = {')
765 code.indent()
766 code('AllMap,')
767 for flag, compound, desc in allFlags:
768 if compound:
769 code('${flag}Map,')
770 # file trailer
771 code.dedent()
772 code('};')
773
774 code.write(str(target[0]))
775
776def traceFlagsHH(target, source, env):
777 assert(len(target) == 1)
778
779 allFlags = getFlags(source)
780 code = code_formatter()
781
782 # file header boilerplate
783 code('''\
784/*
785 * DO NOT EDIT THIS FILE!
786 *
787 * Automatically generated from traceflags.py
788 */
789
790#ifndef __BASE_TRACE_FLAGS_HH__
791#define __BASE_TRACE_FLAGS_HH__
792
793namespace Trace {
794
795enum Flags {''')
796
797 # Generate the enum. Base flags come first, then compound flags.
798 idx = 0
799 code.indent()
800 for flag, compound, desc in allFlags:
801 if not compound:
802 code('$flag = $idx,')
803 idx += 1
804
805 numBaseFlags = idx
806 code('NumFlags = $idx,')
807 code.dedent()
808 code()
809
810 # put a comment in here to separate base from compound flags
811 code('''
812// The remaining enum values are *not* valid indices for Trace::flags.
813// They are "compound" flags, which correspond to sets of base
814// flags, and are used by changeFlag.''')
815
816 code.indent()
817 code('All = $idx,')
818 idx += 1
819 for flag, compound, desc in allFlags:
820 if compound:
821 code('$flag = $idx,')
822 idx += 1
823
824 numCompoundFlags = idx - numBaseFlags
825 code('NumCompoundFlags = $numCompoundFlags')
826 code.dedent()
827
828 # trailer boilerplate
829 code('''\
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 code.write(str(target[0]))
846
847flags = map(Value, trace_flags.values())
848env.Command('base/traceflags.py', flags,
849 MakeAction(traceFlagsPy, " [ TRACING] $STRIP_TARGET"))
850PySource('m5', 'base/traceflags.py')
851
852env.Command('base/traceflags.hh', flags,
853 MakeAction(traceFlagsHH, " [ TRACING] $STRIP_TARGET"))
854env.Command('base/traceflags.cc', flags,
855 MakeAction(traceFlagsCC, " [ TRACING] $STRIP_TARGET"))
856Source('base/traceflags.cc')
857
858# Embed python files. All .py files that have been indicated by a
859# PySource() call in a SConscript need to be embedded into the M5
860# library. To do that, we compile the file to byte code, marshal the
861# byte code, compress it, and then generate a c++ file that
862# inserts the result into an array.
863def embedPyFile(target, source, env):
864 def c_str(string):
865 if string is None:
866 return "0"
867 return '"%s"' % string
868
869 '''Action function to compile a .py into a code object, marshal
870 it, compress it, and stick it into an asm file so the code appears
871 as just bytes with a label in the data section'''
872
873 src = file(str(source[0]), 'r').read()
874
875 pysource = PySource.tnodes[source[0]]
876 compiled = compile(src, pysource.abspath, 'exec')
877 marshalled = marshal.dumps(compiled)
878 compressed = zlib.compress(marshalled)
879 data = compressed
880 sym = pysource.symname
881
882 code = code_formatter()
883 code('''\
884#include "sim/init.hh"
885
886namespace {
887
888const char data_${sym}[] = {
889''')
890 code.indent()
891 step = 16
892 for i in xrange(0, len(data), step):
893 x = array.array('B', data[i:i+step])
894 code(''.join('%d,' % d for d in x))
895 code.dedent()
896
897 code('''};
898
899EmbeddedPython embedded_${sym}(
900 ${{c_str(pysource.arcname)}},
901 ${{c_str(pysource.abspath)}},
902 ${{c_str(pysource.modpath)}},
903 data_${sym},
904 ${{len(data)}},
905 ${{len(marshalled)}});
906
907/* namespace */ }
908''')
909 code.write(str(target[0]))
910
911for source in PySource.all:
912 env.Command(source.cpp, source.tnode,
913 MakeAction(embedPyFile, " [EMBED PY] $STRIP_TARGET"))
914 Source(source.cpp)
915
916########################################################################
917#
918# Define binaries. Each different build type (debug, opt, etc.) gets
919# a slightly different build environment.
920#
921
922# List of constructed environments to pass back to SConstruct
923envList = []
924
925date_source = Source('base/date.cc', skip_lib=True)
926
927# Function to create a new build environment as clone of current
928# environment 'env' with modified object suffix and optional stripped
929# binary. Additional keyword arguments are appended to corresponding
930# build environment vars.
931def makeEnv(label, objsfx, strip = False, **kwargs):
932 # SCons doesn't know to append a library suffix when there is a '.' in the
933 # name. Use '_' instead.
934 libname = 'm5_' + label
935 exename = 'm5.' + label
936
937 new_env = env.Clone(OBJSUFFIX=objsfx, SHOBJSUFFIX=objsfx + 's')
938 new_env.Label = label
939 new_env.Append(**kwargs)
940
941 swig_env = new_env.Clone()
942 swig_env.Append(CCFLAGS='-Werror')
943 if env['GCC']:
944 swig_env.Append(CCFLAGS='-Wno-uninitialized')
945 swig_env.Append(CCFLAGS='-Wno-sign-compare')
946 swig_env.Append(CCFLAGS='-Wno-parentheses')
947
948 werror_env = new_env.Clone()
949 werror_env.Append(CCFLAGS='-Werror')
950
951 def make_obj(source, static, extra_deps = None):
952 '''This function adds the specified source to the correct
953 build environment, and returns the corresponding SCons Object
954 nodes'''
955
956 if source.swig:
957 env = swig_env
958 elif source.Werror:
959 env = werror_env
960 else:
961 env = new_env
962
963 if static:
964 obj = env.StaticObject(source.tnode)
965 else:
966 obj = env.SharedObject(source.tnode)
967
968 if extra_deps:
969 env.Depends(obj, extra_deps)
970
971 return obj
972
973 static_objs = [ make_obj(s, True) for s in Source.get(skip_lib=False)]
974 shared_objs = [ make_obj(s, False) for s in Source.get(skip_lib=False)]
975
976 static_date = make_obj(date_source, static=True, extra_deps=static_objs)
977 static_objs.append(static_date)
978
979 shared_date = make_obj(date_source, static=False, extra_deps=shared_objs)
980 shared_objs.append(shared_date)
981
982 # First make a library of everything but main() so other programs can
983 # link against m5.
984 static_lib = new_env.StaticLibrary(libname, static_objs)
985 shared_lib = new_env.SharedLibrary(libname, shared_objs)
986
987 for target, sources in unit_tests:
988 objs = [ make_obj(s, static=True) for s in sources ]
989 new_env.Program("unittest/%s.%s" % (target, label), objs + static_objs)
990
991 # Now link a stub with main() and the static library.
992 bin_objs = [make_obj(s, True) for s in Source.get(bin_only=True) ]
993 progname = exename
994 if strip:
995 progname += '.unstripped'
996
997 targets = new_env.Program(progname, bin_objs + static_objs)
998
999 if strip:
1000 if sys.platform == 'sunos5':
1001 cmd = 'cp $SOURCE $TARGET; strip $TARGET'
1002 else:
1003 cmd = 'strip $SOURCE -o $TARGET'
1004 targets = new_env.Command(exename, progname,
1005 MakeAction(cmd, " [ STRIP] $STRIP_TARGET"))
1006
1007 new_env.M5Binary = targets[0]
1008 envList.append(new_env)
1009
1010# Debug binary
1011ccflags = {}
1012if env['GCC']:
1013 if sys.platform == 'sunos5':
1014 ccflags['debug'] = '-gstabs+'
1015 else:
1016 ccflags['debug'] = '-ggdb3'
1017 ccflags['opt'] = '-g -O3'
1018 ccflags['fast'] = '-O3'
1019 ccflags['prof'] = '-O3 -g -pg'
1020elif env['SUNCC']:
1021 ccflags['debug'] = '-g0'
1022 ccflags['opt'] = '-g -O'
1023 ccflags['fast'] = '-fast'
1024 ccflags['prof'] = '-fast -g -pg'
1025elif env['ICC']:
1026 ccflags['debug'] = '-g -O0'
1027 ccflags['opt'] = '-g -O'
1028 ccflags['fast'] = '-fast'
1029 ccflags['prof'] = '-fast -g -pg'
1030else:
1031 print 'Unknown compiler, please fix compiler options'
1032 Exit(1)
1033
1034makeEnv('debug', '.do',
1035 CCFLAGS = Split(ccflags['debug']),
1036 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
1037
1038# Optimized binary
1039makeEnv('opt', '.o',
1040 CCFLAGS = Split(ccflags['opt']),
1041 CPPDEFINES = ['TRACING_ON=1'])
1042
1043# "Fast" binary
1044makeEnv('fast', '.fo', strip = True,
1045 CCFLAGS = Split(ccflags['fast']),
1046 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
1047
1048# Profiled binary
1049makeEnv('prof', '.po',
1050 CCFLAGS = Split(ccflags['prof']),
1051 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
1052 LINKFLAGS = '-pg')
1053
1054Return('envList')