diff options
-rw-r--r-- | SConscript | 9 | ||||
-rw-r--r-- | arch/alpha/alpha_tru64_process.cc | 2 | ||||
-rw-r--r-- | build/SConstruct | 5 | ||||
-rw-r--r-- | configs/splash2/run.mpy | 50 | ||||
-rw-r--r-- | cpu/base_cpu.cc | 3 | ||||
-rw-r--r-- | cpu/simple_cpu/simple_cpu.cc | 29 | ||||
-rw-r--r-- | dev/pciconfigall.cc | 5 | ||||
-rw-r--r-- | dev/pcidev.cc | 10 | ||||
-rw-r--r-- | objects/AlphaConsole.mpy | 9 | ||||
-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) | 412 | ||||
-rw-r--r-- | python/m5/convert.py | 181 | ||||
-rw-r--r-- | python/m5/objects/AlphaConsole.mpy | 9 | ||||
-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) | 4 | ||||
-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) | 4 | ||||
-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) | 4 | ||||
-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) | 6 | ||||
-rw-r--r-- | python/m5/objects/Ide.mpy (renamed from objects/Ide.mpy) | 2 | ||||
-rw-r--r-- | python/m5/objects/IntrControl.mpy (renamed from objects/IntrControl.mpy) | 2 | ||||
-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) | 9 | ||||
-rw-r--r-- | python/m5/objects/PhysicalMemory.mpy (renamed from objects/PhysicalMemory.mpy) | 2 | ||||
-rw-r--r-- | python/m5/objects/Platform.mpy (renamed from objects/Platform.mpy) | 2 | ||||
-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) | 2 | ||||
-rw-r--r-- | python/m5/objects/SimpleDisk.mpy (renamed from objects/SimpleDisk.mpy) | 2 | ||||
-rw-r--r-- | python/m5/objects/Tsunami.mpy (renamed from objects/Tsunami.mpy) | 8 | ||||
-rw-r--r-- | python/m5/objects/Uart.mpy (renamed from objects/Uart.mpy) | 2 | ||||
-rw-r--r-- | python/m5/smartdict.py | 108 | ||||
-rw-r--r-- | sim/main.cc | 2 | ||||
-rw-r--r-- | sim/sim_object.cc | 19 | ||||
-rw-r--r-- | sim/sim_object.hh | 13 | ||||
-rwxr-xr-x | test/genini.py | 16 | ||||
-rw-r--r-- | util/stats/display.py | 2 | ||||
-rw-r--r-- | util/stats/info.py | 36 | ||||
-rw-r--r-- | util/stats/print.py | 2 |
45 files changed, 761 insertions, 286 deletions
diff --git a/SConscript b/SConscript index 19f84f913..3b3c871bc 100644 --- a/SConscript +++ b/SConscript @@ -183,6 +183,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 @@ -199,8 +202,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 @@ -376,8 +377,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/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc index 8660cc5c5..a211e0ae8 100644 --- a/arch/alpha/alpha_tru64_process.cc +++ b/arch/alpha/alpha_tru64_process.cc @@ -957,7 +957,7 @@ class Tru64 { Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index]; if (ssp->nxm_u.nxm_active != 0) - return Tru64::KERN_NOT_RECEIVER; + return (int) Tru64::KERN_NOT_RECEIVER; ssp->nxm_u.pth_id = attrp->pthid; ssp->nxm_u.nxm_active = uniq_val | 1; diff --git a/build/SConstruct b/build/SConstruct index 3d7db1db2..e33373243 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')) + ################################################### # @@ -289,7 +292,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/cpu/base_cpu.cc b/cpu/base_cpu.cc index 181b484e7..74e57baa6 100644 --- a/cpu/base_cpu.cc +++ b/cpu/base_cpu.cc @@ -197,8 +197,7 @@ BaseCPU::registerExecContexts() void BaseCPU::switchOut(SamplingCPU *sampler) { - // default: do nothing, signal done - sampler->signalSwitched(); + panic("This CPU doesn't support sampling!"); } void diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 86aeab7d7..6a95a52c2 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -393,13 +393,11 @@ template <class T> Fault SimpleCPU::read(Addr addr, T &data, unsigned flags) { - if (status() == DcacheMissStall) { + if (status() == DcacheMissStall || status() == DcacheMissSwitch) { Fault fault = xc->read(memReq,data); if (traceData) { traceData->setAddr(addr); - if (fault == No_Fault) - traceData->setData(data); } return fault; } @@ -428,21 +426,11 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) // do functional access fault = xc->read(memReq, data); - if (traceData) { - traceData->setAddr(addr); - if (fault == No_Fault) - traceData->setData(data); - } } } else if(fault == No_Fault) { // do functional access fault = xc->read(memReq, data); - if (traceData) { - traceData->setAddr(addr); - if (fault == No_Fault) - traceData->setData(data); - } } if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) @@ -498,11 +486,6 @@ template <class T> Fault SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { - if (traceData) { - traceData->setAddr(addr); - traceData->setData(data); - } - memReq->reset(addr, sizeof(T), flags); // translate to physical address @@ -605,6 +588,8 @@ SimpleCPU::processCacheCompletion() case DcacheMissStall: if (memReq->cmd.isRead()) { curStaticInst->execute(this,traceData); + if (traceData) + traceData->finalize(); } dcacheStallCycles += curTick - lastDcacheStall; _status = Running; @@ -613,6 +598,8 @@ SimpleCPU::processCacheCompletion() case DcacheMissSwitch: if (memReq->cmd.isRead()) { curStaticInst->execute(this,traceData); + if (traceData) + traceData->finalize(); } _status = SwitchedOut; sampler->signalSwitched(); @@ -785,8 +772,12 @@ SimpleCPU::tick() comLoadEventQueue[0]->serviceEvents(numLoad); } - if (traceData) + // If we have a dcache miss, then we can't finialize the instruction + // trace yet because we want to populate it with the data later + if (traceData && + !(status() == DcacheMissStall && memReq->cmd.isRead())) { traceData->finalize(); + } traceFunctions(xc->regs.pc); 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/objects/AlphaConsole.mpy b/objects/AlphaConsole.mpy deleted file mode 100644 index 79918a01e..000000000 --- a/objects/AlphaConsole.mpy +++ /dev/null @@ -1,9 +0,0 @@ -from Device import PioDevice - -simobj AlphaConsole(PioDevice): - type = 'AlphaConsole' - cpu = Param.BaseCPU(Super, "Processor") - disk = Param.SimpleDisk("Simple Disk") - num_cpus = Param.Int(1, "Number of CPUs") - sim_console = Param.SimConsole(Super, "The Simulator Console") - system = Param.BaseSystem(Super, "system object") 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..e6ad5a0ba 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,16 +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) - class Singleton(type): def __call__(cls, *args, **kwargs): if hasattr(cls, '_instance'): @@ -149,25 +139,90 @@ class Singleton(type): ##################################################################### class Proxy(object): - def __init__(self, path = ()): + def __init__(self, path): self._object = None - self._path = path + if path == 'any': + self._path = None + else: + # path is a list of (attr,index) tuples + self._path = [(path,None)] + self._index = None + self._multiplier = None def __getattr__(self, attr): - return Proxy(self._path + (attr, )) + if attr == '__bases__': + return super(Proxy, self).__getattr__(self, attr) + self._path.append((attr,None)) + return self def __setattr__(self, attr, value): if not attr.startswith('_'): raise AttributeError, 'cannot set attribute %s' % attr super(Proxy, self).__setattr__(attr, value) - def _convert(self): - obj = self._object - for attr in self._path: - obj = obj.__getattribute__(attr) + # support indexing on proxies (e.g., parent.cpu[0]) + def __getitem__(self, key): + if not isinstance(key, int): + raise TypeError, "Proxy object requires integer index" + if self._path == None: + raise IndexError, "Index applied to 'any' proxy" + # replace index portion of last path element with new index + self._path[-1] = (self._path[-1][0], key) + return self + + # support multiplying proxies by constants + def __mul__(self, other): + if not isinstance(other, int): + raise TypeError, "Proxy multiplier must be integer" + if self._multiplier == None: + self._multiplier = other + else: + # support chained multipliers + self._multiplier *= other + return self + + def _mulcheck(self, result): + if self._multiplier == None: + return result + if not isinstance(result, int): + raise TypeError, "Proxy with multiplier resolves to " \ + "non-integer value" + return result * self._multiplier + + def unproxy(self, base, ptype): + obj = base + done = False + while not done: + if obj is None: + 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 + obj = obj.parent + + return self._mulcheck(found) + + def getindex(obj, index): + if index == None: + return obj + try: + obj = obj[index] + except TypeError: + if index != 0: + raise + # if index is 0 and item is not subscriptable, just + # use item itself (so cpu[0] works on uniprocessors) return obj + getindex = staticmethod(getindex) -Super = Proxy() +class ProxyFactory(object): + def __getattr__(self, attr): + return Proxy(attr) + +# global object for handling parent.foo proxies +parent = ProxyFactory() def isSubClass(value, cls): try: @@ -188,7 +243,7 @@ def isSimObject(value): return False def isSimObjSequence(value): - if not issequence(value): + if not isinstance(value, (list, tuple)): return False for val in value: @@ -208,6 +263,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 +322,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 +345,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 +501,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) @@ -429,7 +517,7 @@ class MetaConfigNode(type): if isNullPointer(child) or instance.top_child_names.has_key(name): return - if issequence(child): + if isinstance(child, (list, tuple)): kid = [] for i,c in enumerate(child): n = '%s%d' % (name, i) @@ -449,7 +537,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() @@ -457,10 +545,10 @@ class MetaConfigNode(type): for key,value in cls._getvalues().iteritems(): if isConfigNode(value): cls.add_child(instance, key, value) - if issequence(value): - list = [ v for v in value if isConfigNode(v) ] - if len(list): - cls.add_child(instance, key, list) + if isinstance(value, (list, tuple)): + vals = [ v for v in value if isConfigNode(v) ] + if len(vals): + cls.add_child(instance, key, vals) for pname,param in cls._getparams().iteritems(): try: @@ -471,7 +559,7 @@ class MetaConfigNode(type): try: if isConfigNode(value): value = instance.child_objects[value] - elif issequence(value): + elif isinstance(value, (list, tuple)): v = [] for val in value: if isConfigNode(val): @@ -560,7 +648,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 +672,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 = {} @@ -617,50 +708,40 @@ class Node(object): if issubclass(child.realtype, realtype): if obj is not None: raise AttributeError, \ - 'Super matched more than one: %s %s' % \ + 'parent.any matched more than one: %s %s' % \ (obj.path, child.path) obj = child return obj, obj is not None try: obj = self - for node in path[:-1]: - obj = obj.child_names[node] + for (node,index) in path[:-1]: + if obj.child_names.has_key(node): + obj = obj.child_names[node] + else: + obj = obj.top_child_names[node] + obj = Proxy.getindex(obj, index) - last = path[-1] + (last,index) = path[-1] if obj.child_names.has_key(last): value = obj.child_names[last] - if issubclass(value.realtype, realtype): - return value, True + return Proxy.getindex(value, index), True + elif obj.top_child_names.has_key(last): + value = obj.top_child_names[last] + return Proxy.getindex(value, index), True elif obj.param_names.has_key(last): value = obj.param_names[last] realtype._convert(value.value) - return value.value, True + return Proxy.getindex(value.value, index), True except KeyError: pass return None, False - def unproxy(self, ptype, value): - if not isinstance(value, Proxy): - return value - - if value is None: - raise AttributeError, 'Error while fixing up %s' % self.path - - obj = self - done = False - while not done: - if obj is None: - raise AttributeError, \ - 'Parent of %s type %s not found at path %s' \ - % (self.name, ptype, value._path) - found, done = obj.find(ptype, value._path) - if isinstance(found, Proxy): - done = False - obj = obj.parent - - return found + def unproxy(self, param, ptype): + if not isinstance(param, Proxy): + return param + return param.unproxy(self, ptype) def fixup(self): self.all[self.path] = self @@ -670,10 +751,10 @@ class Node(object): pval = param.value try: - if issequence(pval): - param.value = [ self.unproxy(ptype, pv) for pv in pval ] + if isinstance(pval, (list, tuple)): + param.value = [ self.unproxy(pv, ptype) for pv in pval ] else: - param.value = self.unproxy(ptype, pval) + param.value = self.unproxy(pval, ptype) except: print 'Error while fixing up %s:%s' % (self.path, param.name) raise @@ -849,13 +930,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 +974,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, '' @@ -921,7 +1004,7 @@ class _VectorParam(_Param): if value == None: return True - if issequence(value): + if isinstance(value, (list, tuple)): for val in value: if not isinstance(val, Proxy): self.ptype._convert(val) @@ -934,7 +1017,7 @@ class _VectorParam(_Param): if value == None: return [] - if issequence(value): + if isinstance(value, (list, tuple)): # list: coerce each element into new list return [ self.ptype._convert(v) for v in value ] else: @@ -942,7 +1025,7 @@ class _VectorParam(_Param): return self.ptype._convert(value) def string(self, value): - if issequence(value): + if isinstance(value, (list, tuple)): return ' '.join([ self.ptype._string(v) for v in value]) else: return self.ptype._string(value) @@ -970,99 +1053,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 +1183,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 +1223,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 +1330,7 @@ class MetaEnum(type): return s # Base class for enum types. -class Enum(object): +class Enum(ParamType): __metaclass__ = MetaEnum vals = [] @@ -1257,8 +1350,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 +1363,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 +1383,19 @@ 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__ = ['ConfigNode', 'SimObject', 'ParamContext', 'Param', 'VectorParam', + 'parent', '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/python/m5/objects/AlphaConsole.mpy b/python/m5/objects/AlphaConsole.mpy new file mode 100644 index 000000000..63aea5b7d --- /dev/null +++ b/python/m5/objects/AlphaConsole.mpy @@ -0,0 +1,9 @@ +from Device import PioDevice + +simobj AlphaConsole(PioDevice): + type = 'AlphaConsole' + cpu = Param.BaseCPU(parent.any, "Processor") + disk = Param.SimpleDisk("Simple Disk") + num_cpus = Param.Int(1, "Number of CPUs") + sim_console = Param.SimConsole(parent.any, "The Simulator Console") + system = Param.BaseSystem(parent.any, "system object") 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..d84e30e53 100644 --- a/objects/BaseCPU.mpy +++ b/python/m5/objects/BaseCPU.mpy @@ -4,11 +4,11 @@ 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") - system = Param.BaseSystem(Super, "system object") + system = Param.BaseSystem(parent.any, "system object") else: workload = VectorParam.Process("processes to run") 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..450b6a58e 100644 --- a/objects/BaseSystem.mpy +++ b/python/m5/objects/BaseSystem.mpy @@ -1,8 +1,8 @@ simobj BaseSystem(SimObject): type = 'BaseSystem' abstract = True - memctrl = Param.MemoryController(Super, "memory controller") - physmem = Param.PhysicalMemory(Super, "phsyical memory") + memctrl = Param.MemoryController(parent.any, "memory controller") + physmem = Param.PhysicalMemory(parent.any, "phsyical memory") kernel = Param.String("file that contains the kernel code") console = Param.String("file that contains the console code") pal = Param.String("file that contains palcode") 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..a0d02a647 100644 --- a/objects/Device.mpy +++ b/python/m5/objects/Device.mpy @@ -14,7 +14,7 @@ simobj FooPioDevice(FunctionalMemory): type = 'PioDevice' abstract = True addr = Param.Addr("Device Address") - mmu = Param.MemoryController(Super, "Memory Controller") + mmu = Param.MemoryController(parent.any, "Memory Controller") io_bus = Param.Bus(NULL, "The IO Bus to attach to") pio_latency = Param.Tick(1, "Programmed IO latency in bus cycles") @@ -25,7 +25,7 @@ simobj FooDmaDevice(FooPioDevice): simobj PioDevice(FooPioDevice): type = 'PioDevice' abstract = True - platform = Param.Platform(Super, "Platform") + platform = Param.Platform(parent.any, "Platform") simobj DmaDevice(PioDevice): type = 'DmaDevice' 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..cd251f36d 100644 --- a/objects/Ethernet.mpy +++ b/python/m5/objects/Ethernet.mpy @@ -49,8 +49,8 @@ simobj EtherDev(DmaDevice): intr_delay = Param.Tick(0, "Interrupt Delay in microseconds") payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload") - physmem = Param.PhysicalMemory(Super, "Physical Memory") - tlaser = Param.Turbolaser(Super, "Turbolaser") + physmem = Param.PhysicalMemory(parent.any, "Physical Memory") + tlaser = Param.Turbolaser(parent.any, "Turbolaser") simobj NSGigE(PciDevice): type = 'NSGigE' @@ -73,7 +73,7 @@ simobj NSGigE(PciDevice): intr_delay = Param.Tick(0, "Interrupt Delay in microseconds") payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload") - physmem = Param.PhysicalMemory(Super, "Physical Memory") + physmem = Param.PhysicalMemory(parent.any, "Physical Memory") simobj EtherDevInt(EtherInt): type = 'EtherDevInt' diff --git a/objects/Ide.mpy b/python/m5/objects/Ide.mpy index ce760ad96..786109efa 100644 --- a/objects/Ide.mpy +++ b/python/m5/objects/Ide.mpy @@ -7,7 +7,7 @@ simobj IdeDisk(SimObject): delay = Param.Tick(1, "Fixed disk delay in microseconds") driveID = Param.IdeID('master', "Drive ID") image = Param.DiskImage("Disk image") - physmem = Param.PhysicalMemory(Super, "Physical memory") + physmem = Param.PhysicalMemory(parent.any, "Physical memory") simobj IdeController(PciDevice): type = 'IdeController' diff --git a/objects/IntrControl.mpy b/python/m5/objects/IntrControl.mpy index 1ef5a17ee..144be0fd4 100644 --- a/objects/IntrControl.mpy +++ b/python/m5/objects/IntrControl.mpy @@ -1,3 +1,3 @@ simobj IntrControl(SimObject): type = 'IntrControl' - cpu = Param.BaseCPU(Super, "the cpu") + cpu = Param.BaseCPU(parent.any, "the cpu") 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..b9b3e5a95 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 = 0xffffffffL 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 + configdata = Param.PciConfigData(parent.any, "PCI Config data") + configspace = Param.PciConfigAll(parent.any, "PCI Configspace") diff --git a/objects/PhysicalMemory.mpy b/python/m5/objects/PhysicalMemory.mpy index d1e4ad4b4..e6df2a161 100644 --- a/objects/PhysicalMemory.mpy +++ b/python/m5/objects/PhysicalMemory.mpy @@ -4,4 +4,4 @@ simobj PhysicalMemory(FunctionalMemory): type = 'PhysicalMemory' range = Param.AddrRange("Device Address") file = Param.String('', "memory mapped file") - mmu = Param.MemoryController(Super, "Memory Controller") + mmu = Param.MemoryController(parent.any, "Memory Controller") diff --git a/objects/Platform.mpy b/python/m5/objects/Platform.mpy index d0510eaf8..a71ab3b77 100644 --- a/objects/Platform.mpy +++ b/python/m5/objects/Platform.mpy @@ -2,4 +2,4 @@ simobj Platform(SimObject): type = 'Platform' abstract = True interrupt_frequency = Param.Tick(1200, "frequency of interrupts") - intrctrl = Param.IntrControl(Super, "interrupt controller") + intrctrl = Param.IntrControl(parent.any, "interrupt controller") 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..3588a949d 100644 --- a/objects/SimConsole.mpy +++ b/python/m5/objects/SimConsole.mpy @@ -5,7 +5,7 @@ simobj ConsoleListener(SimObject): simobj SimConsole(SimObject): type = 'SimConsole' append_name = Param.Bool(True, "append name() to filename") - intr_control = Param.IntrControl(Super, "interrupt controller") + intr_control = Param.IntrControl(parent.any, "interrupt controller") listener = Param.ConsoleListener("console listener") number = Param.Int(0, "console number") output = Param.String('console', "file to dump output to") diff --git a/objects/SimpleDisk.mpy b/python/m5/objects/SimpleDisk.mpy index c4dd5435b..b616fb3d1 100644 --- a/objects/SimpleDisk.mpy +++ b/python/m5/objects/SimpleDisk.mpy @@ -1,4 +1,4 @@ simobj SimpleDisk(SimObject): type = 'SimpleDisk' disk = Param.DiskImage("Disk Image") - physmem = Param.PhysicalMemory(Super, "Physical Memory") + physmem = Param.PhysicalMemory(parent.any, "Physical Memory") diff --git a/objects/Tsunami.mpy b/python/m5/objects/Tsunami.mpy index cfe23977e..a8471cee2 100644 --- a/objects/Tsunami.mpy +++ b/python/m5/objects/Tsunami.mpy @@ -4,12 +4,12 @@ from Platform import Platform simobj Tsunami(Platform): type = 'Tsunami' pciconfig = Param.PciConfigAll("PCI configuration") - system = Param.BaseSystem(Super, "system") + system = Param.BaseSystem(parent.any, "system") interrupt_frequency = Param.Int(1024, "frequency of interrupts") simobj TsunamiCChip(FooPioDevice): type = 'TsunamiCChip' - tsunami = Param.Tsunami(Super, "Tsunami") + tsunami = Param.Tsunami(parent.any, "Tsunami") simobj TsunamiFake(FooPioDevice): type = 'TsunamiFake' @@ -18,8 +18,8 @@ simobj TsunamiIO(FooPioDevice): type = 'TsunamiIO' time = Param.UInt64(1136073600, "System time to use (0 for actual time, default is 1/1/06)") - tsunami = Param.Tsunami(Super, "Tsunami") + tsunami = Param.Tsunami(parent.any, "Tsunami") simobj TsunamiPChip(FooPioDevice): type = 'TsunamiPChip' - tsunami = Param.Tsunami(Super, "Tsunami") + tsunami = Param.Tsunami(parent.any, "Tsunami") diff --git a/objects/Uart.mpy b/python/m5/objects/Uart.mpy index 76ee8805f..5a6c25f8e 100644 --- a/objects/Uart.mpy +++ b/python/m5/objects/Uart.mpy @@ -2,5 +2,5 @@ from Device import PioDevice simobj Uart(PioDevice): type = 'Uart' - console = Param.SimConsole(Super, "The console") + console = Param.SimConsole(parent.any, "The console") size = Param.Addr(0x8, "Device size") diff --git a/python/m5/smartdict.py b/python/m5/smartdict.py new file mode 100644 index 000000000..1ba5d8410 --- /dev/null +++ b/python/m5/smartdict.py @@ -0,0 +1,108 @@ +# 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) + + + # __getitem__ uses dict.get() to return 'False' if the key is not + # found (rather than raising KeyError). Note that this does *not* + # set the key's value to 'False' in the dict, so that even after + # we call env['foo'] we still get a meaningful answer from "'foo' + # in env" (which calls dict.__contains__, which we do not + # override). + 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.cc b/sim/sim_object.cc index 818648b98..559415102 100644 --- a/sim/sim_object.cc +++ b/sim/sim_object.cc @@ -61,14 +61,29 @@ namespace Stats { // // SimObject constructor: used to maintain static simObjectList // +SimObject::SimObject(Params *p) + : _params(p) +{ +#ifdef DEBUG + doDebugBreak = false; +#endif + + doRecordEvent = !Stats::event_ignore.match(name()); + simObjectList.push_back(this); +} + +// +// SimObject constructor: used to maintain static simObjectList +// SimObject::SimObject(const string &_name) - : objName(_name) + : _params(new Params) { + _params->name = _name; #ifdef DEBUG doDebugBreak = false; #endif - doRecordEvent = !Stats::event_ignore.match(_name); + doRecordEvent = !Stats::event_ignore.match(name()); simObjectList.push_back(this); } diff --git a/sim/sim_object.hh b/sim/sim_object.hh index f4b316ebb..db8d4f4d3 100644 --- a/sim/sim_object.hh +++ b/sim/sim_object.hh @@ -48,8 +48,16 @@ */ class SimObject : public Serializable, protected StartupCallback { + public: + struct Params { + std::string name; + }; + protected: - std::string objName; + Params *_params; + + public: + const Params *params() const { return _params; } private: friend class Serializer; @@ -60,11 +68,12 @@ class SimObject : public Serializable, protected StartupCallback static SimObjectList simObjectList; public: + SimObject(Params *_params); SimObject(const std::string &_name); virtual ~SimObject() {} - virtual const std::string name() const { return objName; } + virtual const std::string name() const { return params()->name; } // initialization pass of all objects. // Gets invoked after construction, before unserialize. 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) diff --git a/util/stats/display.py b/util/stats/display.py index 68a26852d..4c17d4427 100644 --- a/util/stats/display.py +++ b/util/stats/display.py @@ -68,7 +68,7 @@ class VectorDisplay: p.flags = self.flags p.precision = self.precision - if issequence(self.value): + if isinstance(self.value, (list, tuple)): if not len(self.value): return diff --git a/util/stats/info.py b/util/stats/info.py index 01d7bdb0f..3f6a8dbc3 100644 --- a/util/stats/info.py +++ b/util/stats/info.py @@ -6,9 +6,6 @@ display_run = 0 global globalTicks globalTicks = None -def issequence(t): - return isinstance(t, types.TupleType) or isinstance(t, types.ListType) - def total(f): if isinstance(f, FormulaStat): v = f.value @@ -16,7 +13,7 @@ def total(f): v = f f = FormulaStat() - if issequence(v): + if isinstance(v, (list, tuple)): f.value = reduce(operator.add, v) else: f.value = v @@ -29,7 +26,7 @@ def unaryop(op, f): else: v = f - if issequence(v): + if isinstance(v, (list, tuple)): return map(op, v) else: return op(v) @@ -109,19 +106,19 @@ def binaryop(op, lf, rf): return result def sums(x, y): - if issequence(x): + if isinstance(x, (list, tuple)): return map(lambda x, y: x + y, x, y) else: return x + y -def alltrue(list): - return reduce(lambda x, y: x and y, list) +def alltrue(seq): + return reduce(lambda x, y: x and y, seq) -def allfalse(list): - return not reduce(lambda x, y: x or y, list) +def allfalse(seq): + return not reduce(lambda x, y: x or y, seq) -def enumerate(list): - return map(None, range(len(list)), list) +def enumerate(seq): + return map(None, range(len(seq)), seq) def cmp(a, b): if a < b: @@ -323,10 +320,11 @@ class Vector(Statistic,FormulaStat): len(self.value) == len(other.value) def __eq__(self, other): - if issequence(self.value) != issequence(other.value): + if isinstance(self.value, (list, tuple)) != \ + isinstance(other.value, (list, tuple)): return False - if issequence(self.value): + if isinstance(self.value, (list, tuple)): if len(self.value) != len(other.value): return False else: @@ -348,7 +346,7 @@ class Vector(Statistic,FormulaStat): def __itruediv__(self, other): if not other: return self - if issequence(self.value): + if isinstance(self.value, (list, tuple)): for i in xrange(len(self.value)): self.value[i] /= other else: @@ -642,7 +640,8 @@ class VectorDist(Statistic): return alltrue(map(lambda x, y : x == y, self.dist, other.dist)) def __isub__(self, other): - if issequence(self.dist) and issequence(other.dist): + if isinstance(self.dist, (list, tuple)) and \ + isinstance(other.dist, (list, tuple)): for sd,od in zip(self.dist, other.dist): sd -= od else: @@ -650,7 +649,8 @@ class VectorDist(Statistic): return self def __iadd__(self, other): - if issequence(self.dist) and issequence(other.dist): + if isinstance(self.dist, (list, tuple)) and \ + isinstance(other.dist, (list, tuple)): for sd,od in zip(self.dist, other.dist): sd += od else: @@ -660,7 +660,7 @@ class VectorDist(Statistic): def __itruediv__(self, other): if not other: return self - if issequence(self.dist): + if isinstance(self.dist, (list, tuple)): for dist in self.dist: dist /= other else: diff --git a/util/stats/print.py b/util/stats/print.py index f4492cd2b..1ed50eef0 100644 --- a/util/stats/print.py +++ b/util/stats/print.py @@ -71,7 +71,7 @@ class VectorDisplay: p.flags = self.flags p.precision = self.precision - if issequence(self.value): + if isinstance(self.value, (list, tuple)): if not len(self.value): return |