-# Copyright (c) 2012-2014, 2017, 2018 ARM Limited
+# Copyright (c) 2012-2014, 2017-2019 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
#####################################################################
from __future__ import print_function
+import six
+if six.PY3:
+ long = int
import copy
import datetime
from .util import *
def isSimObject(*args, **kwargs):
+ from . import SimObject
return SimObject.isSimObject(*args, **kwargs)
def isSimObjectSequence(*args, **kwargs):
+ from . import SimObject
return SimObject.isSimObjectSequence(*args, **kwargs)
def isSimObjectClass(*args, **kwargs):
+ from . import SimObject
return SimObject.isSimObjectClass(*args, **kwargs)
allParams = {}
def __getattr__(self, attr):
if attr == 'ptype':
+ from . import SimObject
ptype = SimObject.allClasses[self.ptype_str]
assert isSimObjectClass(ptype)
self.ptype = ptype
def __init__(self, *args, **kwargs):
# Disable interleaving and hashing by default
- self.intlvHighBit = 0
- self.xorHighBit = 0
self.intlvBits = 0
self.intlvMatch = 0
+ self.masks = []
def handle_kwargs(self, kwargs):
# An address range needs to have an upper limit, specified
raise TypeError("Either end or size must be specified")
# Now on to the optional bit
- if 'intlvHighBit' in kwargs:
- self.intlvHighBit = int(kwargs.pop('intlvHighBit'))
- if 'xorHighBit' in kwargs:
- self.xorHighBit = int(kwargs.pop('xorHighBit'))
- if 'intlvBits' in kwargs:
- self.intlvBits = int(kwargs.pop('intlvBits'))
if 'intlvMatch' in kwargs:
self.intlvMatch = int(kwargs.pop('intlvMatch'))
+ if 'masks' in kwargs:
+ self.masks = [ long(x) for x in list(kwargs.pop('masks')) ]
+ self.intlvBits = len(self.masks)
+ else:
+ if 'intlvBits' in kwargs:
+ self.intlvBits = int(kwargs.pop('intlvBits'))
+ self.masks = [0] * self.intlvBits
+ if 'intlvHighBit' not in kwargs:
+ raise TypeError("No interleave bits specified")
+ intlv_high_bit = int(kwargs.pop('intlvHighBit'))
+ xor_high_bit = 0
+ if 'xorHighBit' in kwargs:
+ xor_high_bit = int(kwargs.pop('xorHighBit'))
+ for i in range(0, self.intlvBits):
+ bit1 = intlv_high_bit - i
+ mask = 1 << bit1
+ if xor_high_bit != 0:
+ bit2 = xor_high_bit - i
+ mask |= 1 << bit2
+ self.masks[self.intlvBits - i - 1] = mask
+
if len(args) == 0:
self.start = Addr(kwargs.pop('start'))
handle_kwargs(self, kwargs)
raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
def __str__(self):
- return '%s:%s:%s:%s:%s:%s' \
- % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\
- self.intlvBits, self.intlvMatch)
+ if len(self.masks) == 0:
+ return '%s:%s' % (self.start, self.end)
+ else:
+ return '%s:%s:%s:%s' % (self.start, self.end, self.intlvMatch,
+ ':'.join(str(m) for m in self.masks))
def size(self):
# Divide the size by the size of the interleaving slice
@classmethod
def cxx_ini_predecls(cls, code):
code('#include <sstream>')
+ code('#include <vector>')
+ code('#include "base/types.hh"')
@classmethod
def cxx_ini_parse(cls, code, src, dest, ret):
- code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;')
- code('uint64_t _intlvBits = 0, _intlvMatch = 0;')
+ code('bool _ret = true;')
+ code('uint64_t _start, _end, _intlvMatch = 0;')
+ code('std::vector<Addr> _masks;')
code('char _sep;')
code('std::istringstream _stream(${src});')
code('_stream >> _start;')
code('_stream.get(_sep);')
+ code('_ret = _sep == \':\';')
code('_stream >> _end;')
code('if (!_stream.fail() && !_stream.eof()) {')
code(' _stream.get(_sep);')
- code(' _stream >> _intlvHighBit;')
- code(' _stream.get(_sep);')
- code(' _stream >> _xorHighBit;')
- code(' _stream.get(_sep);')
- code(' _stream >> _intlvBits;')
- code(' _stream.get(_sep);')
+ code(' _ret = ret && _sep == \':\';')
code(' _stream >> _intlvMatch;')
+ code(' while (!_stream.fail() && !_stream.eof()) {')
+ code(' _stream.get(_sep);')
+ code(' _ret = ret && _sep == \':\';')
+ code(' Addr mask;')
+ code(' _stream >> mask;')
+ code(' _masks.push_back(mask);')
+ code(' }')
code('}')
- code('bool _ret = !_stream.fail() &&'
- '_stream.eof() && _sep == \':\';')
+ code('_ret = _ret && !_stream.fail() && _stream.eof();')
code('if (_ret)')
- code(' ${dest} = AddrRange(_start, _end, _intlvHighBit, \
- _xorHighBit, _intlvBits, _intlvMatch);')
+ code(' ${dest} = AddrRange(_start, _end, _masks, _intlvMatch);')
code('${ret} _ret;')
def getValue(self):
from _m5.range import AddrRange
return AddrRange(long(self.start), long(self.end),
- int(self.intlvHighBit), int(self.xorHighBit),
- int(self.intlvBits), int(self.intlvMatch))
+ self.masks, int(self.intlvMatch))
# Boolean parameter type. Python doesn't let you subclass bool, since
# it doesn't want to let you create multiple instances of True and
for elem_name in cls.map.keys():
code('} else if (%s == "%s") {' % (src, elem_name))
code.indent()
- code('%s = Enums::%s;' % (dest, elem_name))
+ name = cls.__name__ if cls.enum_name is None else cls.enum_name
+ code('%s = %s::%s;' % (dest, name if cls.is_class else 'Enums',
+ elem_name))
code('%s true;' % ret)
code.dedent()
code('} else {')
# Port reference: encapsulates a reference to a particular port on a
# particular SimObject.
class PortRef(object):
- def __init__(self, simobj, name, role):
+ def __init__(self, simobj, name, role, is_source):
assert(isSimObject(simobj) or isSimObjectClass(simobj))
self.simobj = simobj
self.name = name
self.role = role
+ self.is_source = is_source
self.peer = None # not associated with another port yet
self.ccConnected = False # C++ port connection done?
self.index = -1 # always -1 for non-vector ports
# for config.json
def get_config_as_dict(self):
- return {'role' : self.role, 'peer' : str(self.peer)}
+ return {'role' : self.role, 'peer' : str(self.peer),
+ 'is_source' : str(self.is_source)}
def __getattr__(self, attr):
if attr == 'peerObj':
fatal("Port %s is already connected to %s, cannot connect %s\n",
self, self.peer, other);
self.peer = other
+
if proxy.isproxy(other):
other.set_param_desc(PortParamDesc())
- elif isinstance(other, PortRef):
- if other.peer is not self:
- other.connect(self)
- else:
+ return
+ elif not isinstance(other, PortRef):
raise TypeError("assigning non-port reference '%s' to port '%s'" \
% (other, self))
- # Allow a master/slave port pair to be spliced between
- # a port and its connected peer. Useful operation for connecting
- # instrumentation structures into a system when it is necessary
- # to connect the instrumentation after the full system has been
- # constructed.
- def splice(self, new_master_peer, new_slave_peer):
+ if not Port.is_compat(self, other):
+ fatal("Ports %s and %s with roles '%s' and '%s' "
+ "are not compatible", self, other, self.role, other.role)
+
+ if other.peer is not self:
+ other.connect(self)
+
+ # Allow a compatible port pair to be spliced between a port and its
+ # connected peer. Useful operation for connecting instrumentation
+ # structures into a system when it is necessary to connect the
+ # instrumentation after the full system has been constructed.
+ def splice(self, new_1, new_2):
if not self.peer or proxy.isproxy(self.peer):
fatal("Port %s not connected, cannot splice in new peers\n", self)
- if not isinstance(new_master_peer, PortRef) or \
- not isinstance(new_slave_peer, PortRef):
+ if not isinstance(new_1, PortRef) or not isinstance(new_2, PortRef):
raise TypeError(
"Splicing non-port references '%s','%s' to port '%s'" % \
- (new_master_peer, new_slave_peer, self))
+ (new_1, new_2, self))
old_peer = self.peer
- if self.role == 'SLAVE':
- self.peer = new_master_peer
- old_peer.peer = new_slave_peer
- new_master_peer.connect(self)
- new_slave_peer.connect(old_peer)
- elif self.role == 'MASTER':
- self.peer = new_slave_peer
- old_peer.peer = new_master_peer
- new_slave_peer.connect(self)
- new_master_peer.connect(old_peer)
+
+ if Port.is_compat(old_peer, new_1) and Port.is_compat(self, new_2):
+ old_peer.peer = new_1
+ new_1.peer = old_peer
+ self.peer = new_2
+ new_2.peer = self
+ elif Port.is_compat(old_peer, new_2) and Port.is_compat(self, new_1):
+ old_peer.peer = new_2
+ new_2.peer = old_peer
+ self.peer = new_1
+ new_1.peer = self
else:
- panic("Port %s has unknown role, "+\
- "cannot splice in new peers\n", self)
+ fatal("Ports %s(%s) and %s(%s) can't be compatibly spliced with "
+ "%s(%s) and %s(%s)", self, self.role,
+ old_peer, old_peer.role, new_1, new_1.role,
+ new_2, new_2.role)
def clone(self, simobj, memo):
if self in memo:
# Call C++ to create corresponding port connection between C++ objects
def ccConnect(self):
- from _m5.pyobject import connectPorts
-
if self.ccConnected: # already done this
return
if not self.peer: # nothing to connect to
return
- # check that we connect a master to a slave
- if self.role == peer.role:
- raise TypeError(
- "cannot connect '%s' and '%s' due to identical role '%s'" % \
- (peer, self, self.role))
-
- if self.role == 'SLAVE':
- # do nothing and let the master take care of it
- return
+ port = self.simobj.getPort(self.name, self.index)
+ peer_port = peer.simobj.getPort(peer.name, peer.index)
+ port.bind(peer_port)
- try:
- # self is always the master and peer the slave
- 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
# A reference to an individual element of a VectorPort... much like a
# PortRef, but has an index.
class VectorPortElementRef(PortRef):
- def __init__(self, simobj, name, role, index):
- PortRef.__init__(self, simobj, name, role)
+ def __init__(self, simobj, name, role, is_source, index):
+ PortRef.__init__(self, simobj, name, role, is_source)
self.index = index
def __str__(self):
# A reference to a complete vector-valued port (not just a single element).
# Can be indexed to retrieve individual VectorPortElementRef instances.
class VectorPortRef(object):
- def __init__(self, simobj, name, role):
+ def __init__(self, simobj, name, role, is_source):
assert(isSimObject(simobj) or isSimObjectClass(simobj))
self.simobj = simobj
self.name = name
self.role = role
+ self.is_source = is_source
self.elements = []
def __str__(self):
# for config.json
def get_config_as_dict(self):
return {'role' : self.role,
- 'peer' : [el.ini_str() for el in self.elements]}
+ 'peer' : [el.ini_str() for el in self.elements],
+ 'is_source' : str(self.is_source)}
def __getitem__(self, key):
if not isinstance(key, int):
raise TypeError("VectorPort index must be integer")
if key >= len(self.elements):
# need to extend list
- ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
+ ext = [VectorPortElementRef(
+ self.simobj, self.name, self.role, self.is_source, i)
for i in range(len(self.elements), key+1)]
self.elements.extend(ext)
return self.elements[key]
# logical port in the SimObject class, not a particular port on a
# SimObject instance. The latter are represented by PortRef objects.
class Port(object):
+ # Port("role", "description")
+
+ _compat_dict = { }
+
+ @classmethod
+ def compat(cls, role, peer):
+ cls._compat_dict.setdefault(role, set()).add(peer)
+ cls._compat_dict.setdefault(peer, set()).add(role)
+
+ @classmethod
+ def is_compat(cls, one, two):
+ for port in one, two:
+ if not port.role in Port._compat_dict:
+ fatal("Unrecognized role '%s' for port %s\n", port.role, port)
+ return one.role in Port._compat_dict[two.role]
+
+ def __init__(self, role, desc, is_source=False):
+ self.desc = desc
+ self.role = role
+ self.is_source = is_source
+
# Generate a PortRef for this port on the given SimObject with the
# given name
def makeRef(self, simobj):
- return PortRef(simobj, self.name, self.role)
+ return PortRef(simobj, self.name, self.role, self.is_source)
# Connect an instance of this port (on the given SimObject with
# the given name) with the port described by the supplied PortRef
def cxx_decl(self, code):
code('unsigned int port_${{self.name}}_connection_count;')
-class MasterPort(Port):
- # MasterPort("description")
- def __init__(self, *args):
- if len(args) == 1:
- self.desc = args[0]
- self.role = 'MASTER'
- else:
- raise TypeError('wrong number of arguments')
-
-class SlavePort(Port):
- # SlavePort("description")
- def __init__(self, *args):
- if len(args) == 1:
- self.desc = args[0]
- self.role = 'SLAVE'
- else:
- raise TypeError('wrong number of arguments')
+Port.compat('GEM5 REQUESTER', 'GEM5 RESPONDER')
+
+class RequestPort(Port):
+ # RequestPort("description")
+ def __init__(self, desc):
+ super(RequestPort, self).__init__(
+ 'GEM5 REQUESTER', desc, is_source=True)
+
+class ResponsePort(Port):
+ # ResponsePort("description")
+ def __init__(self, desc):
+ super(ResponsePort, self).__init__('GEM5 RESPONDER', desc)
# VectorPort description object. Like Port, but represents a vector
# of connections (e.g., as on a XBar).
class VectorPort(Port):
- def __init__(self, *args):
- self.isVec = True
-
def makeRef(self, simobj):
- return VectorPortRef(simobj, self.name, self.role)
-
-class VectorMasterPort(VectorPort):
- # VectorMasterPort("description")
- def __init__(self, *args):
- if len(args) == 1:
- self.desc = args[0]
- self.role = 'MASTER'
- VectorPort.__init__(self, *args)
- else:
- raise TypeError('wrong number of arguments')
-
-class VectorSlavePort(VectorPort):
- # VectorSlavePort("description")
- def __init__(self, *args):
- if len(args) == 1:
- self.desc = args[0]
- self.role = 'SLAVE'
- VectorPort.__init__(self, *args)
- else:
- raise TypeError('wrong number of arguments')
+ return VectorPortRef(simobj, self.name, self.role, self.is_source)
+
+class VectorRequestPort(VectorPort):
+ # VectorRequestPort("description")
+ def __init__(self, desc):
+ super(VectorRequestPort, self).__init__(
+ 'GEM5 REQUESTER', desc, is_source=True)
+
+class VectorResponsePort(VectorPort):
+ # VectorResponsePort("description")
+ def __init__(self, desc):
+ super(VectorResponsePort, self).__init__('GEM5 RESPONDER', desc)
+
+# Old names, maintained for compatibility.
+MasterPort = RequestPort
+SlavePort = ResponsePort
+VectorMasterPort = VectorRequestPort
+VectorSlavePort = VectorResponsePort
# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
# proxy objects (via set_param_desc()) so that proxy error messages
'MaxAddr', 'MaxTick', 'AllMemory',
'Time',
'NextEthernetAddr', 'NULL',
- 'MasterPort', 'SlavePort',
+ 'Port', 'RequestPort', 'ResponsePort', 'MasterPort', 'SlavePort',
+ 'VectorPort', 'VectorRequestPort', 'VectorResponsePort',
'VectorMasterPort', 'VectorSlavePort']
-
-from . import SimObject