* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
+ * Andreas Hansson
*/
/**
* Definition of a bus object.
*/
-#include <algorithm>
-#include <limits>
-
#include "base/misc.hh"
#include "base/trace.hh"
#include "debug/Bus.hh"
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)
{
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;
}
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);
}
}
}
{
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.
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;
}
}
} 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) {
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;
}
}
DPRINTF(Bus, "Unable to find destination for addr %#llx, "
"will use default port\n", addr);
- return defaultId;
+ return defaultPortId;
}
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++) {
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();
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",
}
} else {
- assert((id < maxId && id >= 0) || id == defaultId);
+ assert(id < interfaces.size() && id >= 0);
BusPort *port = interfaces[id];
// Clean out any previously existent ids
// 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);
}
*
* Authors: Ron Dreslinski
* Ali Saidi
+ * Andreas Hansson
*/
/**
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
Event * drainEvent;
-
- static const int defaultId = -3; //Make it unique from Broadcast
-
typedef range_map<Addr,int>::iterator PortIter;
range_map<Addr, int> portMap;
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.*/
}
/** 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
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. */