diff --git a/SConscript b/SConscript index cff240a69..3b3c871bc 100644 --- a/SConscript +++ b/SConscript @@ -378,7 +378,7 @@ env.Command(Split('''arch/alpha/decoder.cc # header files into a place where they can be found. SConscript('libelf/SConscript-local', exports = 'env', duplicate=0) SConscript('python/SConscript', exports = ['env'], duplicate=0) - +SConscript('simobj/SConscript', exports = 'env', duplicate=0) # This function adds the specified sources to the given build # environment, and returns a list of all the corresponding SCons diff --git a/build/SConstruct b/build/SConstruct index 3d7db1db2..0f688ac3b 100644 --- a/build/SConstruct +++ b/build/SConstruct @@ -289,7 +289,7 @@ for build_dir in build_dirs: ################################################### # # Let SCons do its thing. At this point SCons will use the defined -# build enviornments to build the requested targets. +# build environments to build the requested targets. # ################################################### diff --git a/python/SConscript b/python/SConscript index 81bc52286..a50903964 100644 --- a/python/SConscript +++ b/python/SConscript @@ -26,7 +26,14 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os, os.path, re +import os, os.path, re, sys + +Import('env') + +# tell python where to find m5 python code +sys.path.append(os.path.join(env['SRCDIR'], 'python')) + +import m5scons def WriteEmbeddedPyFile(target, source, path, name, ext, filename): if isinstance(source, str): @@ -89,7 +96,6 @@ def splitpath(path): path.insert(0, base) return path, file -Import('env') def MakeEmbeddedPyFile(target, source, env): target = file(str(target[0]), 'w') @@ -145,27 +151,11 @@ def MakeEmbeddedPyFile(target, source, env): WriteEmbeddedPyFile(target, pyfile, path, name, ext, filename) def MakeDefinesPyFile(target, source, env): - target = file(str(target[0]), 'w') - - print >>target, "import os" - defines = env['CPPDEFINES'] - if isinstance(defines, list): - for var in defines: - if isinstance(var, tuple): - key,val = var - else: - key,val = var,'True' - - if not isinstance(key, basestring): - panic("invalid type for define: %s" % type(key)) - - print >>target, "os.environ['%s'] = '%s'" % (key, val) - - elif isinstance(defines, dict): - for key,val in defines.iteritems(): - print >>target, "os.environ['%s'] = '%s'" % (key, val) - else: - panic("invalid type for defines: %s" % type(defines)) + f = file(str(target[0]), 'w') + print >>f, "import __main__" + print >>f, "__main__.m5_build_env = ", + print >>f, m5scons.flatten_defines(env['CPPDEFINES']) + f.close() CFileCounter = 0 def MakePythonCFile(target, source, env): diff --git a/python/m5/__init__.py b/python/m5/__init__.py index 3d54a83da..16f48dba3 100644 --- a/python/m5/__init__.py +++ b/python/m5/__init__.py @@ -1,10 +1,36 @@ +import sys, os + +# the mpy import code is added to the global import meta_path as a +# side effect of this import from mpy_importer import AddToPath, LoadMpyFile -from config import * -config.add_param_types(config.__dict__) +# define this here so we can use it right away if necessary +def panic(string): + print >>sys.stderr, 'panic:', string + sys.exit(1) +# find the m5 compile options: must be specified as a dict in +# __main__.m5_build_env. +import __main__ +if not hasattr(__main__, 'm5_build_env'): + panic("__main__ must define m5_build_env") + +# make a SmartDict out of the build options for our local use +import smartdict +build_env = smartdict.SmartDict() +build_env.update(__main__.m5_build_env) + +# make a SmartDict out of the OS environment too +env = smartdict.SmartDict() +env.update(os.environ) + +# import the main m5 config code +from config import * +config.add_param_types(config) + +# import the built-in object definitions from objects import * -config.add_param_types(objects.__dict__) +config.add_param_types(objects) cpp_classes = config.MetaSimObject.cpp_classes cpp_classes.sort() diff --git a/python/m5/config.py b/python/m5/config.py index 7dfc4fb04..a9d7a2f41 100644 --- a/python/m5/config.py +++ b/python/m5/config.py @@ -27,7 +27,6 @@ from __future__ import generators import os, re, sys, types, inspect -from smartdict import SmartDict from convert import * noDot = False @@ -36,13 +35,6 @@ try: except: noDot = True -env = SmartDict() -env.update(os.environ) - -def panic(string): - print >>sys.stderr, 'panic:', string - sys.exit(1) - def issequence(value): return isinstance(value, tuple) or isinstance(value, list) @@ -1347,7 +1339,7 @@ class SimObject(ConfigNode, ParamType): # __all__ defines the list of symbols that get exported when # 'from config import *' is invoked. Try to keep this reasonably # short to avoid polluting other namespaces. -__all__ = ['env', 'issequence', 'panic', +__all__ = ['issequence', 'ConfigNode', 'SimObject', 'ParamContext', 'Param', 'VectorParam', 'Super', 'Enum', 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', diff --git a/python/m5/objects/BaseCPU.mpy b/python/m5/objects/BaseCPU.mpy index be93e8ad1..5d8305d88 100644 --- a/python/m5/objects/BaseCPU.mpy +++ b/python/m5/objects/BaseCPU.mpy @@ -4,7 +4,7 @@ simobj BaseCPU(SimObject): icache = Param.BaseMem(NULL, "L1 instruction cache object") dcache = Param.BaseMem(NULL, "L1 data cache object") - if env.get('FULL_SYSTEM', 'False'): + if build_env['FULL_SYSTEM']: dtb = Param.AlphaDTB("Data TLB") itb = Param.AlphaITB("Instruction TLB") mem = Param.FunctionalMemory("memory") diff --git a/python/m5/smartdict.py b/python/m5/smartdict.py index e282bc07b..4ea8210d3 100644 --- a/python/m5/smartdict.py +++ b/python/m5/smartdict.py @@ -1,6 +1,23 @@ +# The SmartDict class fixes a couple of issues with using the content +# of os.environ or similar dicts of strings as Python variables: +# +# 1) Undefined variables should return False rather than raising KeyError. +# +# 2) String values of 'False', '0', etc., should evaluate to False +# (not just the empty string). +# +# #1 is solved by overriding __getitem__, and #2 is solved by using a +# proxy class for values and overriding __nonzero__ on the proxy. +# Everything else is just to (a) make proxies behave like normal +# values otherwise, (b) make sure any dict operation returns a proxy +# rather than a normal value, and (c) coerce values written to the +# dict to be strings. + + from convert import * class SmartDict(dict): + class Proxy(str): def __int__(self): return int(to_integer(str(self))) @@ -58,7 +75,7 @@ class SmartDict(dict): def __getitem__(self, key): - return self.Proxy(dict.__getitem__(self, key)) + return self.Proxy(dict.get(self, key, 'False')) def __setitem__(self, key, item): dict.__setitem__(self, key, str(item)) @@ -77,9 +94,9 @@ class SmartDict(dict): for key,value in dict.iteritems(self): yield key, self.Proxy(value) - def get(self, key, default=''): + def get(self, key, default='False'): return self.Proxy(dict.get(self, key, str(default))) - def setdefault(self, key, default=''): + def setdefault(self, key, default='False'): return self.Proxy(dict.setdefault(self, key, str(default))) diff --git a/sim/sim_object.hh b/sim/sim_object.hh index f4b316ebb..b8a3090ad 100644 --- a/sim/sim_object.hh +++ b/sim/sim_object.hh @@ -60,6 +60,10 @@ class SimObject : public Serializable, protected StartupCallback static SimObjectList simObjectList; public: + +// for Params struct +#include "simobj/param/SimObject.hh" + SimObject(const std::string &_name); virtual ~SimObject() {} diff --git a/test/genini.py b/test/genini.py index 025ba998a..b8eda5d46 100755 --- a/test/genini.py +++ b/test/genini.py @@ -35,6 +35,8 @@ sys.path.append(joinpath(mypath, '../util/pbs')) pathlist = [ '.' ] +m5_build_env = {} + try: opts, args = getopt.getopt(sys.argv[1:], '-E:I:') for opt,arg in opts: @@ -42,11 +44,12 @@ try: offset = arg.find('=') if offset == -1: name = arg - value = True + value = '1' else: name = arg[:offset] value = arg[offset+1:] os.environ[name] = value + m5_build_env[name] = value if opt == '-I': pathlist.append(arg) except getopt.GetoptError: