IGbE: Implement sending packet that is contained in more than 2 descriptors.
[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 imp
32 import os
33 import sys
34
35 from os.path import basename, exists, isdir, isfile, join as joinpath
36
37 import SCons
38
39 # This file defines how to build a particular configuration of M5
40 # based on variable settings in the 'env' build environment.
41
42 Import('*')
43
44 # Children need to see the environment
45 Export('env')
46
47 def sort_list(_list):
48 """return a sorted copy of '_list'"""
49 if isinstance(_list, list):
50 _list = _list[:]
51 else:
52 _list = list(_list)
53 _list.sort()
54 return _list
55
56 class PySourceFile(object):
57 def __init__(self, package, source):
58 filename = str(source)
59 pyname = basename(filename)
60 assert pyname.endswith('.py')
61 name = pyname[:-3]
62 path = package.split('.')
63 modpath = path
64 if name != '__init__':
65 modpath += [name]
66 modpath = '.'.join(modpath)
67
68 arcpath = package.split('.') + [ pyname + 'c' ]
69 arcname = joinpath(*arcpath)
70
71 self.source = source
72 self.pyname = pyname
73 self.srcpath = source.srcnode().abspath
74 self.package = package
75 self.modpath = modpath
76 self.arcname = arcname
77 self.filename = filename
78 self.compiled = File(filename + 'c')
79
80 ########################################################################
81 # Code for adding source files of various types
82 #
83 cc_sources = []
84 def Source(source):
85 '''Add a C/C++ source file to the build'''
86 if not isinstance(source, SCons.Node.FS.File):
87 source = File(source)
88
89 cc_sources.append(source)
90
91 py_sources = []
92 def PySource(package, source):
93 '''Add a python source file to the named package'''
94 if not isinstance(source, SCons.Node.FS.File):
95 source = File(source)
96
97 source = PySourceFile(package, source)
98 py_sources.append(source)
99
100 sim_objects_fixed = False
101 sim_object_modfiles = set()
102 def SimObject(source):
103 '''Add a SimObject python file as a python source object and add
104 it to a list of sim object modules'''
105
106 if sim_objects_fixed:
107 raise AttributeError, "Too late to call SimObject now."
108
109 if not isinstance(source, SCons.Node.FS.File):
110 source = File(source)
111
112 PySource('m5.objects', source)
113 modfile = basename(str(source))
114 assert modfile.endswith('.py')
115 modname = modfile[:-3]
116 sim_object_modfiles.add(modname)
117
118 swig_sources = []
119 def SwigSource(package, source):
120 '''Add a swig file to build'''
121 if not isinstance(source, SCons.Node.FS.File):
122 source = File(source)
123 val = source,package
124 swig_sources.append(val)
125
126 # Children should have access
127 Export('Source')
128 Export('PySource')
129 Export('SimObject')
130 Export('SwigSource')
131
132 ########################################################################
133 #
134 # Trace Flags
135 #
136 all_flags = {}
137 trace_flags = []
138 def TraceFlag(name, desc=''):
139 if name in all_flags:
140 raise AttributeError, "Flag %s already specified" % name
141 flag = (name, (), desc)
142 trace_flags.append(flag)
143 all_flags[name] = ()
144
145 def CompoundFlag(name, flags, desc=''):
146 if name in all_flags:
147 raise AttributeError, "Flag %s already specified" % name
148
149 compound = tuple(flags)
150 for flag in compound:
151 if flag not in all_flags:
152 raise AttributeError, "Trace flag %s not found" % flag
153 if all_flags[flag]:
154 raise AttributeError, \
155 "Compound flag can't point to another compound flag"
156
157 flag = (name, compound, desc)
158 trace_flags.append(flag)
159 all_flags[name] = compound
160
161 Export('TraceFlag')
162 Export('CompoundFlag')
163
164 ########################################################################
165 #
166 # Set some compiler variables
167 #
168
169 # Include file paths are rooted in this directory. SCons will
170 # automatically expand '.' to refer to both the source directory and
171 # the corresponding build directory to pick up generated include
172 # files.
173 env.Append(CPPPATH=Dir('.'))
174
175 # Add a flag defining what THE_ISA should be for all compilation
176 env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
177
178 ########################################################################
179 #
180 # Walk the tree and execute all SConscripts in subdirectories
181 #
182
183 for base_dir in base_dir_list:
184 here = Dir('.').srcnode().abspath
185 for root, dirs, files in os.walk(base_dir, topdown=True):
186 if root == here:
187 # we don't want to recurse back into this SConscript
188 continue
189
190 if 'SConscript' in files:
191 build_dir = joinpath(env['BUILDDIR'], root[len(base_dir) + 1:])
192 SConscript(joinpath(root, 'SConscript'), build_dir=build_dir)
193
194 for opt in env.ExportOptions:
195 env.ConfigFile(opt)
196
197 ########################################################################
198 #
199 # Prevent any SimObjects from being added after this point, they
200 # should all have been added in the SConscripts above
201 #
202 sim_objects_fixed = True
203
204 ########################################################################
205 #
206 # Manually turn python/generate.py into a python module and import it
207 #
208 generate_file = File('python/generate.py')
209 generate_module = imp.new_module('generate')
210 sys.modules['generate'] = generate_module
211 exec file(generate_file.srcnode().abspath, 'r') in generate_module.__dict__
212
213 ########################################################################
214 #
215 # build a generate
216 #
217 from generate import Generate
218 optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
219 generate = Generate(py_sources, sim_object_modfiles, optionDict)
220 m5 = generate.m5
221
222 ########################################################################
223 #
224 # calculate extra dependencies
225 #
226 module_depends = ["m5", "m5.SimObject", "m5.params"]
227 module_depends = [ File(generate.py_modules[dep]) for dep in module_depends ]
228 file_depends = [ generate_file ]
229 depends = module_depends + file_depends
230
231 ########################################################################
232 #
233 # Commands for the basic automatically generated python files
234 #
235
236 # Generate a file with all of the compile options in it
237 env.Command('python/m5/defines.py', Value(optionDict),
238 generate.makeDefinesPyFile)
239 PySource('m5', 'python/m5/defines.py')
240
241 # Generate a file that wraps the basic top level files
242 env.Command('python/m5/info.py',
243 [ '#/AUTHORS', '#/LICENSE', '#/README', '#/RELEASE_NOTES' ],
244 generate.makeInfoPyFile)
245 PySource('m5', 'python/m5/info.py')
246
247 # Generate an __init__.py file for the objects package
248 env.Command('python/m5/objects/__init__.py',
249 [ Value(o) for o in sort_list(sim_object_modfiles) ],
250 generate.makeObjectsInitFile)
251 PySource('m5.objects', 'python/m5/objects/__init__.py')
252
253 ########################################################################
254 #
255 # Create all of the SimObject param headers and enum headers
256 #
257
258 # Generate all of the SimObject param struct header files
259 params_hh_files = []
260 for name,simobj in generate.sim_objects.iteritems():
261 extra_deps = [ File(generate.py_modules[simobj.__module__]) ]
262
263 hh_file = File('params/%s.hh' % name)
264 params_hh_files.append(hh_file)
265 env.Command(hh_file, Value(name), generate.createSimObjectParam)
266 env.Depends(hh_file, depends + extra_deps)
267
268 # Generate any parameter header files needed
269 for name,param in generate.params.iteritems():
270 if isinstance(param, m5.params.VectorParamDesc):
271 ext = 'vptype'
272 else:
273 ext = 'ptype'
274
275 i_file = File('params/%s_%s.i' % (name, ext))
276 env.Command(i_file, Value(name), generate.createSwigParam)
277 env.Depends(i_file, depends)
278
279 # Generate all enum header files
280 for name,enum in generate.enums.iteritems():
281 extra_deps = [ File(generate.py_modules[enum.__module__]) ]
282
283 cc_file = File('enums/%s.cc' % name)
284 env.Command(cc_file, Value(name), generate.createEnumStrings)
285 env.Depends(cc_file, depends + extra_deps)
286 Source(cc_file)
287
288 hh_file = File('enums/%s.hh' % name)
289 env.Command(hh_file, Value(name), generate.createEnumParam)
290 env.Depends(hh_file, depends + extra_deps)
291
292 # Build the big monolithic swigged params module (wraps all SimObject
293 # param structs and enum structs)
294 params_file = File('params/params.i')
295 names = sort_list(generate.sim_objects.keys())
296 env.Command(params_file, [ Value(v) for v in names ],
297 generate.buildParams)
298 env.Depends(params_file, params_hh_files + depends)
299 SwigSource('m5.objects', params_file)
300
301 # Build all swig modules
302 swig_modules = []
303 for source,package in swig_sources:
304 filename = str(source)
305 assert filename.endswith('.i')
306
307 base = '.'.join(filename.split('.')[:-1])
308 module = basename(base)
309 cc_file = base + '_wrap.cc'
310 py_file = base + '.py'
311
312 env.Command([cc_file, py_file], source,
313 '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
314 '-o ${TARGETS[0]} $SOURCES')
315 env.Depends(py_file, source)
316 env.Depends(cc_file, source)
317
318 swig_modules.append(Value(module))
319 Source(cc_file)
320 PySource(package, py_file)
321
322 # Generate the main swig init file
323 env.Command('swig/init.cc', swig_modules, generate.makeSwigInit)
324 Source('swig/init.cc')
325
326 # Generate traceflags.py
327 flags = [ Value(f) for f in trace_flags ]
328 env.Command('base/traceflags.py', flags, generate.traceFlagsPy)
329 PySource('m5', 'base/traceflags.py')
330
331 env.Command('base/traceflags.hh', flags, generate.traceFlagsHH)
332 env.Command('base/traceflags.cc', flags, generate.traceFlagsCC)
333 Source('base/traceflags.cc')
334
335 # Build the zip file
336 py_compiled = []
337 py_zip_depends = []
338 for source in py_sources:
339 env.Command(source.compiled, source.source, generate.compilePyFile)
340 py_compiled.append(source.compiled)
341
342 # make the zipfile depend on the archive name so that the archive
343 # is rebuilt if the name changes
344 py_zip_depends.append(Value(source.arcname))
345
346 # Add the zip file target to the environment.
347 m5zip = File('m5py.zip')
348 env.Command(m5zip, py_compiled, generate.buildPyZip)
349 env.Depends(m5zip, py_zip_depends)
350
351 ########################################################################
352 #
353 # Define binaries. Each different build type (debug, opt, etc.) gets
354 # a slightly different build environment.
355 #
356
357 # List of constructed environments to pass back to SConstruct
358 envList = []
359
360 # This function adds the specified sources to the given build
361 # environment, and returns a list of all the corresponding SCons
362 # Object nodes (including an extra one for date.cc). We explicitly
363 # add the Object nodes so we can set up special dependencies for
364 # date.cc.
365 def make_objs(sources, env):
366 objs = [env.Object(s) for s in sources]
367 # make date.cc depend on all other objects so it always gets
368 # recompiled whenever anything else does
369 date_obj = env.Object('base/date.cc')
370 env.Depends(date_obj, objs)
371 objs.append(date_obj)
372 return objs
373
374 # Function to create a new build environment as clone of current
375 # environment 'env' with modified object suffix and optional stripped
376 # binary. Additional keyword arguments are appended to corresponding
377 # build environment vars.
378 def makeEnv(label, objsfx, strip = False, **kwargs):
379 newEnv = env.Copy(OBJSUFFIX=objsfx)
380 newEnv.Label = label
381 newEnv.Append(**kwargs)
382 exe = 'm5.' + label # final executable
383 bin = exe + '.bin' # executable w/o appended Python zip archive
384 newEnv.Program(bin, make_objs(cc_sources, newEnv))
385 if strip:
386 stripped_bin = bin + '.stripped'
387 if sys.platform == 'sunos5':
388 cmd = 'cp $SOURCE $TARGET; strip $TARGET'
389 else:
390 cmd = 'strip $SOURCE -o $TARGET'
391 newEnv.Command(stripped_bin, bin, cmd)
392 bin = stripped_bin
393 targets = newEnv.Concat(exe, [bin, 'm5py.zip'])
394 newEnv.M5Binary = targets[0]
395 envList.append(newEnv)
396
397 # Debug binary
398 ccflags = {}
399 if env['GCC']:
400 if sys.platform == 'sunos5':
401 ccflags['debug'] = '-gstabs+'
402 else:
403 ccflags['debug'] = '-ggdb3'
404 ccflags['opt'] = '-g -O3'
405 ccflags['fast'] = '-O3'
406 ccflags['prof'] = '-O3 -g -pg'
407 elif env['SUNCC']:
408 ccflags['debug'] = '-g0'
409 ccflags['opt'] = '-g -O'
410 ccflags['fast'] = '-fast'
411 ccflags['prof'] = '-fast -g -pg'
412 elif env['ICC']:
413 ccflags['debug'] = '-g -O0'
414 ccflags['opt'] = '-g -O'
415 ccflags['fast'] = '-fast'
416 ccflags['prof'] = '-fast -g -pg'
417 else:
418 print 'Unknown compiler, please fix compiler options'
419 Exit(1)
420
421 makeEnv('debug', '.do',
422 CCFLAGS = Split(ccflags['debug']),
423 CPPDEFINES = ['DEBUG', 'TRACING_ON=1'])
424
425 # Optimized binary
426 makeEnv('opt', '.o',
427 CCFLAGS = Split(ccflags['opt']),
428 CPPDEFINES = ['TRACING_ON=1'])
429
430 # "Fast" binary
431 makeEnv('fast', '.fo', strip = True,
432 CCFLAGS = Split(ccflags['fast']),
433 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'])
434
435 # Profiled binary
436 makeEnv('prof', '.po',
437 CCFLAGS = Split(ccflags['prof']),
438 CPPDEFINES = ['NDEBUG', 'TRACING_ON=0'],
439 LINKFLAGS = '-pg')
440
441 Return('envList')