X86: Add a .serializing directive that makes a macroop serializing.
[gem5.git] / src / python / m5 / params.py
index d83d5f73fb13c9295b036ff830fbb15a26693611..38e320b5302dcd16aa39bd35659351c2149ffccc 100644 (file)
@@ -1,4 +1,5 @@
 # Copyright (c) 2004-2006 The Regents of The University of Michigan
+# Copyright (c) 2010 Advanced Micro Devices, Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 #
 #####################################################################
 
-import sys, inspect, copy
-import convert
+import copy
+import datetime
+import re
+import sys
+import time
+import math
+
+import proxy
+import ticks
 from util import *
 
+def isSimObject(*args, **kwargs):
+    return SimObject.isSimObject(*args, **kwargs)
+
+def isSimObjectSequence(*args, **kwargs):
+    return SimObject.isSimObjectSequence(*args, **kwargs)
+
+def isSimObjectClass(*args, **kwargs):
+    return SimObject.isSimObjectClass(*args, **kwargs)
+
+allParams = {}
+
+class MetaParamValue(type):
+    def __new__(mcls, name, bases, dct):
+        cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
+        assert name not in allParams
+        allParams[name] = cls
+        return cls
+
+
 # Dummy base class to identify types that are legitimate for SimObject
 # parameters.
 class ParamValue(object):
+    __metaclass__ = MetaParamValue
 
     cxx_predecls = []
     swig_predecls = []
@@ -67,6 +95,8 @@ class ParamValue(object):
 
 # Regular parameter description.
 class ParamDesc(object):
+    file_ext = 'ptype'
+
     def __init__(self, ptype_str, ptype, *args, **kwargs):
         self.ptype_str = ptype_str
         # remember ptype only if it is provided
@@ -100,15 +130,11 @@ class ParamDesc(object):
 
     def __getattr__(self, attr):
         if attr == 'ptype':
-            try:
-                ptype = eval(self.ptype_str, objects.__dict__)
-                if not isinstance(ptype, type):
-                    raise NameError
-                self.ptype = ptype
-                return ptype
-            except NameError:
-                raise TypeError, \
-                      "Param qualifier '%s' is not a type" % self.ptype_str
+            ptype = SimObject.allClasses[self.ptype_str]
+            assert isSimObjectClass(ptype)
+            self.ptype = ptype
+            return ptype
+
         raise AttributeError, "'%s' object has no attribute '%s'" % \
               (type(self).__name__, attr)
 
@@ -140,38 +166,86 @@ class ParamDesc(object):
 # single value.
 
 class VectorParamValue(list):
+    __metaclass__ = MetaParamValue
+    def __setattr__(self, attr, value):
+        raise AttributeError, \
+              "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
+
     def ini_str(self):
         return ' '.join([v.ini_str() for v in self])
 
+    def getValue(self):
+        return [ v.getValue() for v in self ]
+
     def unproxy(self, base):
         return [v.unproxy(base) for v in self]
 
-class SimObjVector(VectorParamValue):
-    def print_ini(self):
+class SimObjectVector(VectorParamValue):
+    # support clone operation
+    def __call__(self, **kwargs):
+        return SimObjectVector([v(**kwargs) for v in self])
+
+    def clear_parent(self, old_parent):
         for v in self:
-            v.print_ini()
+            v.clear_parent(old_parent)
+
+    def set_parent(self, parent, name):
+        if len(self) == 1:
+            self[0].set_parent(parent, name)
+        else:
+            width = int(math.ceil(math.log(len(self))/math.log(10)))
+            for i,v in enumerate(self):
+                v.set_parent(parent, "%s%0*d" % (name, width, i))
+
+    def get_parent(self):
+        parent_set = set(v._parent for v in self)
+        if len(parent_set) != 1:
+            raise RuntimeError, \
+                  "SimObjectVector elements have inconsistent parent value."
+        return parent_set.pop()
+
+    # return 'cpu0 cpu1' etc. for print_ini()
+    def get_name(self):
+        return ' '.join([v._name for v in self])
+
+    # By iterating through the constituent members of the vector here
+    # we can nicely handle iterating over all a SimObject's children
+    # without having to provide lots of special functions on
+    # SimObjectVector directly.
+    def descendants(self):
+        for v in self:
+            for obj in v.descendants():
+                yield obj
 
 class VectorParamDesc(ParamDesc):
+    file_ext = 'vptype'
+
     # Convert assigned value to appropriate type.  If the RHS is not a
     # list or tuple, it generates a single-element list.
     def convert(self, value):
         if isinstance(value, (list, tuple)):
             # list: coerce each element into new list
             tmp_list = [ ParamDesc.convert(self, v) for v in value ]
-            if isSimObjectSequence(tmp_list):
-                return SimObjVector(tmp_list)
-            else:
-                return VectorParamValue(tmp_list)
         else:
-            # singleton: leave it be (could coerce to a single-element
-            # list here, but for some historical reason we don't...
-            return ParamDesc.convert(self, value)
+            # singleton: coerce to a single-element list
+            tmp_list = [ ParamDesc.convert(self, value) ]
 
-    def cxx_predecls(self):
-        return ['#include <vector>'] + self.ptype.cxx_predecls
+        if isSimObjectSequence(tmp_list):
+            return SimObjectVector(tmp_list)
+        else:
+            return VectorParamValue(tmp_list)
 
     def swig_predecls(self):
-        return ['%include "std_vector.i"'] + self.ptype.swig_predecls
+        return ['%%include "%s_vptype.i"' % self.ptype_str]
+
+    def swig_decl(self):
+        cxx_type = re.sub('std::', '', self.ptype.cxx_type)
+        vdecl = 'namespace std { %%template(vector_%s) vector< %s >; }' % \
+                (self.ptype_str, cxx_type)
+        return ['%include "std_vector.i"'] + self.ptype.swig_predecls + [vdecl]
+
+    def cxx_predecls(self):
+        return ['#include <vector>'] + self.ptype.cxx_predecls
 
     def cxx_decl(self):
         return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name)
@@ -188,15 +262,10 @@ class ParamFactory(object):
 
     # E.g., Param.Int(5, "number of widgets")
     def __call__(self, *args, **kwargs):
-        caller_frame = inspect.currentframe().f_back
         ptype = None
         try:
-            ptype = eval(self.ptype_str,
-                         caller_frame.f_globals, caller_frame.f_locals)
-            if not isinstance(ptype, type):
-                raise TypeError, \
-                      "Param qualifier is not a type: %s" % ptype
-        except NameError:
+            ptype = allParams[self.ptype_str]
+        except KeyError:
             # if name isn't defined yet, assume it's a SimObject, and
             # try to resolve it later
             pass
@@ -225,7 +294,10 @@ class String(ParamValue,str):
     cxx_predecls = ['#include <string>']
     swig_predecls = ['%include "std_string.i"\n' +
                      '%apply const std::string& {std::string *};']
-    pass
+    swig_predecls = ['%include "std_string.i"' ]
+
+    def getValue(self):
+        return self
 
 # superclass for "numeric" parameter values, to emulate math
 # operations in a type-safe way.  e.g., a Latency times an int returns
@@ -268,7 +340,7 @@ class NumericParamValue(ParamValue):
         return newobj
 
 # Metaclass for bounds-checked integer parameters.  See CheckedInt.
-class CheckedIntType(type):
+class CheckedIntType(MetaParamValue):
     def __init__(cls, name, bases, dict):
         super(CheckedIntType, cls).__init__(name, bases, dict)
 
@@ -280,18 +352,18 @@ class CheckedIntType(type):
 
         if not cls.cxx_predecls:
             # most derived types require this, so we just do it here once
-            cls.cxx_predecls = ['#include "sim/host.hh"']
+            cls.cxx_predecls = ['#include "base/types.hh"']
 
         if not cls.swig_predecls:
             # most derived types require this, so we just do it here once
-            cls.swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
-                                 '%import "sim/host.hh"']
+            cls.swig_predecls = ['%import "stdint.i"\n' +
+                                 '%import "base/types.hh"']
 
         if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
             if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
                 panic("CheckedInt subclass %s must define either\n" \
-                      "    'min' and 'max' or 'size' and 'unsigned'\n" \
-                      name);
+                      "    'min' and 'max' or 'size' and 'unsigned'\n",
+                      name);
             if cls.unsigned:
                 cls.min = 0
                 cls.max = 2 ** cls.size - 1
@@ -321,6 +393,9 @@ class CheckedInt(NumericParamValue):
                   % type(value).__name__
         self._check()
 
+    def getValue(self):
+        return long(self.value)
+
 class Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
 class Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
 
@@ -341,7 +416,17 @@ class UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
 class Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
 
 class Float(ParamValue, float):
-    pass
+    cxx_type = 'double'
+
+    def __init__(self, value):
+        if isinstance(value, (int, long, float, NumericParamValue, Float)):
+            self.value = float(value)
+        else:
+            raise TypeError, "Can't convert object of type %s to Float" \
+                  % type(value).__name__
+
+    def getValue(self):
+        return float(self.value)
 
 class MemorySize(CheckedInt):
     cxx_type = 'uint64_t'
@@ -355,6 +440,7 @@ class MemorySize(CheckedInt):
         self._check()
 
 class MemorySize32(CheckedInt):
+    cxx_type = 'uint32_t'
     size = 32
     unsigned = True
     def __init__(self, value):
@@ -366,7 +452,6 @@ class MemorySize32(CheckedInt):
 
 class Addr(CheckedInt):
     cxx_type = 'Addr'
-    cxx_predecls = ['#include "targetarch/isa_traits.hh"']
     size = 64
     unsigned = True
     def __init__(self, value):
@@ -385,7 +470,7 @@ class Addr(CheckedInt):
             return self.value + other
 
 
-class MetaRange(type):
+class MetaRange(MetaParamValue):
     def __init__(cls, name, bases, dict):
         super(MetaRange, cls).__init__(name, bases, dict)
         if name == 'Range':
@@ -417,6 +502,9 @@ class Range(ParamValue):
             elif isinstance(args[0], Range):
                 self.first = self.type(args[0].first)
                 self.second = self.type(args[0].second)
+            elif isinstance(args[0], (list, tuple)):
+                self.first = self.type(args[0][0])
+                self.second = self.type(args[0][1])
             else:
                 self.first = self.type(0)
                 self.second = self.type(args[0]) - 1
@@ -435,9 +523,27 @@ class Range(ParamValue):
 
 class AddrRange(Range):
     type = Addr
+    swig_predecls = ['%include "python/swig/range.i"']
+
+    def getValue(self):
+        from m5.objects.params import AddrRange
+
+        value = AddrRange()
+        value.start = long(self.first)
+        value.end = long(self.second)
+        return value
 
 class TickRange(Range):
     type = Tick
+    swig_predecls = ['%include "python/swig/range.i"']
+
+    def getValue(self):
+        from m5.objects.params import TickRange
+
+        value = TickRange()
+        value.start = long(self.first)
+        value.end = long(self.second)
+        return value
 
 # Boolean parameter type.  Python doesn't let you subclass bool, since
 # it doesn't want to let you create multiple instances of True and
@@ -450,6 +556,9 @@ class Bool(ParamValue):
         except TypeError:
             self.value = bool(value)
 
+    def getValue(self):
+        return bool(self.value)
+
     def __str__(self):
         return str(self.value)
 
@@ -470,17 +579,18 @@ def IncEthernetAddr(addr, val = 1):
     assert(bytes[0] <= 255)
     return ':'.join(map(lambda x: '%02x' % x, bytes))
 
-class NextEthernetAddr(object):
-    addr = "00:90:00:00:00:01"
+_NextEthernetAddr = "00:90:00:00:00:01"
+def NextEthernetAddr():
+    global _NextEthernetAddr
 
-    def __init__(self, inc = 1):
-        self.value = NextEthernetAddr.addr
-        NextEthernetAddr.addr = IncEthernetAddr(NextEthernetAddr.addr, inc)
+    value = _NextEthernetAddr
+    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
+    return value
 
 class EthernetAddr(ParamValue):
     cxx_type = 'Net::EthAddr'
     cxx_predecls = ['#include "base/inet.hh"']
-    swig_predecls = ['class Net::EthAddr;']
+    swig_predecls = ['%include "python/swig/inet.i"']
     def __init__(self, value):
         if value == NextEthernetAddr:
             self.value = value
@@ -501,17 +611,92 @@ class EthernetAddr(ParamValue):
 
     def unproxy(self, base):
         if self.value == NextEthernetAddr:
-            self.addr = self.value().value
+            return EthernetAddr(self.value())
         return self
 
+    def getValue(self):
+        from m5.objects.params import EthAddr
+        return EthAddr(self.value)
+
+    def ini_str(self):
+        return self.value
+
+time_formats = [ "%a %b %d %H:%M:%S %Z %Y",
+                 "%a %b %d %H:%M:%S %Z %Y",
+                 "%Y/%m/%d %H:%M:%S",
+                 "%Y/%m/%d %H:%M",
+                 "%Y/%m/%d",
+                 "%m/%d/%Y %H:%M:%S",
+                 "%m/%d/%Y %H:%M",
+                 "%m/%d/%Y",
+                 "%m/%d/%y %H:%M:%S",
+                 "%m/%d/%y %H:%M",
+                 "%m/%d/%y"]
+
+
+def parse_time(value):
+    from time import gmtime, strptime, struct_time, time
+    from datetime import datetime, date
+
+    if isinstance(value, struct_time):
+        return value
+
+    if isinstance(value, (int, long)):
+        return gmtime(value)
+
+    if isinstance(value, (datetime, date)):
+        return value.timetuple()
+
+    if isinstance(value, str):
+        if value in ('Now', 'Today'):
+            return time.gmtime(time.time())
+
+        for format in time_formats:
+            try:
+                return strptime(value, format)
+            except ValueError:
+                pass
+
+    raise ValueError, "Could not parse '%s' as a time" % value
+
+class Time(ParamValue):
+    cxx_type = 'tm'
+    cxx_predecls = [ '#include <time.h>' ]
+    swig_predecls = [ '%include "python/swig/time.i"' ]
+    def __init__(self, value):
+        self.value = parse_time(value)
+
+    def getValue(self):
+        from m5.objects.params import tm
+
+        c_time = tm()
+        py_time = self.value
+
+        # UNIX is years since 1900
+        c_time.tm_year = py_time.tm_year - 1900;
+
+        # Python starts at 1, UNIX starts at 0
+        c_time.tm_mon =  py_time.tm_mon - 1;
+        c_time.tm_mday = py_time.tm_mday;
+        c_time.tm_hour = py_time.tm_hour;
+        c_time.tm_min = py_time.tm_min;
+        c_time.tm_sec = py_time.tm_sec;
+
+        # Python has 0 as Monday, UNIX is 0 as sunday
+        c_time.tm_wday = py_time.tm_wday + 1
+        if c_time.tm_wday > 6:
+            c_time.tm_wday -= 7;
+
+        # Python starts at 1, Unix starts at 0
+        c_time.tm_yday = py_time.tm_yday - 1;
+
+        return c_time
+
     def __str__(self):
-        if self.value == NextEthernetAddr:
-            if hasattr(self, 'addr'):
-                return self.addr
-            else:
-                return "NextEthernetAddr (unresolved)"
-        else:
-            return self.value
+        return time.asctime(self.value)
+
+    def ini_str(self):
+        return str(self)
 
 # Enumerated types are a little more complex.  The user specifies the
 # type as Enum(foo) where foo is either a list or dictionary of
@@ -527,9 +712,16 @@ class EthernetAddr(ParamValue):
 # classes (_ListEnum and _DictEnum) to serve as base classes, then
 # derive the new type from the appropriate base class on the fly.
 
-
+allEnums = {}
 # Metaclass for Enum types
-class MetaEnum(type):
+class MetaEnum(MetaParamValue):
+    def __new__(mcls, name, bases, dict):
+        assert name not in allEnums
+
+        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
+        allEnums[name] = cls
+        return cls
+
     def __init__(cls, name, bases, init_dict):
         if init_dict.has_key('map'):
             if not isinstance(cls.map, dict):
@@ -550,7 +742,7 @@ class MetaEnum(type):
             raise TypeError, "Enum-derived class must define "\
                   "attribute 'map' or 'vals'"
 
-        cls.cxx_type = name + '::Enum'
+        cls.cxx_type = 'Enums::%s' % name
 
         super(MetaEnum, cls).__init__(name, bases, init_dict)
 
@@ -558,10 +750,33 @@ class MetaEnum(type):
     # Note that we wrap the enum in a class/struct to act as a namespace,
     # so that the enum strings can be brief w/o worrying about collisions.
     def cxx_decl(cls):
-        s = 'struct %s {\n  enum Enum {\n    ' % cls.__name__
-        s += ',\n    '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals])
-        s += '\n  };\n};\n'
-        return s
+        name = cls.__name__
+        code = "#ifndef __ENUM__%s\n" % name
+        code += '#define __ENUM__%s\n' % name
+        code += '\n'
+        code += 'namespace Enums {\n'
+        code += '    enum %s {\n' % name
+        for val in cls.vals:
+            code += '        %s = %d,\n' % (val, cls.map[val])
+        code += '        Num_%s = %d,\n' % (name, len(cls.vals))
+        code += '    };\n'
+        code += '    extern const char *%sStrings[Num_%s];\n' % (name, name)
+        code += '}\n'
+        code += '\n'
+        code += '#endif\n'
+        return code
+
+    def cxx_def(cls):
+        name = cls.__name__
+        code = '#include "enums/%s.hh"\n' % name
+        code += 'namespace Enums {\n'
+        code += '    const char *%sStrings[Num_%s] =\n' % (name, name)
+        code += '    {\n'
+        for val in cls.vals:
+            code += '        "%s",\n' % val
+        code += '    };\n'
+        code += '}\n'
+        return code
 
 # Base class for enum types.
 class Enum(ParamValue):
@@ -574,50 +789,38 @@ class Enum(ParamValue):
                   % (value, self.vals)
         self.value = value
 
+    def getValue(self):
+        return int(self.map[self.value])
+
     def __str__(self):
         return self.value
 
-ticks_per_sec = None
-
 # how big does a rounding error need to be before we warn about it?
 frequency_tolerance = 0.001  # 0.1%
 
-# convert a floting-point # of ticks to integer, and warn if rounding
-# discards too much precision
-def tick_check(float_ticks):
-    if float_ticks == 0:
-        return 0
-    int_ticks = int(round(float_ticks))
-    err = (float_ticks - int_ticks) / float_ticks
-    if err > frequency_tolerance:
-        print >> sys.stderr, "Warning: rounding error > tolerance"
-        print >> sys.stderr, "    %f rounded to %d" % (float_ticks, int_ticks)
-        #raise ValueError
-    return int_ticks
-
-def getLatency(value):
-    if isinstance(value, Latency) or isinstance(value, Clock):
-        return value.value
-    elif isinstance(value, Frequency) or isinstance(value, RootClock):
-        return 1 / value.value
-    elif isinstance(value, str):
-        try:
-            return convert.toLatency(value)
-        except ValueError:
-            try:
-                return 1 / convert.toFrequency(value)
-            except ValueError:
-                pass # fall through
-    raise ValueError, "Invalid Frequency/Latency value '%s'" % value
+class TickParamValue(NumericParamValue):
+    cxx_type = 'Tick'
+    cxx_predecls = ['#include "base/types.hh"']
+    swig_predecls = ['%import "stdint.i"\n' +
+                     '%import "base/types.hh"']
 
+    def getValue(self):
+        return long(self.value)
 
-class Latency(NumericParamValue):
-    cxx_type = 'Tick'
-    cxx_predecls = ['#include "sim/host.hh"']
-    swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
-                     '%import "sim/host.hh"']
+class Latency(TickParamValue):
     def __init__(self, value):
-        self.value = getLatency(value)
+        if isinstance(value, (Latency, Clock)):
+            self.ticks = value.ticks
+            self.value = value.value
+        elif isinstance(value, Frequency):
+            self.ticks = value.ticks
+            self.value = 1.0 / value.value
+        elif value.endswith('t'):
+            self.ticks = True
+            self.value = int(value[:-1])
+        else:
+            self.ticks = False
+            self.value = convert.toLatency(value)
 
     def __getattr__(self, attr):
         if attr in ('latency', 'period'):
@@ -626,17 +829,31 @@ class Latency(NumericParamValue):
             return Frequency(self)
         raise AttributeError, "Latency object has no attribute '%s'" % attr
 
+    def getValue(self):
+        if self.ticks or self.value == 0:
+            value = self.value
+        else:
+            value = ticks.fromSeconds(self.value)
+        return long(value)
+
     # convert latency to ticks
     def ini_str(self):
-        return str(tick_check(self.value * ticks_per_sec))
+        return '%d' % self.getValue()
 
-class Frequency(NumericParamValue):
-    cxx_type = 'Tick'
-    cxx_predecls = ['#include "sim/host.hh"']
-    swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
-                     '%import "sim/host.hh"']
+class Frequency(TickParamValue):
     def __init__(self, value):
-        self.value = 1 / getLatency(value)
+        if isinstance(value, (Latency, Clock)):
+            if value.value == 0:
+                self.value = 0
+            else:
+                self.value = 1.0 / value.value
+            self.ticks = value.ticks
+        elif isinstance(value, Frequency):
+            self.value = value.value
+            self.ticks = value.ticks
+        else:
+            self.ticks = False
+            self.value = convert.toFrequency(value)
 
     def __getattr__(self, attr):
         if attr == 'frequency':
@@ -645,41 +862,38 @@ class Frequency(NumericParamValue):
             return Latency(self)
         raise AttributeError, "Frequency object has no attribute '%s'" % attr
 
-    # convert frequency to ticks per period
-    def ini_str(self):
-        return self.period.ini_str()
-
-# Just like Frequency, except ini_str() is absolute # of ticks per sec (Hz).
-# We can't inherit from Frequency because we don't want it to be directly
-# assignable to a regular Frequency parameter.
-class RootClock(ParamValue):
-    cxx_type = 'Tick'
-    cxx_predecls = ['#include "sim/host.hh"']
-    swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
-                     '%import "sim/host.hh"']
-    def __init__(self, value):
-        self.value = 1 / getLatency(value)
-
-    def __getattr__(self, attr):
-        if attr == 'frequency':
-            return Frequency(self)
-        if attr in ('latency', 'period'):
-            return Latency(self)
-        raise AttributeError, "Frequency object has no attribute '%s'" % attr
+    # convert latency to ticks
+    def getValue(self):
+        if self.ticks or self.value == 0:
+            value = self.value
+        else:
+            value = ticks.fromSeconds(1.0 / self.value)
+        return long(value)
 
     def ini_str(self):
-        return str(tick_check(self.value))
+        return '%d' % self.getValue()
 
 # A generic frequency and/or Latency value.  Value is stored as a latency,
 # but to avoid ambiguity this object does not support numeric ops (* or /).
 # An explicit conversion to a Latency or Frequency must be made first.
 class Clock(ParamValue):
     cxx_type = 'Tick'
-    cxx_predecls = ['#include "sim/host.hh"']
-    swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
-                     '%import "sim/host.hh"']
+    cxx_predecls = ['#include "base/types.hh"']
+    swig_predecls = ['%import "stdint.i"\n' +
+                     '%import "base/types.hh"']
     def __init__(self, value):
-        self.value = getLatency(value)
+        if isinstance(value, (Latency, Clock)):
+            self.ticks = value.ticks
+            self.value = value.value
+        elif isinstance(value, Frequency):
+            self.ticks = value.ticks
+            self.value = 1.0 / value.value
+        elif value.endswith('t'):
+            self.ticks = True
+            self.value = int(value[:-1])
+        else:
+            self.ticks = False
+            self.value = convert.anyToLatency(value)
 
     def __getattr__(self, attr):
         if attr == 'frequency':
@@ -688,32 +902,53 @@ class Clock(ParamValue):
             return Latency(self)
         raise AttributeError, "Frequency object has no attribute '%s'" % attr
 
+    def getValue(self):
+        return self.period.getValue()
+
     def ini_str(self):
         return self.period.ini_str()
 
 class NetworkBandwidth(float,ParamValue):
     cxx_type = 'float'
     def __new__(cls, value):
-        val = convert.toNetworkBandwidth(value) / 8.0
+        # convert to bits per second
+        val = convert.toNetworkBandwidth(value)
         return super(cls, NetworkBandwidth).__new__(cls, val)
 
     def __str__(self):
         return str(self.val)
 
+    def getValue(self):
+        # convert to seconds per byte
+        value = 8.0 / float(self)
+        # convert to ticks per byte
+        value = ticks.fromSeconds(value)
+        return float(value)
+
     def ini_str(self):
-        return '%f' % (ticks_per_sec / float(self))
+        return '%f' % self.getValue()
 
 class MemoryBandwidth(float,ParamValue):
     cxx_type = 'float'
-    def __new__(self, value):
+    def __new__(cls, value):
+        # we want the number of ticks per byte of data
         val = convert.toMemoryBandwidth(value)
         return super(cls, MemoryBandwidth).__new__(cls, val)
 
     def __str__(self):
         return str(self.val)
 
+    def getValue(self):
+        # convert to seconds per byte
+        value = float(self)
+        if value:
+            value = 1.0 / float(self)
+        # convert to ticks per byte
+        value = ticks.fromSeconds(value)
+        return float(value)
+
     def ini_str(self):
-        return '%f' % (ticks_per_sec / float(self))
+        return '%f' % self.getValue()
 
 #
 # "Constants"... handy aliases for various values.
@@ -740,9 +975,13 @@ class NullSimObject(object):
 
     def set_path(self, parent, name):
         pass
+
     def __str__(self):
         return 'Null'
 
+    def getValue(self):
+        return None
+
 # The only instance you'll ever need...
 NULL = NullSimObject()
 
@@ -799,6 +1038,7 @@ class PortRef(object):
         if self.peer and not proxy.isproxy(self.peer):
             print "warning: overwriting port", self, \
                   "value", self.peer, "with", other
+            self.peer.peer = None
         self.peer = other
         if proxy.isproxy(other):
             other.set_param_desc(PortParamDesc())
@@ -836,12 +1076,21 @@ class PortRef(object):
 
     # Call C++ to create corresponding port connection between C++ objects
     def ccConnect(self):
+        from m5.objects.params import connectPorts
+
         if self.ccConnected: # already done this
             return
         peer = self.peer
-        internal.main.connectPorts(self.simobj.getCCObject(), self.name,
-                                   self.index, peer.simobj.getCCObject(),
-                                   peer.name, peer.index)
+        if not self.peer: # nothing to connect to
+            return
+        try:
+            connectPorts(self.simobj.getCCObject(), self.name, self.index,
+                         peer.simobj.getCCObject(), peer.name, peer.index)
+        except:
+            print "Error connecting port %s.%s to %s.%s" % \
+                  (self.simobj.path(), self.name,
+                   peer.simobj.path(), peer.name)
+            raise
         self.ccConnected = True
         peer.ccConnected = True
 
@@ -961,6 +1210,14 @@ class PortParamDesc(object):
     ptype_str = 'Port'
     ptype = Port
 
+baseEnums = allEnums.copy()
+baseParams = allParams.copy()
+
+def clear():
+    global allEnums, allParams
+
+    allEnums = baseEnums.copy()
+    allParams = baseParams.copy()
 
 __all__ = ['Param', 'VectorParam',
            'Enum', 'Bool', 'String', 'Float',
@@ -969,15 +1226,12 @@ __all__ = ['Param', 'VectorParam',
            'Counter', 'Addr', 'Tick', 'Percent',
            'TcpPort', 'UdpPort', 'EthernetAddr',
            'MemorySize', 'MemorySize32',
-           'Latency', 'Frequency', 'RootClock', 'Clock',
+           'Latency', 'Frequency', 'Clock',
            'NetworkBandwidth', 'MemoryBandwidth',
            'Range', 'AddrRange', 'TickRange',
            'MaxAddr', 'MaxTick', 'AllMemory',
+           'Time',
            'NextEthernetAddr', 'NULL',
            'Port', 'VectorPort']
 
-# see comment on imports at end of __init__.py.
-from SimObject import isSimObject, isSimObjectSequence, isSimObjectClass
-import proxy
-import objects
-import internal
+import SimObject