diff options
-rw-r--r-- | arch/alpha/alpha_tru64_process.cc | 4 | ||||
-rw-r--r-- | configs/splash2/run.mpy | 4 | ||||
-rw-r--r-- | python/m5/__init__.py | 8 | ||||
-rw-r--r-- | python/m5/config.py | 221 | ||||
-rw-r--r-- | python/m5/convert.py | 16 | ||||
-rw-r--r-- | python/m5/multidict.py | 158 | ||||
-rw-r--r-- | python/m5/smartdict.py | 8 | ||||
-rw-r--r-- | sim/process.cc | 1 | ||||
-rw-r--r-- | sim/process.hh | 9 | ||||
-rw-r--r-- | sim/syscall_emul.hh | 4 |
10 files changed, 273 insertions, 160 deletions
diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc index 1722b658e..a211e0ae8 100644 --- a/arch/alpha/alpha_tru64_process.cc +++ b/arch/alpha/alpha_tru64_process.cc @@ -877,6 +877,10 @@ class Tru64 { *configptr_ptr = config_addr; configptr_ptr.copyOut(xc->mem); + // Register this as a valid address range with the process + process->nxm_start = base_addr; + process->nxm_end = cur_addr; + return 0; } diff --git a/configs/splash2/run.mpy b/configs/splash2/run.mpy index a19dcdc93..800bff6f8 100644 --- a/configs/splash2/run.mpy +++ b/configs/splash2/run.mpy @@ -5,12 +5,12 @@ if 'SYSTEM' not in env: if env['SYSTEM'] == 'Simple': from SimpleConfig import * - BaseCPU.workload = Super.workload + BaseCPU.workload = parent.workload SimpleStandAlone.cpu = [ CPU() for i in xrange(int(env['NP'])) ] root = SimpleStandAlone elif env['SYSTEM'] == 'Detailed': from DetailedConfig import * - BaseCPU.workload = Super.workload + BaseCPU.workload = parent.workload DetailedStandAlone.cpu = [ DetailedCPU() for i in xrange(int(env['NP'])) ] root = DetailedStandAlone else: diff --git a/python/m5/__init__.py b/python/m5/__init__.py index 16f48dba3..27bd91749 100644 --- a/python/m5/__init__.py +++ b/python/m5/__init__.py @@ -1,14 +1,14 @@ 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) +# 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 + # find the m5 compile options: must be specified as a dict in # __main__.m5_build_env. import __main__ diff --git a/python/m5/config.py b/python/m5/config.py index e6ad5a0ba..f696adc79 100644 --- a/python/m5/config.py +++ b/python/m5/config.py @@ -27,7 +27,9 @@ from __future__ import generators import os, re, sys, types, inspect +from m5 import panic from convert import * +from multidict import multidict noDot = False try: @@ -150,8 +152,11 @@ class Proxy(object): self._multiplier = None def __getattr__(self, attr): + # python uses __bases__ internally for inheritance if attr == '__bases__': return super(Proxy, self).__getattr__(self, attr) + if (self._path == None): + panic("Can't add attributes to 'any' proxy") self._path.append((attr,None)) return self @@ -197,12 +202,14 @@ class Proxy(object): raise AttributeError, \ 'Parent of %s type %s not found at path %s' \ % (base.name, ptype, self._path) - found, done = obj.find(ptype, self._path) - if isinstance(found, Proxy): - done = False + + result, done = obj.find(ptype, self._path) obj = obj.parent - return self._mulcheck(found) + if isinstance(result, Proxy): + result = result.unproxy(obj, ptype) + + return self._mulcheck(result) def getindex(obj, index): if index == None: @@ -320,17 +327,20 @@ class MetaConfigNode(type): super(MetaConfigNode, cls).__init__(name, bases, dict) # initialize required attributes - cls._params = {} - cls._values = {} + cls._params = multidict() + cls._values = multidict() cls._param_types = {} cls._bases = [c for c in cls.__mro__ if isConfigNode(c)] cls._anon_subclass_counter = 0 - # 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 base in cls._bases: - for key,val in base._values.iteritems(): + # We don't support multiple inheritence. If you want to, you + # must fix multidict to deal with it properly. + cnbase = [ base for base in bases if isConfigNode(base) ] + if len(cnbase) == 1: + # 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 cnbase[0]._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 @@ -340,10 +350,17 @@ class MetaConfigNode(type): if isConfigNode(val): cls._values[key] = val() - elif isSimObjSequence(val): + elif isSimObjSequence(val) and len(val): cls._values[key] = [ v() for v in val ] - elif isNullPointer(val): - cls._values[key] = val + + cls._params.parent = cnbase[0]._params + cls._values.parent = cnbase[0]._values + + elif len(cnbase) > 1: + panic("""\ +The config hierarchy only supports single inheritence of SimObject +classes. You're trying to derive from: +%s""" % str(cnbase)) # process param types from _init_dict, as these may be needed # by param descriptions also in _init_dict @@ -357,9 +374,7 @@ class MetaConfigNode(type): 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) + cls._new_param(key, val) # init-time-only keywords elif cls.init_keywords.has_key(key): @@ -382,99 +397,6 @@ class MetaConfigNode(type): else: setattr(cls, key, val) - - def _isvalue(cls, name): - for c in cls._bases: - if c._params.has_key(name): - return True - - for c in cls._bases: - if c._values.has_key(name): - return True - - return False - - # generator that iterates across all parameters for this class and - # all classes it inherits from - def _getparams(cls): - params = {} - for c in cls._bases: - for p,v in c._params.iteritems(): - if not params.has_key(p): - params[p] = v - return params - - # Lookup a parameter description by name in the given class. - def _getparam(cls, name, default = AttributeError): - for c in cls._bases: - if c._params.has_key(name): - return c._params[name] - if isSubClass(default, Exception): - raise default, \ - "object '%s' has no attribute '%s'" % (cls.__name__, name) - else: - return default - - def _hasvalue(cls, name): - for c in cls._bases: - if c._values.has_key(name): - return True - - return False - - def _getvalues(cls): - values = {} - for i,c in enumerate(cls._bases): - for p,v in c._values.iteritems(): - if not values.has_key(p): - values[p] = v - for p,v in c._params.iteritems(): - if not values.has_key(p) and hasattr(v, 'default'): - try: - v.valid(v.default) - except TypeError: - panic("Invalid default %s for param %s in node %s" - % (v.default,p,cls.__name__)) - v = v.default - cls._setvalue(p, v) - values[p] = v - - return values - - def _getvalue(cls, name, default = AttributeError): - value = None - for c in cls._bases: - if c._values.has_key(name): - value = c._values[name] - break - if value is not None: - return value - - param = cls._getparam(name, None) - if param is not None and hasattr(param, 'default'): - param.valid(param.default) - value = param.default - cls._setvalue(name, value) - return value - - if isSubClass(default, Exception): - raise default, 'value for %s not found' % name - else: - return default - - def _setvalue(cls, name, value): - cls._values[name] = value - - def __getattr__(cls, attr): - if cls._isvalue(attr): - return Value(cls, attr) - - if attr == '_cpp_param_decl' and hasattr(cls, 'type'): - return cls.type + '*' - - raise AttributeError, \ - "object '%s' has no attribute '%s'" % (cls.__name__, attr) - def _set_keyword(cls, keyword, val, kwtype): if not isinstance(val, kwtype): raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ @@ -483,6 +405,13 @@ class MetaConfigNode(type): val = classmethod(val) type.__setattr__(cls, keyword, val) + def _new_param(cls, name, value): + cls._params[name] = value + if hasattr(value, 'default'): + cls._values[name] = value.default + # try to resolve local param types in local param_types scope + value.maybe_resolve_type(cls._param_types) + # Set attribute (called on foo.attr = value when foo is an # instance of class cls). def __setattr__(cls, attr, value): @@ -496,23 +425,33 @@ class MetaConfigNode(type): return # must be SimObject param - param = cls._getparam(attr, None) + param = cls._params.get(attr, None) if param: # It's ok: set attribute by delegating to 'object' class. # Note the use of param.make_value() to verify/canonicalize # the assigned value try: param.valid(value) - except: - panic("Error setting param %s.%s to %s\n" % \ - (cls.__name__, attr, value)) - cls._setvalue(attr, value) + except Exception, e: + panic("Exception: %s\nError setting param %s.%s to %s\n" % \ + (e, cls.__name__, attr, value)) + cls._values[attr] = value elif isConfigNode(value) or isSimObjSequence(value): - cls._setvalue(attr, value) + cls._values[attr] = value else: raise AttributeError, \ "Class %s has no parameter %s" % (cls.__name__, attr) + def __getattr__(cls, attr): + if cls._params.has_key(attr) or cls._values.has_key(attr): + return Value(cls, attr) + + if attr == '_cpp_param_decl' and hasattr(cls, 'type'): + return cls.type + '*' + + raise AttributeError, \ + "object '%s' has no attribute '%s'" % (cls.__name__, attr) + def add_child(cls, instance, name, child): if isNullPointer(child) or instance.top_child_names.has_key(name): return @@ -542,7 +481,7 @@ class MetaConfigNode(type): if hasattr(cls, 'check'): cls.check() - for key,value in cls._getvalues().iteritems(): + for key,value in cls._values.iteritems(): if isConfigNode(value): cls.add_child(instance, key, value) if isinstance(value, (list, tuple)): @@ -550,11 +489,10 @@ class MetaConfigNode(type): if len(vals): cls.add_child(instance, key, vals) - for pname,param in cls._getparams().iteritems(): - try: - value = cls._getvalue(pname) - except: - panic('Error getting %s' % pname) + for pname,param in cls._params.iteritems(): + value = cls._values.get(pname, None) + if value is None: + panic('Error getting %s from %s' % (pname, name)) try: if isConfigNode(value): @@ -571,10 +509,9 @@ class MetaConfigNode(type): p = NodeParam(pname, param, value) instance.params.append(p) instance.param_names[pname] = p - except: - print 'Exception while evaluating %s.%s' % \ - (instance.path, pname) - raise + except Exception, e: + raise e.__class__, 'Exception while evaluating %s.%s\n%s' % \ + (instance.path, pname, e) return instance @@ -613,7 +550,7 @@ class ConfigNode(object): cls._anon_subclass_counter += 1 return cls.__metaclass__(name, (cls, ), kwargs) -class ParamContext(ConfigNode): +class ParamContext(ConfigNode,ParamType): pass class MetaSimObject(MetaConfigNode): @@ -755,9 +692,9 @@ class Node(object): param.value = [ self.unproxy(pv, ptype) for pv in pval ] else: param.value = self.unproxy(pval, ptype) - except: - print 'Error while fixing up %s:%s' % (self.path, param.name) - raise + except Exception, e: + raise e.__class__, 'Error while fixing up %s:%s\n%s' % \ + (self.path, param.name, e) for child in self.children: assert(child != self) @@ -776,9 +713,8 @@ class Node(object): # before cpu0). Changing ordering can also influence timing # in the current memory system, as caches get added to a bus # in different orders which affects their priority in the - # case of simulataneous requests. We should uncomment the - # following line once we take care of that issue. - # self.children.sort(lambda x,y: cmp(x.name, y.name)) + # case of simulataneous requests. + self.children.sort(lambda x,y: cmp(x.name, y.name)) children = [ c.name for c in self.children if not c.paramcontext] print 'children =', ' '.join(children) @@ -790,9 +726,9 @@ class Node(object): value = param.convert(param.value) string = param.string(value) - except: - print 'exception in %s:%s' % (self.path, param.name) - raise + except Exception, e: + raise e.__class__, 'exception in %s:%s\n%s' % \ + (self.path, param.name, e) print '%s = %s' % (param.name, string) @@ -825,8 +761,9 @@ class Node(object): value = param.convert(param.value) string = param.string(value) - except: - print 'exception in %s:%s' % (self.name, param.name) + except Exception, e: + raise e.__class__, 'exception in %s:%s\n%s' % \ + (self.name, param.name, e) raise if isConfigNode(param.ptype) and string != "Null": simobjs.append(string) @@ -835,7 +772,8 @@ class Node(object): for so in simobjs: label += "|<%s> %s" % (so, so) - dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, tailport="w")) + dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, + tailport="w")) label += '}' dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label)) @@ -875,7 +813,7 @@ class Value(object): super(Value, self).__setattr__('obj', obj) def _getattr(self): - return self.obj._getvalue(self.attr) + return self.obj._values.get(self.attr) def __setattr__(self, attr, value): setattr(self._getattr(), attr, value) @@ -895,6 +833,9 @@ class Value(object): def __str__(self): return str(self._getattr()) + def __len__(self): + return len(self._getattr()) + # Regular parameter. class _Param(object): def __init__(self, ptype, *args, **kwargs): diff --git a/python/m5/convert.py b/python/m5/convert.py index b3f34e4ab..2ebe93889 100644 --- a/python/m5/convert.py +++ b/python/m5/convert.py @@ -22,7 +22,7 @@ pebi = tebi * 1024 exbi = pebi * 1024 # memory size configuration stuff -def to_integer(value): +def toInteger(value): if not isinstance(value, str): result = int(value) elif value.endswith('Ei'): @@ -64,7 +64,7 @@ def to_integer(value): return result -def to_bool(val): +def toBool(val): t = type(val) if t == bool: return val @@ -82,9 +82,9 @@ def to_bool(val): elif val == "false" or val == "f" or val == "no" or val == "n": return False - return to_integer(val) != 0 + return toInteger(val) != 0 -def to_frequency(value): +def toFrequency(value): if not isinstance(value, str): result = float(value) elif value.endswith('THz'): @@ -102,7 +102,7 @@ def to_frequency(value): return result -def to_latency(value): +def toLatency(value): if not isinstance(value, str): result = float(value) elif value.endswith('c'): @@ -122,7 +122,7 @@ def to_latency(value): return result; -def to_network_bandwidth(value): +def toNetworkBandwidth(value): if not isinstance(value, str): result = float(value) elif value.endswith('Tbps'): @@ -140,7 +140,7 @@ def to_network_bandwidth(value): return result -def to_memory_bandwidth(value): +def toMemoryBandwidth(value): if not isinstance(value, str): result = int(value) elif value.endswith('PB/s'): @@ -160,7 +160,7 @@ def to_memory_bandwidth(value): return result -def to_memory_size(value): +def toMemorySize(value): if not isinstance(value, str): result = int(value) elif value.endswith('PB'): diff --git a/python/m5/multidict.py b/python/m5/multidict.py new file mode 100644 index 000000000..d0c27fa8e --- /dev/null +++ b/python/m5/multidict.py @@ -0,0 +1,158 @@ +__all__ = [ 'multidict' ] + +class multidict(object): + __nodefault = object() + def __init__(self, parent = {}, **kwargs): + self.dict = dict(**kwargs) + self.parent = parent + self.deleted = {} + + def __str__(self): + return str(dict(self.items())) + + def __repr__(self): + return `dict(self.items())` + + def __contains__(self, key): + return self.dict.has_key(key) or self.parent.has_key(key) + + def __delitem__(self, key): + try: + del self.dict[key] + except KeyError, e: + if key in self.parent: + self.deleted[key] = True + else: + raise KeyError, e + + def __setitem__(self, key, value): + self.deleted.pop(key, False) + self.dict[key] = value + + def __getitem__(self, key): + try: + return self.dict[key] + except KeyError, e: + if not self.deleted.get(key, False) and key in self.parent: + return self.parent[key] + else: + raise KeyError, e + + def __len__(self): + return len(self.dict) + len(self.parent) + + def next(self): + for key,value in self.dict.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: + yield key,value + + def has_key(self, key): + return key in self + + def iteritems(self): + for item in self.next(): + yield item + + def items(self): + return [ item for item in self.next() ] + + def iterkeys(self): + for key,value in self.next(): + yield key + + def keys(self): + return [ key for key,value in self.next() ] + + def itervalues(self): + for key,value in self.next(): + yield value + + def values(self): + return [ value for key,value in self.next() ] + + def get(self, key, default=__nodefault): + try: + return self[key] + except KeyError, e: + if default != self.__nodefault: + return default + else: + raise KeyError, e + + def setdefault(self, key, default): + try: + return self[key] + except KeyError: + self.deleted.pop(key, False) + self.dict[key] = default + return default + + def _dump(self): + print 'multidict dump' + node = self + while isinstance(node, multidict): + print ' ', node.dict + node = node.parent + + def _dumpkey(self, key): + values = [] + node = self + while isinstance(node, multidict): + if key in node.dict: + values.append(node.dict[key]) + node = node.parent + print key, values + +if __name__ == '__main__': + test1 = multidict() + test2 = multidict(test1) + test3 = multidict(test2) + test4 = multidict(test3) + + test1['a'] = 'test1_a' + test1['b'] = 'test1_b' + test1['c'] = 'test1_c' + test1['d'] = 'test1_d' + test1['e'] = 'test1_e' + + test2['a'] = 'test2_a' + del test2['b'] + test2['c'] = 'test2_c' + del test1['a'] + + test2.setdefault('f', multidict) + + print 'test1>', test1.items() + print 'test2>', test2.items() + #print test1['a'] + print test1['b'] + print test1['c'] + print test1['d'] + print test1['e'] + + print test2['a'] + #print test2['b'] + print test2['c'] + print test2['d'] + print test2['e'] + + for key in test2.iterkeys(): + print key + + test2.get('g', 'foo') + #test2.get('b') + test2.get('b', 'bar') + test2.setdefault('b', 'blah') + print test1 + print test2 + print `test2` + + print len(test2) + + test3['a'] = [ 0, 1, 2, 3 ] + + print test4 diff --git a/python/m5/smartdict.py b/python/m5/smartdict.py index 1ba5d8410..0dbcc50b0 100644 --- a/python/m5/smartdict.py +++ b/python/m5/smartdict.py @@ -20,13 +20,13 @@ class SmartDict(dict): class Proxy(str): def __int__(self): - return int(to_integer(str(self))) + return int(toInteger(str(self))) def __long__(self): - return long(to_integer(str(self))) + return long(toInteger(str(self))) def __float__(self): - return float(to_integer(str(self))) + return float(toInteger(str(self))) def __nonzero__(self): - return to_bool(str(self)) + return toBool(str(self)) def convert(self, other): t = type(other) if t == bool: diff --git a/sim/process.cc b/sim/process.cc index 7111e8733..c18b31da7 100644 --- a/sim/process.cc +++ b/sim/process.cc @@ -89,6 +89,7 @@ Process::Process(const string &nm, } mmap_start = mmap_end = 0; + nxm_start = nxm_end = 0; // other parameters will be initialized when the program is loaded } diff --git a/sim/process.hh b/sim/process.hh index 1ab43cd62..51d7639ac 100644 --- a/sim/process.hh +++ b/sim/process.hh @@ -97,6 +97,10 @@ class Process : public SimObject Addr mmap_start; Addr mmap_end; + // Base of region for nxm data + Addr nxm_start; + Addr nxm_end; + std::string prog_fname; // file name Addr prog_entry; // entry point (initial PC) @@ -159,9 +163,10 @@ class Process : public SimObject bool validDataAddr(Addr addr) { return ((data_base <= addr && addr < brk_point) || - ((stack_base - 16*1024*1024) <= addr && addr < stack_base) || + (next_thread_stack_base <= addr && addr < stack_base) || (text_base <= addr && addr < (text_base + text_size)) || - (mmap_start <= addr && addr < mmap_end)); + (mmap_start <= addr && addr < mmap_end) || + (nxm_start <= addr && addr < nxm_end)); } virtual void syscall(ExecContext *xc) = 0; diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh index 51a075a28..69c17c330 100644 --- a/sim/syscall_emul.hh +++ b/sim/syscall_emul.hh @@ -412,6 +412,10 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) // user didn't give an address... pick one from our "mmap region" start = p->mmap_end; p->mmap_end += RoundUp<Addr>(length, VMPageSize); + if (p->nxm_start != 0) { + //If we have an nxm space, make sure we haven't colided + assert(p->mmap_end < p->nxm_start); + } } if (!(flags & OS::TGT_MAP_ANONYMOUS)) { |