MEM: Introduce the master/slave port roles in the Python classes
This patch classifies all ports in Python as either Master or Slave and enforces a binding of master to slave. Conceptually, a master (such as a CPU or DMA port) issues requests, and receives responses, and conversely, a slave (such as a memory or a PIO device) receives requests and sends back responses. Currently there is no differentiation between coherent and non-coherent masters and slaves. The classification as master/slave also involves splitting the dual role port of the bus into a master and slave port and updating all the system assembly scripts to use the appropriate port. Similarly, the interrupt devices have to have their int_port split into a master and slave port. The intdev and its children have minimal changes to facilitate the extra port. Note that this patch does not enforce any port typing in the C++ world, it merely ensures that the Python objects have a notion of the port roles and are connected in an appropriate manner. This check is carried when two ports are connected, e.g. bus.master = memory.port. The following patches will make use of the classifications and specialise the C++ ports into masters and slaves.
This commit is contained in:
@@ -46,7 +46,7 @@ from m5.params import *
|
||||
# There are a few things we need that aren't in params.__all__ since
|
||||
# normal users don't need them
|
||||
from m5.params import ParamDesc, VectorParamDesc, \
|
||||
isNullPointer, SimObjectVector
|
||||
isNullPointer, SimObjectVector, Port
|
||||
|
||||
from m5.proxy import *
|
||||
from m5.proxy import isproxy
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
# Copyright (c) 2012 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
# not be construed as granting a license to any other intellectual
|
||||
# property including but not limited to intellectual property relating
|
||||
# to a hardware implementation of the functionality of the software
|
||||
# licensed hereunder. You may use the software subject to the license
|
||||
# terms below provided that you ensure that this notice is replicated
|
||||
# unmodified and in its entirety in all distributions of the software,
|
||||
# modified or unmodified, in source code or in binary form.
|
||||
#
|
||||
# Copyright (c) 2004-2006 The Regents of The University of Michigan
|
||||
# Copyright (c) 2010-2011 Advanced Micro Devices, Inc.
|
||||
# All rights reserved.
|
||||
@@ -28,6 +40,7 @@
|
||||
# Authors: Steve Reinhardt
|
||||
# Nathan Binkert
|
||||
# Gabe Black
|
||||
# Andreas Hansson
|
||||
|
||||
#####################################################################
|
||||
#
|
||||
@@ -1324,10 +1337,11 @@ AllMemory = AddrRange(0, MaxAddr)
|
||||
# Port reference: encapsulates a reference to a particular port on a
|
||||
# particular SimObject.
|
||||
class PortRef(object):
|
||||
def __init__(self, simobj, name):
|
||||
def __init__(self, simobj, name, role):
|
||||
assert(isSimObject(simobj) or isSimObjectClass(simobj))
|
||||
self.simobj = simobj
|
||||
self.name = name
|
||||
self.role = role
|
||||
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
|
||||
@@ -1397,12 +1411,24 @@ class PortRef(object):
|
||||
def ccConnect(self):
|
||||
from m5.internal.pyobject import connectPorts
|
||||
|
||||
if self.role == 'SLAVE':
|
||||
# do nothing and let the master take care of it
|
||||
return
|
||||
|
||||
if self.ccConnected: # already done this
|
||||
return
|
||||
peer = self.peer
|
||||
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)
|
||||
|
||||
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:
|
||||
@@ -1416,8 +1442,8 @@ class PortRef(object):
|
||||
# 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, index):
|
||||
PortRef.__init__(self, simobj, name)
|
||||
def __init__(self, simobj, name, role, index):
|
||||
PortRef.__init__(self, simobj, name, role)
|
||||
self.index = index
|
||||
|
||||
def __str__(self):
|
||||
@@ -1426,10 +1452,11 @@ class VectorPortElementRef(PortRef):
|
||||
# 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):
|
||||
def __init__(self, simobj, name, role):
|
||||
assert(isSimObject(simobj) or isSimObjectClass(simobj))
|
||||
self.simobj = simobj
|
||||
self.name = name
|
||||
self.role = role
|
||||
self.elements = []
|
||||
|
||||
def __str__(self):
|
||||
@@ -1444,7 +1471,7 @@ class VectorPortRef(object):
|
||||
raise TypeError, "VectorPort index must be integer"
|
||||
if key >= len(self.elements):
|
||||
# need to extend list
|
||||
ext = [VectorPortElementRef(self.simobj, self.name, i)
|
||||
ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
|
||||
for i in range(len(self.elements), key+1)]
|
||||
self.elements.extend(ext)
|
||||
return self.elements[key]
|
||||
@@ -1488,34 +1515,62 @@ class VectorPortRef(object):
|
||||
# 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("description")
|
||||
def __init__(self, *args):
|
||||
if len(args) == 1:
|
||||
self.desc = args[0]
|
||||
else:
|
||||
raise TypeError, 'wrong number of arguments'
|
||||
# self.name is set by SimObject class on assignment
|
||||
# e.g., pio_port = Port("blah") sets self.name to 'pio_port'
|
||||
|
||||
# Generate a PortRef for this port on the given SimObject with the
|
||||
# given name
|
||||
def makeRef(self, simobj):
|
||||
return PortRef(simobj, self.name)
|
||||
return PortRef(simobj, self.name, self.role)
|
||||
|
||||
# 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, ref):
|
||||
self.makeRef(simobj).connect(ref)
|
||||
|
||||
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'
|
||||
|
||||
# VectorPort description object. Like Port, but represents a vector
|
||||
# of connections (e.g., as on a Bus).
|
||||
class VectorPort(Port):
|
||||
def __init__(self, *args):
|
||||
Port.__init__(self, *args)
|
||||
self.isVec = True
|
||||
|
||||
def makeRef(self, simobj):
|
||||
return VectorPortRef(simobj, self.name)
|
||||
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'
|
||||
|
||||
# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
|
||||
# proxy objects (via set_param_desc()) so that proxy error messages
|
||||
@@ -1549,6 +1604,7 @@ __all__ = ['Param', 'VectorParam',
|
||||
'MaxAddr', 'MaxTick', 'AllMemory',
|
||||
'Time',
|
||||
'NextEthernetAddr', 'NULL',
|
||||
'Port', 'VectorPort']
|
||||
'MasterPort', 'SlavePort',
|
||||
'VectorMasterPort', 'VectorSlavePort']
|
||||
|
||||
import SimObject
|
||||
|
||||
Reference in New Issue
Block a user