- Add capability to auto-generate Param structs from
authorSteve Reinhardt <stever@eecs.umich.edu>
Mon, 14 Mar 2005 12:46:26 +0000 (07:46 -0500)
committerSteve Reinhardt <stever@eecs.umich.edu>
Mon, 14 Mar 2005 12:46:26 +0000 (07:46 -0500)
.mpy SimObject descriptions.  Structs are defined
in simobj/param/ObjectName.hh.
- Move compile-time python params (from CPPDEFINES) to
separate dict from run-time params (from os.environ).
The former are needed to generate proper param structs.
This also helps prevent users from messing things up
by setting the wrong environment vars (which could have
overridden compile-time settings in the old system).
- Other misc cleanup of m5 python package.

SConscript:
    Include simobj/SConscript
build/SConstruct:
    Fix type in comment
python/SConscript:
    Move CPPDEFINES dict-generating code to m5scons.flatten_defines
python/m5/__init__.py:
    - Generate a build_env SmartDict here to hold compile-time
    params (passed in via __main__.m5_build_env).
    - Move panic and env here from config.py.
python/m5/config.py:
    Move panic, env to top level (m5/__init__.py)
python/m5/objects/BaseCPU.mpy:
    Use build_env instead of env for compile-time params
python/m5/smartdict.py:
    Add some comments.
sim/sim_object.hh:
    Include auto-generated Param struct.  Not used yet,
    just here as proof of concept.
test/genini.py:
    Put -E arguments in build_env as well as os.environ

--HG--
extra : convert_revision : cf6f4a2565b230c495b33b18612d6030988adac5

SConscript
build/SConstruct
python/SConscript
python/m5/__init__.py
python/m5/config.py
python/m5/objects/BaseCPU.mpy
python/m5/smartdict.py
sim/sim_object.hh
test/genini.py

index cff240a69f9b4828e50f293c0f591a6af3ab6c23..3b3c871bc29362a230774c21426d7a053a0aec23 100644 (file)
@@ -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
index 3d7db1db2a73f24a582c92b251fc9718dd9282da..0f688ac3b14da80c4389f876355d41758db54602 100644 (file)
@@ -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.
 #
 ###################################################
 
index 81bc52286be11f5493606a328345c5eb401148bf..a50903964c0234e9ea399cb053f2d1a4914a9cd0 100644 (file)
 # (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):
index 3d54a83da66e90e20ea62a0a51d782ff8a3ef10a..16f48dba3c628dfb7a793368d23fc2e8f1656a0f 100644 (file)
@@ -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
 
+# 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.__dict__)
+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()
index 7dfc4fb0417972ad9d9fb34b0df3e749489be45f..a9d7a2f41cf696c48b47424a9672988c3f7bb870 100644 (file)
@@ -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',
index be93e8ad1c6c6aa63d7f876ce09dd81e3dc5cc9d..5d8305d888a4480df476b80f0b5c05be0df34007 100644 (file)
@@ -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")
index e282bc07b722d4bf2e8486cc7e7dc6711f8ec311..4ea8210d361cf2bc760d13f871c2ee8b2cc26a8c 100644 (file)
@@ -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)))
 
index f4b316ebb7b284c12f389f74bc990f62494b5233..b8a3090ad95c29672980d1aad21a9fb2d6e9bf09 100644 (file)
@@ -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() {}
index 025ba998a3d8da758bdfebe526366cb70331d0bd..b8eda5d46fda5d6efcec2adb1bccda61689943b9 100755 (executable)
@@ -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: