+# Commands for the basic automatically generated python files
+#
+
+# Generate Python file containing a dict specifying the current
+# buildEnv flags.
+def makeDefinesPyFile(target, source, env):
+ build_env = source[0].get_contents()
+
+ code = code_formatter()
+ code("""
+import m5.internal
+import m5.util
+
+buildEnv = m5.util.SmartDict($build_env)
+
+compileDate = m5.internal.core.compileDate
+_globals = globals()
+for key,val in m5.internal.core.__dict__.iteritems():
+ if key.startswith('flag_'):
+ flag = key[5:]
+ _globals[flag] = val
+del _globals
+""")
+ code.write(target[0].abspath)
+
+defines_info = Value(build_env)
+# Generate a file with all of the compile options in it
+env.Command('python/m5/defines.py', defines_info,
+ MakeAction(makeDefinesPyFile, Transform("DEFINES", 0)))
+PySource('m5', 'python/m5/defines.py')
+
+# Generate python file containing info about the M5 source code
+def makeInfoPyFile(target, source, env):
+ code = code_formatter()
+ for src in source:
+ data = ''.join(file(src.srcnode().abspath, 'r').xreadlines())
+ code('$src = ${{repr(data)}}')
+ code.write(str(target[0]))
+
+# Generate a file that wraps the basic top level files
+env.Command('python/m5/info.py',
+ [ '#/COPYING', '#/LICENSE', '#/README', ],
+ MakeAction(makeInfoPyFile, Transform("INFO")))
+PySource('m5', 'python/m5/info.py')
+
+########################################################################
+#
+# Create all of the SimObject param headers and enum headers
+#
+
+def createSimObjectParamStruct(target, source, env):
+ assert len(target) == 1 and len(source) == 1
+
+ name = str(source[0].get_contents())
+ obj = sim_objects[name]
+
+ code = code_formatter()
+ obj.cxx_param_decl(code)
+ code.write(target[0].abspath)
+
+def createParamSwigWrapper(target, source, env):
+ assert len(target) == 1 and len(source) == 1
+
+ name = str(source[0].get_contents())
+ param = params_to_swig[name]
+
+ code = code_formatter()
+ param.swig_decl(code)
+ code.write(target[0].abspath)
+
+def createEnumStrings(target, source, env):
+ assert len(target) == 1 and len(source) == 1
+
+ name = str(source[0].get_contents())
+ obj = all_enums[name]
+
+ code = code_formatter()
+ obj.cxx_def(code)
+ code.write(target[0].abspath)
+
+def createEnumDecls(target, source, env):
+ assert len(target) == 1 and len(source) == 1
+
+ name = str(source[0].get_contents())
+ obj = all_enums[name]
+
+ code = code_formatter()
+ obj.cxx_decl(code)
+ code.write(target[0].abspath)
+
+def createEnumSwigWrapper(target, source, env):
+ assert len(target) == 1 and len(source) == 1
+
+ name = str(source[0].get_contents())
+ obj = all_enums[name]
+
+ code = code_formatter()
+ obj.swig_decl(code)
+ code.write(target[0].abspath)
+
+def createSimObjectSwigWrapper(target, source, env):
+ name = source[0].get_contents()
+ obj = sim_objects[name]
+
+ code = code_formatter()
+ obj.swig_decl(code)
+ code.write(target[0].abspath)
+
+# Generate all of the SimObject param C++ struct header files
+params_hh_files = []
+for name,simobj in sorted(sim_objects.iteritems()):
+ py_source = PySource.modules[simobj.__module__]
+ extra_deps = [ py_source.tnode ]
+
+ hh_file = File('params/%s.hh' % name)
+ params_hh_files.append(hh_file)
+ env.Command(hh_file, Value(name),
+ MakeAction(createSimObjectParamStruct, Transform("SO PARAM")))
+ env.Depends(hh_file, depends + extra_deps)
+
+# Generate any needed param SWIG wrapper files
+params_i_files = []
+for name,param in params_to_swig.iteritems():
+ i_file = File('python/m5/internal/%s.i' % (param.swig_module_name()))
+ params_i_files.append(i_file)
+ env.Command(i_file, Value(name),
+ MakeAction(createParamSwigWrapper, Transform("SW PARAM")))
+ env.Depends(i_file, depends)
+ SwigSource('m5.internal', i_file)
+
+# Generate all enum header files
+for name,enum in sorted(all_enums.iteritems()):
+ py_source = PySource.modules[enum.__module__]
+ extra_deps = [ py_source.tnode ]
+
+ cc_file = File('enums/%s.cc' % name)
+ env.Command(cc_file, Value(name),
+ MakeAction(createEnumStrings, Transform("ENUM STR")))
+ env.Depends(cc_file, depends + extra_deps)
+ Source(cc_file)
+
+ hh_file = File('enums/%s.hh' % name)
+ env.Command(hh_file, Value(name),
+ MakeAction(createEnumDecls, Transform("ENUMDECL")))
+ env.Depends(hh_file, depends + extra_deps)
+
+ i_file = File('python/m5/internal/enum_%s.i' % name)
+ env.Command(i_file, Value(name),
+ MakeAction(createEnumSwigWrapper, Transform("ENUMSWIG")))
+ env.Depends(i_file, depends + extra_deps)
+ SwigSource('m5.internal', i_file)
+
+# Generate SimObject SWIG wrapper files
+for name,simobj in sim_objects.iteritems():
+ py_source = PySource.modules[simobj.__module__]
+ extra_deps = [ py_source.tnode ]
+
+ i_file = File('python/m5/internal/param_%s.i' % name)
+ env.Command(i_file, Value(name),
+ MakeAction(createSimObjectSwigWrapper, Transform("SO SWIG")))
+ env.Depends(i_file, depends + extra_deps)
+ SwigSource('m5.internal', i_file)
+
+# Generate the main swig init file
+def makeEmbeddedSwigInit(target, source, env):
+ code = code_formatter()
+ module = source[0].get_contents()
+ code('''\
+#include "sim/init.hh"
+
+extern "C" {
+ void init_${module}();
+}
+
+EmbeddedSwig embed_swig_${module}(init_${module});
+''')
+ code.write(str(target[0]))
+
+# Build all swig modules
+for swig in SwigSource.all:
+ env.Command([swig.cc_source.tnode, swig.py_source.tnode], swig.tnode,
+ MakeAction('$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} '
+ '-o ${TARGETS[0]} $SOURCES', Transform("SWIG")))
+ cc_file = str(swig.tnode)
+ init_file = '%s/%s_init.cc' % (dirname(cc_file), basename(cc_file))
+ env.Command(init_file, Value(swig.module),
+ MakeAction(makeEmbeddedSwigInit, Transform("EMBED SW")))
+ Source(init_file, **swig.guards)
+
+# Build all protocol buffers if we have got protoc and protobuf available
+if env['HAVE_PROTOBUF']:
+ for proto in ProtoBuf.all:
+ # Use both the source and header as the target, and the .proto
+ # file as the source. When executing the protoc compiler, also
+ # specify the proto_path to avoid having the generated files
+ # include the path.
+ env.Command([proto.cc_file, proto.hh_file], proto.tnode,
+ MakeAction('$PROTOC --cpp_out ${TARGET.dir} '
+ '--proto_path ${SOURCE.dir} $SOURCE',
+ Transform("PROTOC")))
+
+ # Add the C++ source file
+ Source(proto.cc_file, **proto.guards)
+elif ProtoBuf.all:
+ print 'Got protobuf to build, but lacks support!'
+ Exit(1)
+
+#
+# Handle debug flags
+#
+def makeDebugFlagCC(target, source, env):
+ assert(len(target) == 1 and len(source) == 1)
+
+ val = eval(source[0].get_contents())
+ name, compound, desc = val
+ compound = list(sorted(compound))
+
+ code = code_formatter()
+
+ # file header
+ code('''
+/*
+ * DO NOT EDIT THIS FILE! Automatically generated
+ */
+
+#include "base/debug.hh"
+''')
+
+ for flag in compound:
+ code('#include "debug/$flag.hh"')
+ code()
+ code('namespace Debug {')
+ code()
+
+ if not compound:
+ code('SimpleFlag $name("$name", "$desc");')
+ else:
+ code('CompoundFlag $name("$name", "$desc",')
+ code.indent()
+ last = len(compound) - 1
+ for i,flag in enumerate(compound):
+ if i != last:
+ code('$flag,')
+ else:
+ code('$flag);')
+ code.dedent()
+
+ code()
+ code('} // namespace Debug')
+
+ code.write(str(target[0]))
+
+def makeDebugFlagHH(target, source, env):
+ assert(len(target) == 1 and len(source) == 1)
+
+ val = eval(source[0].get_contents())
+ name, compound, desc = val
+
+ code = code_formatter()
+
+ # file header boilerplate
+ code('''\
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated by SCons
+ */
+
+#ifndef __DEBUG_${name}_HH__
+#define __DEBUG_${name}_HH__
+
+namespace Debug {
+''')
+
+ if compound:
+ code('class CompoundFlag;')
+ code('class SimpleFlag;')
+
+ if compound:
+ code('extern CompoundFlag $name;')
+ for flag in compound:
+ code('extern SimpleFlag $flag;')
+ else:
+ code('extern SimpleFlag $name;')
+
+ code('''
+}
+
+#endif // __DEBUG_${name}_HH__
+''')
+
+ code.write(str(target[0]))
+
+for name,flag in sorted(debug_flags.iteritems()):
+ n, compound, desc = flag
+ assert n == name
+
+ env.Command('debug/%s.hh' % name, Value(flag),
+ MakeAction(makeDebugFlagHH, Transform("TRACING", 0)))
+ env.Command('debug/%s.cc' % name, Value(flag),
+ MakeAction(makeDebugFlagCC, Transform("TRACING", 0)))
+ Source('debug/%s.cc' % name)
+
+# Embed python files. All .py files that have been indicated by a
+# PySource() call in a SConscript need to be embedded into the M5
+# library. To do that, we compile the file to byte code, marshal the
+# byte code, compress it, and then generate a c++ file that
+# inserts the result into an array.
+def embedPyFile(target, source, env):
+ def c_str(string):
+ if string is None:
+ return "0"
+ return '"%s"' % string
+
+ '''Action function to compile a .py into a code object, marshal
+ it, compress it, and stick it into an asm file so the code appears
+ as just bytes with a label in the data section'''
+
+ src = file(str(source[0]), 'r').read()
+
+ pysource = PySource.tnodes[source[0]]
+ compiled = compile(src, pysource.abspath, 'exec')
+ marshalled = marshal.dumps(compiled)
+ compressed = zlib.compress(marshalled)
+ data = compressed
+ sym = pysource.symname
+
+ code = code_formatter()
+ code('''\
+#include "sim/init.hh"
+
+namespace {
+
+const uint8_t data_${sym}[] = {
+''')
+ code.indent()
+ step = 16
+ for i in xrange(0, len(data), step):
+ x = array.array('B', data[i:i+step])
+ code(''.join('%d,' % d for d in x))
+ code.dedent()
+
+ code('''};
+
+EmbeddedPython embedded_${sym}(
+ ${{c_str(pysource.arcname)}},
+ ${{c_str(pysource.abspath)}},
+ ${{c_str(pysource.modpath)}},
+ data_${sym},
+ ${{len(data)}},
+ ${{len(marshalled)}});
+
+} // anonymous namespace
+''')
+ code.write(str(target[0]))
+
+for source in PySource.all:
+ env.Command(source.cpp, source.tnode,
+ MakeAction(embedPyFile, Transform("EMBED PY")))
+ Source(source.cpp)
+
+########################################################################