summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/test/fs.py87
-rw-r--r--configs/test/test.py2
-rw-r--r--src/SConscript2
-rw-r--r--src/dev/io_device.hh4
-rw-r--r--src/mem/bridge.cc2
-rw-r--r--src/mem/bridge.hh2
-rw-r--r--src/mem/bus.cc2
-rw-r--r--src/mem/bus.hh2
-rw-r--r--src/mem/mem_object.hh2
-rw-r--r--src/mem/physical.cc4
-rw-r--r--src/mem/physical.hh2
-rw-r--r--src/python/m5/__init__.py11
-rw-r--r--src/python/m5/config.py512
-rw-r--r--src/python/m5/objects/Bridge.py2
-rw-r--r--src/python/m5/objects/Bus.py1
-rw-r--r--src/python/m5/objects/Device.py2
-rw-r--r--src/python/m5/objects/PhysicalMemory.py1
-rw-r--r--src/sim/builder.cc22
-rw-r--r--src/sim/builder.hh26
-rw-r--r--src/sim/main.cc113
-rw-r--r--src/sim/param.cc22
-rw-r--r--src/sim/param.hh10
-rw-r--r--src/sim/serialize.cc9
-rw-r--r--src/sim/serialize.hh10
-rw-r--r--src/sim/sim_object.cc1
25 files changed, 477 insertions, 376 deletions
diff --git a/configs/test/fs.py b/configs/test/fs.py
index 55e7003a4..c742e916c 100644
--- a/configs/test/fs.py
+++ b/configs/test/fs.py
@@ -129,17 +129,7 @@ class BaseTsunami(Tsunami):
ethernet = NSGigE(configdata=NSGigEPciData(),
pci_bus=0, pci_dev=1, pci_func=0)
etherint = NSGigEInt(device=Parent.ethernet)
-# ethernet = Sinic(configdata=SinicPciData(),
-# pci_bus=0, pci_dev=1, pci_func=0)
-# etherint = SinicInt(device=Parent.ethernet)
console = AlphaConsole(pio_addr=0x80200000000, disk=Parent.simple_disk)
-# bridge = PciFake(configdata=BridgePciData(), pci_bus=0, pci_dev=2, pci_func=0)
-
-#class FreeBSDTsunami(BaseTsunami):
-# disk0 = FreeBSDRootDisk(delay='0us', driveID='master')
-# ide = IdeController(disks=[Parent.disk0],
-# configdata=IdeControllerPciData(),
-# pci_func=0, pci_dev=0, pci_bus=0)
class LinuxTsunami(BaseTsunami):
disk0 = LinuxRootDisk(driveID='master')
@@ -149,45 +139,45 @@ class LinuxTsunami(BaseTsunami):
configdata=IdeControllerPciData(),
pci_func=0, pci_dev=0, pci_bus=0)
-class LinuxAlphaSystem(LinuxAlphaSystem):
+class MyLinuxAlphaSystem(LinuxAlphaSystem):
magicbus = Bus(bus_id=0)
magicbus2 = Bus(bus_id=1)
bridge = Bridge()
physmem = PhysicalMemory(range = AddrRange('128MB'))
- c0a = Connector(side_a=Parent.magicbus, side_b=Parent.bridge, side_b_name="side_a")
- c0b = Connector(side_a=Parent.magicbus2, side_b=Parent.bridge, side_b_name="side_b")
- c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus2)
+ bridge.side_a = magicbus.port
+ bridge.side_b = magicbus2.port
+ physmem.port = magicbus2.port
tsunami = LinuxTsunami()
- c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus)
- c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus)
- c4 = Connector(side_a=Parent.tsunami.pciconfig, side_a_name='pio', side_b=Parent.magicbus)
- c5 = Connector(side_a=Parent.tsunami.fake_sm_chip, side_a_name='pio', side_b=Parent.magicbus)
- c6 = Connector(side_a=Parent.tsunami.ethernet, side_a_name='pio', side_b=Parent.magicbus)
- c6a = Connector(side_a=Parent.tsunami.ethernet, side_a_name='dma', side_b=Parent.magicbus)
- c7 = Connector(side_a=Parent.tsunami.fake_uart1, side_a_name='pio', side_b=Parent.magicbus)
- c8 = Connector(side_a=Parent.tsunami.fake_uart2, side_a_name='pio', side_b=Parent.magicbus)
- c9 = Connector(side_a=Parent.tsunami.fake_uart3, side_a_name='pio', side_b=Parent.magicbus)
- c10 = Connector(side_a=Parent.tsunami.fake_uart4, side_a_name='pio', side_b=Parent.magicbus)
- c11 = Connector(side_a=Parent.tsunami.ide, side_a_name='pio', side_b=Parent.magicbus)
- c13 = Connector(side_a=Parent.tsunami.ide, side_a_name='dma', side_b=Parent.magicbus)
- c12 = Connector(side_a=Parent.tsunami.fake_ppc, side_a_name='pio', side_b=Parent.magicbus)
- c14 = Connector(side_a=Parent.tsunami.fake_OROM, side_a_name='pio', side_b=Parent.magicbus)
- c16 = Connector(side_a=Parent.tsunami.fake_pnp_addr, side_a_name='pio', side_b=Parent.magicbus)
- c17 = Connector(side_a=Parent.tsunami.fake_pnp_write, side_a_name='pio', side_b=Parent.magicbus)
- c18 = Connector(side_a=Parent.tsunami.fake_pnp_read0, side_a_name='pio', side_b=Parent.magicbus)
- c19 = Connector(side_a=Parent.tsunami.fake_pnp_read1, side_a_name='pio', side_b=Parent.magicbus)
- c20 = Connector(side_a=Parent.tsunami.fake_pnp_read2, side_a_name='pio', side_b=Parent.magicbus)
- c21 = Connector(side_a=Parent.tsunami.fake_pnp_read3, side_a_name='pio', side_b=Parent.magicbus)
- c22 = Connector(side_a=Parent.tsunami.fake_pnp_read4, side_a_name='pio', side_b=Parent.magicbus)
- c23 = Connector(side_a=Parent.tsunami.fake_pnp_read5, side_a_name='pio', side_b=Parent.magicbus)
- c24 = Connector(side_a=Parent.tsunami.fake_pnp_read6, side_a_name='pio', side_b=Parent.magicbus)
- c25 = Connector(side_a=Parent.tsunami.fake_pnp_read7, side_a_name='pio', side_b=Parent.magicbus)
- c27 = Connector(side_a=Parent.tsunami.fake_ata0, side_a_name='pio', side_b=Parent.magicbus)
- c28 = Connector(side_a=Parent.tsunami.fake_ata1, side_a_name='pio', side_b=Parent.magicbus)
- c30 = Connector(side_a=Parent.tsunami.fb, side_a_name='pio', side_b=Parent.magicbus)
- c31 = Connector(side_a=Parent.tsunami.io, side_a_name='pio', side_b=Parent.magicbus)
- c32 = Connector(side_a=Parent.tsunami.uart, side_a_name='pio', side_b=Parent.magicbus)
- c33 = Connector(side_a=Parent.tsunami.console, side_a_name='pio', side_b=Parent.magicbus)
+ tsunami.cchip.pio = magicbus.port
+ tsunami.pchip.pio = magicbus.port
+ tsunami.pciconfig.pio = magicbus.port
+ tsunami.fake_sm_chip.pio = magicbus.port
+ tsunami.ethernet.pio = magicbus.port
+ tsunami.ethernet.dma = magicbus.port
+ tsunami.fake_uart1.pio = magicbus.port
+ tsunami.fake_uart2.pio = magicbus.port
+ tsunami.fake_uart3.pio = magicbus.port
+ tsunami.fake_uart4.pio = magicbus.port
+ tsunami.ide.pio = magicbus.port
+ tsunami.ide.dma = magicbus.port
+ tsunami.fake_ppc.pio = magicbus.port
+ tsunami.fake_OROM.pio = magicbus.port
+ tsunami.fake_pnp_addr.pio = magicbus.port
+ tsunami.fake_pnp_write.pio = magicbus.port
+ tsunami.fake_pnp_read0.pio = magicbus.port
+ tsunami.fake_pnp_read1.pio = magicbus.port
+ tsunami.fake_pnp_read2.pio = magicbus.port
+ tsunami.fake_pnp_read3.pio = magicbus.port
+ tsunami.fake_pnp_read4.pio = magicbus.port
+ tsunami.fake_pnp_read5.pio = magicbus.port
+ tsunami.fake_pnp_read6.pio = magicbus.port
+ tsunami.fake_pnp_read7.pio = magicbus.port
+ tsunami.fake_ata0.pio = magicbus.port
+ tsunami.fake_ata1.pio = magicbus.port
+ tsunami.fb.pio = magicbus.port
+ tsunami.io.pio = magicbus.port
+ tsunami.uart.pio = magicbus.port
+ tsunami.console.pio = magicbus.port
raw_image = RawDiskImage(image_file=disk('linux-latest.img'),
read_only=True)
simple_disk = SimpleDisk(disk=Parent.raw_image)
@@ -196,7 +186,7 @@ class LinuxAlphaSystem(LinuxAlphaSystem):
cpu = TimingSimpleCPU()
else:
cpu = AtomicSimpleCPU()
- cpu.mem = Parent.magicbus2
+ cpu.mem = magicbus2
cpu.itb = AlphaITB()
cpu.dtb = AlphaDTB()
sim_console = SimConsole(listener=ConsoleListener(port=3456))
@@ -224,11 +214,12 @@ def DualRoot(clientSystem, serverSystem):
self.clock = '5GHz'
return self
-root = DualRoot(LinuxAlphaSystem(readfile=script('netperf-stream-nt-client.rcS')),
- LinuxAlphaSystem(readfile=script('netperf-server.rcS')))
+root = DualRoot(
+ MyLinuxAlphaSystem(readfile=script('netperf-stream-nt-client.rcS')),
+ MyLinuxAlphaSystem(readfile=script('netperf-server.rcS')))
m5.instantiate(root)
exit_event = m5.simulate()
-print 'Exiting @', m5.curTick(), 'because', exit_event.getCause()
+print 'Exiting @ cycle', m5.curTick(), 'because', exit_event.getCause()
diff --git a/configs/test/test.py b/configs/test/test.py
index 9ab5f6e00..251755e71 100644
--- a/configs/test/test.py
+++ b/configs/test/test.py
@@ -41,7 +41,7 @@ cpu.workload = process
cpu.mem = magicbus
system = System(physmem = mem, cpu = cpu)
-system.c1 = Connector(side_a = mem, side_b = magicbus)
+mem.port = magicbus.port
root = Root(system = system)
# instantiate configuration
diff --git a/src/SConscript b/src/SConscript
index a1c18711c..e6ed43804 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -97,14 +97,12 @@ base_sources = Split('''
mem/bridge.cc
mem/bus.cc
- mem/connector.cc
mem/mem_object.cc
mem/packet.cc
mem/physical.cc
mem/port.cc
sim/builder.cc
- sim/configfile.cc
sim/debug.cc
sim/eventq.cc
sim/faults.cc
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index 195ca0fb7..cd2c25eeb 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -247,7 +247,7 @@ class PioDevice : public MemObject
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 (pioPort != NULL)
@@ -309,7 +309,7 @@ class DmaDevice : public PioDevice
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 (pioPort != NULL)
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
index 3718cbaaf..29ea2e12f 100644
--- a/src/mem/bridge.cc
+++ b/src/mem/bridge.cc
@@ -59,7 +59,7 @@ Bridge::Bridge(const std::string &n, int qsa, int qsb,
}
Port *
-Bridge::getPort(const std::string &if_name)
+Bridge::getPort(const std::string &if_name, int idx)
{
BridgePort *port;
diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh
index 37fb92662..b3525d3e0 100644
--- a/src/mem/bridge.hh
+++ b/src/mem/bridge.hh
@@ -177,7 +177,7 @@ class Bridge : public MemObject
public:
/** 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();
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 919acd23c..19a3dc9e4 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -38,7 +38,7 @@
#include "sim/builder.hh"
Port *
-Bus::getPort(const std::string &if_name)
+Bus::getPort(const std::string &if_name, int idx)
{
// if_name ignored? forced to be empty?
int id = interfaces.size();
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 50bfba6e4..c2b78c31f 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -161,7 +161,7 @@ class Bus : public MemObject
public:
/** 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();
diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh
index ac547619d..c81ea03d8 100644
--- a/src/mem/mem_object.hh
+++ b/src/mem/mem_object.hh
@@ -50,7 +50,7 @@ class MemObject : public SimObject
public:
/** 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__
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index fb31fb4a3..2d66602ab 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -173,9 +173,9 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
}
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)
panic("PhysicalMemory::getPort: additional port requested to memory!");
port = new MemoryPort(name() + "-port", this);
diff --git a/src/mem/physical.hh b/src/mem/physical.hh
index 88ea543da..50fa75ed3 100644
--- a/src/mem/physical.hh
+++ b/src/mem/physical.hh
@@ -108,7 +108,7 @@ class PhysicalMemory : public MemObject
public:
int deviceBlockSize();
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();
// fast back-door memory access for vtophys(), remote gdb, etc.
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
index 2d4825b0e..f849a899b 100644
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -103,6 +103,12 @@ build_env.update(defines.m5_build_env)
env = smartdict.SmartDict()
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]
+ return obj.getCCObject()
+
# The final hook to generate .ini files. Called from the user script
# once the config is built.
def instantiate(root):
@@ -112,7 +118,10 @@ def instantiate(root):
root.print_ini()
sys.stdout.close() # close config.ini
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
if not noDot:
dot = pydot.Dot()
diff --git a/src/python/m5/config.py b/src/python/m5/config.py
index 97e13c900..058e72578 100644
--- a/src/python/m5/config.py
+++ b/src/python/m5/config.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# Copyright (c) 2004-2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
# Authors: Steve Reinhardt
# Nathan Binkert
-import os, re, sys, types, inspect
+import os, re, sys, types, inspect, copy
import m5
from m5 import panic
@@ -84,65 +84,22 @@ class Singleton(type):
#
# Once a set of Python objects have been instantiated in a hierarchy,
# calling 'instantiate(obj)' (where obj is the root of the hierarchy)
-# will generate a .ini file. See simple-4cpu.py for an example
-# (corresponding to m5-test/simple-4cpu.ini).
+# will generate a .ini file.
#
#####################################################################
-#####################################################################
-#
-# ConfigNode/SimObject classes
-#
-# The Python class hierarchy rooted by ConfigNode (which is the base
-# class of SimObject, which in turn is the base class of all other M5
-# SimObject classes) has special attribute behavior. In general, an
-# object in this hierarchy has three categories of attribute-like
-# things:
-#
-# 1. Regular Python methods and variables. These must start with an
-# underscore to be treated normally.
-#
-# 2. SimObject parameters. These values are stored as normal Python
-# attributes, but all assignments to these attributes are checked
-# against the pre-defined set of parameters stored in the class's
-# _params dictionary. Assignments to attributes that do not
-# correspond to predefined parameters, or that are not of the correct
-# type, incur runtime errors.
+# dict to look up SimObjects based on path
+instanceDict = {}
+
+#############################
#
-# 3. Hierarchy children. The child nodes of a ConfigNode are stored
-# in the node's _children dictionary, but can be accessed using the
-# Python attribute dot-notation (just as they are printed out by the
-# simulator). Children cannot be created using attribute assigment;
-# they must be added by specifying the parent node in the child's
-# constructor or using the '+=' operator.
-
-# The SimObject parameters are the most complex, for a few reasons.
-# First, both parameter descriptions and parameter values are
-# inherited. Thus parameter description lookup must go up the
-# inheritance chain like normal attribute lookup, but this behavior
-# must be explicitly coded since the lookup occurs in each class's
-# _params attribute. Second, because parameter values can be set
-# on SimObject classes (to implement default values), the parameter
-# checking behavior must be enforced on class attribute assignments as
-# well as instance attribute assignments. Finally, because we allow
-# class specialization via inheritance (e.g., see the L1Cache class in
-# the simple-4cpu.py example), we must do parameter checking even on
-# class instantiation. To provide all these features, we use a
-# metaclass to define most of the SimObject parameter behavior for
-# this class hierarchy.
+# Utility methods
#
-#####################################################################
+#############################
def isSimObject(value):
return isinstance(value, SimObject)
-def isSimObjectClass(value):
- try:
- return issubclass(value, SimObject)
- except TypeError:
- # happens if value is not a class at all
- return False
-
def isSimObjectSequence(value):
if not isinstance(value, (list, tuple)) or len(value) == 0:
return False
@@ -153,22 +110,9 @@ def isSimObjectSequence(value):
return True
-def isSimObjectClassSequence(value):
- if not isinstance(value, (list, tuple)) or len(value) == 0:
- return False
-
- for val in value:
- if not isNullPointer(val) and not isSimObjectClass(val):
- return False
-
- return True
-
def isSimObjectOrSequence(value):
return isSimObject(value) or isSimObjectSequence(value)
-def isSimObjectClassOrSequence(value):
- return isSimObjectClass(value) or isSimObjectClassSequence(value)
-
def isNullPointer(value):
return isinstance(value, NullSimObject)
@@ -188,40 +132,36 @@ def applyOrMap(objOrSeq, meth, *args, **kwargs):
return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq]
-# The metaclass for ConfigNode (and thus for everything that derives
-# from ConfigNode, including SimObject). This class controls how new
-# classes that derive from ConfigNode are instantiated, and provides
-# inherited class behavior (just like a class controls how instances
-# of that class are instantiated, and provides inherited instance
-# behavior).
+# The metaclass for SimObject. This class controls how new classes
+# that derive from SimObject are instantiated, and provides inherited
+# class behavior (just like a class controls how instances of that
+# class are instantiated, and provides inherited instance behavior).
class MetaSimObject(type):
# Attributes that can be set only at initialization time
init_keywords = { 'abstract' : types.BooleanType,
'type' : types.StringType }
# Attributes that can be set any time
- keywords = { 'check' : types.FunctionType,
- 'children' : types.ListType }
+ keywords = { 'check' : types.FunctionType }
# __new__ is called before __init__, and is where the statements
# in the body of the class definition get loaded into the class's
- # __dict__. We intercept this to filter out parameter assignments
+ # __dict__. We intercept this to filter out parameter & port assignments
# and only allow "private" attributes to be passed to the base
# __new__ (starting with underscore).
def __new__(mcls, name, bases, dict):
- if dict.has_key('_init_dict'):
- # must have been called from makeSubclass() rather than
- # via Python class declaration; bypass filtering process.
- cls_dict = dict
- else:
- # 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]
- cls_dict['_init_dict'] = dict
+ # Copy "private" attributes, functions, and classes to the
+ # official dict. Everything else goes in _init_dict to be
+ # filtered in __init__.
+ cls_dict = {}
+ value_dict = {}
+ for key,val in dict.items():
+ if key.startswith('_') or isinstance(val, (types.FunctionType,
+ types.TypeType)):
+ cls_dict[key] = val
+ else:
+ # must be a param/port setting
+ value_dict[key] = val
+ cls_dict['_value_dict'] = value_dict
return super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict)
# subclass initialization
@@ -231,10 +171,15 @@ class MetaSimObject(type):
super(MetaSimObject, cls).__init__(name, bases, dict)
# initialize required attributes
- cls._params = multidict()
- cls._values = multidict()
- cls._instantiated = False # really instantiated or subclassed
- cls._anon_subclass_counter = 0
+
+ # class-only attributes
+ cls._params = multidict() # param descriptions
+ cls._ports = multidict() # port descriptions
+
+ # class or instance attributes
+ cls._values = multidict() # param values
+ cls._port_map = multidict() # port bindings
+ cls._instantiated = False # really instantiated, cloned, or subclassed
# We don't support multiple inheritance. If you want to, you
# must fix multidict to deal with it properly.
@@ -243,22 +188,34 @@ class MetaSimObject(type):
base = bases[0]
- # the only time the following is not true is when we define
- # the SimObject class itself
+ # Set up general inheritance via multidicts. A subclass will
+ # inherit all its settings from the base class. The only time
+ # the following is not true is when we define the SimObject
+ # class itself (in which case the multidicts have no parent).
if isinstance(base, MetaSimObject):
cls._params.parent = base._params
+ cls._ports.parent = base._ports
cls._values.parent = base._values
+ cls._port_map.parent = base._port_map
+ # mark base as having been subclassed
base._instantiated = True
- # now process the _init_dict items
- for key,val in cls._init_dict.items():
- if isinstance(val, (types.FunctionType, types.TypeType)):
- type.__setattr__(cls, key, val)
-
+ # Now process the _value_dict items. They could be defining
+ # new (or overriding existing) parameters or ports, setting
+ # class keywords (e.g., 'abstract'), or setting parameter
+ # values or port bindings. The first 3 can only be set when
+ # the class is defined, so we handle them here. The others
+ # can be set later too, so just emulate that by calling
+ # setattr().
+ for key,val in cls._value_dict.items():
# param descriptions
- elif isinstance(val, ParamDesc):
+ if isinstance(val, ParamDesc):
cls._new_param(key, val)
+ # port objects
+ elif isinstance(val, Port):
+ cls._ports[key] = val
+
# init-time-only keywords
elif cls.init_keywords.has_key(key):
cls._set_keyword(key, val, cls.init_keywords[key])
@@ -267,27 +224,6 @@ class MetaSimObject(type):
else:
setattr(cls, key, val)
- # Pull the deep-copy memoization dict out of the class dict if
- # it's there...
- memo = cls.__dict__.get('_memo', {})
-
- # Handle SimObject values
- for key,val in cls._values.iteritems():
- # SimObject instances need to be promoted to classes.
- # Existing classes should not have any instance values, so
- # these can only occur at the lowest level dict (the
- # parameters just being set in this class definition).
- if isSimObjectOrSequence(val):
- assert(val == cls._values.local[key])
- cls._values[key] = applyOrMap(val, 'makeClass', memo)
- # SimObject classes need to be subclassed so that
- # parameters that get set at this level only affect this
- # level and derivatives.
- elif isSimObjectClassOrSequence(val):
- assert(not cls._values.local.has_key(key))
- cls._values[key] = applyOrMap(val, 'makeSubclass', {}, memo)
-
-
def _set_keyword(cls, keyword, val, kwtype):
if not isinstance(val, kwtype):
raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \
@@ -313,15 +249,19 @@ class MetaSimObject(type):
cls._set_keyword(attr, value, cls.keywords[attr])
return
- # must be SimObject param
- param = cls._params.get(attr, None)
- if param:
- # It's ok: set attribute by delegating to 'object' class.
- if isSimObjectOrSequence(value) and cls._instantiated:
- raise AttributeError, \
- "Cannot set SimObject parameter '%s' after\n" \
+ if cls._ports.has_key(attr):
+ self._ports[attr].connect(self, attr, value)
+ return
+
+ if isSimObjectOrSequence(value) and cls._instantiated:
+ raise RuntimeError, \
+ "cannot set SimObject parameter '%s' after\n" \
" class %s has been instantiated or subclassed" \
% (attr, cls.__name__)
+
+ # check for param
+ param = cls._params.get(attr, None)
+ if param:
try:
cls._values[attr] = param.convert(value)
except Exception, e:
@@ -329,9 +269,9 @@ class MetaSimObject(type):
(e, cls.__name__, attr, value)
e.args = (msg, )
raise
- # I would love to get rid of this
elif isSimObjectOrSequence(value):
- cls._values[attr] = value
+ # if RHS is a SimObject, it's an implicit child assignment
+ cls._values[attr] = value
else:
raise AttributeError, \
"Class %s has no parameter %s" % (cls.__name__, attr)
@@ -343,23 +283,7 @@ class MetaSimObject(type):
raise AttributeError, \
"object '%s' has no attribute '%s'" % (cls.__name__, attr)
- # Create a subclass of this class. Basically a function interface
- # to the standard Python class definition mechanism, primarily for
- # internal use. 'memo' dict param supports "deep copy" (really
- # "deep subclass") operations... within a given operation,
- # multiple references to a class should result in a single
- # subclass object with multiple references to it (as opposed to
- # mutiple unique subclasses).
- def makeSubclass(cls, init_dict, memo = {}):
- subcls = memo.get(cls)
- if not subcls:
- name = cls.__name__ + '_' + str(cls._anon_subclass_counter)
- cls._anon_subclass_counter += 1
- subcls = MetaSimObject(name, (cls,),
- { '_init_dict': init_dict, '_memo': memo })
- return subcls
-
-# The ConfigNode class is the root of the special hierarchy. Most of
+# The SimObject class is the root of the special hierarchy. Most of
# the code in this class deals with the configuration hierarchy itself
# (parent/child node relationships).
class SimObject(object):
@@ -367,82 +291,79 @@ class SimObject(object):
# get this metaclass.
__metaclass__ = MetaSimObject
- # __new__ operator allocates new instances of the class. We
- # override it here just to support "deep instantiation" operation
- # via the _memo dict. When recursively instantiating an object
- # hierarchy we want to make sure that each class is instantiated
- # only once, and that if there are multiple references to the same
- # original class, we end up with the corresponding instantiated
- # references all pointing to the same instance.
- def __new__(cls, _memo = None, **kwargs):
- if _memo is not None and _memo.has_key(cls):
- # return previously instantiated object
- assert(len(kwargs) == 0)
- return _memo[cls]
- else:
- # Need a new one... if it needs to be memoized, this will
- # happen in __init__. We defer the insertion until then
- # so __init__ can use the memo dict to tell whether or not
- # to perform the initialization.
- return super(SimObject, cls).__new__(cls, **kwargs)
-
- # Initialize new instance previously allocated by __new__. For
- # objects with SimObject-valued params, we need to recursively
- # instantiate the classes represented by those param values as
- # well (in a consistent "deep copy"-style fashion; see comment
- # above).
- def __init__(self, _memo = None, **kwargs):
- if _memo is not None:
- # We're inside a "deep instantiation"
- assert(isinstance(_memo, dict))
- assert(len(kwargs) == 0)
- if _memo.has_key(self.__class__):
- # __new__ returned an existing, already initialized
- # instance, so there's nothing to do here
- assert(_memo[self.__class__] == self)
- return
- # no pre-existing object, so remember this one here
- _memo[self.__class__] = self
- else:
- # This is a new top-level instantiation... don't memoize
- # this objcet, but prepare to memoize any recursively
- # instantiated objects.
- _memo = {}
-
- self.__class__._instantiated = True
+ # Initialize new instance. For objects with SimObject-valued
+ # children, we need to recursively clone the classes represented
+ # by those param values as well in a consistent "deep copy"-style
+ # fashion. That is, we want to make sure that each instance is
+ # cloned only once, and that if there are multiple references to
+ # the same original object, we end up with the corresponding
+ # cloned references all pointing to the same cloned instance.
+ def __init__(self, **kwargs):
+ ancestor = kwargs.get('_ancestor')
+ memo_dict = kwargs.get('_memo')
+ if memo_dict is None:
+ # prepare to memoize any recursively instantiated objects
+ memo_dict = {}
+ elif ancestor:
+ # memoize me now to avoid problems with recursive calls
+ memo_dict[ancestor] = self
+
+ if not ancestor:
+ ancestor = self.__class__
+ ancestor._instantiated = True
+ # initialize required attributes
+ self._parent = None
self._children = {}
+ self._ccObject = None # pointer to C++ object
+ self._instantiated = False # really "cloned"
+
# Inherit parameter values from class using multidict so
# individual value settings can be overridden.
- self._values = multidict(self.__class__._values)
- # For SimObject-valued parameters, the class should have
- # classes (not instances) for the values. We need to
- # instantiate these classes rather than just inheriting the
- # class object.
- for key,val in self.__class__._values.iteritems():
- if isSimObjectClass(val):
- setattr(self, key, val(_memo))
- elif isSimObjectClassSequence(val) and len(val):
- setattr(self, key, [ v(_memo) for v in val ])
+ self._values = multidict(ancestor._values)
+ # clone SimObject-valued parameters
+ for key,val in ancestor._values.iteritems():
+ if isSimObject(val):
+ setattr(self, key, val(_memo=memo_dict))
+ elif isSimObjectSequence(val) and len(val):
+ setattr(self, key, [ v(_memo=memo_dict) for v in val ])
+ # clone port references. no need to use a multidict here
+ # since we will be creating new references for all ports.
+ self._port_map = {}
+ for key,val in ancestor._port_map.iteritems():
+ self._port_map[key] = applyOrMap(val, 'clone', memo_dict)
# apply attribute assignments from keyword args, if any
for key,val in kwargs.iteritems():
setattr(self, key, val)
- # Use this instance as a template to create a new class.
- def makeClass(self, memo = {}):
- cls = memo.get(self)
- if not cls:
- cls = self.__class__.makeSubclass(self._values.local)
- memo[self] = cls
- return cls
-
- # Direct instantiation of instances (cloning) is no longer
- # allowed; must generate class from instance first.
+ # "Clone" the current instance by creating another instance of
+ # this instance's class, but that inherits its parameter values
+ # and port mappings from the current instance. If we're in a
+ # "deep copy" recursive clone, check the _memo dict to see if
+ # we've already cloned this instance.
def __call__(self, **kwargs):
- raise TypeError, "cannot instantiate SimObject; "\
- "use makeClass() to make class first"
+ memo_dict = kwargs.get('_memo')
+ if memo_dict is None:
+ # no memo_dict: must be top-level clone operation.
+ # this is only allowed at the root of a hierarchy
+ if self._parent:
+ raise RuntimeError, "attempt to clone object %s " \
+ "not at the root of a tree (parent = %s)" \
+ % (self, self._parent)
+ # create a new dict and use that.
+ memo_dict = {}
+ kwargs['_memo'] = memo_dict
+ elif memo_dict.has_key(self):
+ # clone already done & memoized
+ return memo_dict[self]
+ return self.__class__(_ancestor = self, **kwargs)
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):
return self._values[attr]
@@ -457,10 +378,19 @@ class SimObject(object):
object.__setattr__(self, attr, value)
return
+ if self._ports.has_key(attr):
+ # set up port connection
+ self._ports[attr].connect(self, attr, value)
+ return
+
+ if isSimObjectOrSequence(value) and self._instantiated:
+ raise RuntimeError, \
+ "cannot set SimObject parameter '%s' after\n" \
+ " instance been cloned %s" % (attr, `self`)
+
# must be SimObject param
param = self._params.get(attr, None)
if param:
- # It's ok: set attribute by delegating to 'object' class.
try:
value = param.convert(value)
except Exception, e:
@@ -468,7 +398,6 @@ class SimObject(object):
(e, self.__class__.__name__, attr, value)
e.args = (msg, )
raise
- # I would love to get rid of this
elif isSimObjectOrSequence(value):
pass
else:
@@ -507,13 +436,13 @@ class SimObject(object):
self._children[name] = value
def set_path(self, parent, name):
- if not hasattr(self, '_parent'):
+ if not self._parent:
self._parent = parent
self._name = name
parent.add_child(name, self)
def path(self):
- if not hasattr(self, '_parent'):
+ if not self._parent:
return 'root'
ppath = self._parent.path()
if ppath == 'root':
@@ -554,6 +483,8 @@ class SimObject(object):
def print_ini(self):
print '[' + self.path() + ']' # .ini section header
+ instanceDict[self.path()] = self
+
if hasattr(self, 'type') and not isinstance(self, ParamContext):
print 'type=%s' % self.type
@@ -585,6 +516,33 @@ class SimObject(object):
for child in child_names:
self._children[child].print_ini()
+ # Call C++ to create C++ object corresponding to this object and
+ # (recursively) all its children
+ def createCCObject(self):
+ self.getCCObject() # force creation
+ for child in self._children.itervalues():
+ child.createCCObject()
+
+ # Get C++ object corresponding to this object, calling C++ if
+ # necessary to construct it. Does *not* recursively create
+ # children.
+ def getCCObject(self):
+ if not self._ccObject:
+ self._ccObject = -1 # flag to catch cycles in recursion
+ self._ccObject = m5.main.createSimObject(self.path())
+ elif self._ccObject == -1:
+ raise RuntimeError, "%s: recursive call to getCCObject()" \
+ % self.path()
+ return self._ccObject
+
+ # 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.
# this code is currently broken.
def outputDot(self, dot):
@@ -675,9 +633,9 @@ class BaseProxy(object):
if self._search_up:
while not done:
- try: obj = obj._parent
- except: break
-
+ obj = obj._parent
+ if not obj:
+ break
result, done = self.find(obj)
if not done:
@@ -793,16 +751,16 @@ Self = ProxyFactory(search_self = True, search_up = False)
#
# Parameter description classes
#
-# The _params dictionary in each class maps parameter names to
-# either a Param or a VectorParam object. These objects contain the
+# The _params dictionary in each class maps parameter names to either
+# a Param or a VectorParam object. These objects contain the
# parameter description string, the parameter type, and the default
-# value (loaded from the PARAM section of the .odesc files). The
-# _convert() method on these objects is used to force whatever value
-# is assigned to the parameter to the appropriate type.
+# value (if any). The convert() method on these objects is used to
+# force whatever value is assigned to the parameter to the appropriate
+# type.
#
# Note that the default values are loaded into the class's attribute
# space when the parameter dictionary is initialized (in
-# MetaConfigNode._setparams()); after that point they aren't used.
+# MetaSimObject._new_param()); after that point they aren't used.
#
#####################################################################
@@ -1419,6 +1377,107 @@ MaxAddr = Addr.max
MaxTick = Tick.max
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):
+ assert(isSimObject(simobj))
+ 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
+
+ def clone(self, memo):
+ newRef = copy.copy(self)
+ assert(isSimObject(newRef.simobj))
+ newRef.simobj = newRef.simobj(_memo=memo)
+ # Tricky: if I'm the *second* PortRef in the pair to be
+ # cloned, then my peer is still in the middle of its clone
+ # method, and thus hasn't returned to its owner's
+ # SimObject.__init__ to get installed in _port_map. As a
+ # result I have no way of finding the *new* peer object. So I
+ # mark myself as "waiting" for my peer, and I let the *first*
+ # PortRef clone call set up both peer pointers after I return.
+ newPeer = newRef.simobj._port_map.get(self.name)
+ if newPeer:
+ if self.isVec:
+ assert(self.index != -1)
+ newPeer = newPeer[self.index]
+ # other guy is all set up except for his peer pointer
+ assert(newPeer.peer == -1) # peer must be waiting for handshake
+ newPeer.peer = newRef
+ newRef.peer = newPeer
+ else:
+ # other guy is in clone; just wait for him to do the work
+ newRef.peer = -1 # mark as waiting for handshake
+ return newRef
+
+ # 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.getCCObject(), self.name, self.index,
+ peer.simobj.getCCObject(), 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):
+ if not isinstance(ref, PortRef):
+ raise TypeError, \
+ "assigning non-port reference port '%s'" % name
+ 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
@@ -1436,5 +1495,6 @@ __all__ = ['SimObject', 'ParamContext', 'Param', 'VectorParam',
'NetworkBandwidth', 'MemoryBandwidth',
'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory',
'Null', 'NULL',
- 'NextEthernetAddr']
+ 'NextEthernetAddr',
+ 'Port', 'VectorPort']
diff --git a/src/python/m5/objects/Bridge.py b/src/python/m5/objects/Bridge.py
index 880535755..c9e673afb 100644
--- a/src/python/m5/objects/Bridge.py
+++ b/src/python/m5/objects/Bridge.py
@@ -3,6 +3,8 @@ from MemObject import MemObject
class Bridge(MemObject):
type = 'Bridge'
+ side_a = Port('Side A port')
+ side_b = Port('Side B port')
queue_size_a = Param.Int(16, "The number of requests to buffer")
queue_size_b = Param.Int(16, "The number of requests to buffer")
delay = Param.Latency('0ns', "The latency of this bridge")
diff --git a/src/python/m5/objects/Bus.py b/src/python/m5/objects/Bus.py
index c37dab438..019e15034 100644
--- a/src/python/m5/objects/Bus.py
+++ b/src/python/m5/objects/Bus.py
@@ -3,4 +3,5 @@ from MemObject import MemObject
class Bus(MemObject):
type = 'Bus'
+ port = VectorPort("vector port for connecting devices")
bus_id = Param.Int(0, "blah")
diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py
index 7798f5f04..222f750da 100644
--- a/src/python/m5/objects/Device.py
+++ b/src/python/m5/objects/Device.py
@@ -4,6 +4,7 @@ from MemObject import MemObject
class PioDevice(MemObject):
type = 'PioDevice'
abstract = True
+ pio = Port("Programmed I/O port")
platform = Param.Platform(Parent.any, "Platform this device is part of")
system = Param.System(Parent.any, "System this device is part of")
@@ -16,3 +17,4 @@ class BasicPioDevice(PioDevice):
class DmaDevice(PioDevice):
type = 'DmaDevice'
abstract = True
+ dma = Port("DMA port")
diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py
index bed90d555..9cc7510a2 100644
--- a/src/python/m5/objects/PhysicalMemory.py
+++ b/src/python/m5/objects/PhysicalMemory.py
@@ -3,6 +3,7 @@ from MemObject import *
class PhysicalMemory(MemObject):
type = 'PhysicalMemory'
+ port = Port("the access port")
range = Param.AddrRange("Device Address")
file = Param.String('', "memory mapped file")
latency = Param.Latency(Parent.clock, "latency of an access")
diff --git a/src/sim/builder.cc b/src/sim/builder.cc
index 121275c83..9074cc899 100644
--- a/src/sim/builder.cc
+++ b/src/sim/builder.cc
@@ -33,17 +33,14 @@
#include "base/inifile.hh"
#include "base/misc.hh"
#include "sim/builder.hh"
-#include "sim/configfile.hh"
-#include "sim/config_node.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
#include "sim/root.hh"
using namespace std;
-SimObjectBuilder::SimObjectBuilder(ConfigNode *_configNode)
- : ParamContext(_configNode->getPath(), NoAutoInit),
- configNode(_configNode)
+SimObjectBuilder::SimObjectBuilder(const std::string &_iniSection)
+ : ParamContext(_iniSection, NoAutoInit)
{
}
@@ -78,8 +75,7 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
void
SimObjectBuilder::printErrorProlog(ostream &os)
{
- ccprintf(os, "Error creating object '%s' of type '%s':\n",
- iniSection, configNode->getType());
+ ccprintf(os, "Error creating object '%s':\n", iniSection);
}
@@ -112,9 +108,13 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
//
//
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
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
// builder instance (context with parameters for object creation)
- SimObjectBuilder *objectBuilder = (*createFunc)(configNode);
+ SimObjectBuilder *objectBuilder = (*createFunc)(iniSection);
assert(objectBuilder != NULL);
@@ -166,7 +166,7 @@ SimObjectClass::describeAllClasses(ostream &os)
os << "[" << className << "]\n";
// create dummy object builder just to instantiate parameters
- SimObjectBuilder *objectBuilder = (*createFunc)(NULL);
+ SimObjectBuilder *objectBuilder = (*createFunc)("");
// now get the object builder to describe ite params
objectBuilder->describeParams(os);
diff --git a/src/sim/builder.hh b/src/sim/builder.hh
index 8d0846155..2997fe5c3 100644
--- a/src/sim/builder.hh
+++ b/src/sim/builder.hh
@@ -55,14 +55,8 @@ class SimObject;
//
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:
- SimObjectBuilder(ConfigNode *_configNode);
+ SimObjectBuilder(const std::string &_iniSection);
virtual ~SimObjectBuilder();
@@ -77,9 +71,6 @@ class SimObjectBuilder : public ParamContext
// configuration hierarchy node label and position)
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
// values in this context. This function is overridden in derived
// 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
// an optional config hierarchy node (specified by the third
// 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;
@@ -137,7 +128,8 @@ class SimObjectClass
// create SimObject given name of class and pointer to
// 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
// SimObject classes
@@ -156,15 +148,15 @@ class OBJ_CLASS##Builder : public SimObjectBuilder \
#define END_DECLARE_SIM_OBJECT_PARAMS(OBJ_CLASS) \
\
- OBJ_CLASS##Builder(ConfigNode *configNode); \
+ OBJ_CLASS##Builder(const std::string &iniSection); \
virtual ~OBJ_CLASS##Builder() {} \
\
OBJ_CLASS *create(); \
};
#define BEGIN_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
-OBJ_CLASS##Builder::OBJ_CLASS##Builder(ConfigNode *configNode) \
- : SimObjectBuilder(configNode),
+ OBJ_CLASS##Builder::OBJ_CLASS##Builder(const std::string &iSec) \
+ : SimObjectBuilder(iSec),
#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) \
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, \
diff --git a/src/sim/main.cc b/src/sim/main.cc
index f3b74489d..f63aec9cc 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -57,9 +57,10 @@
#include "base/time.hh"
#include "cpu/base.hh"
#include "cpu/smt.hh"
+#include "mem/mem_object.hh"
+#include "mem/port.hh"
#include "sim/async.hh"
#include "sim/builder.hh"
-#include "sim/configfile.hh"
#include "sim/host.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
@@ -296,26 +297,109 @@ main(int argc, char **argv)
Py_Finalize();
}
+IniFile inifile;
-/// Initialize C++ configuration. Exported to Python via SWIG; invoked
-/// from m5.instantiate().
+SimObject *
+createSimObject(const string &name)
+{
+ 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
-initialize()
+loadIniFile(PyObject *_resolveFunc)
{
+ resolveFunc = _resolveFunc;
configStream = simout.find("config.out");
// The configuration database is now complete; start processing it.
- IniFile inifile;
inifile.load("config.ini");
// Initialize statistics database
Stats::InitSimStats();
+}
+
+
+/**
+ * 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;
+}
- // Now process the configuration hierarchy and create the SimObjects.
- ConfigHierarchy configHierarchy(inifile);
- configHierarchy.build();
- configHierarchy.createSimObjects();
+/**
+ * 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.
ParamContext::parseAllContexts(inifile);
ParamContext::checkAllContexts();
@@ -323,20 +407,13 @@ initialize()
// Echo all parameter settings to stats file as well.
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
SimObject::initAll();
// Restore checkpointed state, if any.
+#if 0
configHierarchy.unserializeSimObjects();
-
- // Done processing the configuration database.
- // Check for unreferenced entries.
- if (inifile.printUnreferenced())
- panic("unreferenced sections/entries in the intermediate ini file");
+#endif
SimObject::regAllStats();
diff --git a/src/sim/param.cc b/src/sim/param.cc
index 7f648b8e1..b1c50946b 100644
--- a/src/sim/param.cc
+++ b/src/sim/param.cc
@@ -39,8 +39,6 @@
#include "base/range.hh"
#include "base/str.hh"
#include "base/trace.hh"
-#include "sim/config_node.hh"
-#include "sim/configfile.hh"
#include "sim/param.hh"
#include "sim/sim_object.hh"
@@ -521,7 +519,9 @@ parseSimObjectParam(ParamContext *context, const string &s, SimObject *&value)
obj = NULL;
}
else {
- obj = context->resolveSimObject(s);
+ // defined in main.cc
+ extern SimObject *resolveSimObject(const string &);
+ obj = resolveSimObject(s);
if (obj == NULL)
return false;
@@ -696,22 +696,6 @@ ParamContext::printErrorProlog(ostream &os)
}
//
-// 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
//
void
diff --git a/src/sim/param.hh b/src/sim/param.hh
index 49db17df9..1bc55c125 100644
--- a/src/sim/param.hh
+++ b/src/sim/param.hh
@@ -36,10 +36,10 @@
#include <string>
#include <vector>
-#include "sim/configfile.hh"
#include "sim/startup.hh"
// forward decls
+class IniFile;
class BaseParam;
class SimObject;
@@ -132,18 +132,10 @@ class ParamContext : protected StartupCallback
// print context information for parameter error
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
// prefix to create unique names in resolveSimObject()
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.
static void parseAllContexts(IniFile &iniFile);
diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc
index 5270802d1..07e3b8a56 100644
--- a/src/sim/serialize.cc
+++ b/src/sim/serialize.cc
@@ -44,7 +44,6 @@
#include "base/output.hh"
#include "base/str.hh"
#include "base/trace.hh"
-#include "sim/config_node.hh"
#include "sim/eventq.hh"
#include "sim/param.hh"
#include "sim/serialize.hh"
@@ -442,9 +441,8 @@ Serializable::create(Checkpoint *cp, const std::string &section)
}
-Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path,
- const ConfigNode *_configNode)
- : db(new IniFile), basePath(path), configNode(_configNode), cptDir(cpt_dir)
+Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path)
+ : db(new IniFile), basePath(path), cptDir(cpt_dir)
{
string filename = cpt_dir + "/" + Checkpoint::baseFilename;
if (!db->load(filename)) {
@@ -470,9 +468,6 @@ Checkpoint::findObj(const std::string &section, const std::string &entry,
if (!db->find(section, entry, path))
return false;
- if ((value = configNode->resolveSimObject(path)) != NULL)
- return true;
-
if ((value = objMap[path]) != NULL)
return true;
diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh
index 1eb721cf4..1bcb235e6 100644
--- a/src/sim/serialize.hh
+++ b/src/sim/serialize.hh
@@ -42,8 +42,8 @@
#include <map>
#include "sim/host.hh"
-#include "sim/configfile.hh"
+class IniFile;
class Serializable;
class Checkpoint;
@@ -177,7 +177,7 @@ class SerializableClass
// an optional config hierarchy node (specified by the third
// argument). A pointer to the new SerializableBuilder is returned.
typedef Serializable *(*CreateFunc)(Checkpoint *cp,
- const std::string &section);
+ const std::string &section);
static std::map<std::string,CreateFunc> *classMap;
@@ -191,7 +191,7 @@ class SerializableClass
// create Serializable given name of class and pointer to
// configuration hierarchy node
static Serializable *createObject(Checkpoint *cp,
- const std::string &section);
+ const std::string &section);
};
//
@@ -209,12 +209,10 @@ class Checkpoint
IniFile *db;
const std::string basePath;
- const ConfigNode *configNode;
std::map<std::string, Serializable*> objMap;
public:
- Checkpoint(const std::string &cpt_dir, const std::string &path,
- const ConfigNode *_configNode);
+ Checkpoint(const std::string &cpt_dir, const std::string &path);
const std::string cptDir;
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index 117ca9325..97e6de439 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -38,7 +38,6 @@
#include "base/trace.hh"
#include "base/stats/events.hh"
#include "base/serializer.hh"
-#include "sim/configfile.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"