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