Merge zizzer:/bk/m5 into zeep.eecs.umich.edu:/z/saidi/work/m5

--HG--
extra : convert_revision : a61ddd67647fc6a6e8e12d918cc71ae9da69f869
This commit is contained in:
Ali Saidi 2005-03-09 15:56:29 -05:00
commit 2897665685
14 changed files with 358 additions and 299 deletions

View file

@ -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

View file

@ -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."

View file

@ -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."

View file

@ -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

View file

@ -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

View file

@ -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 &section)
{
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 &section);
};
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 &section)
EtherLink::Link::unserialize(const string &base, Checkpoint *cp,
const string &section)
{
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 &section)
{
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 &section)
Serializable *
LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
{
EtherLink::Link *link;
UNSERIALIZE_OBJPTR(link);
return new LinkDelayEvent(link);
return new LinkDelayEvent();
}
REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)

View file

@ -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 &section);
void serialize(const std::string &base, std::ostream &os);
void unserialize(const std::string &base, Checkpoint *cp,
const std::string &section);
};
/*
@ -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();

View file

@ -4,10 +4,12 @@ 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')):
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,
@ -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

View file

@ -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'

View file

@ -1,6 +1,6 @@
from Pci import PciDevice
IdeID = Enum('master', 'slave')
class IdeID(Enum): vals = ['master', 'slave']
simobj IdeDisk(SimObject):
type = 'IdeDisk'

View file

@ -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)

View file

@ -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():
if key.startswith('_'):
cls_dict[key] = val
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)
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
# initialize attributes with values from class definition
for key,value in dict.iteritems():
# turn an expression that was munged in the importer
# 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], value)
setattr(c, key[-1], val)
# default: use normal path (ends up in __setattr__)
else:
setattr(cls, key, val)
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'):
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):
@ -470,16 +463,12 @@ class MetaConfigNode(type):
cls.add_child(instance, key, list)
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
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,15 +797,9 @@ 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)
def __getattr__(self, attr):
if attr == 'disable':
return self.obj._getdisable(self.attr)
else:
return getattr(self._getattr(), attr)
def __getitem__(self, 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()

View file

@ -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 = {}

View file

@ -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.