The MemoryObject tha owns a port should delete it if it so chooses when deletePortRefs() is called on it with that port as a parameter.
In this way a MemoryObject can keep a functional port around and give it to anyone who wants to do functional accesses rather than creating a new one each time. src/mem/bus.cc: src/mem/bus.hh: src/mem/cache/cache_impl.hh: only keep around one func port we give to anyone who wants it. Otherwise we can run out of port ids reasonably quickly if a lot of functional accesses are happening (e.g. remote debugging, dprintk, etc) --HG-- extra : convert_revision : 6a9e3e96f51cedaab6de1b36cf317203899a3716
This commit is contained in:
parent
c46e946c94
commit
d0ea8ff088
4 changed files with 25 additions and 5 deletions
|
@ -52,9 +52,19 @@ Bus::getPort(const std::string &if_name, int idx)
|
|||
} else
|
||||
fatal("Default port already set\n");
|
||||
}
|
||||
int id;
|
||||
if (if_name == "functional") {
|
||||
if (!funcPort) {
|
||||
id = maxId++;
|
||||
funcPort = new BusPort(csprintf("%s-p%d-func", name(), id), this, id);
|
||||
funcPortId = id;
|
||||
interfaces[id] = funcPort;
|
||||
}
|
||||
return funcPort;
|
||||
}
|
||||
|
||||
// if_name ignored? forced to be empty?
|
||||
int id = maxId++;
|
||||
id = maxId++;
|
||||
assert(maxId < std::numeric_limits<typeof(maxId)>::max());
|
||||
BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
|
||||
interfaces[id] = bp;
|
||||
|
@ -64,10 +74,15 @@ Bus::getPort(const std::string &if_name, int idx)
|
|||
void
|
||||
Bus::deletePortRefs(Port *p)
|
||||
{
|
||||
|
||||
BusPort *bp = dynamic_cast<BusPort*>(p);
|
||||
if (bp == NULL)
|
||||
panic("Couldn't convert Port* to BusPort*\n");
|
||||
// If this is our one functional port
|
||||
if (funcPort == bp)
|
||||
return;
|
||||
interfaces.erase(bp->getId());
|
||||
delete bp;
|
||||
}
|
||||
|
||||
/** Get the ranges of anyone other buses that we are connected to. */
|
||||
|
@ -520,7 +535,7 @@ Bus::recvStatusChange(Port::Status status, int id)
|
|||
m5::hash_map<short,BusPort*>::iterator intIter;
|
||||
|
||||
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
|
||||
if (intIter->first != id)
|
||||
if (intIter->first != id && intIter->first != funcPortId)
|
||||
intIter->second->sendStatusChange(Port::RangeChange);
|
||||
|
||||
if (id != defaultId && defaultPort)
|
||||
|
|
|
@ -63,6 +63,7 @@ class Bus : public MemObject
|
|||
|
||||
Event * drainEvent;
|
||||
|
||||
|
||||
static const int defaultId = -3; //Make it unique from Broadcast
|
||||
|
||||
struct DevMap {
|
||||
|
@ -249,6 +250,9 @@ class Bus : public MemObject
|
|||
/** Port that handles requests that don't match any of the interfaces.*/
|
||||
BusPort *defaultPort;
|
||||
|
||||
BusPort *funcPort;
|
||||
int funcPortId;
|
||||
|
||||
/** Has the user specified their own default responder? */
|
||||
bool responderSet;
|
||||
|
||||
|
@ -266,7 +270,8 @@ class Bus : public MemObject
|
|||
bool responder_set)
|
||||
: MemObject(n), busId(bus_id), clock(_clock), width(_width),
|
||||
tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false),
|
||||
maxId(0), defaultPort(NULL), responderSet(responder_set)
|
||||
maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4),
|
||||
responderSet(responder_set)
|
||||
{
|
||||
//Both the width and clock period must be positive
|
||||
if (width <= 0)
|
||||
|
|
3
src/mem/cache/cache_impl.hh
vendored
3
src/mem/cache/cache_impl.hh
vendored
|
@ -1183,7 +1183,8 @@ Cache<TagStore,Coherence>::deletePortRefs(Port *p)
|
|||
{
|
||||
if (cpuSidePort == p || memSidePort == p)
|
||||
panic("Can only delete functional ports\n");
|
||||
// nothing else to do
|
||||
|
||||
delete p;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ Port::removeConn()
|
|||
{
|
||||
if (peer->getOwner())
|
||||
peer->getOwner()->deletePortRefs(peer);
|
||||
delete peer;
|
||||
peer = NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue