MEM: Make the bus default port yet another port

This patch removes the idiosyncratic nature of the default bus port
and makes it yet another port in the list of interfaces. Rather than
having a specific pointer to the default port we merely track the
identifier of this port. This change makes future port diversification
easier and overall cleans up the bus code.
This commit is contained in:
Andreas Hansson 2012-01-17 12:55:09 -06:00
parent 55cf3f4ac1
commit acd289b7ef
2 changed files with 35 additions and 125 deletions

View file

@ -38,6 +38,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
* Andreas Hansson
*/
/**
@ -45,9 +46,6 @@
* Definition of a bus object.
*/
#include <algorithm>
#include <limits>
#include "base/misc.hh"
#include "base/trace.hh"
#include "debug/Bus.hh"
@ -58,8 +56,7 @@
Bus::Bus(const BusParams *p)
: MemObject(p), busId(p->bus_id), clock(p->clock),
headerCycles(p->header_cycles), width(p->width), tickNextIdle(0),
drainEvent(NULL), busIdle(this), inRetry(false), maxId(0),
defaultPort(NULL),
drainEvent(NULL), busIdle(this), inRetry(false), defaultPortId(-1),
useDefaultRange(p->use_default_range), defaultBlockSize(p->block_size),
cachedBlockSize(0), cachedBlockSizeValid(false)
{
@ -70,28 +67,25 @@ Bus::Bus(const BusParams *p)
fatal("Bus clock period must be positive\n");
if (headerCycles <= 0)
fatal("Number of header cycles must be positive\n");
clearBusCache();
clearPortCache();
}
Port *
Bus::getPort(const std::string &if_name, int idx)
{
std::string portName;
int id = interfaces.size();
if (if_name == "default") {
if (defaultPort == NULL) {
defaultPort = new BusPort(csprintf("%s-default",name()), this,
defaultId);
cachedBlockSizeValid = false;
return defaultPort;
if (defaultPortId == -1) {
defaultPortId = id;
portName = csprintf("%s-default", name());
} else
fatal("Default port already set\n");
fatal("Default port already set on %s\n", name());
} else {
portName = csprintf("%s-p%d", name(), id);
}
int id;
// if_name ignored? forced to be empty?
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;
BusPort *bp = new BusPort(portName, this, id);
interfaces.push_back(bp);
cachedBlockSizeValid = false;
return bp;
}
@ -99,16 +93,16 @@ Bus::getPort(const std::string &if_name, int idx)
void
Bus::init()
{
m5::hash_map<short,BusPort*>::iterator intIter;
std::vector<BusPort*>::iterator intIter;
// iterate over our interfaces and determine which of our neighbours
// are snooping and add them as snoopers
for (intIter = interfaces.begin(); intIter != interfaces.end();
intIter++) {
if (intIter->second->getPeer()->isSnooping()) {
if ((*intIter)->getPeer()->isSnooping()) {
DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n",
intIter->second->getPeer()->name());
snoopPorts.push_back(intIter->second);
(*intIter)->getPeer()->name());
snoopPorts.push_back(*intIter);
}
}
}
@ -188,16 +182,7 @@ Bus::recvTiming(PacketPtr pkt)
{
short src = pkt->getSrc();
BusPort *src_port;
if (src == defaultId)
src_port = defaultPort;
else {
src_port = checkBusCache(src);
if (src_port == NULL) {
src_port = interfaces[src];
updateBusCache(src, src_port);
}
}
BusPort *src_port = interfaces[src];
// If the bus is busy, or other devices are in line ahead of the current
// one, put this device on the retry list.
@ -223,8 +208,7 @@ Bus::recvTiming(PacketPtr pkt)
if (dest == Packet::Broadcast) {
dest_port_id = findPort(pkt->getAddr());
dest_port = (dest_port_id == defaultId) ?
defaultPort : interfaces[dest_port_id];
dest_port = interfaces[dest_port_id];
SnoopIter s_end = snoopPorts.end();
for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
BusPort *p = *s_iter;
@ -235,20 +219,10 @@ Bus::recvTiming(PacketPtr pkt)
}
}
} else {
assert(dest < maxId);
assert(dest < interfaces.size());
assert(dest != src); // catch infinite loops
dest_port_id = dest;
if (dest_port_id == defaultId)
dest_port = defaultPort;
else {
dest_port = checkBusCache(dest);
if (dest_port == NULL) {
dest_port = interfaces[dest_port_id];
// updateBusCache(dest_port_id, dest_port);
}
}
dest_port = (dest_port_id == defaultId) ?
defaultPort : interfaces[dest_port_id];
dest_port = interfaces[dest_port_id];
}
if (dest_port_id == src) {
@ -346,7 +320,7 @@ Bus::findPort(Addr addr)
for (AddrRangeIter i = defaultRange.begin(); i != a_end; i++) {
if (*i == addr) {
DPRINTF(Bus, " found addr %#llx on default\n", addr);
return defaultId;
return defaultPortId;
}
}
@ -355,7 +329,7 @@ Bus::findPort(Addr addr)
DPRINTF(Bus, "Unable to find destination for addr %#llx, "
"will use default port\n", addr);
return defaultId;
return defaultPortId;
}
@ -379,16 +353,7 @@ Bus::recvAtomic(PacketPtr pkt)
int orig_src = pkt->getSrc();
int target_port_id = findPort(pkt->getAddr());
BusPort *target_port;
if (target_port_id == defaultId)
target_port = defaultPort;
else {
target_port = checkBusCache(target_port_id);
if (target_port == NULL) {
target_port = interfaces[target_port_id];
updateBusCache(target_port_id, target_port);
}
}
BusPort *target_port = interfaces[target_port_id];
SnoopIter s_end = snoopPorts.end();
for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
@ -444,7 +409,7 @@ Bus::recvFunctional(PacketPtr pkt)
assert(pkt->getDest() == Packet::Broadcast);
int port_id = findPort(pkt->getAddr());
Port *port = (port_id == defaultId) ? defaultPort : interfaces[port_id];
Port *port = interfaces[port_id];
// The packet may be changed by another bus on snoops, restore the
// id after each
int src_id = pkt->getSrc();
@ -491,11 +456,11 @@ Bus::recvRangeChange(int id)
DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
clearPortCache();
if (id == defaultId) {
if (id == defaultPortId) {
defaultRange.clear();
// Only try to update these ranges if the user set a default responder.
if (useDefaultRange) {
AddrRangeList ranges = defaultPort->getPeer()->getAddrRanges();
AddrRangeList ranges = interfaces[id]->getPeer()->getAddrRanges();
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
defaultRange.push_back(*iter);
DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n",
@ -504,7 +469,7 @@ Bus::recvRangeChange(int id)
}
} else {
assert((id < maxId && id >= 0) || id == defaultId);
assert(id < interfaces.size() && id >= 0);
BusPort *port = interfaces[id];
// Clean out any previously existent ids
@ -533,14 +498,12 @@ Bus::recvRangeChange(int id)
// tell all our peers that our address range has changed.
// Don't tell the device that caused this change, it already knows
m5::hash_map<short,BusPort*>::iterator intIter;
std::vector<BusPort*>::const_iterator intIter;
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
if (intIter->first != id)
intIter->second->sendRangeChange();
if ((*intIter)->getId() != id)
(*intIter)->sendRangeChange();
if (id != defaultId && defaultPort)
defaultPort->sendRangeChange();
inRecvRangeChange.erase(id);
}

View file

@ -39,6 +39,7 @@
*
* Authors: Ron Dreslinski
* Ali Saidi
* Andreas Hansson
*/
/**
@ -91,7 +92,7 @@ class Bus : public MemObject
void onRetryList(bool newVal)
{ _onRetryList = newVal; }
int getId() { return id; }
int getId() const { return id; }
/**
* Determine if this port should be considered a snooper. This
@ -167,9 +168,6 @@ class Bus : public MemObject
Event * drainEvent;
static const int defaultId = -3; //Make it unique from Broadcast
typedef range_map<Addr,int>::iterator PortIter;
range_map<Addr, int> portMap;
@ -297,12 +295,9 @@ class Bus : public MemObject
bool inRetry;
std::set<int> inRecvRangeChange;
/** max number of bus ids we've handed out so far */
short maxId;
/** An array of pointers to the peer port interfaces
/** An ordered vector of pointers to the peer port interfaces
connected to this bus.*/
m5::hash_map<short,BusPort*> interfaces;
std::vector<BusPort*> interfaces;
/** An array of pointers to ports that retry should be called on because the
* original send failed for whatever reason.*/
@ -331,7 +326,7 @@ class Bus : public MemObject
}
/** Port that handles requests that don't match any of the interfaces.*/
BusPort *defaultPort;
short defaultPortId;
/** If true, use address range provided by default device. Any
address not handled by another port and not in default device's
@ -343,54 +338,6 @@ class Bus : public MemObject
unsigned cachedBlockSize;
bool cachedBlockSizeValid;
// Cache for the peer port interfaces
struct BusCache {
bool valid;
short id;
BusPort *port;
};
BusCache busCache[3];
// Checks the peer port interfaces cache for the port id and returns
// a pointer to the matching port
inline BusPort* checkBusCache(short id) {
if (busCache[0].valid && id == busCache[0].id) {
return busCache[0].port;
}
if (busCache[1].valid && id == busCache[1].id) {
return busCache[1].port;
}
if (busCache[2].valid && id == busCache[2].id) {
return busCache[2].port;
}
return NULL;
}
// Replaces the earliest entry in the cache with a new entry
inline void updateBusCache(short id, BusPort *port) {
busCache[2].valid = busCache[1].valid;
busCache[2].id = busCache[1].id;
busCache[2].port = busCache[1].port;
busCache[1].valid = busCache[0].valid;
busCache[1].id = busCache[0].id;
busCache[1].port = busCache[0].port;
busCache[0].valid = true;
busCache[0].id = id;
busCache[0].port = port;
}
// Invalidates the cache. Needs to be called in constructor.
inline void clearBusCache() {
busCache[2].valid = false;
busCache[1].valid = false;
busCache[0].valid = false;
}
public:
/** A function used to return the port associated with this bus object. */