Move SimObject creation and Port connection loops
into Python. Add Port and VectorPort objects and support for specifying port connections via assignment. The whole C++ ConfigNode hierarchy is gone now, as are C++ Connector objects. configs/test/fs.py: configs/test/test.py: Rewrite for new port connector syntax. src/SConscript: Remove unneeded files: - mem/connector.* - sim/config* src/dev/io_device.hh: src/mem/bridge.cc: src/mem/bridge.hh: src/mem/bus.cc: src/mem/bus.hh: src/mem/mem_object.hh: src/mem/physical.cc: src/mem/physical.hh: Allow getPort() to take an optional index to support vector ports (eventually). src/python/m5/__init__.py: Move SimObject construction and port connection operations into Python (with C++ calls). src/python/m5/config.py: Move SimObject construction and port connection operations into Python (with C++ calls). Add support for declaring and connecting MemObject ports in Python. src/python/m5/objects/Bus.py: src/python/m5/objects/PhysicalMemory.py: Add port declaration. src/sim/builder.cc: src/sim/builder.hh: src/sim/serialize.cc: src/sim/serialize.hh: ConfigNodes are gone; builder just gets the name of a .ini file section now. src/sim/main.cc: Move SimObject construction and port connection operations into Python (with C++ calls). Split remaining initialization operations into two parts, loadIniFile() and finalInit(). src/sim/param.cc: src/sim/param.hh: SimObject resolution done globally in Python now (not via ConfigNode hierarchy). src/sim/sim_object.cc: Remove unneeded #include. --HG-- extra : convert_revision : 2fa4001eaaec0c9a4231ef6e854f8e156d930dfe
This commit is contained in:
parent
285b88a57b
commit
e981a97dec
23 changed files with 308 additions and 137 deletions
|
@ -154,40 +154,40 @@ class LinuxAlphaSystem(LinuxAlphaSystem):
|
||||||
magicbus2 = Bus(bus_id=1)
|
magicbus2 = Bus(bus_id=1)
|
||||||
bridge = Bridge()
|
bridge = Bridge()
|
||||||
physmem = PhysicalMemory(range = AddrRange('128MB'))
|
physmem = PhysicalMemory(range = AddrRange('128MB'))
|
||||||
c0a = Connector(side_a=Parent.magicbus, side_b=Parent.bridge, side_b_name="side_a")
|
bridge.side_a = magicbus
|
||||||
c0b = Connector(side_a=Parent.magicbus2, side_b=Parent.bridge, side_b_name="side_b")
|
bridge.side_b = magicbus2
|
||||||
c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus2)
|
c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus2)
|
||||||
tsunami = LinuxTsunami()
|
tsunami = LinuxTsunami()
|
||||||
c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.cchip.pio = magicbus
|
||||||
c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.pchip.pio = magicbus
|
||||||
c4 = Connector(side_a=Parent.tsunami.pciconfig, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.pciconfig.pio = magicbus
|
||||||
c5 = Connector(side_a=Parent.tsunami.fake_sm_chip, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_sm_chip.pio = magicbus
|
||||||
c6 = Connector(side_a=Parent.tsunami.ethernet, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.ethernet.pio = magicbus
|
||||||
c6a = Connector(side_a=Parent.tsunami.ethernet, side_a_name='dma', side_b=Parent.magicbus)
|
tsunami.ethernet.dma = magicbus
|
||||||
c7 = Connector(side_a=Parent.tsunami.fake_uart1, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_uart1.pio = magicbus
|
||||||
c8 = Connector(side_a=Parent.tsunami.fake_uart2, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_uart2.pio = magicbus
|
||||||
c9 = Connector(side_a=Parent.tsunami.fake_uart3, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_uart3.pio = magicbus
|
||||||
c10 = Connector(side_a=Parent.tsunami.fake_uart4, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_uart4.pio = magicbus
|
||||||
c11 = Connector(side_a=Parent.tsunami.ide, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.ide.pio = magicbus
|
||||||
c13 = Connector(side_a=Parent.tsunami.ide, side_a_name='dma', side_b=Parent.magicbus)
|
tsunami.ide.dma = magicbus
|
||||||
c12 = Connector(side_a=Parent.tsunami.fake_ppc, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_ppc.pio = magicbus
|
||||||
c14 = Connector(side_a=Parent.tsunami.fake_OROM, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_OROM.pio = magicbus
|
||||||
c16 = Connector(side_a=Parent.tsunami.fake_pnp_addr, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_addr.pio = magicbus
|
||||||
c17 = Connector(side_a=Parent.tsunami.fake_pnp_write, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_write.pio = magicbus
|
||||||
c18 = Connector(side_a=Parent.tsunami.fake_pnp_read0, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_read0.pio = magicbus
|
||||||
c19 = Connector(side_a=Parent.tsunami.fake_pnp_read1, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_read1.pio = magicbus
|
||||||
c20 = Connector(side_a=Parent.tsunami.fake_pnp_read2, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_read2.pio = magicbus
|
||||||
c21 = Connector(side_a=Parent.tsunami.fake_pnp_read3, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_read3.pio = magicbus
|
||||||
c22 = Connector(side_a=Parent.tsunami.fake_pnp_read4, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_read4.pio = magicbus
|
||||||
c23 = Connector(side_a=Parent.tsunami.fake_pnp_read5, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_read5.pio = magicbus
|
||||||
c24 = Connector(side_a=Parent.tsunami.fake_pnp_read6, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_read6.pio = magicbus
|
||||||
c25 = Connector(side_a=Parent.tsunami.fake_pnp_read7, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_pnp_read7.pio = magicbus
|
||||||
c27 = Connector(side_a=Parent.tsunami.fake_ata0, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_ata0.pio = magicbus
|
||||||
c28 = Connector(side_a=Parent.tsunami.fake_ata1, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fake_ata1.pio = magicbus
|
||||||
c30 = Connector(side_a=Parent.tsunami.fb, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.fb.pio = magicbus
|
||||||
c31 = Connector(side_a=Parent.tsunami.io, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.io.pio = magicbus
|
||||||
c32 = Connector(side_a=Parent.tsunami.uart, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.uart.pio = magicbus
|
||||||
c33 = Connector(side_a=Parent.tsunami.console, side_a_name='pio', side_b=Parent.magicbus)
|
tsunami.console.pio = magicbus
|
||||||
raw_image = RawDiskImage(image_file=disk('linux-latest.img'),
|
raw_image = RawDiskImage(image_file=disk('linux-latest.img'),
|
||||||
read_only=True)
|
read_only=True)
|
||||||
simple_disk = SimpleDisk(disk=Parent.raw_image)
|
simple_disk = SimpleDisk(disk=Parent.raw_image)
|
||||||
|
|
|
@ -41,7 +41,7 @@ cpu.workload = process
|
||||||
cpu.mem = magicbus
|
cpu.mem = magicbus
|
||||||
|
|
||||||
system = System(physmem = mem, cpu = cpu)
|
system = System(physmem = mem, cpu = cpu)
|
||||||
system.c1 = Connector(side_a = mem, side_b = magicbus)
|
mem.port = magicbus.port
|
||||||
root = Root(system = system)
|
root = Root(system = system)
|
||||||
|
|
||||||
# instantiate configuration
|
# instantiate configuration
|
||||||
|
|
|
@ -97,14 +97,12 @@ base_sources = Split('''
|
||||||
|
|
||||||
mem/bridge.cc
|
mem/bridge.cc
|
||||||
mem/bus.cc
|
mem/bus.cc
|
||||||
mem/connector.cc
|
|
||||||
mem/mem_object.cc
|
mem/mem_object.cc
|
||||||
mem/packet.cc
|
mem/packet.cc
|
||||||
mem/physical.cc
|
mem/physical.cc
|
||||||
mem/port.cc
|
mem/port.cc
|
||||||
|
|
||||||
sim/builder.cc
|
sim/builder.cc
|
||||||
sim/configfile.cc
|
|
||||||
sim/debug.cc
|
sim/debug.cc
|
||||||
sim/eventq.cc
|
sim/eventq.cc
|
||||||
sim/faults.cc
|
sim/faults.cc
|
||||||
|
|
|
@ -247,7 +247,7 @@ class PioDevice : public MemObject
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
virtual Port *getPort(const std::string &if_name)
|
virtual Port *getPort(const std::string &if_name, int idx = -1)
|
||||||
{
|
{
|
||||||
if (if_name == "pio") {
|
if (if_name == "pio") {
|
||||||
if (pioPort != NULL)
|
if (pioPort != NULL)
|
||||||
|
@ -309,7 +309,7 @@ class DmaDevice : public PioDevice
|
||||||
|
|
||||||
bool dmaPending() { return dmaPort->dmaPending(); }
|
bool dmaPending() { return dmaPort->dmaPending(); }
|
||||||
|
|
||||||
virtual Port *getPort(const std::string &if_name)
|
virtual Port *getPort(const std::string &if_name, int idx = -1)
|
||||||
{
|
{
|
||||||
if (if_name == "pio") {
|
if (if_name == "pio") {
|
||||||
if (pioPort != NULL)
|
if (pioPort != NULL)
|
||||||
|
|
|
@ -59,7 +59,7 @@ Bridge::Bridge(const std::string &n, int qsa, int qsb,
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
Bridge::getPort(const std::string &if_name)
|
Bridge::getPort(const std::string &if_name, int idx)
|
||||||
{
|
{
|
||||||
BridgePort *port;
|
BridgePort *port;
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ class Bridge : public MemObject
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** A function used to return the port associated with this bus object. */
|
/** A function used to return the port associated with this bus object. */
|
||||||
virtual Port *getPort(const std::string &if_name);
|
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#include "sim/builder.hh"
|
#include "sim/builder.hh"
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
Bus::getPort(const std::string &if_name)
|
Bus::getPort(const std::string &if_name, int idx)
|
||||||
{
|
{
|
||||||
// if_name ignored? forced to be empty?
|
// if_name ignored? forced to be empty?
|
||||||
int id = interfaces.size();
|
int id = interfaces.size();
|
||||||
|
|
|
@ -161,7 +161,7 @@ class Bus : public MemObject
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** A function used to return the port associated with this bus object. */
|
/** A function used to return the port associated with this bus object. */
|
||||||
virtual Port *getPort(const std::string &if_name);
|
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ class MemObject : public SimObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Additional function to return the Port of a memory object. */
|
/** Additional function to return the Port of a memory object. */
|
||||||
virtual Port *getPort(const std::string &if_name) = 0;
|
virtual Port *getPort(const std::string &if_name, int idx = -1) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__MEM_MEM_OBJECT_HH__
|
#endif //__MEM_MEM_OBJECT_HH__
|
||||||
|
|
|
@ -173,9 +173,9 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
PhysicalMemory::getPort(const std::string &if_name)
|
PhysicalMemory::getPort(const std::string &if_name, int idx)
|
||||||
{
|
{
|
||||||
if (if_name == "") {
|
if (if_name == "port" && idx == -1) {
|
||||||
if (port != NULL)
|
if (port != NULL)
|
||||||
panic("PhysicalMemory::getPort: additional port requested to memory!");
|
panic("PhysicalMemory::getPort: additional port requested to memory!");
|
||||||
port = new MemoryPort(name() + "-port", this);
|
port = new MemoryPort(name() + "-port", this);
|
||||||
|
|
|
@ -108,7 +108,7 @@ class PhysicalMemory : public MemObject
|
||||||
public:
|
public:
|
||||||
int deviceBlockSize();
|
int deviceBlockSize();
|
||||||
void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
|
void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
|
||||||
virtual Port *getPort(const std::string &if_name);
|
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||||
void virtual init();
|
void virtual init();
|
||||||
|
|
||||||
// fast back-door memory access for vtophys(), remote gdb, etc.
|
// fast back-door memory access for vtophys(), remote gdb, etc.
|
||||||
|
|
|
@ -80,6 +80,16 @@ build_env.update(defines.m5_build_env)
|
||||||
env = smartdict.SmartDict()
|
env = smartdict.SmartDict()
|
||||||
env.update(os.environ)
|
env.update(os.environ)
|
||||||
|
|
||||||
|
|
||||||
|
# Function to provide to C++ so it can look up instances based on paths
|
||||||
|
def resolveSimObject(name):
|
||||||
|
obj = config.instanceDict[name]
|
||||||
|
if not obj._ccObject:
|
||||||
|
obj.createCCObject()
|
||||||
|
if obj._ccObject == -1:
|
||||||
|
panic("resolveSimObject: recursive lookup error on %s" % name)
|
||||||
|
return obj._ccObject
|
||||||
|
|
||||||
# The final hook to generate .ini files. Called from the user script
|
# The final hook to generate .ini files. Called from the user script
|
||||||
# once the config is built.
|
# once the config is built.
|
||||||
def instantiate(root):
|
def instantiate(root):
|
||||||
|
@ -89,7 +99,10 @@ def instantiate(root):
|
||||||
root.print_ini()
|
root.print_ini()
|
||||||
sys.stdout.close() # close config.ini
|
sys.stdout.close() # close config.ini
|
||||||
sys.stdout = sys.__stdout__ # restore to original
|
sys.stdout = sys.__stdout__ # restore to original
|
||||||
main.initialize() # load config.ini into C++ and process it
|
main.loadIniFile(resolveSimObject) # load config.ini into C++
|
||||||
|
root.createCCObject()
|
||||||
|
root.connectPorts()
|
||||||
|
main.finalInit()
|
||||||
noDot = True # temporary until we fix dot
|
noDot = True # temporary until we fix dot
|
||||||
if not noDot:
|
if not noDot:
|
||||||
dot = pydot.Dot()
|
dot = pydot.Dot()
|
||||||
|
|
|
@ -133,6 +133,10 @@ class Singleton(type):
|
||||||
#
|
#
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# dict to look up SimObjects based on path
|
||||||
|
instanceDict = {}
|
||||||
|
|
||||||
def isSimObject(value):
|
def isSimObject(value):
|
||||||
return isinstance(value, SimObject)
|
return isinstance(value, SimObject)
|
||||||
|
|
||||||
|
@ -200,7 +204,8 @@ class MetaSimObject(type):
|
||||||
'type' : types.StringType }
|
'type' : types.StringType }
|
||||||
# Attributes that can be set any time
|
# Attributes that can be set any time
|
||||||
keywords = { 'check' : types.FunctionType,
|
keywords = { 'check' : types.FunctionType,
|
||||||
'children' : types.ListType }
|
'children' : types.ListType,
|
||||||
|
'ccObject' : types.ObjectType }
|
||||||
|
|
||||||
# __new__ is called before __init__, and is where the statements
|
# __new__ is called before __init__, and is where the statements
|
||||||
# in the body of the class definition get loaded into the class's
|
# in the body of the class definition get loaded into the class's
|
||||||
|
@ -233,6 +238,7 @@ class MetaSimObject(type):
|
||||||
# initialize required attributes
|
# initialize required attributes
|
||||||
cls._params = multidict()
|
cls._params = multidict()
|
||||||
cls._values = multidict()
|
cls._values = multidict()
|
||||||
|
cls._ports = multidict()
|
||||||
cls._instantiated = False # really instantiated or subclassed
|
cls._instantiated = False # really instantiated or subclassed
|
||||||
cls._anon_subclass_counter = 0
|
cls._anon_subclass_counter = 0
|
||||||
|
|
||||||
|
@ -248,6 +254,7 @@ class MetaSimObject(type):
|
||||||
if isinstance(base, MetaSimObject):
|
if isinstance(base, MetaSimObject):
|
||||||
cls._params.parent = base._params
|
cls._params.parent = base._params
|
||||||
cls._values.parent = base._values
|
cls._values.parent = base._values
|
||||||
|
cls._ports.parent = base._ports
|
||||||
base._instantiated = True
|
base._instantiated = True
|
||||||
|
|
||||||
# now process the _init_dict items
|
# now process the _init_dict items
|
||||||
|
@ -259,6 +266,10 @@ class MetaSimObject(type):
|
||||||
elif isinstance(val, ParamDesc):
|
elif isinstance(val, ParamDesc):
|
||||||
cls._new_param(key, val)
|
cls._new_param(key, val)
|
||||||
|
|
||||||
|
# port objects
|
||||||
|
elif isinstance(val, Port):
|
||||||
|
cls._ports[key] = val
|
||||||
|
|
||||||
# init-time-only keywords
|
# init-time-only keywords
|
||||||
elif cls.init_keywords.has_key(key):
|
elif cls.init_keywords.has_key(key):
|
||||||
cls._set_keyword(key, val, cls.init_keywords[key])
|
cls._set_keyword(key, val, cls.init_keywords[key])
|
||||||
|
@ -313,6 +324,10 @@ class MetaSimObject(type):
|
||||||
cls._set_keyword(attr, value, cls.keywords[attr])
|
cls._set_keyword(attr, value, cls.keywords[attr])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if cls._ports.has_key(attr):
|
||||||
|
self._ports[attr].connect(self, attr, value)
|
||||||
|
return
|
||||||
|
|
||||||
# must be SimObject param
|
# must be SimObject param
|
||||||
param = cls._params.get(attr, None)
|
param = cls._params.get(attr, None)
|
||||||
if param:
|
if param:
|
||||||
|
@ -428,6 +443,9 @@ class SimObject(object):
|
||||||
for key,val in kwargs.iteritems():
|
for key,val in kwargs.iteritems():
|
||||||
setattr(self, key, val)
|
setattr(self, key, val)
|
||||||
|
|
||||||
|
self._ccObject = None # pointer to C++ object
|
||||||
|
self._port_map = {} # map of port connections
|
||||||
|
|
||||||
# Use this instance as a template to create a new class.
|
# Use this instance as a template to create a new class.
|
||||||
def makeClass(self, memo = {}):
|
def makeClass(self, memo = {}):
|
||||||
cls = memo.get(self)
|
cls = memo.get(self)
|
||||||
|
@ -443,6 +461,11 @@ class SimObject(object):
|
||||||
"use makeClass() to make class first"
|
"use makeClass() to make class first"
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
|
if self._ports.has_key(attr):
|
||||||
|
# return reference that can be assigned to another port
|
||||||
|
# via __setattr__
|
||||||
|
return self._ports[attr].makeRef(self, attr)
|
||||||
|
|
||||||
if self._values.has_key(attr):
|
if self._values.has_key(attr):
|
||||||
return self._values[attr]
|
return self._values[attr]
|
||||||
|
|
||||||
|
@ -457,6 +480,11 @@ class SimObject(object):
|
||||||
object.__setattr__(self, attr, value)
|
object.__setattr__(self, attr, value)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self._ports.has_key(attr):
|
||||||
|
# set up port connection
|
||||||
|
self._ports[attr].connect(self, attr, value)
|
||||||
|
return
|
||||||
|
|
||||||
# must be SimObject param
|
# must be SimObject param
|
||||||
param = self._params.get(attr, None)
|
param = self._params.get(attr, None)
|
||||||
if param:
|
if param:
|
||||||
|
@ -554,6 +582,8 @@ class SimObject(object):
|
||||||
def print_ini(self):
|
def print_ini(self):
|
||||||
print '[' + self.path() + ']' # .ini section header
|
print '[' + self.path() + ']' # .ini section header
|
||||||
|
|
||||||
|
instanceDict[self.path()] = self
|
||||||
|
|
||||||
if hasattr(self, 'type') and not isinstance(self, ParamContext):
|
if hasattr(self, 'type') and not isinstance(self, ParamContext):
|
||||||
print 'type=%s' % self.type
|
print 'type=%s' % self.type
|
||||||
|
|
||||||
|
@ -585,6 +615,24 @@ class SimObject(object):
|
||||||
for child in child_names:
|
for child in child_names:
|
||||||
self._children[child].print_ini()
|
self._children[child].print_ini()
|
||||||
|
|
||||||
|
# Call C++ to create C++ object corresponding to this object and
|
||||||
|
# (recursively) all its children
|
||||||
|
def createCCObject(self):
|
||||||
|
if self._ccObject:
|
||||||
|
return
|
||||||
|
self._ccObject = -1
|
||||||
|
self._ccObject = m5.main.createSimObject(self.path())
|
||||||
|
for child in self._children.itervalues():
|
||||||
|
child.createCCObject()
|
||||||
|
|
||||||
|
# Create C++ port connections corresponding to the connections in
|
||||||
|
# _port_map (& recursively for all children)
|
||||||
|
def connectPorts(self):
|
||||||
|
for portRef in self._port_map.itervalues():
|
||||||
|
applyOrMap(portRef, 'ccConnect')
|
||||||
|
for child in self._children.itervalues():
|
||||||
|
child.connectPorts()
|
||||||
|
|
||||||
# generate output file for 'dot' to display as a pretty graph.
|
# generate output file for 'dot' to display as a pretty graph.
|
||||||
# this code is currently broken.
|
# this code is currently broken.
|
||||||
def outputDot(self, dot):
|
def outputDot(self, dot):
|
||||||
|
@ -1419,6 +1467,78 @@ MaxAddr = Addr.max
|
||||||
MaxTick = Tick.max
|
MaxTick = Tick.max
|
||||||
AllMemory = AddrRange(0, MaxAddr)
|
AllMemory = AddrRange(0, MaxAddr)
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# Port objects
|
||||||
|
#
|
||||||
|
# Ports are used to interconnect objects in the memory system.
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
# Port reference: encapsulates a reference to a particular port on a
|
||||||
|
# particular SimObject.
|
||||||
|
class PortRef(object):
|
||||||
|
def __init__(self, simobj, name, isVec):
|
||||||
|
self.simobj = simobj
|
||||||
|
self.name = name
|
||||||
|
self.index = -1
|
||||||
|
self.isVec = isVec # is this a vector port?
|
||||||
|
self.peer = None # not associated with another port yet
|
||||||
|
self.ccConnected = False # C++ port connection done?
|
||||||
|
|
||||||
|
# Set peer port reference. Called via __setattr__ as a result of
|
||||||
|
# a port assignment, e.g., "obj1.port1 = obj2.port2".
|
||||||
|
def setPeer(self, other):
|
||||||
|
if self.isVec:
|
||||||
|
curMap = self.simobj._port_map.get(self.name, [])
|
||||||
|
self.index = len(curMap)
|
||||||
|
curMap.append(other)
|
||||||
|
else:
|
||||||
|
curMap = self.simobj._port_map.get(self.name)
|
||||||
|
if curMap and not self.isVec:
|
||||||
|
print "warning: overwriting port", self.simobj, self.name
|
||||||
|
curMap = other
|
||||||
|
self.simobj._port_map[self.name] = curMap
|
||||||
|
self.peer = other
|
||||||
|
|
||||||
|
# Call C++ to create corresponding port connection between C++ objects
|
||||||
|
def ccConnect(self):
|
||||||
|
if self.ccConnected: # already done this
|
||||||
|
return
|
||||||
|
peer = self.peer
|
||||||
|
m5.main.connectPorts(self.simobj._ccObject, self.name, self.index,
|
||||||
|
peer.simobj._ccObject, peer.name, peer.index)
|
||||||
|
self.ccConnected = True
|
||||||
|
peer.ccConnected = True
|
||||||
|
|
||||||
|
# Port description object. Like a ParamDesc object, this represents a
|
||||||
|
# logical port in the SimObject class, not a particular port on a
|
||||||
|
# SimObject instance. The latter are represented by PortRef objects.
|
||||||
|
class Port(object):
|
||||||
|
def __init__(self, desc):
|
||||||
|
self.desc = desc
|
||||||
|
self.isVec = False
|
||||||
|
|
||||||
|
# Generate a PortRef for this port on the given SimObject with the
|
||||||
|
# given name
|
||||||
|
def makeRef(self, simobj, name):
|
||||||
|
return PortRef(simobj, name, self.isVec)
|
||||||
|
|
||||||
|
# Connect an instance of this port (on the given SimObject with
|
||||||
|
# the given name) with the port described by the supplied PortRef
|
||||||
|
def connect(self, simobj, name, ref):
|
||||||
|
myRef = self.makeRef(simobj, name)
|
||||||
|
myRef.setPeer(ref)
|
||||||
|
ref.setPeer(myRef)
|
||||||
|
|
||||||
|
# VectorPort description object. Like Port, but represents a vector
|
||||||
|
# of connections (e.g., as on a Bus).
|
||||||
|
class VectorPort(Port):
|
||||||
|
def __init__(self, desc):
|
||||||
|
Port.__init__(self, desc)
|
||||||
|
self.isVec = True
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
# __all__ defines the list of symbols that get exported when
|
# __all__ defines the list of symbols that get exported when
|
||||||
|
@ -1436,5 +1556,6 @@ __all__ = ['SimObject', 'ParamContext', 'Param', 'VectorParam',
|
||||||
'NetworkBandwidth', 'MemoryBandwidth',
|
'NetworkBandwidth', 'MemoryBandwidth',
|
||||||
'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory',
|
'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory',
|
||||||
'Null', 'NULL',
|
'Null', 'NULL',
|
||||||
'NextEthernetAddr']
|
'NextEthernetAddr',
|
||||||
|
'Port', 'VectorPort']
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,5 @@ from MemObject import MemObject
|
||||||
|
|
||||||
class Bus(MemObject):
|
class Bus(MemObject):
|
||||||
type = 'Bus'
|
type = 'Bus'
|
||||||
|
port = VectorPort("vector port for connecting devices")
|
||||||
bus_id = Param.Int(0, "blah")
|
bus_id = Param.Int(0, "blah")
|
||||||
|
|
|
@ -3,6 +3,7 @@ from MemObject import *
|
||||||
|
|
||||||
class PhysicalMemory(MemObject):
|
class PhysicalMemory(MemObject):
|
||||||
type = 'PhysicalMemory'
|
type = 'PhysicalMemory'
|
||||||
|
port = Port("the access port")
|
||||||
range = Param.AddrRange("Device Address")
|
range = Param.AddrRange("Device Address")
|
||||||
file = Param.String('', "memory mapped file")
|
file = Param.String('', "memory mapped file")
|
||||||
latency = Param.Latency(Parent.clock, "latency of an access")
|
latency = Param.Latency(Parent.clock, "latency of an access")
|
||||||
|
|
|
@ -33,17 +33,14 @@
|
||||||
#include "base/inifile.hh"
|
#include "base/inifile.hh"
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "sim/builder.hh"
|
#include "sim/builder.hh"
|
||||||
#include "sim/configfile.hh"
|
|
||||||
#include "sim/config_node.hh"
|
|
||||||
#include "sim/host.hh"
|
#include "sim/host.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
#include "sim/root.hh"
|
#include "sim/root.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
SimObjectBuilder::SimObjectBuilder(ConfigNode *_configNode)
|
SimObjectBuilder::SimObjectBuilder(const std::string &_iniSection)
|
||||||
: ParamContext(_configNode->getPath(), NoAutoInit),
|
: ParamContext(_iniSection, NoAutoInit)
|
||||||
configNode(_configNode)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,8 +75,7 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
|
||||||
void
|
void
|
||||||
SimObjectBuilder::printErrorProlog(ostream &os)
|
SimObjectBuilder::printErrorProlog(ostream &os)
|
||||||
{
|
{
|
||||||
ccprintf(os, "Error creating object '%s' of type '%s':\n",
|
ccprintf(os, "Error creating object '%s':\n", iniSection);
|
||||||
iniSection, configNode->getType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,9 +108,13 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
SimObject *
|
SimObject *
|
||||||
SimObjectClass::createObject(IniFile &configDB, ConfigNode *configNode)
|
SimObjectClass::createObject(IniFile &configDB, const std::string &iniSection)
|
||||||
{
|
{
|
||||||
const string &type = configNode->getType();
|
string type;
|
||||||
|
if (!configDB.find(iniSection, "type", type)) {
|
||||||
|
// no C++ type associated with this object
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// look up className to get appropriate createFunc
|
// look up className to get appropriate createFunc
|
||||||
if (classMap->find(type) == classMap->end())
|
if (classMap->find(type) == classMap->end())
|
||||||
|
@ -125,7 +125,7 @@ SimObjectClass::createObject(IniFile &configDB, ConfigNode *configNode)
|
||||||
|
|
||||||
// call createFunc with config hierarchy node to get object
|
// call createFunc with config hierarchy node to get object
|
||||||
// builder instance (context with parameters for object creation)
|
// builder instance (context with parameters for object creation)
|
||||||
SimObjectBuilder *objectBuilder = (*createFunc)(configNode);
|
SimObjectBuilder *objectBuilder = (*createFunc)(iniSection);
|
||||||
|
|
||||||
assert(objectBuilder != NULL);
|
assert(objectBuilder != NULL);
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ SimObjectClass::describeAllClasses(ostream &os)
|
||||||
os << "[" << className << "]\n";
|
os << "[" << className << "]\n";
|
||||||
|
|
||||||
// create dummy object builder just to instantiate parameters
|
// create dummy object builder just to instantiate parameters
|
||||||
SimObjectBuilder *objectBuilder = (*createFunc)(NULL);
|
SimObjectBuilder *objectBuilder = (*createFunc)("");
|
||||||
|
|
||||||
// now get the object builder to describe ite params
|
// now get the object builder to describe ite params
|
||||||
objectBuilder->describeParams(os);
|
objectBuilder->describeParams(os);
|
||||||
|
|
|
@ -55,14 +55,8 @@ class SimObject;
|
||||||
//
|
//
|
||||||
class SimObjectBuilder : public ParamContext
|
class SimObjectBuilder : public ParamContext
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
// The corresponding node in the configuration hierarchy.
|
|
||||||
// (optional: may be null if the created object is not in the
|
|
||||||
// hierarchy)
|
|
||||||
ConfigNode *configNode;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SimObjectBuilder(ConfigNode *_configNode);
|
SimObjectBuilder(const std::string &_iniSection);
|
||||||
|
|
||||||
virtual ~SimObjectBuilder();
|
virtual ~SimObjectBuilder();
|
||||||
|
|
||||||
|
@ -77,9 +71,6 @@ class SimObjectBuilder : public ParamContext
|
||||||
// configuration hierarchy node label and position)
|
// configuration hierarchy node label and position)
|
||||||
virtual const std::string &getInstanceName() { return iniSection; }
|
virtual const std::string &getInstanceName() { return iniSection; }
|
||||||
|
|
||||||
// return the configuration hierarchy node for this context.
|
|
||||||
virtual ConfigNode *getConfigNode() { return configNode; }
|
|
||||||
|
|
||||||
// Create the actual SimObject corresponding to the parameter
|
// Create the actual SimObject corresponding to the parameter
|
||||||
// values in this context. This function is overridden in derived
|
// values in this context. This function is overridden in derived
|
||||||
// classes to call a specific constructor for a particular
|
// classes to call a specific constructor for a particular
|
||||||
|
@ -125,7 +116,7 @@ class SimObjectClass
|
||||||
// for the object (specified by the second string argument), and
|
// for the object (specified by the second string argument), and
|
||||||
// an optional config hierarchy node (specified by the third
|
// an optional config hierarchy node (specified by the third
|
||||||
// argument). A pointer to the new SimObjectBuilder is returned.
|
// argument). A pointer to the new SimObjectBuilder is returned.
|
||||||
typedef SimObjectBuilder *(*CreateFunc)(ConfigNode *configNode);
|
typedef SimObjectBuilder *(*CreateFunc)(const std::string &iniSection);
|
||||||
|
|
||||||
static std::map<std::string,CreateFunc> *classMap;
|
static std::map<std::string,CreateFunc> *classMap;
|
||||||
|
|
||||||
|
@ -137,7 +128,8 @@ class SimObjectClass
|
||||||
|
|
||||||
// create SimObject given name of class and pointer to
|
// create SimObject given name of class and pointer to
|
||||||
// configuration hierarchy node
|
// configuration hierarchy node
|
||||||
static SimObject *createObject(IniFile &configDB, ConfigNode *configNode);
|
static SimObject *createObject(IniFile &configDB,
|
||||||
|
const std::string &iniSection);
|
||||||
|
|
||||||
// print descriptions of all parameters registered with all
|
// print descriptions of all parameters registered with all
|
||||||
// SimObject classes
|
// SimObject classes
|
||||||
|
@ -156,15 +148,15 @@ class OBJ_CLASS##Builder : public SimObjectBuilder \
|
||||||
|
|
||||||
#define END_DECLARE_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
#define END_DECLARE_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
||||||
\
|
\
|
||||||
OBJ_CLASS##Builder(ConfigNode *configNode); \
|
OBJ_CLASS##Builder(const std::string &iniSection); \
|
||||||
virtual ~OBJ_CLASS##Builder() {} \
|
virtual ~OBJ_CLASS##Builder() {} \
|
||||||
\
|
\
|
||||||
OBJ_CLASS *create(); \
|
OBJ_CLASS *create(); \
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BEGIN_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
#define BEGIN_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
||||||
OBJ_CLASS##Builder::OBJ_CLASS##Builder(ConfigNode *configNode) \
|
OBJ_CLASS##Builder::OBJ_CLASS##Builder(const std::string &iSec) \
|
||||||
: SimObjectBuilder(configNode),
|
: SimObjectBuilder(iSec),
|
||||||
|
|
||||||
|
|
||||||
#define END_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
#define END_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
|
||||||
|
@ -176,9 +168,9 @@ OBJ_CLASS *OBJ_CLASS##Builder::create()
|
||||||
|
|
||||||
#define REGISTER_SIM_OBJECT(CLASS_NAME, OBJ_CLASS) \
|
#define REGISTER_SIM_OBJECT(CLASS_NAME, OBJ_CLASS) \
|
||||||
SimObjectBuilder * \
|
SimObjectBuilder * \
|
||||||
new##OBJ_CLASS##Builder(ConfigNode *configNode) \
|
new##OBJ_CLASS##Builder(const std::string &iniSection) \
|
||||||
{ \
|
{ \
|
||||||
return new OBJ_CLASS##Builder(configNode); \
|
return new OBJ_CLASS##Builder(iniSection); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
SimObjectClass the##OBJ_CLASS##Class(CLASS_NAME, \
|
SimObjectClass the##OBJ_CLASS##Class(CLASS_NAME, \
|
||||||
|
|
115
src/sim/main.cc
115
src/sim/main.cc
|
@ -57,9 +57,10 @@
|
||||||
#include "base/time.hh"
|
#include "base/time.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/smt.hh"
|
#include "cpu/smt.hh"
|
||||||
|
#include "mem/mem_object.hh"
|
||||||
|
#include "mem/port.hh"
|
||||||
#include "sim/async.hh"
|
#include "sim/async.hh"
|
||||||
#include "sim/builder.hh"
|
#include "sim/builder.hh"
|
||||||
#include "sim/configfile.hh"
|
|
||||||
#include "sim/host.hh"
|
#include "sim/host.hh"
|
||||||
#include "sim/sim_events.hh"
|
#include "sim/sim_events.hh"
|
||||||
#include "sim/sim_exit.hh"
|
#include "sim/sim_exit.hh"
|
||||||
|
@ -296,26 +297,109 @@ main(int argc, char **argv)
|
||||||
Py_Finalize();
|
Py_Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IniFile inifile;
|
||||||
|
|
||||||
/// Initialize C++ configuration. Exported to Python via SWIG; invoked
|
SimObject *
|
||||||
/// from m5.instantiate().
|
createSimObject(const string &name)
|
||||||
void
|
|
||||||
initialize()
|
|
||||||
{
|
{
|
||||||
|
return SimObjectClass::createObject(inifile, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to the Python function that maps names to SimObjects.
|
||||||
|
*/
|
||||||
|
PyObject *resolveFunc = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a pointer to the Python object that SWIG wraps around a C++
|
||||||
|
* SimObject pointer back to the actual C++ pointer. See main.i.
|
||||||
|
*/
|
||||||
|
extern "C" SimObject *convertSwigSimObjectPtr(PyObject *);
|
||||||
|
|
||||||
|
|
||||||
|
SimObject *
|
||||||
|
resolveSimObject(const string &name)
|
||||||
|
{
|
||||||
|
PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str());
|
||||||
|
if (pyPtr == NULL) {
|
||||||
|
PyErr_Print();
|
||||||
|
panic("resolveSimObject: failure on call to Python for %s", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
SimObject *simObj = convertSwigSimObjectPtr(pyPtr);
|
||||||
|
if (simObj == NULL)
|
||||||
|
panic("resolveSimObject: failure on pointer conversion for %s", name);
|
||||||
|
|
||||||
|
return simObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load config.ini into C++ database. Exported to Python via SWIG;
|
||||||
|
* invoked from m5.instantiate().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
loadIniFile(PyObject *_resolveFunc)
|
||||||
|
{
|
||||||
|
resolveFunc = _resolveFunc;
|
||||||
configStream = simout.find("config.out");
|
configStream = simout.find("config.out");
|
||||||
|
|
||||||
// The configuration database is now complete; start processing it.
|
// The configuration database is now complete; start processing it.
|
||||||
IniFile inifile;
|
|
||||||
inifile.load("config.ini");
|
inifile.load("config.ini");
|
||||||
|
|
||||||
// Initialize statistics database
|
// Initialize statistics database
|
||||||
Stats::InitSimStats();
|
Stats::InitSimStats();
|
||||||
|
}
|
||||||
|
|
||||||
// Now process the configuration hierarchy and create the SimObjects.
|
|
||||||
ConfigHierarchy configHierarchy(inifile);
|
|
||||||
configHierarchy.build();
|
|
||||||
configHierarchy.createSimObjects();
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a MemObject port. Helper function for connectPorts().
|
||||||
|
*/
|
||||||
|
Port *
|
||||||
|
lookupPort(SimObject *so, const std::string &name, int i)
|
||||||
|
{
|
||||||
|
MemObject *mo = dynamic_cast<MemObject *>(so);
|
||||||
|
if (mo == NULL) {
|
||||||
|
warn("error casting SimObject %s to MemObject", so->name());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Port *p = mo->getPort(name, i);
|
||||||
|
if (p == NULL)
|
||||||
|
warn("error looking up port %s on object %s", name, so->name());
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect the described MemObject ports. Called from Python via SWIG.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
connectPorts(SimObject *o1, const std::string &name1, int i1,
|
||||||
|
SimObject *o2, const std::string &name2, int i2)
|
||||||
|
{
|
||||||
|
Port *p1 = lookupPort(o1, name1, i1);
|
||||||
|
Port *p2 = lookupPort(o2, name2, i2);
|
||||||
|
|
||||||
|
if (p1 == NULL || p2 == NULL) {
|
||||||
|
warn("connectPorts: port lookup error");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p1->setPeer(p2);
|
||||||
|
p2->setPeer(p1);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do final initialization steps after object construction but before
|
||||||
|
* start of simulation.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
finalInit()
|
||||||
|
{
|
||||||
// Parse and check all non-config-hierarchy parameters.
|
// Parse and check all non-config-hierarchy parameters.
|
||||||
ParamContext::parseAllContexts(inifile);
|
ParamContext::parseAllContexts(inifile);
|
||||||
ParamContext::checkAllContexts();
|
ParamContext::checkAllContexts();
|
||||||
|
@ -323,20 +407,13 @@ initialize()
|
||||||
// Echo all parameter settings to stats file as well.
|
// Echo all parameter settings to stats file as well.
|
||||||
ParamContext::showAllContexts(*configStream);
|
ParamContext::showAllContexts(*configStream);
|
||||||
|
|
||||||
// Any objects that can't connect themselves until after construction should
|
|
||||||
// do so now
|
|
||||||
SimObject::connectAll();
|
|
||||||
|
|
||||||
// Do a second pass to finish initializing the sim objects
|
// Do a second pass to finish initializing the sim objects
|
||||||
SimObject::initAll();
|
SimObject::initAll();
|
||||||
|
|
||||||
// Restore checkpointed state, if any.
|
// Restore checkpointed state, if any.
|
||||||
|
#if 0
|
||||||
configHierarchy.unserializeSimObjects();
|
configHierarchy.unserializeSimObjects();
|
||||||
|
#endif
|
||||||
// Done processing the configuration database.
|
|
||||||
// Check for unreferenced entries.
|
|
||||||
if (inifile.printUnreferenced())
|
|
||||||
panic("unreferenced sections/entries in the intermediate ini file");
|
|
||||||
|
|
||||||
SimObject::regAllStats();
|
SimObject::regAllStats();
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,6 @@
|
||||||
#include "base/range.hh"
|
#include "base/range.hh"
|
||||||
#include "base/str.hh"
|
#include "base/str.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "sim/config_node.hh"
|
|
||||||
#include "sim/configfile.hh"
|
|
||||||
#include "sim/param.hh"
|
#include "sim/param.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
|
|
||||||
|
@ -521,7 +519,9 @@ parseSimObjectParam(ParamContext *context, const string &s, SimObject *&value)
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
obj = context->resolveSimObject(s);
|
// defined in main.cc
|
||||||
|
extern SimObject *resolveSimObject(const string &);
|
||||||
|
obj = resolveSimObject(s);
|
||||||
|
|
||||||
if (obj == NULL)
|
if (obj == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
@ -695,22 +695,6 @@ ParamContext::printErrorProlog(ostream &os)
|
||||||
os << "Parameter error in section [" << iniSection << "]: " << endl;
|
os << "Parameter error in section [" << iniSection << "]: " << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Resolve an object name to a SimObject pointer. The object will be
|
|
||||||
// created as a side-effect if necessary. If the name contains a
|
|
||||||
// colon (e.g., "iq:IQ"), then the object is local (invisible to
|
|
||||||
// outside this context). If there is no colon, the name needs to be
|
|
||||||
// resolved through the configuration hierarchy (only possible for
|
|
||||||
// SimObjectBuilder objects, which return non-NULL for configNode()).
|
|
||||||
//
|
|
||||||
SimObject *
|
|
||||||
ParamContext::resolveSimObject(const string &name)
|
|
||||||
{
|
|
||||||
ConfigNode *n = getConfigNode();
|
|
||||||
return n ? n->resolveSimObject(name) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// static method: call parseParams() on all registered contexts
|
// static method: call parseParams() on all registered contexts
|
||||||
//
|
//
|
||||||
|
|
|
@ -36,10 +36,10 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "sim/configfile.hh"
|
|
||||||
#include "sim/startup.hh"
|
#include "sim/startup.hh"
|
||||||
|
|
||||||
// forward decls
|
// forward decls
|
||||||
|
class IniFile;
|
||||||
class BaseParam;
|
class BaseParam;
|
||||||
class SimObject;
|
class SimObject;
|
||||||
|
|
||||||
|
@ -132,18 +132,10 @@ class ParamContext : protected StartupCallback
|
||||||
// print context information for parameter error
|
// print context information for parameter error
|
||||||
virtual void printErrorProlog(std::ostream &);
|
virtual void printErrorProlog(std::ostream &);
|
||||||
|
|
||||||
// resolve a SimObject name in this context to an object pointer.
|
|
||||||
virtual SimObject *resolveSimObject(const std::string &name);
|
|
||||||
|
|
||||||
// generate the name for this instance of this context (used as a
|
// generate the name for this instance of this context (used as a
|
||||||
// prefix to create unique names in resolveSimObject()
|
// prefix to create unique names in resolveSimObject()
|
||||||
virtual const std::string &getInstanceName() { return iniSection; }
|
virtual const std::string &getInstanceName() { return iniSection; }
|
||||||
|
|
||||||
// return the configuration hierarchy node for this context. Bare
|
|
||||||
// ParamContext objects have no corresponding node, so the default
|
|
||||||
// implementation returns NULL.
|
|
||||||
virtual ConfigNode *getConfigNode() { return NULL; }
|
|
||||||
|
|
||||||
// Parse all parameters registered with all ParamContext objects.
|
// Parse all parameters registered with all ParamContext objects.
|
||||||
static void parseAllContexts(IniFile &iniFile);
|
static void parseAllContexts(IniFile &iniFile);
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
#include "base/output.hh"
|
#include "base/output.hh"
|
||||||
#include "base/str.hh"
|
#include "base/str.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "sim/config_node.hh"
|
|
||||||
#include "sim/eventq.hh"
|
#include "sim/eventq.hh"
|
||||||
#include "sim/param.hh"
|
#include "sim/param.hh"
|
||||||
#include "sim/serialize.hh"
|
#include "sim/serialize.hh"
|
||||||
|
@ -442,9 +441,8 @@ Serializable::create(Checkpoint *cp, const std::string §ion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path,
|
Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path)
|
||||||
const ConfigNode *_configNode)
|
: db(new IniFile), basePath(path), cptDir(cpt_dir)
|
||||||
: db(new IniFile), basePath(path), configNode(_configNode), cptDir(cpt_dir)
|
|
||||||
{
|
{
|
||||||
string filename = cpt_dir + "/" + Checkpoint::baseFilename;
|
string filename = cpt_dir + "/" + Checkpoint::baseFilename;
|
||||||
if (!db->load(filename)) {
|
if (!db->load(filename)) {
|
||||||
|
@ -470,9 +468,6 @@ Checkpoint::findObj(const std::string §ion, const std::string &entry,
|
||||||
if (!db->find(section, entry, path))
|
if (!db->find(section, entry, path))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ((value = configNode->resolveSimObject(path)) != NULL)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if ((value = objMap[path]) != NULL)
|
if ((value = objMap[path]) != NULL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,8 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "sim/host.hh"
|
#include "sim/host.hh"
|
||||||
#include "sim/configfile.hh"
|
|
||||||
|
|
||||||
|
class IniFile;
|
||||||
class Serializable;
|
class Serializable;
|
||||||
class Checkpoint;
|
class Checkpoint;
|
||||||
|
|
||||||
|
@ -209,12 +209,10 @@ class Checkpoint
|
||||||
|
|
||||||
IniFile *db;
|
IniFile *db;
|
||||||
const std::string basePath;
|
const std::string basePath;
|
||||||
const ConfigNode *configNode;
|
|
||||||
std::map<std::string, Serializable*> objMap;
|
std::map<std::string, Serializable*> objMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Checkpoint(const std::string &cpt_dir, const std::string &path,
|
Checkpoint(const std::string &cpt_dir, const std::string &path);
|
||||||
const ConfigNode *_configNode);
|
|
||||||
|
|
||||||
const std::string cptDir;
|
const std::string cptDir;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "base/stats/events.hh"
|
#include "base/stats/events.hh"
|
||||||
#include "base/serializer.hh"
|
#include "base/serializer.hh"
|
||||||
#include "sim/configfile.hh"
|
|
||||||
#include "sim/host.hh"
|
#include "sim/host.hh"
|
||||||
#include "sim/sim_object.hh"
|
#include "sim/sim_object.hh"
|
||||||
#include "sim/stats.hh"
|
#include "sim/stats.hh"
|
||||||
|
|
Loading…
Reference in a new issue