diff options
-rw-r--r-- | SConscript | 9 | ||||
-rw-r--r-- | build/SConstruct | 5 | ||||
-rw-r--r-- | configs/splash2/run.mpy | 50 | ||||
-rw-r--r-- | dev/pciconfigall.cc | 5 | ||||
-rw-r--r-- | dev/pcidev.cc | 10 | ||||
-rw-r--r-- | python/SConscript (renamed from sim/pyconfig/SConscript) | 39 | ||||
-rw-r--r-- | python/m5/__init__.py | 37 | ||||
-rw-r--r-- | python/m5/config.py (renamed from sim/pyconfig/m5config.py) | 259 | ||||
-rw-r--r-- | python/m5/convert.py | 181 | ||||
-rw-r--r-- | python/m5/objects/AlphaConsole.mpy (renamed from objects/AlphaConsole.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/AlphaTLB.mpy (renamed from objects/AlphaTLB.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/BadDevice.mpy (renamed from objects/BadDevice.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/BaseCPU.mpy (renamed from objects/BaseCPU.mpy) | 2 | ||||
-rw-r--r-- | python/m5/objects/BaseCache.mpy (renamed from objects/BaseCache.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/BaseSystem.mpy (renamed from objects/BaseSystem.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Bus.mpy (renamed from objects/Bus.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/CoherenceProtocol.mpy (renamed from objects/CoherenceProtocol.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Device.mpy (renamed from objects/Device.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/DiskImage.mpy (renamed from objects/DiskImage.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Ethernet.mpy (renamed from objects/Ethernet.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Ide.mpy (renamed from objects/Ide.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/IntrControl.mpy (renamed from objects/IntrControl.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/MemTest.mpy (renamed from objects/MemTest.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Pci.mpy (renamed from objects/Pci.mpy) | 5 | ||||
-rw-r--r-- | python/m5/objects/PhysicalMemory.mpy (renamed from objects/PhysicalMemory.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Platform.mpy (renamed from objects/Platform.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Process.mpy (renamed from objects/Process.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Repl.mpy (renamed from objects/Repl.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Root.mpy (renamed from objects/Root.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/SimConsole.mpy (renamed from objects/SimConsole.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/SimpleDisk.mpy (renamed from objects/SimpleDisk.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Tsunami.mpy (renamed from objects/Tsunami.mpy) | 0 | ||||
-rw-r--r-- | python/m5/objects/Uart.mpy (renamed from objects/Uart.mpy) | 0 | ||||
-rw-r--r-- | python/m5/smartdict.py | 102 | ||||
-rw-r--r-- | sim/main.cc | 2 | ||||
-rw-r--r-- | sim/sim_object.hh | 4 | ||||
-rwxr-xr-x | test/genini.py | 16 |
37 files changed, 567 insertions, 159 deletions
diff --git a/SConscript b/SConscript index 94e788ce9..ad9d89ff0 100644 --- a/SConscript +++ b/SConscript @@ -212,6 +212,9 @@ base_sources = Split(''' mem/trace/mem_trace_writer.cc mem/trace/m5_writer.cc + python/pyconfig.cc + python/embedded_py.cc + sim/builder.cc sim/configfile.cc sim/debug.cc @@ -228,8 +231,6 @@ base_sources = Split(''' sim/stat_control.cc sim/trace_context.cc sim/universe.cc - sim/pyconfig/pyconfig.cc - sim/pyconfig/embedded_py.cc ''') # MySql sources @@ -407,8 +408,8 @@ env.Command(Split('''arch/alpha/decoder.cc # SConscript-local is the per-config build, which just copies some # header files into a place where they can be found. SConscript('libelf/SConscript-local', exports = 'env', duplicate=0) -SConscript('sim/pyconfig/SConscript', exports = ['env'], duplicate=0) - +SConscript('python/SConscript', exports = ['env'], duplicate=0) +SConscript('simobj/SConscript', exports = 'env', duplicate=0) # This function adds the specified sources to the given build # environment, and returns a list of all the corresponding SCons diff --git a/build/SConstruct b/build/SConstruct index a1f1cdc5c..068158a4e 100644 --- a/build/SConstruct +++ b/build/SConstruct @@ -62,6 +62,9 @@ if not os.path.isdir('ext'): % EXT_SRCDIR sys.exit(1) +# tell python where to find m5 python code +sys.path.append(os.path.join(SRCDIR, 'python')) + ################################################### # @@ -294,7 +297,7 @@ for build_dir in build_dirs: ################################################### # # Let SCons do its thing. At this point SCons will use the defined -# build enviornments to build the requested targets. +# build environments to build the requested targets. # ################################################### diff --git a/configs/splash2/run.mpy b/configs/splash2/run.mpy new file mode 100644 index 000000000..a19dcdc93 --- /dev/null +++ b/configs/splash2/run.mpy @@ -0,0 +1,50 @@ +import Splash2 + +if 'SYSTEM' not in env: + panic("The SYSTEM environment variable must be set!\ne.g -ESYSTEM=Detailed\n") + +if env['SYSTEM'] == 'Simple': + from SimpleConfig import * + BaseCPU.workload = Super.workload + SimpleStandAlone.cpu = [ CPU() for i in xrange(int(env['NP'])) ] + root = SimpleStandAlone +elif env['SYSTEM'] == 'Detailed': + from DetailedConfig import * + BaseCPU.workload = Super.workload + DetailedStandAlone.cpu = [ DetailedCPU() for i in xrange(int(env['NP'])) ] + root = DetailedStandAlone +else: + panic("The SYSTEM environment variable was set to something improper.\n Use Simple or Detailed\n") + +if 'BENCHMARK' not in env: + panic("The BENCHMARK environment variable must be set!\ne.g. -EBENCHMARK=Cholesky\n") + +if env['BENCHMARK'] == 'Cholesky': + root.workload = Splash2.Cholesky() +elif env['BENCHMARK'] == 'FFT': + root.workload = Splash2.FFT() +elif env['BENCHMARK'] == 'LUContig': + root.workload = Splash2.LU_contig() +elif env['BENCHMARK'] == 'LUNoncontig': + root.workload = Splash2.LU_noncontig() +elif env['BENCHMARK'] == 'Radix': + root.workload = Splash2.Radix() +elif env['BENCHMARK'] == 'Barnes': + root.workload = Splash2.Barnes() +elif env['BENCHMARK'] == 'FMM': + root.workload = Splash2.FMM() +elif env['BENCHMARK'] == 'OceanContig': + root.workload = Splash2.Ocean_contig() +elif env['BENCHMARK'] == 'OceanNoncontig': + root.workload = Splash2.Ocean_noncontig() +elif env['BENCHMARK'] == 'Raytrace': + root.workload = Splash2.Raytrace() +elif env['BENCHMARK'] == 'WaterNSquared': + root.workload = Splash2.Water_nsquared() +elif env['BENCHMARK'] == 'WaterSpatial': + root.workload = Splash2.Water_spatial() +else: + panic("The BENCHMARK environment variable was set to something" \ + +" improper.\nUse Cholesky, FFT, LUContig, LUNoncontig, Radix" \ + +", Barnes, FMM, OceanContig,\nOceanNoncontig, Raytrace," \ + +" WaterNSquared, or WaterSpatial\n") diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc index 1a9804f79..2cbd5adc0 100644 --- a/dev/pciconfigall.cc +++ b/dev/pciconfigall.cc @@ -98,11 +98,12 @@ PciConfigAll::startup() Fault PciConfigAll::read(MemReqPtr &req, uint8_t *data) { - DPRINTF(PciConfigAll, "read va=%#x size=%d\n", - req->vaddr, req->size); Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)); + DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", + req->vaddr, daddr, req->size); + int device = (daddr >> 11) & 0x1F; int func = (daddr >> 8) & 0x7; int reg = daddr & 0xFF; diff --git a/dev/pcidev.cc b/dev/pcidev.cc index c45afadd4..76b42390a 100644 --- a/dev/pcidev.cc +++ b/dev/pcidev.cc @@ -285,11 +285,6 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion) BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) - SimObjectParam<MemoryController *> mmu; - Param<Addr> addr; - SimObjectParam<Bus*> io_bus; - Param<Tick> pio_latency; - Param<uint16_t> VendorID; Param<uint16_t> DeviceID; Param<uint16_t> Command; @@ -327,11 +322,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData) - INIT_PARAM(mmu, "Memory Controller"), - INIT_PARAM(addr, "Device Address"), - INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM(VendorID, "Vendor ID"), INIT_PARAM(DeviceID, "Device ID"), INIT_PARAM_DFLT(Command, "Command Register", 0x00), diff --git a/sim/pyconfig/SConscript b/python/SConscript index 2799ef64f..9c15c6d50 100644 --- a/sim/pyconfig/SConscript +++ b/python/SConscript @@ -26,7 +26,11 @@ # (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') + +import m5scons def WriteEmbeddedPyFile(target, source, path, name, ext, filename): if isinstance(source, str): @@ -89,7 +93,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 +148,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): @@ -193,8 +180,10 @@ EmbedMap %(name)s("%(fname)s", /* namespace */ } ''' -embedded_py_files = ['m5config.py', 'importer.py', '../../util/pbs/jobfile.py'] -objpath = os.path.join(env['SRCDIR'], 'objects') +# base list of .py files to embed +embedded_py_files = [ '../util/pbs/jobfile.py' ] +# add all .py and .mpy 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': diff --git a/python/m5/__init__.py b/python/m5/__init__.py new file mode 100644 index 000000000..16f48dba3 --- /dev/null +++ b/python/m5/__init__.py @@ -0,0 +1,37 @@ +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) + +# import the built-in object definitions +from objects import * +config.add_param_types(objects) + +cpp_classes = config.MetaSimObject.cpp_classes +cpp_classes.sort() + diff --git a/sim/pyconfig/m5config.py b/python/m5/config.py index e6201b3ad..a9d7a2f41 100644 --- a/sim/pyconfig/m5config.py +++ b/python/m5/config.py @@ -27,7 +27,7 @@ from __future__ import generators import os, re, sys, types, inspect -from importer import AddToPath, LoadMpyFile +from convert import * noDot = False try: @@ -35,13 +35,6 @@ try: except: noDot = True -env = {} -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) @@ -208,6 +201,28 @@ class_decorator = 'M5M5_SIMOBJECT_' expr_decorator = 'M5M5_EXPRESSION_' dot_decorator = '_M5M5_DOT_' +# 'Global' map of legitimate types for SimObject parameters. +param_types = {} + +# Dummy base class to identify types that are legitimate for SimObject +# parameters. +class ParamType(object): + pass + +# Add types defined in given context (dict or module) that are derived +# from ParamType to param_types map. +def add_param_types(ctx): + if isinstance(ctx, types.DictType): + source_dict = ctx + elif isinstance(ctx, types.ModuleType): + source_dict = ctx.__dict__ + else: + raise TypeError, \ + "m5.config.add_param_types requires dict or module as arg" + for key,val in source_dict.iteritems(): + if isinstance(val, type) and issubclass(val, ParamType): + param_types[key] = val + # 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 @@ -245,7 +260,7 @@ class MetaConfigNode(type): # initialize required attributes cls._params = {} cls._values = {} - cls._enums = {} + cls._param_types = {} cls._bases = [c for c in cls.__mro__ if isConfigNode(c)] cls._anon_subclass_counter = 0 @@ -268,19 +283,26 @@ class MetaConfigNode(type): elif isNullPointer(val): cls._values[key] = val - # now process _init_dict items + # process param types from _init_dict, as these may be needed + # by param descriptions also in _init_dict + for key,val in cls._init_dict.items(): + if isinstance(val, type) and issubclass(val, ParamType): + cls._param_types[key] = val + if not issubclass(val, ConfigNode): + del cls._init_dict[key] + + # now process remaining _init_dict items for key,val in cls._init_dict.items(): + # param descriptions if isinstance(val, _Param): cls._params[key] = val + # try to resolve local param types in local param_types scope + val.maybe_resolve_type(cls._param_types) # init-time-only keywords elif cls.init_keywords.has_key(key): cls._set_keyword(key, val, cls.init_keywords[key]) - # enums - elif isinstance(val, type) and issubclass(val, Enum): - cls._enums[key] = val - # See description of decorators in the importer.py file. # We just strip off the expr_decorator now since we don't # need from this point on. @@ -417,7 +439,11 @@ class MetaConfigNode(type): # It's ok: set attribute by delegating to 'object' class. # Note the use of param.make_value() to verify/canonicalize # the assigned value - param.valid(value) + try: + param.valid(value) + except: + panic("Error setting param %s.%s to %s\n" % \ + (cls.__name__, attr, value)) cls._setvalue(attr, value) elif isConfigNode(value) or isSimObjSequence(value): cls._setvalue(attr, value) @@ -449,7 +475,7 @@ class MetaConfigNode(type): # Print instance info to .ini file. def instantiate(cls, name, parent = None): - instance = Node(name, cls, cls.type, parent, isParamContext(cls)) + instance = Node(name, cls, parent, isParamContext(cls)) if hasattr(cls, 'check'): cls.check() @@ -560,7 +586,7 @@ class MetaSimObject(MetaConfigNode): def _cpp_decl(cls): name = cls.__name__ code = "" - code += "\n".join([e.cpp_declare() for e in cls._enums.values()]) + code += "\n".join([e.cpp_declare() for e in cls._param_types.values()]) code += "\n" param_names = cls._params.keys() param_names.sort() @@ -584,10 +610,13 @@ class NodeParam(object): class Node(object): all = {} - def __init__(self, name, realtype, type, parent, paramcontext): + def __init__(self, name, realtype, parent, paramcontext): self.name = name self.realtype = realtype - self.type = type + if isSimObject(realtype): + self.type = realtype.type + else: + self.type = None self.parent = parent self.children = [] self.child_names = {} @@ -849,13 +878,24 @@ class _Param(object): if not hasattr(self, 'desc'): raise TypeError, 'desc attribute missing' + def maybe_resolve_type(self, context): + # check if already resolved... don't use hasattr(), + # as that calls __getattr__() + if self.__dict__.has_key('ptype'): + return + try: + self.ptype = context[self.ptype_string] + except KeyError: + # no harm in trying... we'll try again later using global scope + pass + def __getattr__(self, attr): if attr == 'ptype': try: - self.ptype = eval(self.ptype_string) + self.ptype = param_types[self.ptype_string] return self.ptype except: - raise TypeError, 'Param.%s: undefined type' % self.ptype_string + panic("undefined Param type %s" % self.ptype_string) else: raise AttributeError, "'%s' object has no attribute '%s'" % \ (type(self).__name__, attr) @@ -882,19 +922,10 @@ class _ParamProxy(object): # E.g., Param.Int(5, "number of widgets") def __call__(self, *args, **kwargs): - # Param type could be defined only in context of caller (e.g., - # for locally defined Enum subclass). Need to go look up the - # type in that enclosing scope. - caller_frame = inspect.stack()[1][0] - ptype = caller_frame.f_locals.get(self.ptype, None) - if not ptype: ptype = caller_frame.f_globals.get(self.ptype, None) - if not ptype: ptype = globals().get(self.ptype, None) - # ptype could still be None due to circular references... we'll - # try one more time to evaluate lazily when ptype is first needed. - # In the meantime we'll save the type name as a string. - if not ptype: ptype = self.ptype - return _Param(ptype, *args, **kwargs) + return _Param(self.ptype, *args, **kwargs) + # Strange magic to theoretically allow dotted names as Param classes, + # e.g., Param.Foo.Bar(...) to have a param of type Foo.Bar def __getattr__(self, attr): if attr == '__bases__': raise AttributeError, '' @@ -970,99 +1001,109 @@ VectorParam = _VectorParamProxy(None) # to correspond to distinct C++ types as well. # ##################################################################### -# Integer parameter type. -class _CheckedInt(object): + + +# Metaclass for bounds-checked integer parameters. See CheckedInt. +class CheckedIntType(type): + def __init__(cls, name, bases, dict): + super(CheckedIntType, cls).__init__(name, bases, dict) + + # CheckedInt is an abstract base class, so we actually don't + # want to do any processing on it... the rest of this code is + # just for classes that derive from CheckedInt. + if name == 'CheckedInt': + return + + if not (hasattr(cls, 'min') and hasattr(cls, 'max')): + if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): + panic("CheckedInt subclass %s must define either\n" \ + " 'min' and 'max' or 'size' and 'unsigned'\n" \ + % name); + if cls.unsigned: + cls.min = 0 + cls.max = 2 ** cls.size - 1 + else: + cls.min = -(2 ** (cls.size - 1)) + cls.max = (2 ** (cls.size - 1)) - 1 + + cls._cpp_param_decl = cls.cppname + def _convert(cls, value): - t = type(value) - if t == bool: + if isinstance(value, bool): return int(value) - if t != int and t != long and t != float and t != str: - raise TypeError, 'Integer parameter of invalid type %s' % t + if not isinstance(value, (int, long, float, str)): + raise TypeError, 'Integer param of invalid type %s' % type(value) - if t == str or t == float: - value = long(value) + if isinstance(value, (str, float)): + value = long(float(value)) - if not cls._min <= value <= cls._max: - raise TypeError, 'Integer parameter out of bounds %d < %d < %d' % \ - (cls._min, value, cls._max) + if not cls.min <= value <= cls.max: + raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ + (cls.min, value, cls.max) return value - _convert = classmethod(_convert) def _string(cls, value): return str(value) - _string = classmethod(_string) -class CheckedInt(type): - def __new__(cls, cppname, min, max): - # New class derives from _CheckedInt base with proper bounding - # parameters - dict = { '_cpp_param_decl' : cppname, '_min' : min, '_max' : max } - return type.__new__(cls, cppname, (_CheckedInt, ), dict) - -class CheckedIntType(CheckedInt): - def __new__(cls, cppname, size, unsigned): - dict = {} - if unsigned: - min = 0 - max = 2 ** size - 1 - else: - min = -(2 ** (size - 1)) - max = (2 ** (size - 1)) - 1 - - return super(cls, CheckedIntType).__new__(cls, cppname, min, max) +# Abstract superclass for bounds-checked integer parameters. This +# class is subclassed to generate parameter classes with specific +# bounds. Initialization of the min and max bounds is done in the +# metaclass CheckedIntType.__init__. +class CheckedInt(ParamType): + __metaclass__ = CheckedIntType -Int = CheckedIntType('int', 32, False) -Unsigned = CheckedIntType('unsigned', 32, True) +class Int(CheckedInt): cppname = 'int'; size = 32; unsigned = False +class Unsigned(CheckedInt): cppname = 'unsigned'; size = 32; unsigned = True -Int8 = CheckedIntType('int8_t', 8, False) -UInt8 = CheckedIntType('uint8_t', 8, True) -Int16 = CheckedIntType('int16_t', 16, False) -UInt16 = CheckedIntType('uint16_t', 16, True) -Int32 = CheckedIntType('int32_t', 32, False) -UInt32 = CheckedIntType('uint32_t', 32, True) -Int64 = CheckedIntType('int64_t', 64, False) -UInt64 = CheckedIntType('uint64_t', 64, True) +class Int8(CheckedInt): cppname = 'int8_t'; size = 8; unsigned = False +class UInt8(CheckedInt): cppname = 'uint8_t'; size = 8; unsigned = True +class Int16(CheckedInt): cppname = 'int16_t'; size = 16; unsigned = False +class UInt16(CheckedInt): cppname = 'uint16_t'; size = 16; unsigned = True +class Int32(CheckedInt): cppname = 'int32_t'; size = 32; unsigned = False +class UInt32(CheckedInt): cppname = 'uint32_t'; size = 32; unsigned = True +class Int64(CheckedInt): cppname = 'int64_t'; size = 64; unsigned = False +class UInt64(CheckedInt): cppname = 'uint64_t'; size = 64; unsigned = True -Counter = CheckedIntType('Counter', 64, True) -Addr = CheckedIntType('Addr', 64, True) -Tick = CheckedIntType('Tick', 64, True) +class Counter(CheckedInt): cppname = 'Counter'; size = 64; unsigned = True +class Addr(CheckedInt): cppname = 'Addr'; size = 64; unsigned = True +class Tick(CheckedInt): cppname = 'Tick'; size = 64; unsigned = True -Percent = CheckedInt('int', 0, 100) +class Percent(CheckedInt): cppname = 'int'; min = 0; max = 100 class Pair(object): def __init__(self, first, second): self.first = first self.second = second -class _Range(object): +class MetaRange(type): + def __init__(cls, name, bases, dict): + super(MetaRange, cls).__init__(name, bases, dict) + if name == 'Range': + return + cls._cpp_param_decl = 'Range<%s>' % cls.type._cpp_param_decl + def _convert(cls, value): if not isinstance(value, Pair): raise TypeError, 'value %s is not a Pair' % value - return Pair(cls._type._convert(value.first), - cls._type._convert(value.second)) - _convert = classmethod(_convert) + return Pair(cls.type._convert(value.first), + cls.type._convert(value.second)) def _string(cls, value): - return '%s:%s' % (cls._type._string(value.first), - cls._type._string(value.second)) - _string = classmethod(_string) + return '%s:%s' % (cls.type._string(value.first), + cls.type._string(value.second)) + +class Range(ParamType): + __metaclass__ = MetaRange def RangeSize(start, size): return Pair(start, start + size - 1) -class Range(type): - def __new__(cls, type): - dict = { '_cpp_param_decl' : 'Range<%s>' % type._cpp_param_decl, - '_type' : type } - clsname = 'Range_' + type.__name__ - return super(cls, Range).__new__(cls, clsname, (_Range, ), dict) - -AddrRange = Range(Addr) +class AddrRange(Range): type = Addr # Boolean parameter type. -class Bool(object): +class Bool(ParamType): _cpp_param_decl = 'bool' def _convert(value): t = type(value) @@ -1090,7 +1131,7 @@ class Bool(object): _string = staticmethod(_string) # String-valued parameter. -class String(object): +class String(ParamType): _cpp_param_decl = 'string' # Constructor. Value must be Python string. @@ -1130,7 +1171,7 @@ class NextEthernetAddr(object): self.value = self.addr self.addr = IncEthernetAddr(self.addr, inc) -class EthernetAddr(object): +class EthernetAddr(ParamType): _cpp_param_decl = 'EthAddr' def _convert(cls, value): @@ -1237,7 +1278,7 @@ class MetaEnum(type): return s # Base class for enum types. -class Enum(object): +class Enum(ParamType): __metaclass__ = MetaEnum vals = [] @@ -1257,8 +1298,8 @@ class Enum(object): # # Some memory range specifications use this as a default upper bound. -MAX_ADDR = Addr._max -MaxTick = Tick._max +MAX_ADDR = Addr.max +MaxTick = Tick.max # For power-of-two sizing, e.g. 64*K gives an integer value 65536. K = 1024 @@ -1270,9 +1311,6 @@ G = K*M # The final hook to generate .ini files. Called from configuration # script once config is built. def instantiate(root): - if not issubclass(root, Root): - raise AttributeError, 'Can only instantiate the Root of the tree' - instance = root.instantiate('root') instance.fixup() instance.display() @@ -1293,11 +1331,20 @@ def instantiate(root): # parameters to be set by keyword in the constructor. Note that most # of the heavy lifting for the SimObject param handling is done in the # MetaConfigNode metaclass. -class SimObject(ConfigNode): +class SimObject(ConfigNode, ParamType): __metaclass__ = MetaSimObject type = 'SimObject' -from objects import * -cpp_classes = MetaSimObject.cpp_classes -cpp_classes.sort() +# __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__ = ['issequence', + 'ConfigNode', 'SimObject', 'ParamContext', 'Param', 'VectorParam', + 'Super', 'Enum', + 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', + 'Int32', 'UInt32', 'Int64', 'UInt64', + 'Counter', 'Addr', 'Tick', 'Percent', + 'Pair', 'RangeSize', 'AddrRange', 'MAX_ADDR', 'NULL', 'K', 'M', + 'NextEthernetAddr', + 'instantiate'] diff --git a/python/m5/convert.py b/python/m5/convert.py new file mode 100644 index 000000000..b3f34e4ab --- /dev/null +++ b/python/m5/convert.py @@ -0,0 +1,181 @@ +# metric prefixes +exa = 1.0e18 +peta = 1.0e15 +tera = 1.0e12 +giga = 1.0e9 +mega = 1.0e6 +kilo = 1.0e3 + +milli = 1.0e-3 +micro = 1.0e-6 +nano = 1.0e-9 +pico = 1.0e-12 +femto = 1.0e-15 +atto = 1.0e-18 + +# power of 2 prefixes +kibi = 1024 +mebi = kibi * 1024 +gibi = mebi * 1024 +tebi = gibi * 1024 +pebi = tebi * 1024 +exbi = pebi * 1024 + +# memory size configuration stuff +def to_integer(value): + if not isinstance(value, str): + result = int(value) + elif value.endswith('Ei'): + result = int(value[:-2]) * exbi + elif value.endswith('Pi'): + result = int(value[:-2]) * pebi + elif value.endswith('Ti'): + result = int(value[:-2]) * tebi + elif value.endswith('Gi'): + result = int(value[:-2]) * gibi + elif value.endswith('Mi'): + result = int(value[:-2]) * mebi + elif value.endswith('ki'): + result = int(value[:-2]) * kibi + elif value.endswith('E'): + result = int(value[:-1]) * exa + elif value.endswith('P'): + result = int(value[:-1]) * peta + elif value.endswith('T'): + result = int(value[:-1]) * tera + elif value.endswith('G'): + result = int(value[:-1]) * giga + elif value.endswith('M'): + result = int(value[:-1]) * mega + elif value.endswith('k'): + result = int(value[:-1]) * kilo + elif value.endswith('m'): + result = int(value[:-1]) * milli + elif value.endswith('u'): + result = int(value[:-1]) * micro + elif value.endswith('n'): + result = int(value[:-1]) * nano + elif value.endswith('p'): + result = int(value[:-1]) * pico + elif value.endswith('f'): + result = int(value[:-1]) * femto + else: + result = int(value) + + return result + +def to_bool(val): + t = type(val) + if t == bool: + return val + + if t == None: + return False + + if t == int or t == long: + return bool(val) + + if t == str: + val = val.lower() + if val == "true" or val == "t" or val == "yes" or val == "y": + return True + elif val == "false" or val == "f" or val == "no" or val == "n": + return False + + return to_integer(val) != 0 + +def to_frequency(value): + if not isinstance(value, str): + result = float(value) + elif value.endswith('THz'): + result = float(value[:-3]) * tera + elif value.endswith('GHz'): + result = float(value[:-3]) * giga + elif value.endswith('MHz'): + result = float(value[:-3]) * mega + elif value.endswith('kHz'): + result = float(value[:-3]) * kilo + elif value.endswith('Hz'): + result = float(value[:-2]) + else: + result = float(value) + + return result + +def to_latency(value): + if not isinstance(value, str): + result = float(value) + elif value.endswith('c'): + result = float(value[:-1]) + elif value.endswith('ps'): + result = float(value[:-2]) * pico + elif value.endswith('ns'): + result = float(value[:-2]) * nano + elif value.endswith('us'): + result = float(value[:-2]) * micro + elif value.endswith('ms'): + result = float(value[:-2]) * milli + elif value.endswith('s'): + result = float(value[:-1]) + else: + result = float(value) + + return result; + +def to_network_bandwidth(value): + if not isinstance(value, str): + result = float(value) + elif value.endswith('Tbps'): + result = float(value[:-3]) * tera + elif value.endswith('Gbps'): + result = float(value[:-3]) * giga + elif value.endswith('Mbps'): + result = float(value[:-3]) * mega + elif value.endswith('kbps'): + result = float(value[:-3]) * kilo + elif value.endswith('bps'): + result = float(value[:-2]) + else: + result = float(value) + + return result + +def to_memory_bandwidth(value): + if not isinstance(value, str): + result = int(value) + elif value.endswith('PB/s'): + result = int(value[:-4]) * pebi + elif value.endswith('TB/s'): + result = int(value[:-4]) * tebi + elif value.endswith('GB/s'): + result = int(value[:-4]) * gibi + elif value.endswith('MB/s'): + result = int(value[:-4]) * mebi + elif value.endswith('kB/s'): + result = int(value[:-4]) * kibi + elif value.endswith('B/s'): + result = int(value[:-3]) + else: + result = int(value) + + return result + +def to_memory_size(value): + if not isinstance(value, str): + result = int(value) + elif value.endswith('PB'): + result = int(value[:-2]) * pebi + elif value.endswith('TB'): + result = int(value[:-2]) * tebi + elif value.endswith('GB'): + result = int(value[:-2]) * gibi + elif value.endswith('MB'): + result = int(value[:-2]) * mebi + elif value.endswith('kB'): + result = int(value[:-2]) * kibi + elif value.endswith('B'): + result = int(value[:-1]) + else: + result = int(value) + + return result diff --git a/objects/AlphaConsole.mpy b/python/m5/objects/AlphaConsole.mpy index 79918a01e..79918a01e 100644 --- a/objects/AlphaConsole.mpy +++ b/python/m5/objects/AlphaConsole.mpy diff --git a/objects/AlphaTLB.mpy b/python/m5/objects/AlphaTLB.mpy index 8e7cd62cc..8e7cd62cc 100644 --- a/objects/AlphaTLB.mpy +++ b/python/m5/objects/AlphaTLB.mpy diff --git a/objects/BadDevice.mpy b/python/m5/objects/BadDevice.mpy index 35a12e0bf..35a12e0bf 100644 --- a/objects/BadDevice.mpy +++ b/python/m5/objects/BadDevice.mpy diff --git a/objects/BaseCPU.mpy b/python/m5/objects/BaseCPU.mpy index 484fcccd6..5d8305d88 100644 --- a/objects/BaseCPU.mpy +++ b/python/m5/objects/BaseCPU.mpy @@ -4,7 +4,7 @@ simobj BaseCPU(SimObject): icache = Param.BaseMem(NULL, "L1 instruction cache object") dcache = Param.BaseMem(NULL, "L1 data cache object") - if Bool._convert(env.get('FULL_SYSTEM', 'False')): + if build_env['FULL_SYSTEM']: dtb = Param.AlphaDTB("Data TLB") itb = Param.AlphaITB("Instruction TLB") mem = Param.FunctionalMemory("memory") diff --git a/objects/BaseCache.mpy b/python/m5/objects/BaseCache.mpy index 98a422e30..98a422e30 100644 --- a/objects/BaseCache.mpy +++ b/python/m5/objects/BaseCache.mpy diff --git a/objects/BaseSystem.mpy b/python/m5/objects/BaseSystem.mpy index 1cbdf4e99..1cbdf4e99 100644 --- a/objects/BaseSystem.mpy +++ b/python/m5/objects/BaseSystem.mpy diff --git a/objects/Bus.mpy b/python/m5/objects/Bus.mpy index 025d69785..025d69785 100644 --- a/objects/Bus.mpy +++ b/python/m5/objects/Bus.mpy diff --git a/objects/CoherenceProtocol.mpy b/python/m5/objects/CoherenceProtocol.mpy index f3b0026b7..f3b0026b7 100644 --- a/objects/CoherenceProtocol.mpy +++ b/python/m5/objects/CoherenceProtocol.mpy diff --git a/objects/Device.mpy b/python/m5/objects/Device.mpy index 47f8db1cb..47f8db1cb 100644 --- a/objects/Device.mpy +++ b/python/m5/objects/Device.mpy diff --git a/objects/DiskImage.mpy b/python/m5/objects/DiskImage.mpy index 80ef7b072..80ef7b072 100644 --- a/objects/DiskImage.mpy +++ b/python/m5/objects/DiskImage.mpy diff --git a/objects/Ethernet.mpy b/python/m5/objects/Ethernet.mpy index 088df4b93..088df4b93 100644 --- a/objects/Ethernet.mpy +++ b/python/m5/objects/Ethernet.mpy diff --git a/objects/Ide.mpy b/python/m5/objects/Ide.mpy index ce760ad96..ce760ad96 100644 --- a/objects/Ide.mpy +++ b/python/m5/objects/Ide.mpy diff --git a/objects/IntrControl.mpy b/python/m5/objects/IntrControl.mpy index 1ef5a17ee..1ef5a17ee 100644 --- a/objects/IntrControl.mpy +++ b/python/m5/objects/IntrControl.mpy diff --git a/objects/MemTest.mpy b/python/m5/objects/MemTest.mpy index af14ed9c3..af14ed9c3 100644 --- a/objects/MemTest.mpy +++ b/python/m5/objects/MemTest.mpy diff --git a/objects/Pci.mpy b/python/m5/objects/Pci.mpy index caa3c52ff..4daa902ab 100644 --- a/objects/Pci.mpy +++ b/python/m5/objects/Pci.mpy @@ -1,8 +1,7 @@ from Device import FooPioDevice, DmaDevice -simobj PciConfigData(FooPioDevice): +simobj PciConfigData(SimObject): type = 'PciConfigData' - addr = 0xffffffffffffffffL VendorID = Param.UInt16("Vendor ID") DeviceID = Param.UInt16("Device ID") Command = Param.UInt16(0, "Command") @@ -44,9 +43,9 @@ simobj PciConfigAll(FooPioDevice): simobj PciDevice(DmaDevice): type = 'PciDevice' abstract = True + addr = 0xffffffff pci_bus = Param.Int("PCI bus") pci_dev = Param.Int("PCI device number") pci_func = Param.Int("PCI function code") configdata = Param.PciConfigData(Super, "PCI Config data") configspace = Param.PciConfigAll(Super, "PCI Configspace") - addr = 0xffffffffffffffffL diff --git a/objects/PhysicalMemory.mpy b/python/m5/objects/PhysicalMemory.mpy index d1e4ad4b4..d1e4ad4b4 100644 --- a/objects/PhysicalMemory.mpy +++ b/python/m5/objects/PhysicalMemory.mpy diff --git a/objects/Platform.mpy b/python/m5/objects/Platform.mpy index d0510eaf8..d0510eaf8 100644 --- a/objects/Platform.mpy +++ b/python/m5/objects/Platform.mpy diff --git a/objects/Process.mpy b/python/m5/objects/Process.mpy index 6a91c09c2..6a91c09c2 100644 --- a/objects/Process.mpy +++ b/python/m5/objects/Process.mpy diff --git a/objects/Repl.mpy b/python/m5/objects/Repl.mpy index fff5a2a02..fff5a2a02 100644 --- a/objects/Repl.mpy +++ b/python/m5/objects/Repl.mpy diff --git a/objects/Root.mpy b/python/m5/objects/Root.mpy index 0e531054b..0e531054b 100644 --- a/objects/Root.mpy +++ b/python/m5/objects/Root.mpy diff --git a/objects/SimConsole.mpy b/python/m5/objects/SimConsole.mpy index fb74f1775..fb74f1775 100644 --- a/objects/SimConsole.mpy +++ b/python/m5/objects/SimConsole.mpy diff --git a/objects/SimpleDisk.mpy b/python/m5/objects/SimpleDisk.mpy index c4dd5435b..c4dd5435b 100644 --- a/objects/SimpleDisk.mpy +++ b/python/m5/objects/SimpleDisk.mpy diff --git a/objects/Tsunami.mpy b/python/m5/objects/Tsunami.mpy index cfe23977e..cfe23977e 100644 --- a/objects/Tsunami.mpy +++ b/python/m5/objects/Tsunami.mpy diff --git a/objects/Uart.mpy b/python/m5/objects/Uart.mpy index 76ee8805f..76ee8805f 100644 --- a/objects/Uart.mpy +++ b/python/m5/objects/Uart.mpy diff --git a/python/m5/smartdict.py b/python/m5/smartdict.py new file mode 100644 index 000000000..4ea8210d3 --- /dev/null +++ b/python/m5/smartdict.py @@ -0,0 +1,102 @@ +# 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))) + def __long__(self): + return long(to_integer(str(self))) + def __float__(self): + return float(to_integer(str(self))) + def __nonzero__(self): + return to_bool(str(self)) + def convert(self, other): + t = type(other) + if t == bool: + return bool(self) + if t == int: + return int(self) + if t == long: + return long(self) + if t == float: + return float(self) + return str(self) + def __lt__(self, other): + return self.convert(other) < other + def __le__(self, other): + return self.convert(other) <= other + def __eq__(self, other): + return self.convert(other) == other + def __ne__(self, other): + return self.convert(other) != other + def __gt__(self, other): + return self.convert(other) > other + def __ge__(self, other): + return self.convert(other) >= other + + def __add__(self, other): + return self.convert(other) + other + def __sub__(self, other): + return self.convert(other) - other + def __mul__(self, other): + return self.convert(other) * other + def __div__(self, other): + return self.convert(other) / other + def __truediv__(self, other): + return self.convert(other) / other + + def __radd__(self, other): + return other + self.convert(other) + def __rsub__(self, other): + return other - self.convert(other) + def __rmul__(self, other): + return other * self.convert(other) + def __rdiv__(self, other): + return other / self.convert(other) + def __rtruediv__(self, other): + return other / self.convert(other) + + + def __getitem__(self, key): + return self.Proxy(dict.get(self, key, 'False')) + + def __setitem__(self, key, item): + dict.__setitem__(self, key, str(item)) + + def values(self): + return [ self.Proxy(v) for v in dict.values(self) ] + + def itervalues(self): + for value in dict.itervalues(self): + yield self.Proxy(value) + + def items(self): + return [ (k, self.Proxy(v)) for k,v in dict.items(self) ] + + def iteritems(self): + for key,value in dict.iteritems(self): + yield key, self.Proxy(value) + + def get(self, key, default='False'): + return self.Proxy(dict.get(self, key, str(default))) + + def setdefault(self, key, default='False'): + return self.Proxy(dict.setdefault(self, key, str(default))) + diff --git a/sim/main.cc b/sim/main.cc index c15d24453..ee59cb83b 100644 --- a/sim/main.cc +++ b/sim/main.cc @@ -51,6 +51,7 @@ #include "base/time.hh" #include "cpu/base_cpu.hh" #include "cpu/full_cpu/smt.hh" +#include "python/pyconfig.hh" #include "sim/async.hh" #include "sim/builder.hh" #include "sim/configfile.hh" @@ -61,7 +62,6 @@ #include "sim/stat_control.hh" #include "sim/stats.hh" #include "sim/universe.hh" -#include "sim/pyconfig/pyconfig.hh" using namespace std; diff --git a/sim/sim_object.hh b/sim/sim_object.hh index f4b316ebb..b8a3090ad 100644 --- a/sim/sim_object.hh +++ b/sim/sim_object.hh @@ -60,6 +60,10 @@ class SimObject : public Serializable, protected StartupCallback static SimObjectList simObjectList; public: + +// for Params struct +#include "simobj/param/SimObject.hh" + SimObject(const std::string &_name); virtual ~SimObject() {} diff --git a/test/genini.py b/test/genini.py index f4d1575db..b8eda5d46 100755 --- a/test/genini.py +++ b/test/genini.py @@ -30,12 +30,12 @@ from os.path import join as joinpath, realpath mypath = sys.path[0] sys.path.append(joinpath(mypath, '..')) +sys.path.append(joinpath(mypath, '../python')) sys.path.append(joinpath(mypath, '../util/pbs')) -sys.path.append(joinpath(mypath, '../sim/pyconfig')) -from importer import AddToPath, LoadMpyFile +pathlist = [ '.' ] -AddToPath('.') +m5_build_env = {} try: opts, args = getopt.getopt(sys.argv[1:], '-E:I:') @@ -44,17 +44,21 @@ 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': - AddToPath(arg) + pathlist.append(arg) except getopt.GetoptError: sys.exit('Improper Usage') -from m5config import * +from m5 import * + +for path in pathlist: + AddToPath(path) for arg in args: LoadMpyFile(arg) |