From 0337db3388db335ea23f02f3aa00bca9d483ef1c Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 30 May 2006 13:11:34 -0400 Subject: Link in Python interpreter. Use embedded zip archive to carry Python code instead of homegrown embedded string/file mechanism. Do argument parsing in Python instead of C++. SConstruct: Add Python interpreter include path & library. Define two new simple builders which copy & concatenate files, respectively, for use by the Python embedded zipfile code. src/SConscript: Encapsulate environment creation in a function. Add code to append Python zip archive to final executable. Eliminate references to obsolete files. src/python/SConscript: Rewrite to generate embedded zip archive of Python code (replacing old "embedded string" mechanism). src/python/m5/__init__.py: Move main arg-parsing loop here (out of C++ main()). src/python/m5/config.py: Minor fix (version incompatibility?). src/sim/main.cc: Invoke embedded Python interpreter to parse args and generate config.ini, replacing C++ arg parsing code. --HG-- extra : convert_revision : 72d21236b2bee139ff39ba4cf031a4a1f8560029 --- src/python/SConscript | 226 +++++++++++++--------------------------------- src/python/m5/__init__.py | 108 +++++++++++++++++++++- src/python/m5/config.py | 2 +- 3 files changed, 169 insertions(+), 167 deletions(-) (limited to 'src/python') diff --git a/src/python/SConscript b/src/python/SConscript index 4407e403d..1f2d7fe0e 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -27,126 +27,55 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os, os.path, re, sys +from zipfile import PyZipFile -Import('env') +# handy function for path joins +def join(*args): + return os.path.normpath(os.path.join(*args)) -import scons_helper - -def WriteEmbeddedPyFile(target, source, path, name, ext, filename): - if isinstance(source, str): - source = file(source, 'r') - - if isinstance(target, str): - target = file(target, 'w') - - print >>target, "AddModule(%s, %s, %s, %s, '''\\" % \ - (`path`, `name`, `ext`, `filename`) - - for line in source: - line = line - # escape existing backslashes - line = line.replace('\\', '\\\\') - # escape existing triple quotes - line = line.replace("'''", r"\'\'\'") - - print >>target, line, - - print >>target, "''')" - print >>target - -def WriteCFile(target, source, name): - if isinstance(source, str): - source = file(source, 'r') - - if isinstance(target, str): - target = file(target, 'w') - - print >>target, 'const char %s_string[] = {' % name - - count = 0 - from array import array - try: - while True: - foo = array('B') - foo.fromfile(source, 10000) - l = [ str(i) for i in foo.tolist() ] - count += len(l) - for i in xrange(0,9999,20): - print >>target, ','.join(l[i:i+20]) + ',' - except EOFError: - l = [ str(i) for i in foo.tolist() ] - count += len(l) - for i in xrange(0,len(l),20): - print >>target, ','.join(l[i:i+20]) + ',' - print >>target, ','.join(l[i:]) + ',' - - print >>target, '};' - print >>target, 'const int %s_length = %d;' % (name, count) - print >>target - -def splitpath(path): - dir,file = os.path.split(path) - path = [] - assert(file) - while dir: - dir,base = os.path.split(dir) - path.insert(0, base) - return path, file - -def MakeEmbeddedPyFile(target, source, env): - target = file(str(target[0]), 'w') - - tree = {} - for src in source: - src = str(src) - path,pyfile = splitpath(src) - node = tree - for dir in path: - if not node.has_key(dir): - node[dir] = { } - node = node[dir] - - name,ext = pyfile.split('.') - if name == '__init__': - node['.hasinit'] = True - node[pyfile] = (src,name,ext,src) - - done = False - while not done: - done = True - for name,entry in tree.items(): - if not isinstance(entry, dict): continue - if entry.has_key('.hasinit'): continue - - done = False - del tree[name] - for key,val in entry.iteritems(): - if tree.has_key(key): - raise NameError, \ - "dir already has %s can't add it again" % key - tree[key] = val - - files = [] - def populate(node, path = []): - names = node.keys() - names.sort() - for name in names: - if name == '.hasinit': - continue - - entry = node[name] - if isinstance(entry, dict): - if not entry.has_key('.hasinit'): - raise NameError, 'package directory missing __init__.py' - populate(entry, path + [ name ]) - else: - pyfile,name,ext,filename = entry - files.append((pyfile, path, name, ext, filename)) - populate(tree) - - for pyfile, path, name, ext, filename in files: - WriteEmbeddedPyFile(target, pyfile, path, name, ext, filename) +Import('env') +# This SConscript is in charge of collecting .py files and generating a zip archive that is appended to the m5 binary. + +# Copy .py source files here (relative to src/python in the build +# directory). +pyzip_root = 'zip' + +# List of files & directories to include in the zip file. To include +# a package, list only the root directory of the package, not any +# internal .py files (else they will get the path stripped off when +# they are imported into the zip file). +pyzip_files = [] + +# List of additional files on which the zip archive depends, but which +# are not included in pyzip_files... i.e. individual .py files within +# a package. +pyzip_dep_files = [] + +# Add the specified package to the zip archive. Adds the directory to +# pyzip_files and all included .py files to pyzip_dep_files. +def addPkg(pkgdir): + pyzip_files.append(join(pyzip_root, pkgdir)) + origdir = os.getcwd() + srcdir = join(Dir('.').srcnode().abspath, pkgdir) + os.chdir(srcdir) + for path, dirs, files in os.walk('.'): + for i,dir in enumerate(dirs): + if dir == 'SCCS': + del dirs[i] + break + + for f in files: + if f.endswith('.py'): + source = join(pkgdir, path, f) + target = join(pyzip_root, source) + pyzip_dep_files.append(target) + env.CopyFile(target, source) + + os.chdir(origdir) + +# Generate Python file that contains a dict specifying the current +# build_env flags. def MakeDefinesPyFile(target, source, env): f = file(str(target[0]), 'w') print >>f, "import __main__" @@ -154,54 +83,21 @@ def MakeDefinesPyFile(target, source, env): print >>f, source[0] f.close() -CFileCounter = 0 -def MakePythonCFile(target, source, env): - global CFileCounter - target = file(str(target[0]), 'w') - - print >>target, '''\ -#include "base/embedfile.hh" - -namespace { -''' - for src in source: - src = str(src) - fname = os.path.basename(src) - name = 'embedded_file%d' % CFileCounter - CFileCounter += 1 - WriteCFile(target, src, name) - print >>target, '''\ -EmbedMap %(name)s("%(fname)s", - %(name)s_string, %(name)s_length); - -''' % locals() - print >>target, '''\ - -/* namespace */ } -''' - -# base list of .py files to embed -embedded_py_files = [ os.path.join(env['ROOT'], 'util/pbs/jobfile.py') ] -# add all .py files in python/m5 -objpath = os.path.join(env['SRCDIR'], 'python', 'm5') -for root, dirs, files in os.walk(objpath, topdown=True): - for i,dir in enumerate(dirs): - if dir == 'SCCS': - del dirs[i] - break - - assert(root.startswith(objpath)) - for f in files: - if f.endswith('.py'): - embedded_py_files.append(os.path.join(root, f)) - -embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh') - optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions]) env.Command('defines.py', Value(optionDict), MakeDefinesPyFile) -env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile) -env.Depends('embedded_py.cc', embedfile_hh) -env.Command('embedded_py.cc', - ['string_importer.py', 'defines.py', 'embedded_py.py'], - MakePythonCFile) +# Now specify the packages & files for the zip archive. +addPkg('m5') +pyzip_files.append('defines.py') +pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py')) + +# Action function to build the zip archive. Uses the PyZipFile module +# included in the standard Python library. +def buildPyZip(target, source, env): + pzf = PyZipFile(str(target[0]), 'w') + for s in source: + pzf.writepy(str(s)) + +# Add the zip file target to the environment. +env.Command('m5py.zip', pyzip_files, buildPyZip) +env.Depends('m5py.zip', pyzip_dep_files) diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 9bb68a090..06875d1f0 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -24,7 +24,53 @@ # (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 sys, os +import sys, os, time + +import __main__ + +briefCopyright = ''' +Copyright (c) 2001-2006 +The Regents of The University of Michigan +All Rights Reserved +''' + +fullCopyright = ''' +Copyright (c) 2001-2006 +The Regents of The University of Michigan +All Rights Reserved + +Permission is granted to use, copy, create derivative works and +redistribute this software and such derivative works for any purpose, +so long as the copyright notice above, this grant of permission, and +the disclaimer below appear in all copies made; and so long as the +name of The University of Michigan is not used in any advertising or +publicity pertaining to the use or distribution of this software +without specific, written prior authorization. + +THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE +UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT +WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR +IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF +THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES, +INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION +WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +''' + +def sayHello(f): + print >> f, "M5 Simulator System" + print >> f, briefCopyright + print >> f, "M5 compiled on", __main__.compileDate + hostname = os.environ.get('HOSTNAME') + if not hostname: + hostname = os.environ.get('HOST') + if hostname: + print >> f, "M5 executing on", hostname + print >> f, "M5 simulation started", time.ctime() + +sayHello(sys.stderr) # define this here so we can use it right away if necessary def panic(string): @@ -72,3 +118,63 @@ from config import * # import the built-in object definitions from objects import * + +args_left = sys.argv[1:] +configfile_found = False + +while args_left: + arg = args_left.pop(0) + if arg.startswith('--'): + # if arg starts with '--', parse as a special python option + # of the format --= + try: + (var, val) = arg.split('=', 1) + except ValueError: + panic("Could not parse configuration argument '%s'\n" + "Expecting --=\n" % arg); + eval("%s = %s" % (var, repr(val))) + elif arg.startswith('-'): + # if the arg starts with '-', it should be a simulator option + # with a format similar to getopt. + optchar = arg[1] + if len(arg) > 2: + args_left.insert(0, arg[2:]) + if optchar == 'd': + outdir = args_left.pop(0) + elif optchar == 'h': + showBriefHelp(sys.stderr) + sys.exit(1) + elif optchar == 'E': + env_str = args_left.pop(0) + split_result = env_str.split('=', 1) + var = split_result[0] + if len(split_result == 2): + val = split_result[1] + else: + val = True + env[var] = val + elif optchar == 'I': + AddToPath(args_left.pop(0)) + elif optchar == 'P': + eval(args_left.pop(0)) + else: + showBriefHelp(sys.stderr) + panic("invalid argument '%s'\n" % arg_str) + else: + # In any other case, treat the option as a configuration file + # name and load it. + if not arg.endswith('.py'): + panic("Config file '%s' must end in '.py'\n" % arg) + configfile_found = True + m5execfile(arg, globals()) + + +if not configfile_found: + panic("no configuration file specified!") + +if globals().has_key('root') and isinstance(root, Root): + sys.stdout = file('config.ini', 'w') + instantiate(root) +else: + print 'Instantiation skipped: no root object found.' + diff --git a/src/python/m5/config.py b/src/python/m5/config.py index 1e25e0d09..ce7e5a964 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -794,7 +794,7 @@ class ParamFactory(object): # E.g., Param.Int(5, "number of widgets") def __call__(self, *args, **kwargs): - caller_frame = inspect.stack()[1][0] + caller_frame = inspect.currentframe().f_back ptype = None try: ptype = eval(self.ptype_str, -- cgit v1.2.3 From cb0cf2dd8ab1cd60ef13de925ac862268c07297f Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 31 May 2006 19:26:56 -0400 Subject: Updated Authors from bk prs info --HG-- extra : convert_revision : 77f475b156d81c03a2811818fa23593d5615c685 --- src/python/SConscript | 3 +++ src/python/m5/__init__.py | 3 +++ src/python/m5/config.py | 3 +++ src/python/m5/convert.py | 2 ++ src/python/m5/multidict.py | 2 ++ src/python/m5/smartdict.py | 2 ++ 6 files changed, 15 insertions(+) (limited to 'src/python') diff --git a/src/python/SConscript b/src/python/SConscript index 1f2d7fe0e..5a787cfdf 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -25,6 +25,9 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Steve Reinhardt +# Nathan Binkert import os, os.path, re, sys from zipfile import PyZipFile diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 06875d1f0..c44a9ad1f 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -23,6 +23,9 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert +# Steve Reinhardt import sys, os, time diff --git a/src/python/m5/config.py b/src/python/m5/config.py index ce7e5a964..d1471c807 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -23,6 +23,9 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Steve Reinhardt +# Nathan Binkert from __future__ import generators import os, re, sys, types, inspect diff --git a/src/python/m5/convert.py b/src/python/m5/convert.py index 73181e985..580a579bc 100644 --- a/src/python/m5/convert.py +++ b/src/python/m5/convert.py @@ -23,6 +23,8 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert # metric prefixes exa = 1.0e18 diff --git a/src/python/m5/multidict.py b/src/python/m5/multidict.py index fd40ebbbd..698e85b26 100644 --- a/src/python/m5/multidict.py +++ b/src/python/m5/multidict.py @@ -23,6 +23,8 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert __all__ = [ 'multidict' ] diff --git a/src/python/m5/smartdict.py b/src/python/m5/smartdict.py index cd38d7326..d85dbd517 100644 --- a/src/python/m5/smartdict.py +++ b/src/python/m5/smartdict.py @@ -23,6 +23,8 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Authors: Nathan Binkert # The SmartDict class fixes a couple of issues with using the content # of os.environ or similar dicts of strings as Python variables: -- cgit v1.2.3 From 7940c10ace28d5b93a61d4d278e6647e0c497149 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Fri, 2 Jun 2006 18:15:20 -0400 Subject: Fixes to get compiling to work. This is mainly fixing up some includes; changing functions within the XCs; changing MemReqPtrs to Requests or Packets where appropriate. Currently the O3 and Ozone CPUs do not work in the new memory system; I still need to fix up the ports to work and handle responses properly. This check-in is so that the merge between m5 and newmem is no longer outstanding. src/SConscript: Need to include FU Pool for new CPU model. I'll try to figure out a cleaner way to handle this in the future. src/base/traceflags.py: Include new traces flags, fix up merge mess up. src/cpu/SConscript: Include the base_dyn_inst.cc as one of othe sources. Don't compile the Ozone CPU for now. src/cpu/base.cc: Remove an extra } from the merge. src/cpu/base_dyn_inst.cc: Fixes to make compiling work. Don't instantiate the OzoneCPU for now. src/cpu/base_dyn_inst.hh: src/cpu/o3/2bit_local_pred.cc: src/cpu/o3/alpha_cpu_builder.cc: src/cpu/o3/alpha_cpu_impl.hh: src/cpu/o3/alpha_dyn_inst.hh: src/cpu/o3/alpha_params.hh: src/cpu/o3/bpred_unit.cc: src/cpu/o3/btb.hh: src/cpu/o3/commit.hh: src/cpu/o3/commit_impl.hh: src/cpu/o3/cpu.cc: src/cpu/o3/cpu.hh: src/cpu/o3/fetch.hh: src/cpu/o3/fetch_impl.hh: src/cpu/o3/free_list.hh: src/cpu/o3/iew.hh: src/cpu/o3/iew_impl.hh: src/cpu/o3/inst_queue.hh: src/cpu/o3/inst_queue_impl.hh: src/cpu/o3/regfile.hh: src/cpu/o3/sat_counter.hh: src/cpu/op_class.hh: src/cpu/ozone/cpu.hh: src/cpu/checker/cpu.cc: src/cpu/checker/cpu.hh: src/cpu/checker/exec_context.hh: src/cpu/checker/o3_cpu_builder.cc: src/cpu/ozone/cpu_impl.hh: src/mem/request.hh: src/cpu/o3/fu_pool.hh: src/cpu/o3/lsq.hh: src/cpu/o3/lsq_unit.hh: src/cpu/o3/lsq_unit_impl.hh: src/cpu/o3/thread_state.hh: src/cpu/ozone/back_end.hh: src/cpu/ozone/dyn_inst.cc: src/cpu/ozone/dyn_inst.hh: src/cpu/ozone/front_end.hh: src/cpu/ozone/inorder_back_end.hh: src/cpu/ozone/lw_back_end.hh: src/cpu/ozone/lw_lsq.hh: src/cpu/ozone/ozone_impl.hh: src/cpu/ozone/thread_state.hh: Fixes to get compiling to work. src/cpu/o3/alpha_cpu.hh: Fixes to get compiling to work. Float reg accessors have changed, as well as MemReqPtrs to RequestPtrs. src/cpu/o3/alpha_dyn_inst_impl.hh: Fixes to get compiling to work. Pass in the packet to the completeAcc function. Fix up syscall function. --HG-- rename : cpu/activity.cc => src/cpu/activity.cc rename : cpu/activity.hh => src/cpu/activity.hh rename : cpu/checker/cpu.cc => src/cpu/checker/cpu.cc rename : cpu/checker/cpu.hh => src/cpu/checker/cpu.hh rename : cpu/checker/cpu_builder.cc => src/cpu/checker/cpu_builder.cc rename : cpu/checker/exec_context.hh => src/cpu/checker/exec_context.hh rename : cpu/checker/o3_cpu_builder.cc => src/cpu/checker/o3_cpu_builder.cc rename : cpu/o3/dep_graph.hh => src/cpu/o3/dep_graph.hh rename : cpu/o3/fu_pool.cc => src/cpu/o3/fu_pool.cc rename : cpu/o3/fu_pool.hh => src/cpu/o3/fu_pool.hh rename : cpu/o3/lsq.cc => src/cpu/o3/lsq.cc rename : cpu/o3/lsq.hh => src/cpu/o3/lsq.hh rename : cpu/o3/lsq_impl.hh => src/cpu/o3/lsq_impl.hh rename : cpu/o3/lsq_unit.cc => src/cpu/o3/lsq_unit.cc rename : cpu/o3/lsq_unit.hh => src/cpu/o3/lsq_unit.hh rename : cpu/o3/lsq_unit_impl.hh => src/cpu/o3/lsq_unit_impl.hh rename : cpu/o3/scoreboard.cc => src/cpu/o3/scoreboard.cc rename : cpu/o3/scoreboard.hh => src/cpu/o3/scoreboard.hh rename : cpu/o3/thread_state.hh => src/cpu/o3/thread_state.hh rename : cpu/ozone/back_end.cc => src/cpu/ozone/back_end.cc rename : cpu/ozone/back_end.hh => src/cpu/ozone/back_end.hh rename : cpu/ozone/back_end_impl.hh => src/cpu/ozone/back_end_impl.hh rename : cpu/ozone/cpu_builder.cc => src/cpu/ozone/cpu_builder.cc rename : cpu/ozone/dyn_inst.cc => src/cpu/ozone/dyn_inst.cc rename : cpu/ozone/dyn_inst.hh => src/cpu/ozone/dyn_inst.hh rename : cpu/ozone/dyn_inst_impl.hh => src/cpu/ozone/dyn_inst_impl.hh rename : cpu/ozone/front_end.cc => src/cpu/ozone/front_end.cc rename : cpu/ozone/front_end.hh => src/cpu/ozone/front_end.hh rename : cpu/ozone/front_end_impl.hh => src/cpu/ozone/front_end_impl.hh rename : cpu/ozone/inorder_back_end.cc => src/cpu/ozone/inorder_back_end.cc rename : cpu/ozone/inorder_back_end.hh => src/cpu/ozone/inorder_back_end.hh rename : cpu/ozone/inorder_back_end_impl.hh => src/cpu/ozone/inorder_back_end_impl.hh rename : cpu/ozone/inst_queue.cc => src/cpu/ozone/inst_queue.cc rename : cpu/ozone/inst_queue.hh => src/cpu/ozone/inst_queue.hh rename : cpu/ozone/inst_queue_impl.hh => src/cpu/ozone/inst_queue_impl.hh rename : cpu/ozone/lsq_unit.cc => src/cpu/ozone/lsq_unit.cc rename : cpu/ozone/lsq_unit.hh => src/cpu/ozone/lsq_unit.hh rename : cpu/ozone/lsq_unit_impl.hh => src/cpu/ozone/lsq_unit_impl.hh rename : cpu/ozone/lw_back_end.cc => src/cpu/ozone/lw_back_end.cc rename : cpu/ozone/lw_back_end.hh => src/cpu/ozone/lw_back_end.hh rename : cpu/ozone/lw_back_end_impl.hh => src/cpu/ozone/lw_back_end_impl.hh rename : cpu/ozone/lw_lsq.cc => src/cpu/ozone/lw_lsq.cc rename : cpu/ozone/lw_lsq.hh => src/cpu/ozone/lw_lsq.hh rename : cpu/ozone/lw_lsq_impl.hh => src/cpu/ozone/lw_lsq_impl.hh rename : cpu/ozone/null_predictor.hh => src/cpu/ozone/null_predictor.hh rename : cpu/ozone/ozone_impl.hh => src/cpu/ozone/ozone_impl.hh rename : cpu/ozone/rename_table.cc => src/cpu/ozone/rename_table.cc rename : cpu/ozone/rename_table.hh => src/cpu/ozone/rename_table.hh rename : cpu/ozone/rename_table_impl.hh => src/cpu/ozone/rename_table_impl.hh rename : cpu/ozone/simple_impl.hh => src/cpu/ozone/simple_impl.hh rename : cpu/ozone/simple_params.hh => src/cpu/ozone/simple_params.hh rename : cpu/ozone/thread_state.hh => src/cpu/ozone/thread_state.hh rename : cpu/quiesce_event.cc => src/cpu/quiesce_event.cc rename : cpu/quiesce_event.hh => src/cpu/quiesce_event.hh rename : cpu/thread_state.hh => src/cpu/thread_state.hh rename : python/m5/objects/FUPool.py => src/python/m5/objects/FUPool.py rename : python/m5/objects/OzoneCPU.py => src/python/m5/objects/OzoneCPU.py rename : python/m5/objects/SimpleOzoneCPU.py => src/python/m5/objects/SimpleOzoneCPU.py extra : convert_revision : ca7f0fbf65ee1a70d482fb4eda9a1840c7f9b8f8 --- src/python/m5/objects/FUPool.py | 8 +++ src/python/m5/objects/OzoneCPU.py | 89 +++++++++++++++++++++++++++++++++ src/python/m5/objects/SimpleOzoneCPU.py | 86 +++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 src/python/m5/objects/FUPool.py create mode 100644 src/python/m5/objects/OzoneCPU.py create mode 100644 src/python/m5/objects/SimpleOzoneCPU.py (limited to 'src/python') diff --git a/src/python/m5/objects/FUPool.py b/src/python/m5/objects/FUPool.py new file mode 100644 index 000000000..5eecfd12f --- /dev/null +++ b/src/python/m5/objects/FUPool.py @@ -0,0 +1,8 @@ +from m5 import * +from FullCPU import OpType +from FullCPU import OpDesc +from FullCPU import FUDesc + +class FUPool(SimObject): + type = 'FUPool' + FUList = VectorParam.FUDesc("list of FU's for this pool") diff --git a/src/python/m5/objects/OzoneCPU.py b/src/python/m5/objects/OzoneCPU.py new file mode 100644 index 000000000..3fca61e28 --- /dev/null +++ b/src/python/m5/objects/OzoneCPU.py @@ -0,0 +1,89 @@ +from m5 import * +from BaseCPU import BaseCPU + +class DerivOzoneCPU(BaseCPU): + type = 'DerivOzoneCPU' + + numThreads = Param.Unsigned("number of HW thread contexts") + + if not build_env['FULL_SYSTEM']: + mem = Param.FunctionalMemory(NULL, "memory") + + checker = Param.BaseCPU("Checker CPU") + + width = Param.Unsigned("Width") + frontEndWidth = Param.Unsigned("Front end width") + backEndWidth = Param.Unsigned("Back end width") + backEndSquashLatency = Param.Unsigned("Back end squash latency") + backEndLatency = Param.Unsigned("Back end latency") + maxInstBufferSize = Param.Unsigned("Maximum instruction buffer size") + maxOutstandingMemOps = Param.Unsigned("Maximum number of outstanding memory operations") + decodeToFetchDelay = Param.Unsigned("Decode to fetch delay") + renameToFetchDelay = Param.Unsigned("Rename to fetch delay") + iewToFetchDelay = Param.Unsigned("Issue/Execute/Writeback to fetch " + "delay") + commitToFetchDelay = Param.Unsigned("Commit to fetch delay") + fetchWidth = Param.Unsigned("Fetch width") + + renameToDecodeDelay = Param.Unsigned("Rename to decode delay") + iewToDecodeDelay = Param.Unsigned("Issue/Execute/Writeback to decode " + "delay") + commitToDecodeDelay = Param.Unsigned("Commit to decode delay") + fetchToDecodeDelay = Param.Unsigned("Fetch to decode delay") + decodeWidth = Param.Unsigned("Decode width") + + iewToRenameDelay = Param.Unsigned("Issue/Execute/Writeback to rename " + "delay") + commitToRenameDelay = Param.Unsigned("Commit to rename delay") + decodeToRenameDelay = Param.Unsigned("Decode to rename delay") + renameWidth = Param.Unsigned("Rename width") + + commitToIEWDelay = Param.Unsigned("Commit to " + "Issue/Execute/Writeback delay") + renameToIEWDelay = Param.Unsigned("Rename to " + "Issue/Execute/Writeback delay") + issueToExecuteDelay = Param.Unsigned("Issue to execute delay (internal " + "to the IEW stage)") + issueWidth = Param.Unsigned("Issue width") + executeWidth = Param.Unsigned("Execute width") + executeIntWidth = Param.Unsigned("Integer execute width") + executeFloatWidth = Param.Unsigned("Floating point execute width") + executeBranchWidth = Param.Unsigned("Branch execute width") + executeMemoryWidth = Param.Unsigned("Memory execute width") + + iewToCommitDelay = Param.Unsigned("Issue/Execute/Writeback to commit " + "delay") + renameToROBDelay = Param.Unsigned("Rename to reorder buffer delay") + commitWidth = Param.Unsigned("Commit width") + squashWidth = Param.Unsigned("Squash width") + + localPredictorSize = Param.Unsigned("Size of local predictor") + localCtrBits = Param.Unsigned("Bits per counter") + localHistoryTableSize = Param.Unsigned("Size of local history table") + localHistoryBits = Param.Unsigned("Bits for the local history") + globalPredictorSize = Param.Unsigned("Size of global predictor") + globalCtrBits = Param.Unsigned("Bits per counter") + globalHistoryBits = Param.Unsigned("Bits of history") + choicePredictorSize = Param.Unsigned("Size of choice predictor") + choiceCtrBits = Param.Unsigned("Bits of choice counters") + + BTBEntries = Param.Unsigned("Number of BTB entries") + BTBTagSize = Param.Unsigned("Size of the BTB tags, in bits") + + RASSize = Param.Unsigned("RAS size") + + LQEntries = Param.Unsigned("Number of load queue entries") + SQEntries = Param.Unsigned("Number of store queue entries") + LFSTSize = Param.Unsigned("Last fetched store table size") + SSITSize = Param.Unsigned("Store set ID table size") + + numPhysIntRegs = Param.Unsigned("Number of physical integer registers") + numPhysFloatRegs = Param.Unsigned("Number of physical floating point " + "registers") + numIQEntries = Param.Unsigned("Number of instruction queue entries") + numROBEntries = Param.Unsigned("Number of reorder buffer entries") + + instShiftAmt = Param.Unsigned("Number of bits to shift instructions by") + + function_trace = Param.Bool(False, "Enable function trace") + function_trace_start = Param.Tick(0, "Cycle to start function trace") diff --git a/src/python/m5/objects/SimpleOzoneCPU.py b/src/python/m5/objects/SimpleOzoneCPU.py new file mode 100644 index 000000000..0d6403383 --- /dev/null +++ b/src/python/m5/objects/SimpleOzoneCPU.py @@ -0,0 +1,86 @@ +from m5 import * +from BaseCPU import BaseCPU + +class SimpleOzoneCPU(BaseCPU): + type = 'SimpleOzoneCPU' + + numThreads = Param.Unsigned("number of HW thread contexts") + + if not build_env['FULL_SYSTEM']: + mem = Param.FunctionalMemory(NULL, "memory") + + width = Param.Unsigned("Width") + frontEndWidth = Param.Unsigned("Front end width") + backEndWidth = Param.Unsigned("Back end width") + backEndSquashLatency = Param.Unsigned("Back end squash latency") + backEndLatency = Param.Unsigned("Back end latency") + maxInstBufferSize = Param.Unsigned("Maximum instruction buffer size") + decodeToFetchDelay = Param.Unsigned("Decode to fetch delay") + renameToFetchDelay = Param.Unsigned("Rename to fetch delay") + iewToFetchDelay = Param.Unsigned("Issue/Execute/Writeback to fetch " + "delay") + commitToFetchDelay = Param.Unsigned("Commit to fetch delay") + fetchWidth = Param.Unsigned("Fetch width") + + renameToDecodeDelay = Param.Unsigned("Rename to decode delay") + iewToDecodeDelay = Param.Unsigned("Issue/Execute/Writeback to decode " + "delay") + commitToDecodeDelay = Param.Unsigned("Commit to decode delay") + fetchToDecodeDelay = Param.Unsigned("Fetch to decode delay") + decodeWidth = Param.Unsigned("Decode width") + + iewToRenameDelay = Param.Unsigned("Issue/Execute/Writeback to rename " + "delay") + commitToRenameDelay = Param.Unsigned("Commit to rename delay") + decodeToRenameDelay = Param.Unsigned("Decode to rename delay") + renameWidth = Param.Unsigned("Rename width") + + commitToIEWDelay = Param.Unsigned("Commit to " + "Issue/Execute/Writeback delay") + renameToIEWDelay = Param.Unsigned("Rename to " + "Issue/Execute/Writeback delay") + issueToExecuteDelay = Param.Unsigned("Issue to execute delay (internal " + "to the IEW stage)") + issueWidth = Param.Unsigned("Issue width") + executeWidth = Param.Unsigned("Execute width") + executeIntWidth = Param.Unsigned("Integer execute width") + executeFloatWidth = Param.Unsigned("Floating point execute width") + executeBranchWidth = Param.Unsigned("Branch execute width") + executeMemoryWidth = Param.Unsigned("Memory execute width") + + iewToCommitDelay = Param.Unsigned("Issue/Execute/Writeback to commit " + "delay") + renameToROBDelay = Param.Unsigned("Rename to reorder buffer delay") + commitWidth = Param.Unsigned("Commit width") + squashWidth = Param.Unsigned("Squash width") + + localPredictorSize = Param.Unsigned("Size of local predictor") + localCtrBits = Param.Unsigned("Bits per counter") + localHistoryTableSize = Param.Unsigned("Size of local history table") + localHistoryBits = Param.Unsigned("Bits for the local history") + globalPredictorSize = Param.Unsigned("Size of global predictor") + globalCtrBits = Param.Unsigned("Bits per counter") + globalHistoryBits = Param.Unsigned("Bits of history") + choicePredictorSize = Param.Unsigned("Size of choice predictor") + choiceCtrBits = Param.Unsigned("Bits of choice counters") + + BTBEntries = Param.Unsigned("Number of BTB entries") + BTBTagSize = Param.Unsigned("Size of the BTB tags, in bits") + + RASSize = Param.Unsigned("RAS size") + + LQEntries = Param.Unsigned("Number of load queue entries") + SQEntries = Param.Unsigned("Number of store queue entries") + LFSTSize = Param.Unsigned("Last fetched store table size") + SSITSize = Param.Unsigned("Store set ID table size") + + numPhysIntRegs = Param.Unsigned("Number of physical integer registers") + numPhysFloatRegs = Param.Unsigned("Number of physical floating point " + "registers") + numIQEntries = Param.Unsigned("Number of instruction queue entries") + numROBEntries = Param.Unsigned("Number of reorder buffer entries") + + instShiftAmt = Param.Unsigned("Number of bits to shift instructions by") + + function_trace = Param.Bool(False, "Enable function trace") + function_trace_start = Param.Tick(0, "Cycle to start function trace") -- cgit v1.2.3 From 6fa114640604e31433be5821be80effb3ea927ea Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 5 Jun 2006 13:38:07 -0400 Subject: Fix --var=val arg handling. --HG-- extra : convert_revision : 72d46faf9f7562f1c8d936d2e40729e6ca96e217 --- src/python/m5/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/python') diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index c44a9ad1f..5bd9bf22c 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -132,10 +132,11 @@ while args_left: # of the format --= try: (var, val) = arg.split('=', 1) + var = var[2:] except ValueError: panic("Could not parse configuration argument '%s'\n" "Expecting --=\n" % arg); - eval("%s = %s" % (var, repr(val))) + exec "%s = %s" % (var, repr(val)) elif arg.startswith('-'): # if the arg starts with '-', it should be a simulator option # with a format similar to getopt. -- cgit v1.2.3 From 295c7a908cfeecc7276f559ff53282a177f4eb66 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Mon, 5 Jun 2006 14:49:14 -0400 Subject: Same fix for -P option as Steve's previous fix. --HG-- extra : convert_revision : aaefeafa04df1074711f90b9e1f5c488d4c678d3 --- src/python/m5/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/python') diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 5bd9bf22c..4f29c55e8 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -160,7 +160,7 @@ while args_left: elif optchar == 'I': AddToPath(args_left.pop(0)) elif optchar == 'P': - eval(args_left.pop(0)) + exec args_left.pop(0) else: showBriefHelp(sys.stderr) panic("invalid argument '%s'\n" % arg_str) -- cgit v1.2.3 From 090496bf2d4c0f55f7f5869a374b4ec3826bccbc Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Mon, 5 Jun 2006 18:14:39 -0400 Subject: Fixes to get new CPU model working for simple test case. The CPU does not yet support retrying accesses. src/cpu/base_dyn_inst.cc: Delete the allocated data in destructor. src/cpu/base_dyn_inst.hh: Only copy the addresses if the translation succeeded. src/cpu/o3/alpha_cpu.hh: Return actual translating port. Don't panic on setNextNPC() as it's always called, regardless of the architecture, when the process initializes. src/cpu/o3/alpha_cpu_impl.hh: Pass in memobject to the thread state in SE mode. src/cpu/o3/commit_impl.hh: Initialize all variables. src/cpu/o3/decode_impl.hh: Handle early resolution of branches properly. src/cpu/o3/fetch.hh: Switch structure back to requests. src/cpu/o3/fetch_impl.hh: Initialize all variables, create/delete requests properly. src/cpu/o3/lsq_unit.hh: Include sender state along with the packet. Also include a more generic writeback event that's only used for stores forwarding data to loads. src/cpu/o3/lsq_unit_impl.hh: Redo writeback code to support the response path of the memory system. src/cpu/o3/mem_dep_unit.cc: src/cpu/o3/mem_dep_unit_impl.hh: Wrap variables in #ifdefs. src/cpu/o3/store_set.cc: Include to get panic() function. src/cpu/o3/thread_state.hh: Create with MemObject as well. src/cpu/thread_state.hh: Have a translating port in the thread state object. src/python/m5/objects/AlphaFullCPU.py: Mem parameter no longer needed. --HG-- extra : convert_revision : a99381fb25cb183322882ce20935a6f3d1f2b64d --- src/python/m5/objects/AlphaFullCPU.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/python') diff --git a/src/python/m5/objects/AlphaFullCPU.py b/src/python/m5/objects/AlphaFullCPU.py index 043c3c08f..7c772d3f2 100644 --- a/src/python/m5/objects/AlphaFullCPU.py +++ b/src/python/m5/objects/AlphaFullCPU.py @@ -6,9 +6,6 @@ class DerivAlphaFullCPU(BaseCPU): activity = Param.Unsigned("Initial count") numThreads = Param.Unsigned("number of HW thread contexts") - if not build_env['FULL_SYSTEM']: - mem = Param.FunctionalMemory(NULL, "memory") - checker = Param.BaseCPU(NULL, "checker") cachePorts = Param.Unsigned("Cache Ports") -- cgit v1.2.3 From 29e34a739b991af8d8e1eafe75ecb0904c324dc8 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Fri, 9 Jun 2006 23:01:31 -0400 Subject: Move main control from C++ into Python. User script now invokes initialization and simulation loop after building configuration. These functions are exported from C++ to Python using SWIG. SConstruct: Set up SWIG builder & scanner. Set up symlinking of source files into build directory (by not disabling the default behavior). configs/test/test.py: Rewrite to use new script-driven interface. Include a sample option. src/SConscript: Set up symlinking of source files into build directory (by not disabling the default behavior). Add SWIG-generated main_wrap.cc to source list. src/arch/SConscript: Set up symlinking of source files into build directory (by not disabling the default behavior). src/arch/alpha/ev5.cc: src/arch/alpha/isa/decoder.isa: src/cpu/o3/alpha_cpu_impl.hh: src/cpu/trace/opt_cpu.cc: src/cpu/trace/trace_cpu.cc: src/sim/pseudo_inst.cc: src/sim/root.cc: src/sim/serialize.cc: src/sim/syscall_emul.cc: SimExit() is now exitSimLoop(). src/cpu/base.cc: SimExitEvent is now SimLoopExitEvent src/python/SConscript: Add SWIG build command for main.i. Use python/m5 in build dir as source for zip archive... easy now with file duplication enabled. src/python/m5/__init__.py: - Move copyright notice back to C++ so we can print it right away, even for interactive sessions. - Get rid of argument parsing code; just provide default option descriptors for user script to call optparse with. - Don't clutter m5 namespace by sucking in all of m5.config and m5.objects. - Move instantiate() function here from config.py. src/python/m5/config.py: - Move instantiate() function to __init__.py. - Param.Foo deferred type lookups must use m5.objects namespace now (not m5). src/python/m5/objects/AlphaConsole.py: src/python/m5/objects/AlphaFullCPU.py: src/python/m5/objects/AlphaTLB.py: src/python/m5/objects/BadDevice.py: src/python/m5/objects/BaseCPU.py: src/python/m5/objects/BaseCache.py: src/python/m5/objects/Bridge.py: src/python/m5/objects/Bus.py: src/python/m5/objects/CoherenceProtocol.py: src/python/m5/objects/Device.py: src/python/m5/objects/DiskImage.py: src/python/m5/objects/Ethernet.py: src/python/m5/objects/Ide.py: src/python/m5/objects/IntrControl.py: src/python/m5/objects/MemObject.py: src/python/m5/objects/MemTest.py: src/python/m5/objects/Pci.py: src/python/m5/objects/PhysicalMemory.py: src/python/m5/objects/Platform.py: src/python/m5/objects/Process.py: src/python/m5/objects/Repl.py: src/python/m5/objects/Root.py: src/python/m5/objects/SimConsole.py: src/python/m5/objects/SimpleDisk.py: src/python/m5/objects/System.py: src/python/m5/objects/Tsunami.py: src/python/m5/objects/Uart.py: Fix up imports (m5 namespace no longer includes m5.config). src/sim/eventq.cc: src/sim/eventq.hh: Support for Python-called simulate() function: - Use IsExitEvent flag to signal events that want to exit the simulation loop gracefully (instead of calling exit() to terminate the process). - Modify interface to hand exit event object back to caller so it can be inspected for cause. src/sim/host.hh: Add MaxTick constant. src/sim/main.cc: Move copyright notice back to C++ so we can print it right away, even for interactive sessions. Use PYTHONPATH environment var to set module path (instead of clunky code injection method). Move main control from here into Python: - Separate initialization code and simulation loop into separate functions callable from Python. - Make Python interpreter invocation more pure (more like directly invoking interpreter). Add -i and -p flags (only options on binary itself; other options processed by Python). Import readline package when using interactive mode. src/sim/sim_events.cc: SimExitEvent is now SimLoopExitEvent, and uses IsSimExit flag to terminate loop (instead of exiting simulator process). src/sim/sim_events.hh: SimExitEvent is now SimLoopExitEvent, and uses IsSimExit flag to terminate loop (instead of exiting simulator process). Get rid of a few unused constructors. src/sim/sim_exit.hh: SimExit() is now exitSimLoop(). Get rid of unused functions. Add comments. --HG-- extra : convert_revision : 280b0d671516b25545a6f24cefa64a68319ff3d4 --- src/python/SConscript | 28 ++--- src/python/m5/__init__.py | 183 +++++++++-------------------- src/python/m5/config.py | 21 +--- src/python/m5/objects/AlphaConsole.py | 2 +- src/python/m5/objects/AlphaFullCPU.py | 3 +- src/python/m5/objects/AlphaTLB.py | 2 +- src/python/m5/objects/BadDevice.py | 2 +- src/python/m5/objects/BaseCPU.py | 4 +- src/python/m5/objects/BaseCache.py | 2 +- src/python/m5/objects/Bridge.py | 2 +- src/python/m5/objects/Bus.py | 2 +- src/python/m5/objects/CoherenceProtocol.py | 2 +- src/python/m5/objects/Device.py | 2 +- src/python/m5/objects/DiskImage.py | 2 +- src/python/m5/objects/Ethernet.py | 3 +- src/python/m5/objects/Ide.py | 2 +- src/python/m5/objects/IntrControl.py | 2 +- src/python/m5/objects/MemObject.py | 2 +- src/python/m5/objects/MemTest.py | 2 +- src/python/m5/objects/Pci.py | 2 +- src/python/m5/objects/PhysicalMemory.py | 2 +- src/python/m5/objects/Platform.py | 2 +- src/python/m5/objects/Process.py | 2 +- src/python/m5/objects/Repl.py | 2 +- src/python/m5/objects/Root.py | 2 +- src/python/m5/objects/SimConsole.py | 2 +- src/python/m5/objects/SimpleDisk.py | 2 +- src/python/m5/objects/System.py | 3 +- src/python/m5/objects/Tsunami.py | 2 +- src/python/m5/objects/Uart.py | 3 +- 30 files changed, 106 insertions(+), 186 deletions(-) (limited to 'src/python') diff --git a/src/python/SConscript b/src/python/SConscript index 5a787cfdf..7b0f591eb 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -38,11 +38,8 @@ def join(*args): Import('env') -# This SConscript is in charge of collecting .py files and generating a zip archive that is appended to the m5 binary. - -# Copy .py source files here (relative to src/python in the build -# directory). -pyzip_root = 'zip' +# This SConscript is in charge of collecting .py files and generating +# a zip archive that is appended to the m5 binary. # List of files & directories to include in the zip file. To include # a package, list only the root directory of the package, not any @@ -58,7 +55,7 @@ pyzip_dep_files = [] # Add the specified package to the zip archive. Adds the directory to # pyzip_files and all included .py files to pyzip_dep_files. def addPkg(pkgdir): - pyzip_files.append(join(pyzip_root, pkgdir)) + pyzip_files.append(pkgdir) origdir = os.getcwd() srcdir = join(Dir('.').srcnode().abspath, pkgdir) os.chdir(srcdir) @@ -70,10 +67,7 @@ def addPkg(pkgdir): for f in files: if f.endswith('.py'): - source = join(pkgdir, path, f) - target = join(pyzip_root, source) - pyzip_dep_files.append(target) - env.CopyFile(target, source) + pyzip_dep_files.append(join(pkgdir, path, f)) os.chdir(origdir) @@ -81,19 +75,25 @@ def addPkg(pkgdir): # build_env flags. def MakeDefinesPyFile(target, source, env): f = file(str(target[0]), 'w') - print >>f, "import __main__" - print >>f, "__main__.m5_build_env = ", + print >>f, "m5_build_env = ", print >>f, source[0] f.close() optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions]) -env.Command('defines.py', Value(optionDict), MakeDefinesPyFile) +env.Command('m5/defines.py', Value(optionDict), MakeDefinesPyFile) # Now specify the packages & files for the zip archive. addPkg('m5') -pyzip_files.append('defines.py') +pyzip_files.append('m5/defines.py') pyzip_files.append(join(env['ROOT'], 'util/pbs/jobfile.py')) +env.Command(['swig/main_wrap.cc', 'm5/main.py'], + 'swig/main.i', + '$SWIG $SWIGFLAGS -outdir ${TARGETS[1].dir} ' + '-o ${TARGETS[0]} $SOURCES') + +pyzip_dep_files.append('m5/main.py') + # Action function to build the zip archive. Uses the PyZipFile module # included in the standard Python library. def buildPyZip(target, source, env): diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index c44a9ad1f..60a61d66e 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -27,69 +27,26 @@ # Authors: Nathan Binkert # Steve Reinhardt -import sys, os, time +import sys, os, time, atexit, optparse -import __main__ +# import the SWIG-wrapped main C++ functions +import main +# import a few SWIG-wrapped items (those that are likely to be used +# directly by user scripts) completely into this module for +# convenience +from main import simulate, SimLoopExitEvent -briefCopyright = ''' -Copyright (c) 2001-2006 -The Regents of The University of Michigan -All Rights Reserved -''' - -fullCopyright = ''' -Copyright (c) 2001-2006 -The Regents of The University of Michigan -All Rights Reserved - -Permission is granted to use, copy, create derivative works and -redistribute this software and such derivative works for any purpose, -so long as the copyright notice above, this grant of permission, and -the disclaimer below appear in all copies made; and so long as the -name of The University of Michigan is not used in any advertising or -publicity pertaining to the use or distribution of this software -without specific, written prior authorization. - -THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE -UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT -WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR -IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF -THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES, -INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION -WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER -ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -''' - -def sayHello(f): - print >> f, "M5 Simulator System" - print >> f, briefCopyright - print >> f, "M5 compiled on", __main__.compileDate - hostname = os.environ.get('HOSTNAME') - if not hostname: - hostname = os.environ.get('HOST') - if hostname: - print >> f, "M5 executing on", hostname - print >> f, "M5 simulation started", time.ctime() - -sayHello(sys.stderr) +# import the m5 compile options +import defines # define this here so we can use it right away if necessary def panic(string): print >>sys.stderr, 'panic:', string sys.exit(1) -def m5execfile(f, global_dict): - # copy current sys.path - oldpath = sys.path[:] - # push file's directory onto front of path - sys.path.insert(0, os.path.abspath(os.path.dirname(f))) - execfile(f, global_dict) - # restore original path - sys.path = oldpath - -# Prepend given directory to system module search path. +# Prepend given directory to system module search path. We may not +# need this anymore if we can structure our config library more like a +# Python package. def AddToPath(path): # if it's a relative path and we know what directory the current # python script is in, make the path relative to that directory. @@ -100,84 +57,58 @@ def AddToPath(path): # so place the new dir right after that. sys.path.insert(1, path) -# 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") + +# Callback to set trace flags. Not necessarily the best way to do +# things in the long run (particularly if we change how these global +# options are handled). +def setTraceFlags(option, opt_str, value, parser): + objects.Trace.flags = value + +# Standard optparse options. Need to be explicitly included by the +# user script when it calls optparse.OptionParser(). +standardOptions = [ + optparse.make_option("--traceflags", type="string", action="callback", + callback=setTraceFlags) + ] # 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) +build_env.update(defines.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 * - -# import the built-in object definitions -from objects import * - - -args_left = sys.argv[1:] -configfile_found = False - -while args_left: - arg = args_left.pop(0) - if arg.startswith('--'): - # if arg starts with '--', parse as a special python option - # of the format --= - try: - (var, val) = arg.split('=', 1) - except ValueError: - panic("Could not parse configuration argument '%s'\n" - "Expecting --=\n" % arg); - eval("%s = %s" % (var, repr(val))) - elif arg.startswith('-'): - # if the arg starts with '-', it should be a simulator option - # with a format similar to getopt. - optchar = arg[1] - if len(arg) > 2: - args_left.insert(0, arg[2:]) - if optchar == 'd': - outdir = args_left.pop(0) - elif optchar == 'h': - showBriefHelp(sys.stderr) - sys.exit(1) - elif optchar == 'E': - env_str = args_left.pop(0) - split_result = env_str.split('=', 1) - var = split_result[0] - if len(split_result == 2): - val = split_result[1] - else: - val = True - env[var] = val - elif optchar == 'I': - AddToPath(args_left.pop(0)) - elif optchar == 'P': - eval(args_left.pop(0)) - else: - showBriefHelp(sys.stderr) - panic("invalid argument '%s'\n" % arg_str) - else: - # In any other case, treat the option as a configuration file - # name and load it. - if not arg.endswith('.py'): - panic("Config file '%s' must end in '.py'\n" % arg) - configfile_found = True - m5execfile(arg, globals()) - - -if not configfile_found: - panic("no configuration file specified!") - -if globals().has_key('root') and isinstance(root, Root): +# The final hook to generate .ini files. Called from the user script +# once the config is built. +def instantiate(root): + config.ticks_per_sec = float(root.clock.frequency) + # ugly temporary hack to get output to config.ini sys.stdout = file('config.ini', 'w') - instantiate(root) -else: - print 'Instantiation skipped: no root object found.' - + root.print_ini() + sys.stdout.close() # close config.ini + sys.stdout = sys.__stdout__ # restore to original + main.initialize() # load config.ini into C++ and process it + noDot = True # temporary until we fix dot + if not noDot: + dot = pydot.Dot() + instance.outputDot(dot) + dot.orientation = "portrait" + dot.size = "8.5,11" + dot.ranksep="equally" + dot.rank="samerank" + dot.write("config.dot") + dot.write_ps("config.ps") + +# Export curTick to user script. +def curTick(): + return main.cvar.curTick + +# register our C++ exit callback function with Python +atexit.register(main.doExitCleanup) + +# This import allows user scripts to reference 'm5.objects.Foo' after +# just doing an 'import m5' (without an 'import m5.objects'). May not +# matter since most scripts will probably 'from m5.objects import *'. +import objects diff --git a/src/python/m5/config.py b/src/python/m5/config.py index d1471c807..f6a2a84fb 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -728,7 +728,7 @@ class ParamDesc(object): def __getattr__(self, attr): if attr == 'ptype': try: - ptype = eval(self.ptype_str, m5.__dict__) + ptype = eval(self.ptype_str, m5.objects.__dict__) if not isinstance(ptype, type): panic("Param qualifier is not a type: %s" % self.ptype) self.ptype = ptype @@ -1290,23 +1290,6 @@ AllMemory = AddrRange(0, MaxAddr) ##################################################################### -# The final hook to generate .ini files. Called from configuration -# script once config is built. -def instantiate(root): - global ticks_per_sec - ticks_per_sec = float(root.clock.frequency) - root.print_ini() - noDot = True # temporary until we fix dot - if not noDot: - dot = pydot.Dot() - instance.outputDot(dot) - dot.orientation = "portrait" - dot.size = "8.5,11" - dot.ranksep="equally" - dot.rank="samerank" - dot.write("config.dot") - dot.write_ps("config.ps") - # __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. @@ -1322,5 +1305,5 @@ __all__ = ['SimObject', 'ParamContext', 'Param', 'VectorParam', 'NetworkBandwidth', 'MemoryBandwidth', 'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory', 'Null', 'NULL', - 'NextEthernetAddr', 'instantiate'] + 'NextEthernetAddr'] diff --git a/src/python/m5/objects/AlphaConsole.py b/src/python/m5/objects/AlphaConsole.py index 68e6089ab..329b8c5bd 100644 --- a/src/python/m5/objects/AlphaConsole.py +++ b/src/python/m5/objects/AlphaConsole.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Device import BasicPioDevice class AlphaConsole(BasicPioDevice): diff --git a/src/python/m5/objects/AlphaFullCPU.py b/src/python/m5/objects/AlphaFullCPU.py index 48989d057..759ab3cc6 100644 --- a/src/python/m5/objects/AlphaFullCPU.py +++ b/src/python/m5/objects/AlphaFullCPU.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from BaseCPU import BaseCPU class DerivAlphaFullCPU(BaseCPU): diff --git a/src/python/m5/objects/AlphaTLB.py b/src/python/m5/objects/AlphaTLB.py index 5edf8e13d..11c1792ee 100644 --- a/src/python/m5/objects/AlphaTLB.py +++ b/src/python/m5/objects/AlphaTLB.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class AlphaTLB(SimObject): type = 'AlphaTLB' abstract = True diff --git a/src/python/m5/objects/BadDevice.py b/src/python/m5/objects/BadDevice.py index 9cb9a8f03..186b733fa 100644 --- a/src/python/m5/objects/BadDevice.py +++ b/src/python/m5/objects/BadDevice.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Device import BasicPioDevice class BadDevice(BasicPioDevice): diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py index 49cb2a8f3..2e78578df 100644 --- a/src/python/m5/objects/BaseCPU.py +++ b/src/python/m5/objects/BaseCPU.py @@ -1,4 +1,6 @@ -from m5 import * +from m5 import build_env +from m5.config import * + class BaseCPU(SimObject): type = 'BaseCPU' abstract = True diff --git a/src/python/m5/objects/BaseCache.py b/src/python/m5/objects/BaseCache.py index 79d21572a..33f44759b 100644 --- a/src/python/m5/objects/BaseCache.py +++ b/src/python/m5/objects/BaseCache.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from BaseMem import BaseMem class Prefetch(Enum): vals = ['none', 'tagged', 'stride', 'ghb'] diff --git a/src/python/m5/objects/Bridge.py b/src/python/m5/objects/Bridge.py index ada715ce9..880535755 100644 --- a/src/python/m5/objects/Bridge.py +++ b/src/python/m5/objects/Bridge.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from MemObject import MemObject class Bridge(MemObject): diff --git a/src/python/m5/objects/Bus.py b/src/python/m5/objects/Bus.py index 8c5397281..c37dab438 100644 --- a/src/python/m5/objects/Bus.py +++ b/src/python/m5/objects/Bus.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from MemObject import MemObject class Bus(MemObject): diff --git a/src/python/m5/objects/CoherenceProtocol.py b/src/python/m5/objects/CoherenceProtocol.py index 7013000d6..64b6cbacf 100644 --- a/src/python/m5/objects/CoherenceProtocol.py +++ b/src/python/m5/objects/CoherenceProtocol.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class Coherence(Enum): vals = ['uni', 'msi', 'mesi', 'mosi', 'moesi'] class CoherenceProtocol(SimObject): diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py index 2a71bbc65..7798f5f04 100644 --- a/src/python/m5/objects/Device.py +++ b/src/python/m5/objects/Device.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from MemObject import MemObject class PioDevice(MemObject): diff --git a/src/python/m5/objects/DiskImage.py b/src/python/m5/objects/DiskImage.py index 0d55e9329..70d8b2e45 100644 --- a/src/python/m5/objects/DiskImage.py +++ b/src/python/m5/objects/DiskImage.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class DiskImage(SimObject): type = 'DiskImage' abstract = True diff --git a/src/python/m5/objects/Ethernet.py b/src/python/m5/objects/Ethernet.py index 4286c71c8..418670592 100644 --- a/src/python/m5/objects/Ethernet.py +++ b/src/python/m5/objects/Ethernet.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from Device import DmaDevice from Pci import PciDevice diff --git a/src/python/m5/objects/Ide.py b/src/python/m5/objects/Ide.py index 2403e6d36..9ee578177 100644 --- a/src/python/m5/objects/Ide.py +++ b/src/python/m5/objects/Ide.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Pci import PciDevice class IdeID(Enum): vals = ['master', 'slave'] diff --git a/src/python/m5/objects/IntrControl.py b/src/python/m5/objects/IntrControl.py index 66c82c182..514c3fc62 100644 --- a/src/python/m5/objects/IntrControl.py +++ b/src/python/m5/objects/IntrControl.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class IntrControl(SimObject): type = 'IntrControl' cpu = Param.BaseCPU(Parent.any, "the cpu") diff --git a/src/python/m5/objects/MemObject.py b/src/python/m5/objects/MemObject.py index 4d68243e6..d957dae17 100644 --- a/src/python/m5/objects/MemObject.py +++ b/src/python/m5/objects/MemObject.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class MemObject(SimObject): type = 'MemObject' diff --git a/src/python/m5/objects/MemTest.py b/src/python/m5/objects/MemTest.py index 34299faf0..9916d7cb4 100644 --- a/src/python/m5/objects/MemTest.py +++ b/src/python/m5/objects/MemTest.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class MemTest(SimObject): type = 'MemTest' cache = Param.BaseCache("L1 cache") diff --git a/src/python/m5/objects/Pci.py b/src/python/m5/objects/Pci.py index 85cefcd44..9e1e91b13 100644 --- a/src/python/m5/objects/Pci.py +++ b/src/python/m5/objects/Pci.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Device import BasicPioDevice, DmaDevice class PciConfigData(SimObject): diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py index c59910093..bed90d555 100644 --- a/src/python/m5/objects/PhysicalMemory.py +++ b/src/python/m5/objects/PhysicalMemory.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from MemObject import * class PhysicalMemory(MemObject): diff --git a/src/python/m5/objects/Platform.py b/src/python/m5/objects/Platform.py index 4da0ffab4..89fee9991 100644 --- a/src/python/m5/objects/Platform.py +++ b/src/python/m5/objects/Platform.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class Platform(SimObject): type = 'Platform' abstract = True diff --git a/src/python/m5/objects/Process.py b/src/python/m5/objects/Process.py index 60b00229e..0091d8654 100644 --- a/src/python/m5/objects/Process.py +++ b/src/python/m5/objects/Process.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class Process(SimObject): type = 'Process' abstract = True diff --git a/src/python/m5/objects/Repl.py b/src/python/m5/objects/Repl.py index afd256082..8e9f1094f 100644 --- a/src/python/m5/objects/Repl.py +++ b/src/python/m5/objects/Repl.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class Repl(SimObject): type = 'Repl' abstract = True diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py index 205a93c76..373475a7a 100644 --- a/src/python/m5/objects/Root.py +++ b/src/python/m5/objects/Root.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Serialize import Serialize from Statistics import Statistics from Trace import Trace diff --git a/src/python/m5/objects/SimConsole.py b/src/python/m5/objects/SimConsole.py index df3061908..9e1452c6d 100644 --- a/src/python/m5/objects/SimConsole.py +++ b/src/python/m5/objects/SimConsole.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class ConsoleListener(SimObject): type = 'ConsoleListener' port = Param.TcpPort(3456, "listen port") diff --git a/src/python/m5/objects/SimpleDisk.py b/src/python/m5/objects/SimpleDisk.py index e34155ace..44ef709af 100644 --- a/src/python/m5/objects/SimpleDisk.py +++ b/src/python/m5/objects/SimpleDisk.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * class SimpleDisk(SimObject): type = 'SimpleDisk' disk = Param.DiskImage("Disk Image") diff --git a/src/python/m5/objects/System.py b/src/python/m5/objects/System.py index 622b5a870..a8063a274 100644 --- a/src/python/m5/objects/System.py +++ b/src/python/m5/objects/System.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * class System(SimObject): type = 'System' diff --git a/src/python/m5/objects/Tsunami.py b/src/python/m5/objects/Tsunami.py index 27ea0bce8..4613571d8 100644 --- a/src/python/m5/objects/Tsunami.py +++ b/src/python/m5/objects/Tsunami.py @@ -1,4 +1,4 @@ -from m5 import * +from m5.config import * from Device import BasicPioDevice from Platform import Platform diff --git a/src/python/m5/objects/Uart.py b/src/python/m5/objects/Uart.py index 54754aeb9..8e1fd1a37 100644 --- a/src/python/m5/objects/Uart.py +++ b/src/python/m5/objects/Uart.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from Device import BasicPioDevice class Uart(BasicPioDevice): -- cgit v1.2.3 From f693b451a59949ef1a025fe8b391031d2234f1e1 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Fri, 9 Jun 2006 23:33:15 -0400 Subject: Fix up imports in Ozone objects/*.py files. src/python/m5/objects/FUPool.py: src/python/m5/objects/OzoneCPU.py: src/python/m5/objects/SimpleOzoneCPU.py: Fix up imports (m5 namespace no longer includes m5.config). --HG-- extra : convert_revision : 8575ef7d19ef8dfe9524723d7c4f85234d1280d2 --- src/python/m5/objects/FUPool.py | 5 +---- src/python/m5/objects/OzoneCPU.py | 3 ++- src/python/m5/objects/SimpleOzoneCPU.py | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src/python') diff --git a/src/python/m5/objects/FUPool.py b/src/python/m5/objects/FUPool.py index 5eecfd12f..cbf1089cf 100644 --- a/src/python/m5/objects/FUPool.py +++ b/src/python/m5/objects/FUPool.py @@ -1,7 +1,4 @@ -from m5 import * -from FullCPU import OpType -from FullCPU import OpDesc -from FullCPU import FUDesc +from m5.config import * class FUPool(SimObject): type = 'FUPool' diff --git a/src/python/m5/objects/OzoneCPU.py b/src/python/m5/objects/OzoneCPU.py index ea8b6b537..f2d9aea84 100644 --- a/src/python/m5/objects/OzoneCPU.py +++ b/src/python/m5/objects/OzoneCPU.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from BaseCPU import BaseCPU class DerivOzoneCPU(BaseCPU): diff --git a/src/python/m5/objects/SimpleOzoneCPU.py b/src/python/m5/objects/SimpleOzoneCPU.py index 0d6403383..5d968cab0 100644 --- a/src/python/m5/objects/SimpleOzoneCPU.py +++ b/src/python/m5/objects/SimpleOzoneCPU.py @@ -1,4 +1,5 @@ -from m5 import * +from m5 import build_env +from m5.config import * from BaseCPU import BaseCPU class SimpleOzoneCPU(BaseCPU): -- cgit v1.2.3 From 39f85a1de44789bf0afd1d492167d4fe4601bd82 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 10 Jun 2006 19:58:36 -0400 Subject: Only allow SimObject classes to be instantiated (no cloning!). Provide a makeClass() method to generate a new class using a SimObject instance as a template. All instantiation, subclassing, and class generation is done recursively using "deep copy"-style memoization to maintain object relationships in the face of multiple references to shared objects/classes. src/python/m5/multidict.py: Rename local dict attribute from 'dict' to 'local' for clarity. --HG-- extra : convert_revision : 73ed6836216308709d7bb68d09f8131acd5f1822 --- src/python/m5/config.py | 196 ++++++++++++++++++++++++++++++++++----------- src/python/m5/multidict.py | 24 +++--- 2 files changed, 163 insertions(+), 57 deletions(-) (limited to 'src/python') diff --git a/src/python/m5/config.py b/src/python/m5/config.py index f6a2a84fb..9de768d18 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -27,11 +27,10 @@ # Authors: Steve Reinhardt # Nathan Binkert -from __future__ import generators import os, re, sys, types, inspect import m5 -panic = m5.panic +from m5 import panic from convert import * from multidict import multidict @@ -137,6 +136,13 @@ class Singleton(type): def isSimObject(value): return isinstance(value, SimObject) +def isSimObjectClass(value): + try: + return issubclass(value, SimObject) + except TypeError: + # happens if value is not a class at all + return False + def isSimObjSequence(value): if not isinstance(value, (list, tuple)): return False @@ -147,6 +153,16 @@ def isSimObjSequence(value): return True +def isSimObjClassSequence(value): + if not isinstance(value, (list, tuple)): + return False + + for val in value: + if not isNullPointer(val) and not isSimObjectClass(val): + return False + + return True + def isNullPointer(value): return isinstance(value, NullSimObject) @@ -170,19 +186,26 @@ class MetaSimObject(type): # and only allow "private" attributes to be passed to the base # __new__ (starting with underscore). def __new__(mcls, name, bases, dict): - # Copy "private" attributes (including special methods such as __new__) - # to the official dict. Everything else goes in _init_dict to be - # filtered in __init__. - cls_dict = {} - for key,val in dict.items(): - if key.startswith('_'): - cls_dict[key] = val - del dict[key] - cls_dict['_init_dict'] = dict + if dict.has_key('_init_dict'): + # must have been called from makeSubclass() rather than + # via Python class declaration; bypass filtering process. + cls_dict = dict + else: + # Copy "private" attributes (including special methods + # such as __new__) to the official dict. Everything else + # goes in _init_dict to be filtered in __init__. + cls_dict = {} + for key,val in dict.items(): + if key.startswith('_'): + cls_dict[key] = val + del dict[key] + cls_dict['_init_dict'] = dict return super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) - # initialization + # subclass initialization def __init__(cls, name, bases, dict): + # calls type.__init__()... I think that's a no-op, but leave + # it here just in case it's not. super(MetaSimObject, cls).__init__(name, bases, dict) # initialize required attributes @@ -197,27 +220,13 @@ class MetaSimObject(type): base = bases[0] + # the only time the following is not true is when we define + # the SimObject class itself if isinstance(base, MetaSimObject): cls._params.parent = base._params cls._values.parent = base._values - # If your parent has a value in it that's a config node, clone - # it. Do this now so if we update any of the values' - # attributes we are updating the clone and not the original. - for key,val in base._values.iteritems(): - - # don't clone if (1) we're about to overwrite it with - # a local setting or (2) we've already cloned a copy - # from an earlier (more derived) base - if cls._init_dict.has_key(key) or cls._values.has_key(key): - continue - - if isSimObject(val): - cls._values[key] = val() - elif isSimObjSequence(val) and len(val): - cls._values[key] = [ v() for v in val ] - - # now process remaining _init_dict items + # now process the _init_dict items for key,val in cls._init_dict.items(): if isinstance(val, (types.FunctionType, types.TypeType)): type.__setattr__(cls, key, val) @@ -234,6 +243,33 @@ class MetaSimObject(type): else: setattr(cls, key, val) + # Pull the deep-copy memoization dict out of the class dict if + # it's there... + memo = cls.__dict__.get('_memo', {}) + + # Handle SimObject values + for key,val in cls._values.iteritems(): + # SimObject instances need to be promoted to classes. + # Existing classes should not have any instance values, so + # these can only occur at the lowest level dict (the + # parameters just being set in this class definition). + if isSimObject(val): + assert(val == cls._values.local[key]) + cls._values[key] = val.makeClass(memo) + elif isSimObjSequence(val) and len(val): + assert(val == cls._values.local[key]) + cls._values[key] = [ v.makeClass(memo) for v in val ] + # SimObject classes need to be subclassed so that + # parameters that get set at this level only affect this + # level and derivatives. + elif isSimObjectClass(val): + assert(not cls._values.local.has_key(key)) + cls._values[key] = val.makeSubclass({}, memo) + elif isSimObjClassSequence(val) and len(val): + assert(not cls._values.local.has_key(key)) + cls._values[key] = [ v.makeSubclass({}, memo) for v in val ] + + def _set_keyword(cls, keyword, val, kwtype): if not isinstance(val, kwtype): raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ @@ -284,6 +320,22 @@ class MetaSimObject(type): raise AttributeError, \ "object '%s' has no attribute '%s'" % (cls.__name__, attr) + # Create a subclass of this class. Basically a function interface + # to the standard Python class definition mechanism, primarily for + # internal use. 'memo' dict param supports "deep copy" (really + # "deep subclass") operations... within a given operation, + # multiple references to a class should result in a single + # subclass object with multiple references to it (as opposed to + # mutiple unique subclasses). + def makeSubclass(cls, init_dict, memo = {}): + subcls = memo.get(cls) + if not subcls: + name = cls.__name__ + '_' + str(cls._anon_subclass_counter) + cls._anon_subclass_counter += 1 + subcls = MetaSimObject(name, (cls,), + { '_init_dict': init_dict, '_memo': memo }) + return subcls + # The ConfigNode class is the root of the special hierarchy. Most of # the code in this class deals with the configuration hierarchy itself # (parent/child node relationships). @@ -292,27 +344,78 @@ class SimObject(object): # get this metaclass. __metaclass__ = MetaSimObject - def __init__(self, _value_parent = None, **kwargs): + # __new__ operator allocates new instances of the class. We + # override it here just to support "deep instantiation" operation + # via the _memo dict. When recursively instantiating an object + # hierarchy we want to make sure that each class is instantiated + # only once, and that if there are multiple references to the same + # original class, we end up with the corresponding instantiated + # references all pointing to the same instance. + def __new__(cls, _memo = None, **kwargs): + if _memo is not None and _memo.has_key(cls): + # return previously instantiated object + assert(len(kwargs) == 0) + return _memo[cls] + else: + # Need a new one... if it needs to be memoized, this will + # happen in __init__. We defer the insertion until then + # so __init__ can use the memo dict to tell whether or not + # to perform the initialization. + return super(SimObject, cls).__new__(cls, **kwargs) + + # Initialize new instance previously allocated by __new__. For + # objects with SimObject-valued params, we need to recursively + # instantiate the classes represented by those param values as + # well (in a consistent "deep copy"-style fashion; see comment + # above). + def __init__(self, _memo = None, **kwargs): + if _memo is not None: + # We're inside a "deep instantiation" + assert(isinstance(_memo, dict)) + assert(len(kwargs) == 0) + if _memo.has_key(self.__class__): + # __new__ returned an existing, already initialized + # instance, so there's nothing to do here + assert(_memo[self.__class__] == self) + return + # no pre-existing object, so remember this one here + _memo[self.__class__] = self + else: + # This is a new top-level instantiation... don't memoize + # this objcet, but prepare to memoize any recursively + # instantiated objects. + _memo = {} + self._children = {} - if _value_parent and type(_value_parent) != type(self): - # this was called as a type conversion rather than a clone - raise TypeError, "Cannot convert %s to %s" % \ - (_value_parent.__class__.__name__, self.__class__.__name__) - if not _value_parent: - _value_parent = self.__class__ - # clone values - self._values = multidict(_value_parent._values) - for key,val in _value_parent._values.iteritems(): - if isSimObject(val): - setattr(self, key, val()) - elif isSimObjSequence(val) and len(val): - setattr(self, key, [ v() for v in val ]) + # Inherit parameter values from class using multidict so + # individual value settings can be overridden. + self._values = multidict(self.__class__._values) + # For SimObject-valued parameters, the class should have + # classes (not instances) for the values. We need to + # instantiate these classes rather than just inheriting the + # class object. + for key,val in self.__class__._values.iteritems(): + if isSimObjectClass(val): + setattr(self, key, val(_memo)) + elif isSimObjClassSequence(val) and len(val): + setattr(self, key, [ v(_memo) for v in val ]) # apply attribute assignments from keyword args, if any for key,val in kwargs.iteritems(): setattr(self, key, val) + # Use this instance as a template to create a new class. + def makeClass(self, memo = {}): + cls = memo.get(self) + if not cls: + cls = self.__class__.makeSubclass(self._values.local) + memo[self] = cls + return cls + + # Direct instantiation of instances (cloning) is no longer + # allowed; must generate class from instance first. def __call__(self, **kwargs): - return self.__class__(_value_parent = self, **kwargs) + raise TypeError, "cannot instantiate SimObject; "\ + "use makeClass() to make class first" def __getattr__(self, attr): if self._values.has_key(attr): @@ -1069,7 +1172,10 @@ class EthernetAddr(ParamValue): def __str__(self): if self.value == NextEthernetAddr: - return self.addr + if hasattr(self, 'addr'): + return self.addr + else: + return "NextEthernetAddr (unresolved)" else: return self.value diff --git a/src/python/m5/multidict.py b/src/python/m5/multidict.py index 698e85b26..34fc3139b 100644 --- a/src/python/m5/multidict.py +++ b/src/python/m5/multidict.py @@ -31,7 +31,7 @@ __all__ = [ 'multidict' ] class multidict(object): __nodefault = object() def __init__(self, parent = {}, **kwargs): - self.dict = dict(**kwargs) + self.local = dict(**kwargs) self.parent = parent self.deleted = {} @@ -42,11 +42,11 @@ class multidict(object): return `dict(self.items())` def __contains__(self, key): - return self.dict.has_key(key) or self.parent.has_key(key) + return self.local.has_key(key) or self.parent.has_key(key) def __delitem__(self, key): try: - del self.dict[key] + del self.local[key] except KeyError, e: if key in self.parent: self.deleted[key] = True @@ -55,11 +55,11 @@ class multidict(object): def __setitem__(self, key, value): self.deleted.pop(key, False) - self.dict[key] = value + self.local[key] = value def __getitem__(self, key): try: - return self.dict[key] + return self.local[key] except KeyError, e: if not self.deleted.get(key, False) and key in self.parent: return self.parent[key] @@ -67,15 +67,15 @@ class multidict(object): raise KeyError, e def __len__(self): - return len(self.dict) + len(self.parent) + return len(self.local) + len(self.parent) def next(self): - for key,value in self.dict.items(): + for key,value in self.local.items(): yield key,value if self.parent: for key,value in self.parent.next(): - if key not in self.dict and key not in self.deleted: + if key not in self.local and key not in self.deleted: yield key,value def has_key(self, key): @@ -116,22 +116,22 @@ class multidict(object): return self[key] except KeyError: self.deleted.pop(key, False) - self.dict[key] = default + self.local[key] = default return default def _dump(self): print 'multidict dump' node = self while isinstance(node, multidict): - print ' ', node.dict + print ' ', node.local node = node.parent def _dumpkey(self, key): values = [] node = self while isinstance(node, multidict): - if key in node.dict: - values.append(node.dict[key]) + if key in node.local: + values.append(node.local[key]) node = node.parent print key, values -- cgit v1.2.3 From bb58e4b85163f263ebf5ea54fee5dba0109eb88c Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 10 Jun 2006 21:13:36 -0400 Subject: Don't allow SimObject-valued class params to be set after the class has been instantiated or subclassed. This is one of the main situations that leads to confusing results. configs/test/fs.py: Clean up to avoid modifying BaseCPU after it's been subclassed. --HG-- extra : convert_revision : 335cb87bc3b211ecc8969cfb99ffc28f62f1f877 --- src/python/m5/config.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/python') diff --git a/src/python/m5/config.py b/src/python/m5/config.py index 9de768d18..3eb99972f 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -211,6 +211,7 @@ class MetaSimObject(type): # initialize required attributes cls._params = multidict() cls._values = multidict() + cls._instantiated = False # really instantiated or subclassed cls._anon_subclass_counter = 0 # We don't support multiple inheritance. If you want to, you @@ -225,6 +226,7 @@ class MetaSimObject(type): if isinstance(base, MetaSimObject): cls._params.parent = base._params cls._values.parent = base._values + base._instantiated = True # now process the _init_dict items for key,val in cls._init_dict.items(): @@ -299,6 +301,12 @@ class MetaSimObject(type): param = cls._params.get(attr, None) if param: # It's ok: set attribute by delegating to 'object' class. + if (isSimObject(value) or isSimObjSequence(value)) \ + and cls._instantiated: + raise AttributeError, \ + "Cannot set SimObject parameter '%s' after\n" \ + " class %s has been instantiated or subclassed" \ + % (attr, cls.__name__) try: cls._values[attr] = param.convert(value) except Exception, e: @@ -386,6 +394,8 @@ class SimObject(object): # instantiated objects. _memo = {} + self.__class__._instantiated = True + self._children = {} # Inherit parameter values from class using multidict so # individual value settings can be overridden. -- cgit v1.2.3 From d3a57835234ab2ca3830bad380e434ec2c8d2418 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sun, 11 Jun 2006 20:37:56 -0400 Subject: Add some utility functions to ease handling SimObjects and sequences of SimObjects in a uniform manner. --HG-- extra : convert_revision : 5db28b778c6b1ca63ad0a112ad7e92cd610f64d3 --- src/python/m5/config.py | 57 +++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 21 deletions(-) (limited to 'src/python') diff --git a/src/python/m5/config.py b/src/python/m5/config.py index 3eb99972f..97e13c900 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -143,8 +143,8 @@ def isSimObjectClass(value): # happens if value is not a class at all return False -def isSimObjSequence(value): - if not isinstance(value, (list, tuple)): +def isSimObjectSequence(value): + if not isinstance(value, (list, tuple)) or len(value) == 0: return False for val in value: @@ -153,8 +153,8 @@ def isSimObjSequence(value): return True -def isSimObjClassSequence(value): - if not isinstance(value, (list, tuple)): +def isSimObjectClassSequence(value): + if not isinstance(value, (list, tuple)) or len(value) == 0: return False for val in value: @@ -163,9 +163,31 @@ def isSimObjClassSequence(value): return True +def isSimObjectOrSequence(value): + return isSimObject(value) or isSimObjectSequence(value) + +def isSimObjectClassOrSequence(value): + return isSimObjectClass(value) or isSimObjectClassSequence(value) + def isNullPointer(value): return isinstance(value, NullSimObject) +# Apply method to object. +# applyMethod(obj, 'meth', ) is equivalent to obj.meth() +def applyMethod(obj, meth, *args, **kwargs): + return getattr(obj, meth)(*args, **kwargs) + +# If the first argument is an (non-sequence) object, apply the named +# method with the given arguments. If the first argument is a +# sequence, apply the method to each element of the sequence (a la +# 'map'). +def applyOrMap(objOrSeq, meth, *args, **kwargs): + if not isinstance(objOrSeq, (list, tuple)): + return applyMethod(objOrSeq, meth, *args, **kwargs) + else: + return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq] + + # The metaclass for ConfigNode (and thus for everything that derives # from ConfigNode, including SimObject). This class controls how new # classes that derive from ConfigNode are instantiated, and provides @@ -255,21 +277,15 @@ class MetaSimObject(type): # Existing classes should not have any instance values, so # these can only occur at the lowest level dict (the # parameters just being set in this class definition). - if isSimObject(val): - assert(val == cls._values.local[key]) - cls._values[key] = val.makeClass(memo) - elif isSimObjSequence(val) and len(val): + if isSimObjectOrSequence(val): assert(val == cls._values.local[key]) - cls._values[key] = [ v.makeClass(memo) for v in val ] + cls._values[key] = applyOrMap(val, 'makeClass', memo) # SimObject classes need to be subclassed so that # parameters that get set at this level only affect this # level and derivatives. - elif isSimObjectClass(val): - assert(not cls._values.local.has_key(key)) - cls._values[key] = val.makeSubclass({}, memo) - elif isSimObjClassSequence(val) and len(val): + elif isSimObjectClassOrSequence(val): assert(not cls._values.local.has_key(key)) - cls._values[key] = [ v.makeSubclass({}, memo) for v in val ] + cls._values[key] = applyOrMap(val, 'makeSubclass', {}, memo) def _set_keyword(cls, keyword, val, kwtype): @@ -301,8 +317,7 @@ class MetaSimObject(type): param = cls._params.get(attr, None) if param: # It's ok: set attribute by delegating to 'object' class. - if (isSimObject(value) or isSimObjSequence(value)) \ - and cls._instantiated: + if isSimObjectOrSequence(value) and cls._instantiated: raise AttributeError, \ "Cannot set SimObject parameter '%s' after\n" \ " class %s has been instantiated or subclassed" \ @@ -315,7 +330,7 @@ class MetaSimObject(type): e.args = (msg, ) raise # I would love to get rid of this - elif isSimObject(value) or isSimObjSequence(value): + elif isSimObjectOrSequence(value): cls._values[attr] = value else: raise AttributeError, \ @@ -407,7 +422,7 @@ class SimObject(object): for key,val in self.__class__._values.iteritems(): if isSimObjectClass(val): setattr(self, key, val(_memo)) - elif isSimObjClassSequence(val) and len(val): + elif isSimObjectClassSequence(val) and len(val): setattr(self, key, [ v(_memo) for v in val ]) # apply attribute assignments from keyword args, if any for key,val in kwargs.iteritems(): @@ -454,7 +469,7 @@ class SimObject(object): e.args = (msg, ) raise # I would love to get rid of this - elif isSimObject(value) or isSimObjSequence(value): + elif isSimObjectOrSequence(value): pass else: raise AttributeError, "Class %s has no parameter %s" \ @@ -465,7 +480,7 @@ class SimObject(object): if isSimObject(value): value.set_path(self, attr) - elif isSimObjSequence(value): + elif isSimObjectSequence(value): value = SimObjVector(value) [v.set_path(self, "%s%d" % (attr, i)) for i,v in enumerate(value)] @@ -888,7 +903,7 @@ class VectorParamDesc(ParamDesc): if isinstance(value, (list, tuple)): # list: coerce each element into new list tmp_list = [ ParamDesc.convert(self, v) for v in value ] - if isSimObjSequence(tmp_list): + if isSimObjectSequence(tmp_list): return SimObjVector(tmp_list) else: return VectorParamValue(tmp_list) -- cgit v1.2.3