mem: Add ExternalMaster and ExternalSlave ports

This patch adds two MemoryObject's: ExternalMaster and ExternalSlave.
Each object has a single port which can be bound to an externally-
provided bridge to a port of another simulation system at
initialisation.
This commit is contained in:
Andrew Bardsley 2014-10-16 05:49:56 -04:00
parent 83f7e7afaf
commit d6732895a5
7 changed files with 747 additions and 0 deletions

52
src/mem/ExternalMaster.py Normal file
View file

@ -0,0 +1,52 @@
# Copyright (c) 2014 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.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Andrew Bardsley
# Curtis Dunham
from m5.params import *
from MemObject import MemObject
class ExternalMaster(MemObject):
type = 'ExternalMaster'
cxx_header = "mem/external_master.hh"
port = MasterPort("Master port")
port_type = Param.String('stub', 'Registered external port handler'
' to pass this port to in instantiation')
port_data = Param.String('stub', 'A string to pass to the port'
' handler (in a format specific to the handler) to describe how'
' the port should be bound/bindable/discoverable')

54
src/mem/ExternalSlave.py Normal file
View file

@ -0,0 +1,54 @@
# Copyright (c) 2014 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.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Andrew Bardsley
from m5.params import *
from MemObject import MemObject
class ExternalSlave(MemObject):
type = 'ExternalSlave'
cxx_header = "mem/external_slave.hh"
port = SlavePort("Slave port")
addr_ranges = VectorParam.AddrRange([], 'Addresses served by'
' this port\'s external agent')
port_type = Param.String('stub', 'Registered external port handler'
' to pass this port to in instantiation')
port_data = Param.String('stub', 'A string to pass to the port'
' handler (in a format specific to the handler) to describe how'
' the port should be bound/bindable/discoverable')

View file

@ -40,6 +40,8 @@ SimObject('AbstractMemory.py')
SimObject('AddrMapper.py')
SimObject('Bridge.py')
SimObject('DRAMCtrl.py')
SimObject('ExternalMaster.py')
SimObject('ExternalSlave.py')
SimObject('MemObject.py')
SimObject('SimpleMemory.py')
SimObject('XBar.py')
@ -50,6 +52,8 @@ Source('bridge.cc')
Source('coherent_xbar.cc')
Source('drampower.cc')
Source('dram_ctrl.cc')
Source('external_master.cc')
Source('external_slave.cc')
Source('mem_object.cc')
Source('mport.cc')
Source('noncoherent_xbar.cc')
@ -88,6 +92,7 @@ DebugFlag('CommMonitor')
DebugFlag('DRAM')
DebugFlag('DRAMPower')
DebugFlag('DRAMState')
DebugFlag('ExternalPort')
DebugFlag('LLSC')
DebugFlag('MMU')
DebugFlag('MemoryAccess')

107
src/mem/external_master.cc Normal file
View file

@ -0,0 +1,107 @@
/*
* Copyright (c) 2012-2014 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andrew Bardsley
* Curtis Dunham
*/
#include <cctype>
#include <iomanip>
#include "debug/ExternalPort.hh"
#include "mem/external_master.hh"
std::map<std::string, ExternalMaster::Handler *>
ExternalMaster::portHandlers;
ExternalMaster::ExternalMaster(ExternalMasterParams *params) :
MemObject(params),
externalPort(NULL),
portName(params->name + ".port"),
portType(params->port_type),
portData(params->port_data)
{}
BaseMasterPort &
ExternalMaster::getMasterPort(const std::string &if_name,
PortID idx)
{
if (if_name == "port") {
DPRINTF(ExternalPort, "Trying to bind external port: %s %s\n",
portType, portName);
if (!externalPort) {
auto handlerIter = portHandlers.find(portType);
if (handlerIter == portHandlers.end())
fatal("Can't find port handler type '%s'\n", portType);
externalPort = portHandlers[portType]->getExternalPort(portName,
*this, portData);
if (!externalPort) {
fatal("%s: Can't find external port type: %s"
" port_data: '%s'\n", portName, portType, portData);
}
}
return *externalPort;
} else {
return MemObject::getMasterPort(if_name, idx);
}
}
void
ExternalMaster::init()
{
if (!externalPort) {
fatal("ExternalMaster %s: externalPort not set!\n", name());
} else if (!externalPort->isConnected()) {
fatal("ExternalMaster %s is unconnected!\n", name());
}
}
ExternalMaster *
ExternalMasterParams::create()
{
return new ExternalMaster(this);
}
void
ExternalMaster::registerHandler(const std::string &handler_name,
Handler *handler)
{
portHandlers[handler_name] = handler;
}

135
src/mem/external_master.hh Normal file
View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2012-2014 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andrew Bardsley
* Curtis Dunham
*/
/**
* @file
*
* ExternalMaster is a memory object representing a binding from
* a gem5 slave to a master port in a system external to gem5.
*
* During initialisation, a `handler' for the port type specified in the
* port's port_type parameter is found from the registered port handlers
* provided with registerHandler. Once a handler is found, it is passed the
* port_data parameter of the port which can be used to identify the external
* port which is to be bound to. A port handler will usually construct a
* bridge object in the external system to accomodate the port-to-port
* mapping but this bridge is not exposed to gem5 other than be the
* presentation of the MasterPort which can be bound.
*
* The external port must provide a gem5 MasterPort interface.
*/
#ifndef __MEM_EXTERNAL_MASTER__
#define __MEM_EXTERNAL_MASTER__
#include "mem/mem_object.hh"
#include "params/ExternalMaster.hh"
class ExternalMaster : public MemObject
{
public:
/** Derive from this class to create an external port interface */
class Port : public MasterPort
{
protected:
ExternalMaster &owner;
public:
Port(const std::string &name_,
ExternalMaster &owner_) :
MasterPort(name_, &owner_), owner(owner_)
{ }
~Port() { }
/** Any or all of recv... can be overloaded to provide the port's
* functionality */
};
/* Handlers are specific to *types* of port not specific port
* instantiations. A handler will typically build a bridge to the
* external port from gem5 and provide gem5 with a MasterPort that can be
* bound to for each call to Handler::getExternalPort.*/
class Handler
{
public:
/** Create or find an external port which can be bound. Returns
* NULL on failure */
virtual Port *getExternalPort(
const std::string &name, ExternalMaster &owner,
const std::string &port_data) = 0;
};
protected:
/** The peer port for the gem5 port "port" */
Port *externalPort;
/** Name of the bound port. This will be name() + ".port" */
std::string portName;
/** Key to select a port handler */
std::string portType;
/** Handler-specific port configuration */
std::string portData;
/** Registered handlers. Handlers are chosen using the port_type
* parameter on ExternalMasters. port_types form a global namespace
* across the simulation and so handlers are registered into a global
* structure */
static std::map<std::string, Handler *> portHandlers;
public:
ExternalMaster(ExternalMasterParams *params);
/** MasterPort interface. Responds only to port "port" */
BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
/** Register a handler which can provide ports with port_type ==
* handler_name */
static void registerHandler(const std::string &handler_name,
Handler *handler);
void init();
};
#endif // __MEM_EXTERNAL_MASTER__

252
src/mem/external_slave.cc Normal file
View file

@ -0,0 +1,252 @@
/*
* Copyright (c) 2012-2014 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andrew Bardsley
*/
#include <cctype>
#include <iomanip>
#include "debug/ExternalPort.hh"
#include "mem/external_slave.hh"
/** Implement a `stub' port which just responds to requests by printing
* a message. The stub port can be used to configure and test a system
* where the external port is used for a peripheral before connecting
* the external port */
class StubSlavePort : public ExternalSlave::Port
{
public:
class ResponseEvent : public Event
{
public:
StubSlavePort &owner;
ResponseEvent(StubSlavePort &owner_) : owner(owner_) { }
void process();
};
ResponseEvent responseEvent;
/** Stub can handle a single request at a time. This will be
* NULL when no packet is in flight */
PacketPtr responsePacket;
/** Received a new request while processing a first. Need to ask for
* a retry after completing this packet */
bool mustRetry;
StubSlavePort(const std::string &name_,
ExternalSlave &owner_) :
ExternalSlave::Port(name_, owner_),
responseEvent(*this), responsePacket(NULL)
{ }
Tick recvAtomic(PacketPtr packet);
void recvFunctional(PacketPtr packet);
bool recvTimingReq(PacketPtr packet);
bool recvTimingSnoopResp(PacketPtr packet);
void recvRetry();
void recvFunctionalSnoop(PacketPtr packet);
};
class StubSlavePortHandler : public
ExternalSlave::Handler
{
public:
ExternalSlave::Port *getExternalPort(
const std::string &name_,
ExternalSlave &owner,
const std::string &port_data)
{
StringWrap name(name_);
DPRINTF(ExternalPort, "finding stub port '%s'\n", port_data);
return new StubSlavePort(name_, owner);
}
};
Tick
StubSlavePort::recvAtomic(PacketPtr packet)
{
if (DTRACE(ExternalPort)) {
unsigned int M5_VAR_USED size = packet->getSize();
DPRINTF(ExternalPort, "StubSlavePort: recvAtomic a: 0x%x size: %d"
" data: ...\n", packet->getAddr(), size);
DDUMP(ExternalPort, packet->getPtr<uint8_t>(), size);
}
return 0;
}
void
StubSlavePort::recvFunctional(PacketPtr packet)
{
recvAtomic(packet);
}
void
StubSlavePort::ResponseEvent::process()
{
owner.responsePacket->makeResponse();
owner.responsePacket->firstWordDelay = 0;
owner.responsePacket->lastWordDelay = 0;
if (owner.sendTimingResp(owner.responsePacket)) {
owner.responsePacket = NULL;
if (owner.mustRetry)
owner.sendRetry();
owner.mustRetry = false;
}
}
bool
StubSlavePort::recvTimingReq(PacketPtr packet)
{
if (responsePacket) {
mustRetry = true;
return false;
} else {
recvAtomic(packet);
responsePacket = packet;
owner.schedule(responseEvent, curTick());
return true;
}
}
bool
StubSlavePort::recvTimingSnoopResp(PacketPtr packet)
{
fatal("StubSlavePort: function: %s\n", __func__);
return false;
}
void
StubSlavePort::recvRetry()
{
assert(responsePacket);
/* Stub handles only one response at a time so responseEvent should never
* be scheduled at this point. Retrys shouldn't need to schedule, we
* can safely send the response here */
responseEvent.process();
}
void
StubSlavePort::recvFunctionalSnoop(PacketPtr packet)
{
fatal("StubSlavePort: unimplemented function: %s\n", __func__);
}
std::map<std::string, ExternalSlave::Handler *>
ExternalSlave::portHandlers;
AddrRangeList
ExternalSlave::Port::getAddrRanges() const
{
return owner.addrRanges;
}
ExternalSlave::ExternalSlave(ExternalSlaveParams *params) :
MemObject(params),
externalPort(NULL),
portName(params->name + ".port"),
portType(params->port_type),
portData(params->port_data),
addrRanges(params->addr_ranges.begin(), params->addr_ranges.end())
{
/* Register the stub handler if it hasn't already been registered */
if (portHandlers.find("stub") == portHandlers.end())
registerHandler("stub", new StubSlavePortHandler);
}
BaseSlavePort &
ExternalSlave::getSlavePort(const std::string &if_name,
PortID idx)
{
if (if_name == "port") {
DPRINTF(ExternalPort, "Trying to bind external port: %s %s\n",
portType, portName);
if (!externalPort) {
auto handlerIter = portHandlers.find(portType);
if (handlerIter == portHandlers.end())
fatal("Can't find port handler type '%s'\n", portType);
externalPort = portHandlers[portType]->getExternalPort(portName,
*this, portData);
if (!externalPort) {
fatal("%s: Can't find external port type: %s"
" port_data: '%s'\n", portName, portType, portData);
}
}
return *externalPort;
} else {
return MemObject::getSlavePort(if_name, idx);
}
}
void
ExternalSlave::init()
{
if (!externalPort) {
fatal("ExternalSlave %s: externalPort not set!\n", name());
} else if (!externalPort->isConnected()) {
fatal("ExternalSlave %s is unconnected!\n", name());
} else {
externalPort->sendRangeChange();
}
}
ExternalSlave *
ExternalSlaveParams::create()
{
return new ExternalSlave(this);
}
void
ExternalSlave::registerHandler(const std::string &handler_name,
Handler *handler)
{
portHandlers[handler_name] = handler;
}

142
src/mem/external_slave.hh Normal file
View file

@ -0,0 +1,142 @@
/*
* Copyright (c) 2012-2014 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andrew Bardsley
*/
/**
* @file
*
* ExternalSlave is a memory object representing a binding from
* a gem5 master to a slave port in a system external to gem5.
*
* During initialisation, a `handler' for the port type specified in the
* port's port_type parameter is found from the registered port handlers
* provided with registerHandler. Once a handler is found, it is passed the
* port_data parameter of the port which can be used to identify the external
* port which is to be bound to. A port handler will usually construct a
* bridge object in the external system to accomodate the port-to-port
* mapping but this bridge is not exposed to gem5 other than be the
* presentation of the SlavePort which can be bound.
*
* The external port must provide a gem5 SlavePort interface (with the
* exception of getAddrRanges which is provided by the ExternalSlave
* object).
*/
#ifndef __MEM_EXTERNAL_SLAVE__
#define __MEM_EXTERNAL_SLAVE__
#include "mem/mem_object.hh"
#include "params/ExternalSlave.hh"
class ExternalSlave : public MemObject
{
public:
/** Derive from this class to create an external port interface */
class Port : public SlavePort
{
protected:
ExternalSlave &owner;
public:
Port(const std::string &name_,
ExternalSlave &owner_) :
SlavePort(name_, &owner_), owner(owner_)
{ }
~Port() { }
/** Any or all of recv... can be overloaded to provide the port's
* functionality */
AddrRangeList getAddrRanges() const;
};
/* Handlers are specific to *types* of port not specific port
* instantiations. A handler will typically build a bridge to the
* external port from gem5 and provide gem5 with a SlavePort that can be
* bound to for each call to Handler::getExternalPort.*/
class Handler
{
public:
/** Create or find an external port which can be bound. Returns
* NULL on failure */
virtual Port *getExternalPort(
const std::string &name, ExternalSlave &owner,
const std::string &port_data) = 0;
};
protected:
/** The peer port for the gem5 port "port" */
Port *externalPort;
/** Name of the bound port. This will be name() + ".port" */
std::string portName;
/** Key to select a port handler */
std::string portType;
/** Handler-specific port configuration */
std::string portData;
/** The Range of addresses supported by the devices on the external
* side of this port */
AddrRangeList addrRanges;
/** Registered handlers. Handlers are chosen using the port_type
* parameter on ExternalSlaves. port_types form a global namespace
* across the simulation and so handlers are registered into a global
* structure */
static std::map<std::string, Handler *> portHandlers;
public:
ExternalSlave(ExternalSlaveParams *params);
/** SlavePort interface. Responds only to port "port" */
BaseSlavePort &getSlavePort(const std::string &if_name,
PortID idx = InvalidPortID);
/** Register a handler which can provide ports with port_type ==
* handler_name */
static void registerHandler(const std::string &handler_name,
Handler *handler);
void init();
};
#endif // __MEM_EXTERNAL_SLAVE__