diff --git a/configs/boot/nat-netperf-maerts-client.rcS b/configs/boot/nat-netperf-maerts-client.rcS index ab9fd8c4e..ab66b7d4a 100644 --- a/configs/boot/nat-netperf-maerts-client.rcS +++ b/configs/boot/nat-netperf-maerts-client.rcS @@ -22,7 +22,7 @@ echo "262143" > /proc/sys/net/core/wmem_default echo "262143" > /proc/sys/net/core/optmem_max echo "100000" > /proc/sys/net/core/netdev_max_backlog -echo -n "waiting for server..." +echo -n "waiting for natbox..." /usr/bin/netcat -c -l -p 8000 BINARY=/benchmarks/netperf/netperf diff --git a/configs/boot/nat-netperf-server.rcS b/configs/boot/nat-netperf-server.rcS index 5b094b790..69717b7ce 100644 --- a/configs/boot/nat-netperf-server.rcS +++ b/configs/boot/nat-netperf-server.rcS @@ -23,7 +23,8 @@ echo "100000" > /proc/sys/net/core/netdev_max_backlog echo "running netserver..." /benchmarks/netperf/netserver -echo -n "signal client to begin..." +echo -n "signal natbox to begin..." +sleep 1 echo "server ready" | /usr/bin/netcat -c $NATBOX 8000 echo "done." diff --git a/configs/boot/netperf-server.rcS b/configs/boot/netperf-server.rcS index f77ff0ce8..c75d918a2 100644 --- a/configs/boot/netperf-server.rcS +++ b/configs/boot/netperf-server.rcS @@ -22,6 +22,7 @@ echo "running netserver..." /benchmarks/netperf/netserver echo -n "signal client to begin..." +sleep 1 echo "server ready" | /usr/bin/netcat -c $CLIENT 8000 echo "done." diff --git a/configs/boot/nfs-client.rcS b/configs/boot/nfs-client.rcS index a999fb72c..84d15439f 100755 --- a/configs/boot/nfs-client.rcS +++ b/configs/boot/nfs-client.rcS @@ -45,6 +45,6 @@ mkdir /nfs mount 10.0.0.1:/nfs /nfs echo "done." -/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs +/bin/bonnie++ -u 99 -s 500 -r 0 -n 0 -f -F -d /nfs /sbin/m5 exit diff --git a/configs/boot/nfs-server.rcS b/configs/boot/nfs-server.rcS index 21b7ab83c..0cb489a9d 100755 --- a/configs/boot/nfs-server.rcS +++ b/configs/boot/nfs-server.rcS @@ -38,7 +38,7 @@ echo "done." # mknod /dev/sda1 b 8 1 #fi -/sbin/insmod /modules/scsi_debug.ko dev_size_mb=768 +/sbin/insmod /modules/scsi_debug.ko dev_size_mb=512 echo -n "creating partition and formatting..." #echo "1,767,L" > /tmp/sfdisk.run diff --git a/dev/etherlink.cc b/dev/etherlink.cc index 0acc50b0b..81cdbc20f 100644 --- a/dev/etherlink.cc +++ b/dev/etherlink.cc @@ -47,32 +47,32 @@ using namespace std; -EtherLink::EtherLink(const string &name, EtherInt *i1, EtherInt *i2, +EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1, Tick speed, Tick dly, EtherDump *dump) : SimObject(name) { double rate = ((double)ticksPerSecond * 8.0) / (double)speed; Tick delay = US2Ticks(dly); - link1 = new Link(name + ".link1", rate, delay, dump); - link2 = new Link(name + ".link2", rate, delay, dump); + link[0] = new Link(name + ".link0", this, 0, rate, delay, dump); + link[1] = new Link(name + ".link1", this, 1, rate, delay, dump); - int1 = new Interface(name + ".int1", link1, link2); - int2 = new Interface(name + ".int2", link2, link1); + interface[0] = new Interface(name + ".int0", link[0], link[1]); + interface[1] = new Interface(name + ".int1", link[1], link[0]); - int1->setPeer(i1); - i1->setPeer(int1); - int2->setPeer(i2); - i2->setPeer(int2); + interface[0]->setPeer(peer0); + peer0->setPeer(interface[0]); + interface[1]->setPeer(peer1); + peer1->setPeer(interface[1]); } EtherLink::~EtherLink() { - delete link1; - delete link2; + delete link[0]; + delete link[1]; - delete int1; - delete int2; + delete interface[0]; + delete interface[1]; } EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) @@ -82,26 +82,25 @@ EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx) rx->setRxInt(this); } -EtherLink::Link::Link(const string &name, double rate, Tick delay, - EtherDump *d) - : objName(name), txint(NULL), rxint(NULL), ticksPerByte(rate), - linkDelay(delay), dump(d), doneEvent(this) -{} +EtherLink::Link::Link(const string &name, EtherLink *p, int num, + double rate, Tick delay, EtherDump *d) + : objName(name), parent(p), number(num), txint(NULL), rxint(NULL), + ticksPerByte(rate), linkDelay(delay), dump(d), + doneEvent(this) +{ } void EtherLink::serialize(ostream &os) { - nameOut(os, name() + ".link1"); - link1->serialize(os); - nameOut(os, name() + ".link2"); - link2->serialize(os); + link[0]->serialize("link0", os); + link[1]->serialize("link1", os); } void EtherLink::unserialize(Checkpoint *cp, const string §ion) { - link1->unserialize(cp, section + ".link1"); - link2->unserialize(cp, section + ".link2"); + link[0]->unserialize("link0", cp, section); + link[1]->unserialize("link1", cp, section); } void @@ -118,10 +117,9 @@ class LinkDelayEvent : public Event EtherLink::Link *link; PacketPtr packet; - // non-scheduling version for createForUnserialize() - LinkDelayEvent(EtherLink::Link *link); - public: + // non-scheduling version for createForUnserialize() + LinkDelayEvent(); LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when); void process(); @@ -132,7 +130,6 @@ class LinkDelayEvent : public Event const string §ion); }; - void EtherLink::Link::txDone() { @@ -173,43 +170,44 @@ EtherLink::Link::transmit(PacketPtr pkt) } void -EtherLink::Link::serialize(ostream &os) +EtherLink::Link::serialize(const string &base, ostream &os) { bool packet_exists = packet; - SERIALIZE_SCALAR(packet_exists); + paramOut(os, base + ".packet_exists", packet_exists); + if (packet_exists) + packet->serialize(base + ".packet", os); bool event_scheduled = doneEvent.scheduled(); - SERIALIZE_SCALAR(event_scheduled); + paramOut(os, base + ".event_scheduled", event_scheduled); if (event_scheduled) { Tick event_time = doneEvent.when(); - SERIALIZE_SCALAR(event_time); + paramOut(os, base + ".event_time", event_time); } - if (packet_exists) - packet->serialize("packet", os); } void -EtherLink::Link::unserialize(Checkpoint *cp, const string §ion) +EtherLink::Link::unserialize(const string &base, Checkpoint *cp, + const string §ion) { bool packet_exists; - UNSERIALIZE_SCALAR(packet_exists); + paramIn(cp, section, base + ".packet_exists", packet_exists); if (packet_exists) { packet = new PacketData(16384); - packet->unserialize("packet", cp, section); + packet->unserialize(base + ".packet", cp, section); } bool event_scheduled; - UNSERIALIZE_SCALAR(event_scheduled); + paramIn(cp, section, base + ".event_scheduled", event_scheduled); if (event_scheduled) { Tick event_time; - UNSERIALIZE_SCALAR(event_time); + paramIn(cp, section, base + ".event_time", event_time); doneEvent.schedule(event_time); } } -LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l) - : Event(&mainEventQueue), link(l) +LinkDelayEvent::LinkDelayEvent() + : Event(&mainEventQueue), link(NULL) { setFlags(AutoSerialize); setFlags(AutoDelete); @@ -234,7 +232,11 @@ LinkDelayEvent::serialize(ostream &os) { paramOut(os, "type", string("LinkDelayEvent")); Event::serialize(os); - SERIALIZE_OBJPTR(link); + + EtherLink *parent = link->parent; + bool number = link->number; + SERIALIZE_OBJPTR(parent); + SERIALIZE_SCALAR(number); packet->serialize("packet", os); } @@ -244,6 +246,14 @@ void LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) { Event::unserialize(cp, section); + + EtherLink *parent; + bool number; + UNSERIALIZE_OBJPTR(parent); + UNSERIALIZE_SCALAR(number); + + link = parent->link[number]; + packet = new PacketData(16384); packet->unserialize("packet", cp, section); } @@ -252,9 +262,7 @@ LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion) Serializable * LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string §ion) { - EtherLink::Link *link; - UNSERIALIZE_OBJPTR(link); - return new LinkDelayEvent(link); + return new LinkDelayEvent(); } REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent) diff --git a/dev/etherlink.hh b/dev/etherlink.hh index d5cd7d7c8..28ab61301 100644 --- a/dev/etherlink.hh +++ b/dev/etherlink.hh @@ -40,7 +40,7 @@ #include "sim/sim_object.hh" class EtherDump; - +class Checkpoint; /* * Model for a fixed bandwidth full duplex ethernet link */ @@ -53,10 +53,14 @@ class EtherLink : public SimObject /* * Model for a single uni-directional link */ - class Link : public Serializable { + class Link + { protected: std::string objName; + EtherLink *parent; + int number; + Interface *txint; Interface *rxint; @@ -78,11 +82,11 @@ class EtherLink : public SimObject void txComplete(PacketPtr packet); public: - Link(const std::string &name, double rate, Tick delay, - EtherDump *dump); + Link(const std::string &name, EtherLink *p, int num, + double rate, Tick delay, EtherDump *dump); ~Link() {} - virtual const std::string name() const { return objName; } + const std::string name() const { return objName; } bool busy() const { return (bool)packet; } bool transmit(PacketPtr packet); @@ -90,8 +94,9 @@ class EtherLink : public SimObject void setTxInt(Interface *i) { assert(!txint); txint = i; } void setRxInt(Interface *i) { assert(!rxint); rxint = i; } - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(const std::string &base, std::ostream &os); + void unserialize(const std::string &base, Checkpoint *cp, + const std::string §ion); }; /* @@ -108,14 +113,11 @@ class EtherLink : public SimObject void sendDone() { peer->sendDone(); } }; - Link *link1; - Link *link2; - - EtherInt *int1; - EtherInt *int2; + Link *link[2]; + EtherInt *interface[2]; public: - EtherLink(const std::string &name, EtherInt *i1, EtherInt *i2, + EtherLink(const std::string &name, EtherInt *peer0, EtherInt *peer1, Tick speed, Tick delay, EtherDump *dump); virtual ~EtherLink(); diff --git a/objects/BaseCPU.mpy b/objects/BaseCPU.mpy index f6e6ff96c..484fcccd6 100644 --- a/objects/BaseCPU.mpy +++ b/objects/BaseCPU.mpy @@ -4,11 +4,13 @@ simobj BaseCPU(SimObject): icache = Param.BaseMem(NULL, "L1 instruction cache object") dcache = Param.BaseMem(NULL, "L1 data cache object") - dtb = Param.AlphaDTB("Data TLB") - itb = Param.AlphaITB("Instruction TLB") - mem = Param.FunctionalMemory("memory") - system = Param.BaseSystem(Super, "system object") - workload = VectorParam.Process("processes to run") + if Bool._convert(env.get('FULL_SYSTEM', 'False')): + dtb = Param.AlphaDTB("Data TLB") + itb = Param.AlphaITB("Instruction TLB") + mem = Param.FunctionalMemory("memory") + system = Param.BaseSystem(Super, "system object") + else: + workload = VectorParam.Process("processes to run") max_insts_all_threads = Param.Counter(0, "terminate when all threads have reached this inst count") @@ -21,19 +23,3 @@ simobj BaseCPU(SimObject): defer_registration = Param.Bool(False, "defer registration with system (for sampling)") - - def check(self): - has_workload = self._hasvalue('workload') - has_dtb = self._hasvalue('dtb') - has_itb = self._hasvalue('itb') - has_mem = self._hasvalue('mem') - has_system = self._hasvalue('system') - - if has_workload: - self.dtb.disable = True - self.itb.disable = True - self.mem.disable = True - self.system.disable = True - - if has_dtb or has_itb or has_mem or has_system: - self.workload.disable = True diff --git a/objects/CoherenceProtocol.mpy b/objects/CoherenceProtocol.mpy index ae041b638..f3b0026b7 100644 --- a/objects/CoherenceProtocol.mpy +++ b/objects/CoherenceProtocol.mpy @@ -1,4 +1,4 @@ -Coherence = Enum('uni', 'msi', 'mesi', 'mosi', 'moesi') +class Coherence(Enum): vals = ['uni', 'msi', 'mesi', 'mosi', 'moesi'] simobj CoherenceProtocol(SimObject): type = 'CoherenceProtocol' diff --git a/objects/Ide.mpy b/objects/Ide.mpy index c4aa2aca0..ce760ad96 100644 --- a/objects/Ide.mpy +++ b/objects/Ide.mpy @@ -1,6 +1,6 @@ from Pci import PciDevice -IdeID = Enum('master', 'slave') +class IdeID(Enum): vals = ['master', 'slave'] simobj IdeDisk(SimObject): type = 'IdeDisk' diff --git a/sim/pyconfig/SConscript b/sim/pyconfig/SConscript index 9154d3b99..2799ef64f 100644 --- a/sim/pyconfig/SConscript +++ b/sim/pyconfig/SConscript @@ -144,6 +144,29 @@ def MakeEmbeddedPyFile(target, source, env): for pyfile, path, name, ext, filename in files: 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)) + CFileCounter = 0 def MakePythonCFile(target, source, env): global CFileCounter @@ -170,7 +193,7 @@ EmbedMap %(name)s("%(fname)s", /* namespace */ } ''' -embedded_py_files = ['m5config.py', '../../util/pbs/jobfile.py'] +embedded_py_files = ['m5config.py', 'importer.py', '../../util/pbs/jobfile.py'] objpath = os.path.join(env['SRCDIR'], 'objects') for root, dirs, files in os.walk(objpath, topdown=True): for i,dir in enumerate(dirs): @@ -184,7 +207,9 @@ for root, dirs, files in os.walk(objpath, topdown=True): embedded_py_files.append(os.path.join(root, f)) embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh') -env.Depends('embedded_py.cc', embedfile_hh) +env.Command('defines.py', None, MakeDefinesPyFile) env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile) -env.Command('embedded_py.cc', ['importer.py', 'embedded_py.py'], +env.Depends('embedded_py.cc', embedfile_hh) +env.Command('embedded_py.cc', + ['string_importer.py', 'defines.py', 'embedded_py.py'], MakePythonCFile) diff --git a/sim/pyconfig/m5config.py b/sim/pyconfig/m5config.py index c413fef71..e6201b3ad 100644 --- a/sim/pyconfig/m5config.py +++ b/sim/pyconfig/m5config.py @@ -25,7 +25,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from __future__ import generators -import os, re, sys, types +import os, re, sys, types, inspect + +from importer import AddToPath, LoadMpyFile + noDot = False try: import pydot @@ -172,9 +175,6 @@ def isSubClass(value, cls): except: return False -def isParam(self): - return isinstance(self, _Param) - def isConfigNode(value): try: return issubclass(value, ConfigNode) @@ -204,8 +204,8 @@ def isParamContext(value): return False -class_decorator = '_M5M5_SIMOBJECT_' -expr_decorator = '_M5M5_EXPRESSION_' +class_decorator = 'M5M5_SIMOBJECT_' +expr_decorator = 'M5M5_EXPRESSION_' dot_decorator = '_M5M5_DOT_' # The metaclass for ConfigNode (and thus for everything that derives @@ -215,9 +215,11 @@ dot_decorator = '_M5M5_DOT_' # of that class are instantiated, and provides inherited instance # behavior). class MetaConfigNode(type): - keywords = { 'abstract' : types.BooleanType, - 'check' : types.FunctionType, - 'type' : (types.NoneType, types.StringType) } + # Attributes that can be set only at initialization time + init_keywords = {} + # Attributes that can be set any time + keywords = { 'check' : types.FunctionType, + 'children' : types.ListType } # __new__ is called before __init__, and is where the statements # in the body of the class definition get loaded into the class's @@ -225,77 +227,77 @@ class MetaConfigNode(type): # and only allow "private" attributes to be passed to the base # __new__ (starting with underscore). def __new__(mcls, name, bases, dict): - priv = { 'abstract' : False, - # initialize _params and _values dicts to empty - '_params' : {}, - '_values' : {}, - '_disable' : {} } - + # Copy "private" attributes (including special methods such as __new__) + # to the official dict. Everything else goes in _init_dict to be + # filtered in __init__. + cls_dict = {} for key,val in dict.items(): - del dict[key] - - # 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. - if key.startswith(expr_decorator): - key = key[len(expr_decorator):] - - if mcls.keywords.has_key(key): - if not isinstance(val, mcls.keywords[key]): - raise TypeError, \ - 'keyword %s has the wrong type %s should be %s' % \ - (key, type(val), mcls.keywords[key]) - - if isinstance(val, types.FunctionType): - val = classmethod(val) - priv[key] = val - - elif key.startswith('_'): - priv[key] = val - - elif not isNullPointer(val) and isConfigNode(val): - dict[key] = val() - - elif isSimObjSequence(val): - dict[key] = [ v() for v in val ] - - else: - dict[key] = val - - # If your parent has a value in it that's a config node, clone it. - for base in bases: - if not isConfigNode(base): - continue - - for key,value in base._values.iteritems(): - if dict.has_key(key): - continue - - if isConfigNode(value): - priv['_values'][key] = value() - elif isSimObjSequence(value): - priv['_values'][key] = [ val() for val in value ] - - # entries left in dict will get passed to __init__, where we'll - # deal with them as params. - return super(MetaConfigNode, mcls).__new__(mcls, name, bases, priv) + if key.startswith('_'): + cls_dict[key] = val + del dict[key] + cls_dict['_init_dict'] = dict + return super(MetaConfigNode, mcls).__new__(mcls, name, bases, cls_dict) # initialization def __init__(cls, name, bases, dict): - super(MetaConfigNode, cls).__init__(cls, name, bases, {}) + super(MetaConfigNode, cls).__init__(name, bases, dict) + # initialize required attributes + cls._params = {} + cls._values = {} + cls._enums = {} 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(): + + # don't clone if (1) we're about to overwrite it with + # a local setting or (2) we've already cloned a copy + # from an earlier (more derived) base + if cls._init_dict.has_key(key) or cls._values.has_key(key): + continue + + if isConfigNode(val): + cls._values[key] = val() + elif isSimObjSequence(val): + cls._values[key] = [ v() for v in val ] + elif isNullPointer(val): + cls._values[key] = val + + # now process _init_dict items + for key,val in cls._init_dict.items(): + if isinstance(val, _Param): + cls._params[key] = val + + # 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. + elif key.startswith(expr_decorator): + key = key[len(expr_decorator):] + # because it had dots into a list so that we can find the + # proper variable to modify. + key = key.split(dot_decorator) + c = cls + for item in key[:-1]: + c = getattr(c, item) + setattr(c, key[-1], val) + + # default: use normal path (ends up in __setattr__) + else: + setattr(cls, key, val) - # initialize attributes with values from class definition - for key,value in dict.iteritems(): - # turn an expression that was munged in the importer - # because it had dots into a list so that we can find the - # proper variable to modify. - key = key.split(dot_decorator) - c = cls - for item in key[:-1]: - c = getattr(c, item) - setattr(c, key[-1], value) def _isvalue(cls, name): for c in cls._bases: @@ -329,9 +331,6 @@ class MetaConfigNode(type): else: return default - def _setparam(cls, name, value): - cls._params[name] = value - def _hasvalue(cls, name): for c in cls._bases: if c._values.has_key(name): @@ -347,7 +346,11 @@ class MetaConfigNode(type): values[p] = v for p,v in c._params.iteritems(): if not values.has_key(p) and hasattr(v, 'default'): - v.valid(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 @@ -378,25 +381,24 @@ class MetaConfigNode(type): def _setvalue(cls, name, value): cls._values[name] = value - def _getdisable(cls, name): - for c in cls._bases: - if c._disable.has_key(name): - return c._disable[name] - return False - - def _setdisable(cls, name, value): - cls._disable[name] = value - def __getattr__(cls, attr): if cls._isvalue(attr): return Value(cls, attr) - if attr == '_cppname' and hasattr(cls, 'type'): + 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)' % \ + (keyword, type(val), kwtype) + if isinstance(val, types.FunctionType): + val = classmethod(val) + type.__setattr__(cls, keyword, val) + # Set attribute (called on foo.attr = value when foo is an # instance of class cls). def __setattr__(cls, attr, value): @@ -406,11 +408,7 @@ class MetaConfigNode(type): return if cls.keywords.has_key(attr): - raise TypeError, \ - "keyword '%s' can only be set in a simobj definition" % attr - - if isParam(value): - cls._setparam(attr, value) + cls._set_keyword(attr, value, cls.keywords[attr]) return # must be SimObject param @@ -424,8 +422,6 @@ class MetaConfigNode(type): elif isConfigNode(value) or isSimObjSequence(value): cls._setvalue(attr, value) else: - for p,v in cls._getparams().iteritems(): - print p,v raise AttributeError, \ "Class %s has no parameter %s" % (cls.__name__, attr) @@ -459,9 +455,6 @@ class MetaConfigNode(type): cls.check() for key,value in cls._getvalues().iteritems(): - if cls._getdisable(key): - continue - if isConfigNode(value): cls.add_child(instance, key, value) if issequence(value): @@ -471,15 +464,11 @@ class MetaConfigNode(type): for pname,param in cls._getparams().iteritems(): try: - if cls._getdisable(pname): - continue - - try: - value = cls._getvalue(pname) - except: - print 'Error getting %s' % pname - raise + value = cls._getvalue(pname) + except: + panic('Error getting %s' % pname) + try: if isConfigNode(value): value = instance.child_objects[value] elif issequence(value): @@ -530,53 +519,59 @@ class ConfigNode(object): # Specify metaclass. Any class inheriting from ConfigNode will # get this metaclass. __metaclass__ = MetaConfigNode - type = None def __new__(cls, **kwargs): - return MetaConfigNode(cls.__name__, (cls, ), kwargs) - - # Set attribute. All attribute assignments go through here. Must - # be private attribute (starts with '_') or valid parameter entry. - # Basically identical to MetaConfigClass.__setattr__(), except - # this sets attributes on specific instances rather than on classes. - #def __setattr__(self, attr, value): - # if attr.startswith('_'): - # object.__setattr__(self, attr, value) - # return - # not private; look up as param - # param = self.__class__.lookup_param(attr) - # if not param: - # raise AttributeError, \ - # "Class %s has no parameter %s" \ - # % (self.__class__.__name__, attr) - # It's ok: set attribute by delegating to 'object' class. - # Note the use of param.make_value() to verify/canonicalize - # the assigned value. - # v = param.convert(value) - # object.__setattr__(self, attr, v) + name = cls.__name__ + ("_%d" % cls._anon_subclass_counter) + cls._anon_subclass_counter += 1 + return cls.__metaclass__(name, (cls, ), kwargs) class ParamContext(ConfigNode): pass -# SimObject is a minimal extension of ConfigNode, implementing a -# hierarchy node that corresponds to an M5 SimObject. It prints out a -# "type=" line to indicate its SimObject class, prints out the -# assigned parameters corresponding to its class, and allows -# 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): - def _sim_code(cls): +class MetaSimObject(MetaConfigNode): + # init_keywords and keywords are inherited from MetaConfigNode, + # with overrides/additions + init_keywords = MetaConfigNode.init_keywords + init_keywords.update({ 'abstract' : types.BooleanType, + 'type' : types.StringType }) + + keywords = MetaConfigNode.keywords + # no additional keywords + + cpp_classes = [] + + # initialization + def __init__(cls, name, bases, dict): + super(MetaSimObject, cls).__init__(name, bases, dict) + + if hasattr(cls, 'type'): + if name == 'SimObject': + cls._cpp_base = None + elif hasattr(cls._bases[1], 'type'): + cls._cpp_base = cls._bases[1].type + else: + panic("SimObject %s derives from a non-C++ SimObject %s "\ + "(no 'type')" % (cls, cls_bases[1].__name__)) + + # This class corresponds to a C++ class: put it on the global + # list of C++ objects to generate param structs, etc. + MetaSimObject.cpp_classes.append(cls) + + def _cpp_decl(cls): name = cls.__name__ + code = "" + code += "\n".join([e.cpp_declare() for e in cls._enums.values()]) + code += "\n" param_names = cls._params.keys() param_names.sort() - code = "BEGIN_DECLARE_SIM_OBJECT_PARAMS(%s)\n" % name - decls = [" " + cls._params[pname].sim_decl(pname) \ - for pname in param_names] - code += "\n".join(decls) + "\n" - code += "END_DECLARE_SIM_OBJECT_PARAMS(%s)\n\n" % name + code += "struct Params" + if cls._cpp_base: + code += " : public %s::Params" % cls._cpp_base + code += " {\n " + code += "\n ".join([cls._params[pname].cpp_decl(pname) \ + for pname in param_names]) + code += "\n};\n" return code - _sim_code = classmethod(_sim_code) class NodeParam(object): def __init__(self, name, param, value): @@ -697,10 +692,16 @@ class Node(object): if self.children: # instantiate children in same order they were added for # backward compatibility (else we can end up with cpu1 - # before cpu0). + # 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)) children = [ c.name for c in self.children if not c.paramcontext] print 'children =', ' '.join(children) + self.params.sort(lambda x,y: cmp(x.name, y.name)) for param in self.params: try: if param.value is None: @@ -796,16 +797,10 @@ class Value(object): return self.obj._getvalue(self.attr) def __setattr__(self, attr, value): - if attr == 'disable': - self.obj._setdisable(self.attr, value) - else: - setattr(self._getattr(), attr, value) + setattr(self._getattr(), attr, value) def __getattr__(self, attr): - if attr == 'disable': - return self.obj._getdisable(self.attr) - else: - return getattr(self._getattr(), attr) + return getattr(self._getattr(), attr) def __getitem__(self, index): return self._getattr().__getitem__(index) @@ -821,10 +816,13 @@ class Value(object): # Regular parameter. class _Param(object): - def __init__(self, ptype_string, *args, **kwargs): - self.ptype_string = ptype_string - # can't eval ptype_string here to get ptype, since the type might - # not have been defined yet. Do it lazily in __getattr__. + def __init__(self, ptype, *args, **kwargs): + if isinstance(ptype, types.StringType): + self.ptype_string = ptype + elif isinstance(ptype, type): + self.ptype = ptype + else: + raise TypeError, "Param type is not a type (%s)" % ptype if args: if len(args) == 1: @@ -875,8 +873,8 @@ class _Param(object): def set(self, name, instance, value): instance.__dict__[name] = value - def sim_decl(self, name): - return '%s %s;' % (self.ptype._cppname, name) + def cpp_decl(self, name): + return '%s %s;' % (self.ptype._cpp_param_decl, name) class _ParamProxy(object): def __init__(self, type): @@ -884,7 +882,18 @@ class _ParamProxy(object): # E.g., Param.Int(5, "number of widgets") def __call__(self, *args, **kwargs): - return _Param(self.ptype, *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) def __getattr__(self, attr): if attr == '__bases__': @@ -938,8 +947,8 @@ class _VectorParam(_Param): else: return self.ptype._string(value) - def sim_decl(self, name): - return 'std::vector<%s> %s;' % (self.ptype._cppname, name) + def cpp_decl(self, name): + return 'std::vector<%s> %s;' % (self.ptype._cpp_param_decl, name) class _VectorParamProxy(_ParamProxy): # E.g., VectorParam.Int(5, "number of widgets") @@ -989,7 +998,7 @@ class CheckedInt(type): def __new__(cls, cppname, min, max): # New class derives from _CheckedInt base with proper bounding # parameters - dict = { '_cppname' : cppname, '_min' : min, '_max' : max } + dict = { '_cpp_param_decl' : cppname, '_min' : min, '_max' : max } return type.__new__(cls, cppname, (_CheckedInt, ), dict) class CheckedIntType(CheckedInt): @@ -1045,7 +1054,8 @@ def RangeSize(start, size): class Range(type): def __new__(cls, type): - dict = { '_cppname' : 'Range<%s>' % type._cppname, '_type' : 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) @@ -1053,7 +1063,7 @@ AddrRange = Range(Addr) # Boolean parameter type. class Bool(object): - _cppname = 'bool' + _cpp_param_decl = 'bool' def _convert(value): t = type(value) if t == bool: @@ -1081,7 +1091,7 @@ class Bool(object): # String-valued parameter. class String(object): - _cppname = 'string' + _cpp_param_decl = 'string' # Constructor. Value must be Python string. def _convert(cls,value): @@ -1121,7 +1131,7 @@ class NextEthernetAddr(object): self.addr = IncEthernetAddr(self.addr, inc) class EthernetAddr(object): - _cppname = 'EthAddr' + _cpp_param_decl = 'EthAddr' def _convert(cls, value): if value == NextEthernetAddr: @@ -1153,15 +1163,10 @@ class EthernetAddr(object): # only one copy of a particular node class NullSimObject(object): __metaclass__ = Singleton - _cppname = 'NULL' def __call__(cls): return cls - def _sim_code(cls): - pass - _sim_code = classmethod(_sim_code) - def _instantiate(self, parent = None, path = ''): pass @@ -1198,12 +1203,48 @@ Null = NULL = NullSimObject() # derive the new type from the appropriate base class on the fly. -# Base class for Enum types. -class _Enum(object): +# Metaclass for Enum types +class MetaEnum(type): + + def __init__(cls, name, bases, init_dict): + if init_dict.has_key('map'): + if not isinstance(cls.map, dict): + raise TypeError, "Enum-derived class attribute 'map' " \ + "must be of type dict" + # build list of value strings from map + cls.vals = cls.map.keys() + cls.vals.sort() + elif init_dict.has_key('vals'): + if not isinstance(cls.vals, list): + raise TypeError, "Enum-derived class attribute 'vals' " \ + "must be of type list" + # build string->value map from vals sequence + cls.map = {} + for idx,val in enumerate(cls.vals): + cls.map[val] = idx + else: + raise TypeError, "Enum-derived class must define "\ + "attribute 'map' or 'vals'" + + cls._cpp_param_decl = name + + super(MetaEnum, cls).__init__(name, bases, init_dict) + + def cpp_declare(cls): + s = 'enum %s {\n ' % cls.__name__ + s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals]) + s += '\n};\n' + return s + +# Base class for enum types. +class Enum(object): + __metaclass__ = MetaEnum + vals = [] + def _convert(self, value): if value not in self.map: raise TypeError, "Enum param got bad value '%s' (not in %s)" \ - % (value, self.map) + % (value, self.vals) return value _convert = classmethod(_convert) @@ -1211,36 +1252,6 @@ class _Enum(object): def _string(self, value): return str(value) _string = classmethod(_string) - -# Enum metaclass... calling Enum(foo) generates a new type (class) -# that derives from _ListEnum or _DictEnum as appropriate. -class Enum(type): - # counter to generate unique names for generated classes - counter = 1 - - def __new__(cls, *args): - if len(args) > 1: - enum_map = args - else: - enum_map = args[0] - - if isinstance(enum_map, dict): - map = enum_map - elif issequence(enum_map): - map = {} - for idx,val in enumerate(enum_map): - map[val] = idx - else: - raise TypeError, "Enum map must be list or dict (got %s)" % map - - classname = "Enum%04d" % Enum.counter - Enum.counter += 1 - - # New class derives from _Enum base, and gets a 'map' - # attribute containing the specified list or dict. - return type.__new__(cls, classname, (_Enum, ), { 'map': map }) - - # # "Constants"... handy aliases for various values. # @@ -1275,5 +1286,18 @@ def instantiate(root): dot.write("config.dot") dot.write_ps("config.ps") +# SimObject is a minimal extension of ConfigNode, implementing a +# hierarchy node that corresponds to an M5 SimObject. It prints out a +# "type=" line to indicate its SimObject class, prints out the +# assigned parameters corresponding to its class, and allows +# 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): + __metaclass__ = MetaSimObject + type = 'SimObject' + from objects import * +cpp_classes = MetaSimObject.cpp_classes +cpp_classes.sort() diff --git a/util/pbs/jobfile.py b/util/pbs/jobfile.py index 570faa61b..83eb81358 100644 --- a/util/pbs/jobfile.py +++ b/util/pbs/jobfile.py @@ -26,7 +26,9 @@ # # Authors: Nathan Binkert -from os.path import expanduser +from os.path import expanduser, isfile, join as joinpath +import sys + def crossproduct(options): number = len(options) indexes = [ 0 ] * number @@ -49,9 +51,16 @@ def crossproduct(options): done = next() class JobFile(object): - def __init__(self, file): + def __init__(self, jfile): self.data = {} - execfile(expanduser(file), self.data) + jfile = expanduser(jfile) + if not isfile(jfile): + for p in sys.path: + if isfile(joinpath(p, jfile)): + jfile = joinpath(p, jfile) + break + + execfile(jfile, self.data) self.options = self.data['options'] self.environment = self.data['environment'] self.jobinfo = {} diff --git a/util/tracediff b/util/tracediff index 402abbe55..87210f1ed 100755 --- a/util/tracediff +++ b/util/tracediff @@ -51,12 +51,15 @@ $sim2 = shift; # be given to both invocations $simargs = '"' . join('" "', @ARGV) . '"'; -# Redirect config output to cout so that gets diffed too (in case -# that's the source of the problem). -$simargs .= " --root:config_output_file=cout"; +# Run individual invocations in separate dirs so output and intermediate +# files (particularly config.py and config.ini) don't conflict. +$dir1 = "tracediff-$$-1"; +$dir2 = "tracediff-$$-2"; +mkdir($dir1) or die "Can't create dir $dir1\n"; +mkdir($dir2) or die "Can't create dir $dir2\n"; -$cmd1 = "$sim1 $simargs --stats:text_file=tracediff-$$-1.stats 2>&1 |"; -$cmd2 = "$sim2 $simargs --stats:text_file=tracediff-$$-2.stats 2>&1 |"; +$cmd1 = "$sim1 $simargs -d $dir1 2>&1 |"; +$cmd2 = "$sim2 $simargs -d $dir2 2>&1 |"; # This only works if you have rundiff in your path. I just edit it # with an explicit path if necessary.