summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2006-11-10 12:44:15 -0500
committerKevin Lim <ktlim@umich.edu>2006-11-10 12:44:15 -0500
commitb5e68fb54677f601bb00c23af52db8fd6571301f (patch)
treedc3c17198ba4010d907ecd8cb7189aa7959948d4 /src/mem
parent264f9ce374ff4689fec3c32d8289fe76b0b65078 (diff)
parent9ef51f2dbaba88c10366d708f0ca872bb39064e4 (diff)
downloadgem5-b5e68fb54677f601bb00c23af52db8fd6571301f.tar.xz
Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/o3-merge/newmem --HG-- extra : convert_revision : 0c2db1e1b5fdb91c1ac5705ab872a6bfb575a67a
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/bus.cc54
-rw-r--r--src/mem/bus.hh15
-rw-r--r--src/mem/cache/base_cache.cc28
-rw-r--r--src/mem/cache/base_cache.hh33
-rw-r--r--src/mem/physical.cc4
-rw-r--r--src/mem/port.hh31
-rw-r--r--src/mem/port_impl.hh7
-rw-r--r--src/mem/tport.hh4
8 files changed, 141 insertions, 35 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 86a148f87..7b65d252b 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -42,13 +42,14 @@
Port *
Bus::getPort(const std::string &if_name, int idx)
{
- if (if_name == "default")
+ if (if_name == "default") {
if (defaultPort == NULL) {
defaultPort = new BusPort(csprintf("%s-default",name()), this,
- defaultId);
+ defaultId);
return defaultPort;
} else
fatal("Default port already set\n");
+ }
// if_name ignored? forced to be empty?
int id = interfaces.size();
@@ -240,6 +241,9 @@ Bus::recvRetry(int id)
}
}
}
+ //If we weren't able to drain before, we might be able to now.
+ if (drainEvent && retryList.size() == 0 && curTick >= tickNextIdle)
+ drainEvent->process();
}
Port *
@@ -269,7 +273,16 @@ Bus::findPort(Addr addr, int id)
return defaultPort;
}
}
- panic("Unable to find destination for addr: %#llx", addr);
+
+ if (responderSet) {
+ panic("Unable to find destination for addr (user set default "
+ "responder): %#llx", addr);
+ } else {
+ DPRINTF(Bus, "Unable to find destination for addr: %#llx, will use "
+ "default port", addr);
+
+ return defaultPort;
+ }
}
@@ -392,12 +405,15 @@ Bus::recvStatusChange(Port::Status status, int id)
if (id == defaultId) {
defaultRange.clear();
- defaultPort->getPeerAddressRanges(ranges, snoops);
- assert(snoops.size() == 0);
- for(iter = ranges.begin(); iter != ranges.end(); iter++) {
- defaultRange.push_back(*iter);
- DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n",
- iter->start, iter->end);
+ // Only try to update these ranges if the user set a default responder.
+ if (responderSet) {
+ defaultPort->getPeerAddressRanges(ranges, snoops);
+ assert(snoops.size() == 0);
+ for(iter = ranges.begin(); iter != ranges.end(); iter++) {
+ defaultRange.push_back(*iter);
+ DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n",
+ iter->start, iter->end);
+ }
}
} else {
@@ -498,23 +514,39 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
}
}
+unsigned int
+Bus::drain(Event * de)
+{
+ //We should check that we're not "doing" anything, and that noone is
+ //waiting. We might be idle but have someone waiting if the device we
+ //contacted for a retry didn't actually retry.
+ if (curTick >= tickNextIdle && retryList.size() == 0) {
+ return 0;
+ } else {
+ drainEvent = de;
+ return 1;
+ }
+}
+
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus)
Param<int> bus_id;
Param<int> clock;
Param<int> width;
+ Param<bool> responder_set;
END_DECLARE_SIM_OBJECT_PARAMS(Bus)
BEGIN_INIT_SIM_OBJECT_PARAMS(Bus)
INIT_PARAM(bus_id, "a globally unique bus id"),
INIT_PARAM(clock, "bus clock speed"),
- INIT_PARAM(width, "width of the bus (bits)")
+ INIT_PARAM(width, "width of the bus (bits)"),
+ INIT_PARAM(responder_set, "Is a default responder set by the user")
END_INIT_SIM_OBJECT_PARAMS(Bus)
CREATE_SIM_OBJECT(Bus)
{
- return new Bus(getInstanceName(), bus_id, clock, width);
+ return new Bus(getInstanceName(), bus_id, clock, width, responder_set);
}
REGISTER_SIM_OBJECT("Bus", Bus)
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 9fb33b7c3..ff1d2545d 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -59,6 +59,8 @@ class Bus : public MemObject
/** the next tick at which the bus will be idle */
Tick tickNextIdle;
+ Event * drainEvent;
+
static const int defaultId = -3; //Make it unique from Broadcast
struct DevMap {
@@ -144,7 +146,7 @@ class Bus : public MemObject
/** Constructor for the BusPort.*/
BusPort(const std::string &_name, Bus *_bus, int _id)
- : Port(_name), _onRetryList(false), bus(_bus), id(_id)
+ : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id)
{ }
bool onRetryList()
@@ -240,6 +242,9 @@ class Bus : public MemObject
/** Port that handles requests that don't match any of the interfaces.*/
BusPort *defaultPort;
+ /** Has the user specified their own default responder? */
+ bool responderSet;
+
public:
/** A function used to return the port associated with this bus object. */
@@ -247,9 +252,13 @@ class Bus : public MemObject
virtual void init();
- Bus(const std::string &n, int bus_id, int _clock, int _width)
+ unsigned int drain(Event *de);
+
+ Bus(const std::string &n, int bus_id, int _clock, int _width,
+ bool responder_set)
: MemObject(n), busId(bus_id), clock(_clock), width(_width),
- tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL)
+ tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false),
+ defaultPort(NULL), responderSet(responder_set)
{
//Both the width and clock period must be positive
if (width <= 0)
diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc
index 599958222..c26d7782b 100644
--- a/src/mem/cache/base_cache.cc
+++ b/src/mem/cache/base_cache.cc
@@ -42,7 +42,7 @@ using namespace std;
BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
bool _isCpuSide)
- : Port(_name), cache(_cache), isCpuSide(_isCpuSide)
+ : Port(_name, _cache), cache(_cache), isCpuSide(_isCpuSide)
{
blocked = false;
waitingOnRetry = false;
@@ -140,6 +140,9 @@ BaseCache::CachePort::recvRetry()
}
waitingOnRetry = false;
}
+ // Check if we're done draining once this list is empty
+ if (drainList.empty())
+ cache->checkDrain();
}
else if (!isCpuSide)
{
@@ -338,6 +341,10 @@ BaseCache::CacheEvent::process()
cachePort->drainList.push_back(pkt);
cachePort->waitingOnRetry = true;
}
+
+ // Check if we're done draining once this list is empty
+ if (cachePort->drainList.empty())
+ cachePort->cache->checkDrain();
}
const char *
@@ -357,9 +364,7 @@ BaseCache::getPort(const std::string &if_name, int idx)
}
else if (if_name == "functional")
{
- if(cpuSidePort == NULL)
- cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
- return cpuSidePort;
+ return new CachePort(name() + "-cpu_side_port", this, true);
}
else if (if_name == "cpu_side")
{
@@ -601,3 +606,18 @@ BaseCache::regStats()
;
}
+
+unsigned int
+BaseCache::drain(Event *de)
+{
+ // Set status
+ if (!canDrain()) {
+ drainEvent = de;
+
+ changeState(SimObject::Draining);
+ return 1;
+ }
+
+ changeState(SimObject::Drained);
+ return 0;
+}
diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh
index 565280aef..ea7544fbb 100644
--- a/src/mem/cache/base_cache.hh
+++ b/src/mem/cache/base_cache.hh
@@ -105,6 +105,8 @@ class BaseCache : public MemObject
void clearBlocked();
+ bool canDrain() { return drainList.empty(); }
+
bool blocked;
bool mustSendRetry;
@@ -227,6 +229,9 @@ class BaseCache : public MemObject
/** The number of misses to trigger an exit event. */
Counter missCount;
+ /** The drain event. */
+ Event *drainEvent;
+
public:
// Statistics
/**
@@ -340,7 +345,7 @@ class BaseCache : public MemObject
BaseCache(const std::string &name, Params &params)
: MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0),
slaveRequests(0), blkSize(params.blkSize),
- missCount(params.maxMisses)
+ missCount(params.maxMisses), drainEvent(NULL)
{
//Start ports at null if more than one is created we should panic
cpuSidePort = NULL;
@@ -477,6 +482,7 @@ class BaseCache : public MemObject
{
uint8_t flag = 1<<cause;
masterRequests &= ~flag;
+ checkDrain();
}
/**
@@ -512,6 +518,7 @@ class BaseCache : public MemObject
{
uint8_t flag = 1<<cause;
slaveRequests &= ~flag;
+ checkDrain();
}
/**
@@ -589,6 +596,30 @@ class BaseCache : public MemObject
return;
}
}
+
+ virtual unsigned int drain(Event *de);
+
+ void checkDrain()
+ {
+ if (drainEvent && canDrain()) {
+ drainEvent->process();
+ changeState(SimObject::Drained);
+ // Clear the drain event
+ drainEvent = NULL;
+ }
+ }
+
+ bool canDrain()
+ {
+ if (doMasterRequest() || doSlaveRequest()) {
+ return false;
+ } else if (memSidePort && !memSidePort->canDrain()) {
+ return false;
+ } else if (cpuSidePort && !cpuSidePort->canDrain()) {
+ return false;
+ }
+ return true;
+ }
};
#endif //__BASE_CACHE_HH__
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index 0302f7351..39eb63108 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -191,7 +191,9 @@ PhysicalMemory::checkLockedAddrList(Request *req)
void
PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
{
- assert(pkt->getAddr() + pkt->getSize() <= params()->addrRange.size());
+ assert(pkt->getAddr() + pkt->getSize() > params()->addrRange.start &&
+ pkt->getAddr() + pkt->getSize() <= params()->addrRange.start +
+ params()->addrRange.size());
if (pkt->isRead()) {
if (pkt->req->isLocked()) {
diff --git a/src/mem/port.hh b/src/mem/port.hh
index b6eeb9db3..75afc04e6 100644
--- a/src/mem/port.hh
+++ b/src/mem/port.hh
@@ -58,6 +58,8 @@
typedef std::list<Range<Addr> > AddrRangeList;
typedef std::list<Range<Addr> >::iterator AddrRangeIter;
+class MemObject;
+
/**
* Ports are used to interface memory objects to
* each other. They will always come in pairs, and we refer to the other
@@ -81,10 +83,13 @@ class Port
memory objects. */
Port *peer;
+ /** A pointer to the MemObject that owns this port. This may not be set. */
+ MemObject *owner;
+
public:
Port()
- : peer(NULL)
+ : peer(NULL), owner(NULL)
{ }
/**
@@ -92,9 +97,11 @@ class Port
*
* @param _name Port name for DPRINTF output. Should include name
* of memory system object to which the port belongs.
+ * @param _owner Pointer to the MemObject that owns this port.
+ * Will not necessarily be set.
*/
- Port(const std::string &_name)
- : portName(_name), peer(NULL)
+ Port(const std::string &_name, MemObject *_owner = NULL)
+ : portName(_name), peer(NULL), owner(_owner)
{ }
/** Return port name (for DPRINTF). */
@@ -112,16 +119,18 @@ class Port
void setName(const std::string &name)
{ portName = name; }
- /** Function to set the pointer for the peer port.
- @todo should be called by the configuration stuff (python).
- */
+ /** Function to set the pointer for the peer port. */
void setPeer(Port *port);
- /** Function to set the pointer for the peer port.
- @todo should be called by the configuration stuff (python).
- */
+ /** Function to get the pointer to the peer port. */
Port *getPeer() { return peer; }
+ /** Function to set the owner of this port. */
+ void setOwner(MemObject *_owner) { owner = _owner; }
+
+ /** Function to return the owner of this port. */
+ MemObject *getOwner() { return owner; }
+
protected:
/** These functions are protected because they should only be
@@ -247,8 +256,8 @@ class Port
class FunctionalPort : public Port
{
public:
- FunctionalPort(const std::string &_name)
- : Port(_name)
+ FunctionalPort(const std::string &_name, MemObject *_owner = NULL)
+ : Port(_name, _owner)
{}
protected:
diff --git a/src/mem/port_impl.hh b/src/mem/port_impl.hh
index b7980bdd2..989cfd338 100644
--- a/src/mem/port_impl.hh
+++ b/src/mem/port_impl.hh
@@ -28,6 +28,9 @@
* Authors: Ali Saidi
*/
+//To get endianness
+#include "arch/isa_traits.hh"
+
#include "mem/port.hh"
#include "sim/byteswap.hh"
@@ -35,7 +38,7 @@ template <typename T>
void
FunctionalPort::writeHtoG(Addr addr, T d)
{
- d = htog(d);
+ d = TheISA::htog(d);
writeBlob(addr, (uint8_t*)&d, sizeof(T));
}
@@ -46,6 +49,6 @@ FunctionalPort::readGtoH(Addr addr)
{
T d;
readBlob(addr, (uint8_t*)&d, sizeof(T));
- return gtoh(d);
+ return TheISA::gtoh(d);
}
diff --git a/src/mem/tport.hh b/src/mem/tport.hh
index 438ec56dc..3d28ea3e5 100644
--- a/src/mem/tport.hh
+++ b/src/mem/tport.hh
@@ -114,8 +114,8 @@ class SimpleTimingPort : public Port
public:
- SimpleTimingPort(std::string pname)
- : Port(pname), sendEvent(this), drainEvent(NULL)
+ SimpleTimingPort(std::string pname, MemObject *_owner = NULL)
+ : Port(pname, _owner), sendEvent(this), drainEvent(NULL)
{}
/** Hook for draining timing accesses from the system. The